Merging upstream version 4.0.0 (Closes: #1095814).
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
7318203982
commit
07735c967b
62 changed files with 4173 additions and 2396 deletions
25
.converagerc
Normal file
25
.converagerc
Normal file
|
@ -0,0 +1,25 @@
|
|||
[run]
|
||||
branch = True
|
||||
|
||||
[report]
|
||||
; Regexes for lines to exclude from consideration
|
||||
exclude_also =
|
||||
; Don't complain about missing debug-only code:
|
||||
def __repr__
|
||||
if self\.debug
|
||||
|
||||
; Don't complain if tests don't hit defensive assertion code:
|
||||
raise AssertionError
|
||||
raise NotImplementedError
|
||||
|
||||
; Don't complain if non-runnable code isn't run:
|
||||
if 0:
|
||||
if __name__ == .__main__.:
|
||||
|
||||
; Don't complain about abstract methods, they aren't run:
|
||||
@(abc\.)?abstractmethod
|
||||
|
||||
ignore_errors = True
|
||||
|
||||
[html]
|
||||
directory = coverage_html_report
|
|
@ -1,3 +1,4 @@
|
|||
export PYTHONIOENCODING=utf-8
|
||||
export LC_ALL=en_US.UTF-8
|
||||
export LANG=en_US.UTF-8
|
||||
export FORCE_COLOR=true
|
57
.github/workflows/build.yml
vendored
Normal file
57
.github/workflows/build.yml
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
name: Build and Test
|
||||
|
||||
on: [ push ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.11'
|
||||
# cache: 'pipenv' # caching pipenv dependencies
|
||||
- name: Install poetry and pipx
|
||||
run: |
|
||||
pip install poetry && pip install pipx
|
||||
|
||||
- name: Install global dependencies
|
||||
run: |
|
||||
pipx install isort && pipx install black && pipx install bandit && \
|
||||
pipx install pylint && pipx install pre-commit && pipx install poetry
|
||||
|
||||
- name: Install Dependencies
|
||||
run: poetry install --with dev
|
||||
|
||||
- name: Run Makefile
|
||||
run: make check
|
||||
- name: Run make
|
||||
run: poetry run make publish
|
||||
- name: Upload Package
|
||||
uses: actions/upload-artifact@v3.1.2
|
||||
with:
|
||||
name: packages
|
||||
path: dist/
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
|
||||
pypi-publish:
|
||||
name: Upload release to PyPI
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: pypi
|
||||
url: https://pypi.org/p/terminaltables3
|
||||
permissions:
|
||||
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
|
||||
# if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
|
||||
steps:
|
||||
- name: Get packages
|
||||
uses: actions/download-artifact@v3.0.2
|
||||
with:
|
||||
name: packages
|
||||
path: dist/
|
||||
- name: Publish package distributions to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
needs: build
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -94,3 +94,5 @@ test*.png
|
|||
.idea/
|
||||
requirements*.txt
|
||||
.DS_Store
|
||||
|
||||
.build_history/
|
||||
|
|
95
.pre-commit-config.yaml
Normal file
95
.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,95 @@
|
|||
---
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.6.0
|
||||
hooks:
|
||||
# each hook takes about 1s to run. These are expensive-ish checks
|
||||
- id: check-added-large-files
|
||||
- id: check-yaml
|
||||
- id: check-builtin-literals
|
||||
- id: check-byte-order-marker
|
||||
- id: check-case-conflict
|
||||
- id: check-merge-conflict
|
||||
- id: check-symlinks
|
||||
- id: check-toml
|
||||
- id: debug-statements
|
||||
- id: detect-private-key
|
||||
- id: fix-encoding-pragma
|
||||
args: [ --remove ]
|
||||
- id: forbid-new-submodules
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v3.16.0
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [ --py37-plus ]
|
||||
# Buggy? Reports no files change, "FAILURE"
|
||||
# - repo: https://github.com/tox-dev/pyproject-fmt
|
||||
# rev: "0.4.1"
|
||||
# hooks:
|
||||
# - id: pyproject-fmt
|
||||
# works for me, don't know why it is complaining
|
||||
# - repo: https://github.com/abravalheri/validate-pyproject
|
||||
# rev: v0.10.1
|
||||
# hooks:
|
||||
# - id: validate-pyproject
|
||||
- repo: https://github.com/myint/autoflake
|
||||
rev: v2.3.1
|
||||
hooks:
|
||||
- id: autoflake
|
||||
args:
|
||||
- --in-place
|
||||
- --recursive
|
||||
- --expand-star-imports
|
||||
- --remove-all-unused-imports
|
||||
- --remove-duplicate-keys
|
||||
- --remove-unused-variables
|
||||
# black is conflicting with something else
|
||||
# - repo: https://github.com/psf/black
|
||||
# rev: 23.12.1
|
||||
# hooks:
|
||||
# - id: black
|
||||
# language_version: python3.10
|
||||
# - repo: https://github.com/pycqa/isort
|
||||
# rev: 5.11.4
|
||||
# hooks:
|
||||
# - id: isort
|
||||
# name: isort
|
||||
# args:
|
||||
# - --profile black
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.5.2
|
||||
hooks:
|
||||
- id: ruff
|
||||
exclude: ^dead_code/
|
||||
args: [
|
||||
"--config",
|
||||
"pyproject.toml",
|
||||
"--fix",
|
||||
]
|
||||
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||
rev: v1.10.0 # Use the ref you want to point at
|
||||
hooks:
|
||||
- id: python-use-type-annotations
|
||||
- id: python-no-eval
|
||||
- id: python-no-log-warn
|
||||
- id: text-unicode-replacement-char
|
||||
# - repo: https://github.com/igorshubovych/markdownlint-cli
|
||||
# rev: v0.38.0
|
||||
# hooks:
|
||||
# - id: markdownlint
|
||||
# # '--fix'
|
||||
# args: [ 'content/**/*.md', '--config', '.markdownlintrc' ]
|
||||
# - repo: https://github.com/executablebooks/mdformat
|
||||
# rev: 0.7.17 # Use the ref you want to point at
|
||||
# hooks:
|
||||
# - id: mdformat
|
||||
# # Optionally add plugins
|
||||
# additional_dependencies:
|
||||
# - mdformat-gfm
|
||||
# - mdformat-black
|
||||
# - repo: https://github.com/adamchainz/blacken-docs
|
||||
# rev: 1.18.0
|
||||
# hooks:
|
||||
# - id: blacken-docs
|
||||
# additional_dependencies:
|
||||
# - black==23.12.1
|
633
.pylintrc
Normal file
633
.pylintrc
Normal file
|
@ -0,0 +1,633 @@
|
|||
[MAIN]
|
||||
|
||||
# Analyse import fallback blocks. This can be used to support both Python 2 and
|
||||
# 3 compatible code, which means that the block might have code that exists
|
||||
# only in one or another interpreter, leading to false positives when analysed.
|
||||
analyse-fallback-blocks=no
|
||||
|
||||
# Load and enable all available extensions. Use --list-extensions to see a list
|
||||
# all available extensions.
|
||||
#enable-all-extensions=
|
||||
|
||||
# In error mode, checkers without error messages are disabled and for others,
|
||||
# only the ERROR messages are displayed, and no reports are done by default.
|
||||
#errors-only=
|
||||
|
||||
# Always return a 0 (non-error) status code, even if lint errors are found.
|
||||
# This is primarily useful in continuous integration scripts.
|
||||
#exit-zero=
|
||||
|
||||
# A comma-separated list of package or module names from where C extensions may
|
||||
# be loaded. Extensions are loading into the active Python interpreter and may
|
||||
# run arbitrary code.
|
||||
extension-pkg-allow-list=
|
||||
|
||||
# A comma-separated list of package or module names from where C extensions may
|
||||
# be loaded. Extensions are loading into the active Python interpreter and may
|
||||
# run arbitrary code. (This is an alternative name to extension-pkg-allow-list
|
||||
# for backward compatibility.)
|
||||
extension-pkg-whitelist=
|
||||
|
||||
# Return non-zero exit code if any of these messages/categories are detected,
|
||||
# even if score is above --fail-under value. Syntax same as enable. Messages
|
||||
# specified are enabled, while categories only check already-enabled messages.
|
||||
fail-on=
|
||||
|
||||
# Specify a score threshold to be exceeded before program exits with error.
|
||||
fail-under=10
|
||||
|
||||
# Interpret the stdin as a python script, whose filename needs to be passed as
|
||||
# the module_or_package argument.
|
||||
#from-stdin=
|
||||
|
||||
# Files or directories to be skipped. They should be base names, not paths.
|
||||
ignore=CVS
|
||||
|
||||
# Add files or directories matching the regex patterns to the ignore-list. The
|
||||
# regex matches against paths and can be in Posix or Windows format.
|
||||
ignore-paths=
|
||||
|
||||
# Files or directories matching the regex patterns are skipped. The regex
|
||||
# matches against base names, not paths. The default value ignores Emacs file
|
||||
# locks
|
||||
ignore-patterns=^\.#
|
||||
|
||||
# List of module names for which member attributes should not be checked
|
||||
# (useful for modules/projects where namespaces are manipulated during runtime
|
||||
# and thus existing member attributes cannot be deduced by static analysis). It
|
||||
# supports qualified module names, as well as Unix pattern matching.
|
||||
ignored-modules=
|
||||
|
||||
# Python code to execute, usually for sys.path manipulation such as
|
||||
# pygtk.require().
|
||||
#init-hook=
|
||||
|
||||
# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
|
||||
# number of processors available to use.
|
||||
jobs=1
|
||||
|
||||
# Control the amount of potential inferred values when inferring a single
|
||||
# object. This can help the performance when dealing with large functions or
|
||||
# complex, nested conditions.
|
||||
limit-inference-results=100
|
||||
|
||||
# List of plugins (as comma separated values of python module names) to load,
|
||||
# usually to register additional checkers.
|
||||
load-plugins=
|
||||
|
||||
# Pickle collected data for later comparisons.
|
||||
persistent=yes
|
||||
|
||||
# Minimum Python version to use for version dependent checks. Will default to
|
||||
# the version used to run pylint.
|
||||
py-version=3.10
|
||||
|
||||
# Discover python modules and packages in the file system subtree.
|
||||
recursive=no
|
||||
|
||||
# When enabled, pylint would attempt to guess common misconfiguration and emit
|
||||
# user-friendly hints instead of false-positive error messages.
|
||||
suggestion-mode=yes
|
||||
|
||||
# Allow loading of arbitrary C extensions. Extensions are imported into the
|
||||
# active Python interpreter and may run arbitrary code.
|
||||
unsafe-load-any-extension=no
|
||||
|
||||
# In verbose mode, extra non-checker-related info will be displayed.
|
||||
#verbose=
|
||||
|
||||
|
||||
[REPORTS]
|
||||
|
||||
# Python expression which should return a score less than or equal to 10. You
|
||||
# have access to the variables 'fatal', 'error', 'warning', 'refactor',
|
||||
# 'convention', and 'info' which contain the number of messages in each
|
||||
# category, as well as 'statement' which is the total number of statements
|
||||
# analyzed. This score is used by the global evaluation report (RP0004).
|
||||
evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))
|
||||
|
||||
# Template used to display messages. This is a python new-style format string
|
||||
# used to format the message information. See doc for all details.
|
||||
msg-template=
|
||||
|
||||
# Set the output format. Available formats are text, parseable, colorized, json
|
||||
# and msvs (visual studio). You can also give a reporter class, e.g.
|
||||
# mypackage.mymodule.MyReporterClass.
|
||||
#output-format=
|
||||
|
||||
# Tells whether to display a full report or only the messages.
|
||||
reports=no
|
||||
|
||||
# Activate the evaluation score.
|
||||
score=yes
|
||||
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
|
||||
# Only show warnings with the listed confidence levels. Leave empty to show
|
||||
# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE,
|
||||
# UNDEFINED.
|
||||
confidence=HIGH,
|
||||
CONTROL_FLOW,
|
||||
INFERENCE,
|
||||
INFERENCE_FAILURE,
|
||||
UNDEFINED
|
||||
|
||||
# Disable the message, report, category or checker with the given id(s). You
|
||||
# can either give multiple identifiers separated by comma (,) or put this
|
||||
# option multiple times (only on the command line, not in the configuration
|
||||
# file where it should appear only once). You can also use "--disable=all" to
|
||||
# disable everything first and then re-enable specific checks. For example, if
|
||||
# you want to run only the similarities checker, you can use "--disable=all
|
||||
# --enable=similarities". If you want to run only the classes checker, but have
|
||||
# no Warning level messages displayed, use "--disable=all --enable=classes
|
||||
# --disable=W".
|
||||
disable=raw-checker-failed,
|
||||
bad-inline-option,
|
||||
locally-disabled,
|
||||
file-ignored,
|
||||
suppressed-message,
|
||||
useless-suppression,
|
||||
deprecated-pragma,
|
||||
use-symbolic-message-instead,
|
||||
|
||||
# can't care
|
||||
fixme,
|
||||
too-many-lines,
|
||||
too-many-branches,
|
||||
import-error,
|
||||
too-many-statements,
|
||||
useless-import-alias,
|
||||
too-many-locals,
|
||||
consider-using-from-import, # pylint is wrong
|
||||
duplicate-code,
|
||||
too-many-arguments,
|
||||
logging-fstring-interpolation,
|
||||
too-many-instance-attributes,
|
||||
too-many-return-statements,
|
||||
unnecessary-direct-lambda-call,
|
||||
too-few-public-methods,
|
||||
logging-not-lazy,
|
||||
line-too-long,
|
||||
too-many-public-methods,
|
||||
|
||||
# backwards compatibility forever!
|
||||
consider-using-f-string,
|
||||
super-with-arguments
|
||||
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
# either give multiple identifier separated by comma (,) or put this option
|
||||
# multiple time (only on the command line, not in the configuration file where
|
||||
# it should appear only once). See also the "--disable" option for examples.
|
||||
enable=c-extension-no-member
|
||||
|
||||
|
||||
[BASIC]
|
||||
|
||||
# Naming style matching correct argument names.
|
||||
argument-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct argument names. Overrides argument-
|
||||
# naming-style. If left empty, argument names will be checked with the set
|
||||
# naming style.
|
||||
#argument-rgx=
|
||||
|
||||
# Naming style matching correct attribute names.
|
||||
attr-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct attribute names. Overrides attr-naming-
|
||||
# style. If left empty, attribute names will be checked with the set naming
|
||||
# style.
|
||||
#attr-rgx=
|
||||
|
||||
# Bad variable names which should always be refused, separated by a comma.
|
||||
bad-names=foo,
|
||||
bar,
|
||||
baz,
|
||||
toto,
|
||||
tutu,
|
||||
tata
|
||||
|
||||
# Bad variable names regexes, separated by a comma. If names match any regex,
|
||||
# they will always be refused
|
||||
bad-names-rgxs=
|
||||
|
||||
# Naming style matching correct class attribute names.
|
||||
class-attribute-naming-style=any
|
||||
|
||||
# Regular expression matching correct class attribute names. Overrides class-
|
||||
# attribute-naming-style. If left empty, class attribute names will be checked
|
||||
# with the set naming style.
|
||||
#class-attribute-rgx=
|
||||
|
||||
# Naming style matching correct class constant names.
|
||||
class-const-naming-style=UPPER_CASE
|
||||
|
||||
# Regular expression matching correct class constant names. Overrides class-
|
||||
# const-naming-style. If left empty, class constant names will be checked with
|
||||
# the set naming style.
|
||||
#class-const-rgx=
|
||||
|
||||
# Naming style matching correct class names.
|
||||
class-naming-style=PascalCase
|
||||
|
||||
# Regular expression matching correct class names. Overrides class-naming-
|
||||
# style. If left empty, class names will be checked with the set naming style.
|
||||
#class-rgx=
|
||||
|
||||
# Naming style matching correct constant names.
|
||||
const-naming-style=UPPER_CASE
|
||||
|
||||
# Regular expression matching correct constant names. Overrides const-naming-
|
||||
# style. If left empty, constant names will be checked with the set naming
|
||||
# style.
|
||||
#const-rgx=
|
||||
|
||||
# Minimum line length for functions/classes that require docstrings, shorter
|
||||
# ones are exempt.
|
||||
docstring-min-length=-1
|
||||
|
||||
# Naming style matching correct function names.
|
||||
function-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct function names. Overrides function-
|
||||
# naming-style. If left empty, function names will be checked with the set
|
||||
# naming style.
|
||||
#function-rgx=
|
||||
|
||||
# Good variable names which should always be accepted, separated by a comma.
|
||||
good-names=i,
|
||||
j,
|
||||
k,
|
||||
ex,
|
||||
Run,
|
||||
_
|
||||
|
||||
# Good variable names regexes, separated by a comma. If names match any regex,
|
||||
# they will always be accepted
|
||||
good-names-rgxs=
|
||||
|
||||
# Include a hint for the correct naming format with invalid-name.
|
||||
include-naming-hint=no
|
||||
|
||||
# Naming style matching correct inline iteration names.
|
||||
inlinevar-naming-style=any
|
||||
|
||||
# Regular expression matching correct inline iteration names. Overrides
|
||||
# inlinevar-naming-style. If left empty, inline iteration names will be checked
|
||||
# with the set naming style.
|
||||
#inlinevar-rgx=
|
||||
|
||||
# Naming style matching correct method names.
|
||||
method-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct method names. Overrides method-naming-
|
||||
# style. If left empty, method names will be checked with the set naming style.
|
||||
#method-rgx=
|
||||
|
||||
# Naming style matching correct module names.
|
||||
module-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct module names. Overrides module-naming-
|
||||
# style. If left empty, module names will be checked with the set naming style.
|
||||
#module-rgx=
|
||||
|
||||
# Colon-delimited sets of names that determine each other's naming style when
|
||||
# the name regexes allow several styles.
|
||||
name-group=
|
||||
|
||||
# Regular expression which should only match function or class names that do
|
||||
# not require a docstring.
|
||||
no-docstring-rgx=^_
|
||||
|
||||
# List of decorators that produce properties, such as abc.abstractproperty. Add
|
||||
# to this list to register other decorators that produce valid properties.
|
||||
# These decorators are taken in consideration only for invalid-name.
|
||||
property-classes=abc.abstractproperty
|
||||
|
||||
# Regular expression matching correct type variable names. If left empty, type
|
||||
# variable names will be checked with the set naming style.
|
||||
#typevar-rgx=
|
||||
|
||||
# Naming style matching correct variable names.
|
||||
variable-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct variable names. Overrides variable-
|
||||
# naming-style. If left empty, variable names will be checked with the set
|
||||
# naming style.
|
||||
#variable-rgx=
|
||||
|
||||
|
||||
[CLASSES]
|
||||
|
||||
# Warn about protected attribute access inside special methods
|
||||
check-protected-access-in-special-methods=no
|
||||
|
||||
# List of method names used to declare (i.e. assign) instance attributes.
|
||||
defining-attr-methods=__init__,
|
||||
__new__,
|
||||
setUp,
|
||||
__post_init__
|
||||
|
||||
# List of member names, which should be excluded from the protected access
|
||||
# warning.
|
||||
exclude-protected=_asdict,
|
||||
_fields,
|
||||
_replace,
|
||||
_source,
|
||||
_make
|
||||
|
||||
# List of valid names for the first argument in a class method.
|
||||
valid-classmethod-first-arg=cls
|
||||
|
||||
# List of valid names for the first argument in a metaclass class method.
|
||||
valid-metaclass-classmethod-first-arg=cls
|
||||
|
||||
|
||||
[DESIGN]
|
||||
|
||||
# List of regular expressions of class ancestor names to ignore when counting
|
||||
# public methods (see R0903)
|
||||
exclude-too-few-public-methods=
|
||||
|
||||
# List of qualified class names to ignore when counting class parents (see
|
||||
# R0901)
|
||||
ignored-parents=
|
||||
|
||||
# Maximum number of arguments for function / method.
|
||||
max-args=5
|
||||
|
||||
# Maximum number of attributes for a class (see R0902).
|
||||
max-attributes=7
|
||||
|
||||
# Maximum number of boolean expressions in an if statement (see R0916).
|
||||
max-bool-expr=5
|
||||
|
||||
# Maximum number of branch for function / method body.
|
||||
max-branches=12
|
||||
|
||||
# Maximum number of locals for function / method body.
|
||||
max-locals=15
|
||||
|
||||
# Maximum number of parents for a class (see R0901).
|
||||
max-parents=7
|
||||
|
||||
# Maximum number of public methods for a class (see R0904).
|
||||
max-public-methods=20
|
||||
|
||||
# Maximum number of return / yield for function / method body.
|
||||
max-returns=6
|
||||
|
||||
# Maximum number of statements in function / method body.
|
||||
max-statements=50
|
||||
|
||||
# Minimum number of public methods for a class (see R0903).
|
||||
min-public-methods=2
|
||||
|
||||
|
||||
[EXCEPTIONS]
|
||||
|
||||
# Exceptions that will emit a warning when caught.
|
||||
overgeneral-exceptions=builtins.BaseException,
|
||||
builtins.Exception
|
||||
|
||||
|
||||
[FORMAT]
|
||||
|
||||
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
|
||||
expected-line-ending-format=
|
||||
|
||||
# Regexp for a line that is allowed to be longer than the limit.
|
||||
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
|
||||
|
||||
# Number of spaces of indent required inside a hanging or continued line.
|
||||
indent-after-paren=4
|
||||
|
||||
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
|
||||
# tab).
|
||||
indent-string=' '
|
||||
|
||||
# Maximum number of characters on a single line.
|
||||
max-line-length=120
|
||||
|
||||
# Maximum number of lines in a module.
|
||||
max-module-lines=1000
|
||||
|
||||
# Allow the body of a class to be on the same line as the declaration if body
|
||||
# contains single statement.
|
||||
single-line-class-stmt=no
|
||||
|
||||
# Allow the body of an if to be on the same line as the test if there is no
|
||||
# else.
|
||||
single-line-if-stmt=no
|
||||
|
||||
|
||||
[IMPORTS]
|
||||
|
||||
# List of modules that can be imported at any level, not just the top level
|
||||
# one.
|
||||
allow-any-import-level=
|
||||
|
||||
# Allow wildcard imports from modules that define __all__.
|
||||
allow-wildcard-with-all=no
|
||||
|
||||
# Deprecated modules which should not be used, separated by a comma.
|
||||
deprecated-modules=
|
||||
|
||||
# Output a graph (.gv or any supported image format) of external dependencies
|
||||
# to the given file (report RP0402 must not be disabled).
|
||||
ext-import-graph=
|
||||
|
||||
# Output a graph (.gv or any supported image format) of all (i.e. internal and
|
||||
# external) dependencies to the given file (report RP0402 must not be
|
||||
# disabled).
|
||||
import-graph=
|
||||
|
||||
# Output a graph (.gv or any supported image format) of internal dependencies
|
||||
# to the given file (report RP0402 must not be disabled).
|
||||
int-import-graph=
|
||||
|
||||
# Force import order to recognize a module as part of the standard
|
||||
# compatibility libraries.
|
||||
known-standard-library=
|
||||
|
||||
# Force import order to recognize a module as part of a third party library.
|
||||
known-third-party=enchant
|
||||
|
||||
# Couples of modules and preferred modules, separated by a comma.
|
||||
preferred-modules=
|
||||
|
||||
|
||||
[LOGGING]
|
||||
|
||||
# The type of string formatting that logging methods do. `old` means using %
|
||||
# formatting, `new` is for `{}` formatting.
|
||||
logging-format-style=old
|
||||
|
||||
# Logging modules to check that the string format arguments are in logging
|
||||
# function parameter format.
|
||||
logging-modules=logging
|
||||
|
||||
|
||||
[MISCELLANEOUS]
|
||||
|
||||
# List of note tags to take in consideration, separated by a comma.
|
||||
notes=FIXME,
|
||||
XXX,
|
||||
TODO
|
||||
|
||||
# Regular expression of note tags to take in consideration.
|
||||
notes-rgx=
|
||||
|
||||
|
||||
[REFACTORING]
|
||||
|
||||
# Maximum number of nested blocks for function / method body
|
||||
max-nested-blocks=5
|
||||
|
||||
# Complete name of functions that never returns. When checking for
|
||||
# inconsistent-return-statements if a never returning function is called then
|
||||
# it will be considered as an explicit return statement and no message will be
|
||||
# printed.
|
||||
never-returning-functions=sys.exit,argparse.parse_error
|
||||
|
||||
|
||||
[SIMILARITIES]
|
||||
|
||||
# Comments are removed from the similarity computation
|
||||
ignore-comments=yes
|
||||
|
||||
# Docstrings are removed from the similarity computation
|
||||
ignore-docstrings=yes
|
||||
|
||||
# Imports are removed from the similarity computation
|
||||
ignore-imports=yes
|
||||
|
||||
# Signatures are removed from the similarity computation
|
||||
ignore-signatures=yes
|
||||
|
||||
# Minimum lines number of a similarity.
|
||||
min-similarity-lines=4
|
||||
|
||||
|
||||
[SPELLING]
|
||||
|
||||
# Limits count of emitted suggestions for spelling mistakes.
|
||||
max-spelling-suggestions=4
|
||||
|
||||
# Spelling dictionary name. Available dictionaries: none. To make it work,
|
||||
# install the 'python-enchant' package.
|
||||
spelling-dict=
|
||||
|
||||
# List of comma separated words that should be considered directives if they
|
||||
# appear at the beginning of a comment and should not be checked.
|
||||
spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:
|
||||
|
||||
# List of comma separated words that should not be checked.
|
||||
spelling-ignore-words=
|
||||
|
||||
# A path to a file that contains the private dictionary; one word per line.
|
||||
spelling-private-dict-file=
|
||||
|
||||
# Tells whether to store unknown words to the private dictionary (see the
|
||||
# --spelling-private-dict-file option) instead of raising a message.
|
||||
spelling-store-unknown-words=no
|
||||
|
||||
|
||||
[STRING]
|
||||
|
||||
# This flag controls whether inconsistent-quotes generates a warning when the
|
||||
# character used as a quote delimiter is used inconsistently within a module.
|
||||
check-quote-consistency=no
|
||||
|
||||
# This flag controls whether the implicit-str-concat should generate a warning
|
||||
# on implicit string concatenation in sequences defined over several lines.
|
||||
check-str-concat-over-line-jumps=no
|
||||
|
||||
|
||||
[TYPECHECK]
|
||||
|
||||
# List of decorators that produce context managers, such as
|
||||
# contextlib.contextmanager. Add to this list to register other decorators that
|
||||
# produce valid context managers.
|
||||
contextmanager-decorators=contextlib.contextmanager
|
||||
|
||||
# List of members which are set dynamically and missed by pylint inference
|
||||
# system, and so shouldn't trigger E1101 when accessed. Python regular
|
||||
# expressions are accepted.
|
||||
generated-members=
|
||||
|
||||
# Tells whether to warn about missing members when the owner of the attribute
|
||||
# is inferred to be None.
|
||||
ignore-none=yes
|
||||
|
||||
# This flag controls whether pylint should warn about no-member and similar
|
||||
# checks whenever an opaque object is returned when inferring. The inference
|
||||
# can return multiple potential results while evaluating a Python object, but
|
||||
# some branches might not be evaluated, which results in partial inference. In
|
||||
# that case, it might be useful to still emit no-member and other checks for
|
||||
# the rest of the inferred objects.
|
||||
ignore-on-opaque-inference=yes
|
||||
|
||||
# List of symbolic message names to ignore for Mixin members.
|
||||
ignored-checks-for-mixins=no-member,
|
||||
not-async-context-manager,
|
||||
not-context-manager,
|
||||
attribute-defined-outside-init
|
||||
|
||||
# List of class names for which member attributes should not be checked (useful
|
||||
# for classes with dynamically set attributes). This supports the use of
|
||||
# qualified names.
|
||||
ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace
|
||||
|
||||
# Show a hint with possible names when a member name was not found. The aspect
|
||||
# of finding the hint is based on edit distance.
|
||||
missing-member-hint=yes
|
||||
|
||||
# The minimum edit distance a name should have in order to be considered a
|
||||
# similar match for a missing member name.
|
||||
missing-member-hint-distance=1
|
||||
|
||||
# The total number of similar names that should be taken in consideration when
|
||||
# showing a hint for a missing member.
|
||||
missing-member-max-choices=1
|
||||
|
||||
# Regex pattern to define which classes are considered mixins.
|
||||
mixin-class-rgx=.*[Mm]ixin
|
||||
|
||||
# List of decorators that change the signature of a decorated function.
|
||||
signature-mutators=
|
||||
|
||||
|
||||
[VARIABLES]
|
||||
|
||||
# List of additional names supposed to be defined in builtins. Remember that
|
||||
# you should avoid defining new builtins when possible.
|
||||
additional-builtins=
|
||||
|
||||
# Tells whether unused global variables should be treated as a violation.
|
||||
allow-global-unused-variables=yes
|
||||
|
||||
# List of names allowed to shadow builtins
|
||||
allowed-redefined-builtins=
|
||||
|
||||
# List of strings which can identify a callback function by name. A callback
|
||||
# name must start or end with one of those strings.
|
||||
callbacks=cb_,
|
||||
_cb
|
||||
|
||||
# A regular expression matching the name of dummy variables (i.e. expected to
|
||||
# not be used).
|
||||
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
|
||||
|
||||
# Argument names that match this expression will be ignored. Default to name
|
||||
# with leading underscore.
|
||||
ignored-argument-names=_.*|^ignored_|^unused_
|
||||
|
||||
# Tells whether we should check for unused import in __init__ files.
|
||||
init-import=no
|
||||
|
||||
# List of qualified module names which can have objects that can redefine
|
||||
# builtins.
|
||||
redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
|
15
CHANGELOG.md
15
CHANGELOG.md
|
@ -4,7 +4,20 @@ Changelog
|
|||
|
||||
This project adheres to `Semantic Versioning <http://semver.org/>`_.
|
||||
|
||||
3.1.7 - 2016-12-7
|
||||
4.0.0 - 2024-1-1
|
||||
------------------
|
||||
|
||||
Changed
|
||||
* New namespace and package name: terminaltables3
|
||||
* No changes made to the License.
|
||||
|
||||
Added
|
||||
* Started on type annotations
|
||||
|
||||
Removed
|
||||
* Removed Python 2 support. Possibly supports earlier 3.x versions but no longer checking in build script.
|
||||
|
||||
3.1.7 - 2021-1-1
|
||||
------------------
|
||||
|
||||
Added
|
||||
|
|
104
Makefile
Normal file
104
Makefile
Normal file
|
@ -0,0 +1,104 @@
|
|||
# isort . && black . && bandit -r . && pylint && pre-commit run --all-files
|
||||
# Get changed files
|
||||
|
||||
FILES := $(wildcard **/*.py)
|
||||
|
||||
# if you wrap everything in pipenv run, it runs slower.
|
||||
ifeq ($(origin VIRTUAL_ENV),undefined)
|
||||
VENV := poetry run
|
||||
else
|
||||
VENV :=
|
||||
endif
|
||||
|
||||
|
||||
|
||||
clean-pyc:
|
||||
@echo "Removing compiled files"
|
||||
@find . -name '*.pyc' -exec rm -f {} + || true
|
||||
@find . -name '*.pyo' -exec rm -f {} + || true
|
||||
@find . -name '__pycache__' -exec rm -fr {} + || true
|
||||
|
||||
clean-test:
|
||||
@echo "Removing coverage data"
|
||||
@rm -f .coverage || true
|
||||
@rm -f .coverage.* || true
|
||||
|
||||
clean: clean-pyc clean-test
|
||||
|
||||
# tests can't be expected to pass if dependencies aren't installed.
|
||||
# tests are often slow and linting is fast, so run tests on linted code.
|
||||
test: clean .build_history/pylint .build_history/bandit
|
||||
@echo "Running unit tests"
|
||||
export FORCE_COLOR=true
|
||||
# $(VENV) pytest terminaltables3 --doctest-modules
|
||||
# $(VENV) python -m unittest discover
|
||||
# not all tests run in all OSs, giving seemingly low coverage.
|
||||
FORCE_COLOR=true $(VENV) py.test tests --cov=terminaltables3 --cov-report=html --cov-fail-under 75
|
||||
|
||||
.build_history:
|
||||
@mkdir -p .build_history
|
||||
|
||||
.build_history/isort: .build_history $(FILES)
|
||||
@echo "Formatting imports"
|
||||
$(VENV) isort terminaltables3
|
||||
@touch .build_history/isort
|
||||
|
||||
.PHONY: isort
|
||||
isort: .build_history/isort
|
||||
|
||||
.build_history/black: .build_history .build_history/isort $(FILES)
|
||||
@echo "Formatting code"
|
||||
$(VENV) black . --exclude .virtualenv --exclude .tox
|
||||
@touch .build_history/black
|
||||
|
||||
.PHONY: black
|
||||
black: .build_history/black
|
||||
|
||||
.build_history/pre-commit: .build_history .build_history/isort .build_history/black
|
||||
@echo "Pre-commit checks"
|
||||
$(VENV) pre-commit run --all-files
|
||||
@touch .build_history/pre-commit
|
||||
|
||||
.PHONY: pre-commit
|
||||
pre-commit: .build_history/pre-commit
|
||||
|
||||
.build_history/bandit: .build_history $(FILES)
|
||||
@echo "Security checks"
|
||||
$(VENV) bandit .
|
||||
@touch .build_history/bandit
|
||||
|
||||
.PHONY: bandit
|
||||
bandit: .build_history/bandit
|
||||
|
||||
.PHONY: pylint
|
||||
.build_history/pylint: .build_history .build_history/isort .build_history/black $(FILES)
|
||||
@echo "Linting with pylint"
|
||||
# TODO lint tests
|
||||
$(VENV) pylint terminaltables3 --fail-under 10
|
||||
@touch .build_history/pylint
|
||||
|
||||
.PHONY: ruff
|
||||
.build_history/ruff: .build_history .build_history/isort .build_history/black $(FILES)
|
||||
@echo "Linting with ruff"
|
||||
$(VENV) ruff check terminaltables3 tests --fix
|
||||
@touch .build_history/ruff
|
||||
|
||||
.PHONY: ruff
|
||||
ruff: .build_history/ruff
|
||||
|
||||
# for when using -j (jobs, run in parallel)
|
||||
.NOTPARALLEL: .build_history/isort .build_history/black
|
||||
|
||||
check: test pylint ruff bandit pre-commit
|
||||
|
||||
.PHONY: publish
|
||||
publish: check
|
||||
rm -rf dist && poetry build
|
||||
|
||||
.PHONY: build
|
||||
build: check
|
||||
rm -rf dist && poetry build
|
||||
|
||||
.PHONY: mypy
|
||||
mypy:
|
||||
$(VENV) mypy terminaltables3 --ignore-missing-imports --check-untyped-defs
|
16
Pipfile
16
Pipfile
|
@ -1,16 +0,0 @@
|
|||
[[source]]
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
|
||||
[dev-packages]
|
||||
colorama=">=0.3.7"
|
||||
colorclass=">=2.2.0"
|
||||
pytest-cov=">=2.4.0"
|
||||
termcolor = "*"
|
||||
check-wheel-contents = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.9"
|
28
README.md
28
README.md
|
@ -1,11 +1,19 @@
|
|||
## terminaltables
|
||||
|
||||
# What is it
|
||||
|
||||
Easily draw tables in terminal/console applications from a list of lists of strings. Supports multi-line rows.
|
||||
|
||||
- Python 2.6, 2.7, PyPy, PyPy3, 3.3, 3.4, and 3.5+ supported on Linux and OS X.
|
||||
- Python 2.7, 3.3, 3.4, and 3.5+ supported on Windows (both 32 and 64 bit versions of Python).
|
||||
Tested on Python 3.8+
|
||||
|
||||
**This is a fork of the terminaltables project. Which is archived and unmaintained. This library is in a new namespace
|
||||
but should otherwise be a drop in replacement. Maintaining goals consist of maintaining ecosystem compatibility, type
|
||||
annotations and responding to community pull requests.**
|
||||
|
||||
To Upgrade
|
||||
==========
|
||||
Replace all instances of `terminaltables` with `terminaltables3` in your code. If other libraries depend on `terminaltables`
|
||||
in your venv they will not conflict because it is a new namespace.
|
||||
|
||||
As of right now, the documentation as the robpol86 version.
|
||||
|
||||
📖 Full documentation: https://robpol86.github.io/terminaltables
|
||||
|
||||
|
@ -15,19 +23,19 @@ Quickstart
|
|||
Install:
|
||||
|
||||
```bash
|
||||
pip install terminaltables
|
||||
pip install terminaltables3
|
||||
```
|
||||
|
||||
Usage:
|
||||
|
||||
```python
|
||||
from terminaltables import AsciiTable
|
||||
from terminaltables3 import AsciiTable
|
||||
|
||||
table_data = [
|
||||
['Heading1', 'Heading2'],
|
||||
['row1 column1', 'row1 column2'],
|
||||
['row2 column1', 'row2 column2'],
|
||||
['row3 column1', 'row3 column2']
|
||||
["Heading1", "Heading2"],
|
||||
["row1 column1", "row1 column2"],
|
||||
["row2 column1", "row2 column2"],
|
||||
["row3 column1", "row3 column2"],
|
||||
]
|
||||
table = AsciiTable(table_data)
|
||||
print
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
# Configure.
|
||||
language: python
|
||||
python:
|
||||
- 3.5
|
||||
- 3.4
|
||||
- 3.3
|
||||
- pypy3
|
||||
- pypy
|
||||
- 2.7
|
||||
- 2.6
|
||||
sudo: false
|
||||
|
||||
# Environment and matrix.
|
||||
env: TOX_ENV=py
|
||||
matrix:
|
||||
include:
|
||||
- python: 3.5
|
||||
env: TOX_ENV=lint
|
||||
after_success: []
|
||||
- python: 3.5
|
||||
env: TOX_ENV=docs
|
||||
after_success:
|
||||
- eval "$(ssh-agent -s)"; touch docs/key; chmod 0600 $_
|
||||
- openssl aes-256-cbc -d -K "$encrypted_c89fed6a587d_key" -iv "$encrypted_c89fed6a587d_iv" -out docs/key
|
||||
< docs/key.enc && ssh-add $_
|
||||
- git config --global user.email "builds@travis-ci.com"
|
||||
- git config --global user.name "Travis CI"
|
||||
- git remote set-url --push origin "git@github.com:$TRAVIS_REPO_SLUG"
|
||||
- export ${!TRAVIS*}
|
||||
- tox -e docsV
|
||||
|
||||
# Run.
|
||||
install: pip install tox
|
||||
script: tox -e $TOX_ENV
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
# Deploy.
|
||||
deploy:
|
||||
provider: pypi
|
||||
user: Robpol86
|
||||
password:
|
||||
secure:
|
||||
"aj+Hl25+NbtmKpHcqxxNJhaMmawgzEPdLX+NwxwAZuTrvUCdiMtYhF9qxN0USHIlXSGDNc\
|
||||
7ua6nNpYPhjRv7j5YM4uLlK+4Fv/iU+iQcVfy89BS4vlXzUoje6nLIhogsxytb+FjdGZ0PK\
|
||||
JzzxfYr0relUjui/gPYmTQoZ1IiT8A="
|
||||
on:
|
||||
condition: $TRAVIS_PYTHON_VERSION = 3.4
|
||||
tags: true
|
|
@ -1,162 +0,0 @@
|
|||
==============
|
||||
terminaltables
|
||||
==============
|
||||
|
||||
Easily draw tables in terminal/console applications from a list of lists of strings. Supports multi-line rows.
|
||||
|
||||
* Python 2.6, 2.7, PyPy, PyPy3, 3.3, 3.4, and 3.5 supported on Linux and OS X.
|
||||
* Python 2.7, 3.3, 3.4, and 3.5 supported on Windows (both 32 and 64 bit versions of Python).
|
||||
|
||||
📖 Full documentation: https://robpol86.github.io/terminaltables
|
||||
|
||||
.. image:: https://img.shields.io/appveyor/ci/Robpol86/terminaltables/master.svg?style=flat-square&label=AppVeyor%20CI
|
||||
:target: https://ci.appveyor.com/project/Robpol86/terminaltables
|
||||
:alt: Build Status Windows
|
||||
|
||||
.. image:: https://img.shields.io/travis/Robpol86/terminaltables/master.svg?style=flat-square&label=Travis%20CI
|
||||
:target: https://travis-ci.org/Robpol86/terminaltables
|
||||
:alt: Build Status
|
||||
|
||||
.. image:: https://img.shields.io/codecov/c/github/Robpol86/terminaltables/master.svg?style=flat-square&label=Codecov
|
||||
:target: https://codecov.io/gh/Robpol86/terminaltables
|
||||
:alt: Coverage Status
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/terminaltables.svg?style=flat-square&label=Latest
|
||||
:target: https://pypi.python.org/pypi/terminaltables
|
||||
:alt: Latest Version
|
||||
|
||||
Quickstart
|
||||
==========
|
||||
|
||||
Install:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
pip install terminaltables
|
||||
|
||||
Usage:
|
||||
|
||||
.. code::
|
||||
|
||||
from terminaltables import AsciiTable
|
||||
table_data = [
|
||||
['Heading1', 'Heading2'],
|
||||
['row1 column1', 'row1 column2'],
|
||||
['row2 column1', 'row2 column2'],
|
||||
['row3 column1', 'row3 column2']
|
||||
]
|
||||
table = AsciiTable(table_data)
|
||||
print table.table
|
||||
+--------------+--------------+
|
||||
| Heading1 | Heading2 |
|
||||
+--------------+--------------+
|
||||
| row1 column1 | row1 column2 |
|
||||
| row2 column1 | row2 column2 |
|
||||
| row3 column1 | row3 column2 |
|
||||
+--------------+--------------+
|
||||
|
||||
Example Implementations
|
||||
=======================
|
||||
|
||||
.. image:: docs/examples.png?raw=true
|
||||
:alt: Example Scripts Screenshot
|
||||
|
||||
Source code for examples: `example1.py <https://github.com/Robpol86/terminaltables/blob/master/example1.py>`_,
|
||||
`example2.py <https://github.com/Robpol86/terminaltables/blob/master/example2.py>`_, and
|
||||
`example3.py <https://github.com/Robpol86/terminaltables/blob/master/example3.py>`_
|
||||
|
||||
.. changelog-section-start
|
||||
|
||||
Changelog
|
||||
=========
|
||||
|
||||
This project adheres to `Semantic Versioning <http://semver.org/>`_.
|
||||
|
||||
3.1.0 - 2016-10-16
|
||||
------------------
|
||||
|
||||
Added
|
||||
* ``git --porcelain``-like table by liiight: https://github.com/Robpol86/terminaltables/pull/31
|
||||
|
||||
3.0.0 - 2016-05-30
|
||||
------------------
|
||||
|
||||
Added
|
||||
* Support for https://pypi.python.org/pypi/colorama
|
||||
* Support for https://pypi.python.org/pypi/termcolor
|
||||
* Support for RTL characters (Arabic and Hebrew).
|
||||
* Support for non-string items in ``table_data`` like integers.
|
||||
|
||||
Changed
|
||||
* Refactored again, but this time entire project including tests.
|
||||
|
||||
Removed
|
||||
* ``padded_table_data`` property and ``join_row()``. Moving away from repeated string joining/splitting.
|
||||
|
||||
Fixed
|
||||
* ``set_terminal_title()`` Unicode handling on Windows.
|
||||
* https://github.com/Robpol86/terminaltables/issues/18
|
||||
* https://github.com/Robpol86/terminaltables/issues/20
|
||||
* https://github.com/Robpol86/terminaltables/issues/23
|
||||
* https://github.com/Robpol86/terminaltables/issues/26
|
||||
|
||||
2.1.0 - 2015-11-02
|
||||
------------------
|
||||
|
||||
Added
|
||||
* GitHub Flavored Markdown table by bcho: https://github.com/Robpol86/terminaltables/pull/12
|
||||
* Python 3.5 support (Linux/OS X and Windows).
|
||||
|
||||
2.0.0 - 2015-10-11
|
||||
------------------
|
||||
|
||||
Changed
|
||||
* Refactored code. No new features.
|
||||
* Breaking changes: ``UnixTable``/``WindowsTable``/``WindowsTableDouble`` moved. Use ``SingleTable``/``DoubleTable``
|
||||
instead.
|
||||
|
||||
1.2.1 - 2015-09-03
|
||||
------------------
|
||||
|
||||
Fixed
|
||||
* CJK character width fixed by zqqf16 and bcho: https://github.com/Robpol86/terminaltables/pull/9
|
||||
|
||||
1.2.0 - 2015-05-31
|
||||
------------------
|
||||
|
||||
Added
|
||||
* Bottom row separator.
|
||||
|
||||
1.1.1 - 2014-11-03
|
||||
------------------
|
||||
|
||||
Fixed
|
||||
* Python 2.7 64-bit terminal width bug on Windows.
|
||||
|
||||
1.1.0 - 2014-11-02
|
||||
------------------
|
||||
|
||||
Added
|
||||
* Windows support.
|
||||
* Double-lined table.
|
||||
|
||||
1.0.2 - 2014-09-18
|
||||
------------------
|
||||
|
||||
Added
|
||||
* ``table_width`` and ``ok`` properties.
|
||||
|
||||
1.0.1 - 2014-09-12
|
||||
------------------
|
||||
|
||||
Added
|
||||
* Terminal width/height defaults for testing.
|
||||
* ``terminaltables.DEFAULT_TERMINAL_WIDTH``
|
||||
* ``terminaltables.DEFAULT_TERMINAL_HEIGHT``
|
||||
|
||||
1.0.0 - 2014-09-11
|
||||
------------------
|
||||
|
||||
* Initial release.
|
||||
|
||||
.. changelog-section-end
|
|
@ -1,27 +0,0 @@
|
|||
# Configure.
|
||||
environment:
|
||||
PATH: C:\%PYTHON%;C:\%PYTHON%\Scripts;%PATH%
|
||||
PYTHON: Python35
|
||||
matrix:
|
||||
- TOX_ENV: lint
|
||||
- TOX_ENV: py35
|
||||
- TOX_ENV: py34
|
||||
- TOX_ENV: py33
|
||||
- TOX_ENV: py27
|
||||
- TOX_ENV: py
|
||||
PYTHON: Python35-x64
|
||||
- TOX_ENV: py
|
||||
PYTHON: Python34-x64
|
||||
- TOX_ENV: py
|
||||
PYTHON: Python33-x64
|
||||
- TOX_ENV: py
|
||||
PYTHON: Python27-x64
|
||||
|
||||
# Run.
|
||||
build_script: pip install tox
|
||||
test_script: tox -e %TOX_ENV%
|
||||
on_success: IF %TOX_ENV% NEQ lint pip install codecov & codecov
|
||||
|
||||
# Post.
|
||||
on_finish:
|
||||
- FOR %%F IN (test*.png) DO appveyor PushArtifact %%F
|
|
@ -1,109 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
"""Setup script for the project."""
|
||||
|
||||
import codecs
|
||||
import os
|
||||
import re
|
||||
|
||||
from setuptools import Command, setup
|
||||
|
||||
INSTALL_REQUIRES = []
|
||||
LICENSE = 'MIT'
|
||||
NAME = IMPORT = 'terminaltables'
|
||||
VERSION = '3.1.0'
|
||||
|
||||
|
||||
def readme(path='README.rst'):
|
||||
"""Try to read README.rst or return empty string if failed.
|
||||
|
||||
:param str path: Path to README file.
|
||||
|
||||
:return: File contents.
|
||||
:rtype: str
|
||||
"""
|
||||
path = os.path.realpath(os.path.join(os.path.dirname(__file__), path))
|
||||
handle = None
|
||||
url_prefix = 'https://raw.githubusercontent.com/Robpol86/{name}/v{version}/'.format(name=NAME, version=VERSION)
|
||||
try:
|
||||
handle = codecs.open(path, encoding='utf-8')
|
||||
return handle.read(131072).replace('.. image:: docs', '.. image:: {0}docs'.format(url_prefix))
|
||||
except IOError:
|
||||
return ''
|
||||
finally:
|
||||
getattr(handle, 'close', lambda: None)()
|
||||
|
||||
|
||||
class CheckVersion(Command):
|
||||
"""Make sure version strings and other metadata match here, in module/package, tox, and other places."""
|
||||
|
||||
description = 'verify consistent version/etc strings in project'
|
||||
user_options = []
|
||||
|
||||
@classmethod
|
||||
def initialize_options(cls):
|
||||
"""Required by distutils."""
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def finalize_options(cls):
|
||||
"""Required by distutils."""
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def run(cls):
|
||||
"""Check variables."""
|
||||
project = __import__(IMPORT, fromlist=[''])
|
||||
for expected, var in [('@Robpol86', '__author__'), (LICENSE, '__license__'), (VERSION, '__version__')]:
|
||||
if getattr(project, var) != expected:
|
||||
raise SystemExit('Mismatch: {0}'.format(var))
|
||||
# Check changelog.
|
||||
if not re.compile(r'^%s - \d{4}-\d{2}-\d{2}[\r\n]' % VERSION, re.MULTILINE).search(readme()):
|
||||
raise SystemExit('Version not found in readme/changelog file.')
|
||||
# Check tox.
|
||||
if INSTALL_REQUIRES:
|
||||
contents = readme('tox.ini')
|
||||
section = re.compile(r'[\r\n]+install_requires =[\r\n]+(.+?)[\r\n]+\w', re.DOTALL).findall(contents)
|
||||
if not section:
|
||||
raise SystemExit('Missing install_requires section in tox.ini.')
|
||||
in_tox = re.findall(r' ([^=]+)==[\w\d.-]+', section[0])
|
||||
if INSTALL_REQUIRES != in_tox:
|
||||
raise SystemExit('Missing/unordered pinned dependencies in tox.ini.')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
setup(
|
||||
author='@Robpol86',
|
||||
author_email='robpol86@gmail.com',
|
||||
classifiers=[
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Environment :: Console',
|
||||
'Environment :: MacOS X',
|
||||
'Environment :: Win32 (MS Windows)',
|
||||
'Intended Audience :: Developers',
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Operating System :: MacOS :: MacOS X',
|
||||
'Operating System :: Microsoft :: Windows',
|
||||
'Operating System :: POSIX :: Linux',
|
||||
'Operating System :: POSIX',
|
||||
'Programming Language :: Python :: 2.6',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3.3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: Implementation :: PyPy',
|
||||
'Topic :: Software Development :: Libraries',
|
||||
'Topic :: Terminals',
|
||||
'Topic :: Text Processing :: Markup',
|
||||
],
|
||||
cmdclass=dict(check_version=CheckVersion),
|
||||
description='Generate simple tables in terminals from a nested list of strings.',
|
||||
install_requires=INSTALL_REQUIRES,
|
||||
keywords='Shell Bash ANSI ASCII terminal tables',
|
||||
license=LICENSE,
|
||||
long_description=readme(),
|
||||
name=NAME,
|
||||
packages=[IMPORT],
|
||||
url='https://github.com/Robpol86/' + NAME,
|
||||
version=VERSION,
|
||||
zip_safe=True,
|
||||
)
|
55
docs/conf.py
55
docs/conf.py
|
@ -6,50 +6,55 @@ import time
|
|||
|
||||
|
||||
# General configuration.
|
||||
sys.path.append(os.path.realpath(os.path.join(os.path.dirname(__file__), '..')))
|
||||
author = '@Robpol86'
|
||||
copyright = '{}, {}'.format(time.strftime('%Y'), author)
|
||||
html_last_updated_fmt = '%c {}'.format(time.tzname[time.localtime().tm_isdst])
|
||||
master_doc = 'index'
|
||||
project = __import__('setup').NAME
|
||||
pygments_style = 'friendly'
|
||||
release = version = __import__('setup').VERSION
|
||||
templates_path = ['_templates']
|
||||
extensions = list()
|
||||
sys.path.append(os.path.realpath(os.path.join(os.path.dirname(__file__), "..")))
|
||||
author = "@Robpol86"
|
||||
copyright = "{}, {}".format(time.strftime("%Y"), author)
|
||||
html_last_updated_fmt = f"%c {time.tzname[time.localtime().tm_isdst]}"
|
||||
master_doc = "index"
|
||||
project = __import__("setup").NAME
|
||||
pygments_style = "friendly"
|
||||
release = version = __import__("setup").VERSION
|
||||
templates_path = ["_templates"]
|
||||
extensions = []
|
||||
|
||||
|
||||
# Options for HTML output.
|
||||
html_context = dict(
|
||||
conf_py_path='/docs/',
|
||||
conf_py_path="/docs/",
|
||||
display_github=True,
|
||||
github_repo=os.environ.get('TRAVIS_REPO_SLUG', '/' + project).split('/', 1)[1],
|
||||
github_user=os.environ.get('TRAVIS_REPO_SLUG', 'robpol86/').split('/', 1)[0],
|
||||
github_version=os.environ.get('TRAVIS_BRANCH', 'master'),
|
||||
source_suffix='.rst',
|
||||
github_repo=os.environ.get("TRAVIS_REPO_SLUG", "/" + project).split("/", 1)[1],
|
||||
github_user=os.environ.get("TRAVIS_REPO_SLUG", "robpol86/").split("/", 1)[0],
|
||||
github_version=os.environ.get("TRAVIS_BRANCH", "master"),
|
||||
source_suffix=".rst",
|
||||
)
|
||||
html_copy_source = False
|
||||
html_favicon = 'favicon.ico'
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_favicon = "favicon.ico"
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
html_title = project
|
||||
|
||||
|
||||
# autodoc
|
||||
extensions.append('sphinx.ext.autodoc')
|
||||
extensions.append("sphinx.ext.autodoc")
|
||||
|
||||
|
||||
# extlinks.
|
||||
extensions.append('sphinx.ext.extlinks')
|
||||
extlinks = {'github': ('https://github.com/robpol86/{0}/blob/v{1}/%s'.format(project, version), '')}
|
||||
extensions.append("sphinx.ext.extlinks")
|
||||
extlinks = {
|
||||
"github": (
|
||||
f"https://github.com/robpol86/{project}/blob/v{version}/%s",
|
||||
"",
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
# google analytics
|
||||
extensions.append('sphinxcontrib.googleanalytics')
|
||||
googleanalytics_id = 'UA-82627369-1'
|
||||
extensions.append("sphinxcontrib.googleanalytics")
|
||||
googleanalytics_id = "UA-82627369-1"
|
||||
|
||||
|
||||
# SCVersioning.
|
||||
scv_banner_greatest_tag = True
|
||||
scv_grm_exclude = ('.gitignore', '.nojekyll', 'README.rst')
|
||||
scv_overflow = ('-W',)
|
||||
scv_grm_exclude = (".gitignore", ".nojekyll", "README.rst")
|
||||
scv_overflow = ("-W",)
|
||||
scv_show_banner = True
|
||||
scv_sort = ('semver', 'time')
|
||||
scv_sort = ("semver", "time")
|
||||
|
|
19
example1.py
19
example1.py
|
@ -4,39 +4,38 @@
|
|||
Just prints sample text and exits.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
from terminaltables import AsciiTable, DoubleTable, SingleTable
|
||||
from terminaltables3 import AsciiTable, DoubleTable, SingleTable
|
||||
|
||||
TABLE_DATA = (
|
||||
('Platform', 'Years', 'Notes'),
|
||||
('Mk5', '2007-2009', 'The Golf Mk5 Variant was\nintroduced in 2007.'),
|
||||
('MKVI', '2009-2013', 'Might actually be Mk5.'),
|
||||
("Platform", "Years", "Notes"),
|
||||
("Mk5", "2007-2009", "The Golf Mk5 Variant was\nintroduced in 2007."),
|
||||
("MKVI", "2009-2013", "Might actually be Mk5."),
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function."""
|
||||
title = 'Jetta SportWagen'
|
||||
title = "Jetta SportWagen"
|
||||
|
||||
# AsciiTable.
|
||||
table_instance = AsciiTable(TABLE_DATA, title)
|
||||
table_instance.justify_columns[2] = 'right'
|
||||
table_instance.justify_columns[2] = "right"
|
||||
print(table_instance.table)
|
||||
print()
|
||||
|
||||
# SingleTable.
|
||||
table_instance = SingleTable(TABLE_DATA, title)
|
||||
table_instance.justify_columns[2] = 'right'
|
||||
table_instance.justify_columns[2] = "right"
|
||||
print(table_instance.table)
|
||||
print()
|
||||
|
||||
# DoubleTable.
|
||||
table_instance = DoubleTable(TABLE_DATA, title)
|
||||
table_instance.justify_columns[2] = 'right'
|
||||
table_instance.justify_columns[2] = "right"
|
||||
print(table_instance.table)
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
52
example2.py
52
example2.py
|
@ -4,19 +4,21 @@
|
|||
Just prints sample text and exits.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
from colorclass import Color, Windows
|
||||
|
||||
from terminaltables import SingleTable
|
||||
from terminaltables3 import SingleTable
|
||||
|
||||
|
||||
def table_server_timings():
|
||||
"""Return table string to be printed."""
|
||||
table_data = [
|
||||
[Color('{autogreen}<10ms{/autogreen}'), '192.168.0.100, 192.168.0.101'],
|
||||
[Color('{autoyellow}10ms <= 100ms{/autoyellow}'), '192.168.0.102, 192.168.0.103'],
|
||||
[Color('{autored}>100ms{/autored}'), '192.168.0.105'],
|
||||
[Color("{autogreen}<10ms{/autogreen}"), "192.168.0.100, 192.168.0.101"],
|
||||
[
|
||||
Color("{autoyellow}10ms <= 100ms{/autoyellow}"),
|
||||
"192.168.0.102, 192.168.0.103",
|
||||
],
|
||||
[Color("{autored}>100ms{/autored}"), "192.168.0.105"],
|
||||
]
|
||||
table_instance = SingleTable(table_data)
|
||||
table_instance.inner_heading_row_border = False
|
||||
|
@ -26,20 +28,32 @@ def table_server_timings():
|
|||
def table_server_status():
|
||||
"""Return table string to be printed."""
|
||||
table_data = [
|
||||
[Color('Low Space'), Color('{autocyan}Nominal Space{/autocyan}'), Color('Excessive Space')],
|
||||
[Color('Low Load'), Color('Nominal Load'), Color('{autored}High Load{/autored}')],
|
||||
[Color('{autocyan}Low Free RAM{/autocyan}'), Color('Nominal Free RAM'), Color('High Free RAM')],
|
||||
[
|
||||
Color("Low Space"),
|
||||
Color("{autocyan}Nominal Space{/autocyan}"),
|
||||
Color("Excessive Space"),
|
||||
],
|
||||
[
|
||||
Color("Low Load"),
|
||||
Color("Nominal Load"),
|
||||
Color("{autored}High Load{/autored}"),
|
||||
],
|
||||
[
|
||||
Color("{autocyan}Low Free RAM{/autocyan}"),
|
||||
Color("Nominal Free RAM"),
|
||||
Color("High Free RAM"),
|
||||
],
|
||||
]
|
||||
table_instance = SingleTable(table_data, '192.168.0.105')
|
||||
table_instance = SingleTable(table_data, "192.168.0.105")
|
||||
table_instance.inner_heading_row_border = False
|
||||
table_instance.inner_row_border = True
|
||||
table_instance.justify_columns = {0: 'center', 1: 'center', 2: 'center'}
|
||||
table_instance.justify_columns = {0: "center", 1: "center", 2: "center"}
|
||||
return table_instance.table
|
||||
|
||||
|
||||
def table_abcd():
|
||||
"""Return table string to be printed. Two tables on one line."""
|
||||
table_instance = SingleTable([['A', 'B'], ['C', 'D']])
|
||||
table_instance = SingleTable([["A", "B"], ["C", "D"]])
|
||||
|
||||
# Get first table lines.
|
||||
table_instance.outer_border = False
|
||||
|
@ -53,16 +67,18 @@ def table_abcd():
|
|||
|
||||
# Combine.
|
||||
smallest, largest = sorted([table_inner_borders, table_outer_borders], key=len)
|
||||
smallest += [''] * (len(largest) - len(smallest)) # Make both same size.
|
||||
combined = list()
|
||||
smallest += [""] * (len(largest) - len(smallest)) # Make both same size.
|
||||
combined = []
|
||||
for i, row in enumerate(largest):
|
||||
combined.append(row.ljust(10) + ' ' + smallest[i])
|
||||
return '\n'.join(combined)
|
||||
combined.append(row.ljust(10) + " " + smallest[i])
|
||||
return "\n".join(combined)
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function."""
|
||||
Windows.enable(auto_colors=True, reset_atexit=True) # Does nothing if not on Windows.
|
||||
Windows.enable(
|
||||
auto_colors=True, reset_atexit=True
|
||||
) # Does nothing if not on Windows.
|
||||
|
||||
# Server timings.
|
||||
print(table_server_timings())
|
||||
|
@ -77,10 +93,10 @@ def main():
|
|||
print()
|
||||
|
||||
# Instructions.
|
||||
table_instance = SingleTable([['Obey Obey Obey Obey']], 'Instructions')
|
||||
table_instance = SingleTable([["Obey Obey Obey Obey"]], "Instructions")
|
||||
print(table_instance.table)
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
24
example3.py
24
example3.py
|
@ -4,33 +4,37 @@
|
|||
Just prints sample text and exits.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
from textwrap import wrap
|
||||
|
||||
from terminaltables import SingleTable
|
||||
from terminaltables3 import SingleTable
|
||||
|
||||
LONG_STRING = ('Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore '
|
||||
'et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut '
|
||||
'aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum '
|
||||
'dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui '
|
||||
'officia deserunt mollit anim id est laborum.')
|
||||
LONG_STRING = (
|
||||
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore "
|
||||
"et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut "
|
||||
"aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum "
|
||||
"dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui "
|
||||
"officia deserunt mollit anim id est laborum."
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function."""
|
||||
table_data = [
|
||||
['Long String', ''], # One row. Two columns. Long string will replace this empty string.
|
||||
[
|
||||
"Long String",
|
||||
"",
|
||||
], # One row. Two columns. Long string will replace this empty string.
|
||||
]
|
||||
table = SingleTable(table_data)
|
||||
|
||||
# Calculate newlines.
|
||||
max_width = table.column_max_width(1)
|
||||
wrapped_string = '\n'.join(wrap(LONG_STRING, max_width))
|
||||
wrapped_string = "\n".join(wrap(LONG_STRING, max_width))
|
||||
table.table_data[0][1] = wrapped_string
|
||||
|
||||
print(table.table)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
1058
poetry.lock
generated
Normal file
1058
poetry.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,66 +0,0 @@
|
|||
[tool.poetry]
|
||||
name = "terminaltables-whl"
|
||||
version = "3.1.0"
|
||||
description = "Generate simple tables in terminals from a nested list of strings."
|
||||
authors = [
|
||||
"Matthew Martin <matthewdeanmartin@gmail.com>",
|
||||
"Robpol86 <robpol86@gmail.com>",
|
||||
]
|
||||
keywords = ["Shell","Bash","ANSI","ASCII","terminal","tables"]
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Environment :: Console",
|
||||
"Environment :: MacOS X",
|
||||
"Environment :: Win32 (MS Windows)",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Operating System :: MacOS :: MacOS X",
|
||||
"Operating System :: Microsoft :: Windows",
|
||||
"Operating System :: POSIX :: Linux",
|
||||
"Operating System :: POSIX",
|
||||
"Programming Language :: Python :: 2.6",
|
||||
"Programming Language :: Python :: 2.7",
|
||||
"Programming Language :: Python :: 3.3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
"Programming Language :: Python :: 3.6",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: Implementation :: PyPy",
|
||||
"Topic :: Software Development :: Libraries",
|
||||
"Topic :: Terminals",
|
||||
"Topic :: Text Processing :: Markup",
|
||||
]
|
||||
packages = [
|
||||
{ include = "terminaltables" },
|
||||
]
|
||||
include = [
|
||||
"terminaltables/**/*.py",
|
||||
]
|
||||
exclude = [
|
||||
]
|
||||
license = "MIT"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/matthewdeanmartin/terminaltables"
|
||||
homepage = "https://github.com/matthewdeanmartin/terminaltables"
|
||||
documentation = "https://github.com/matthewdeanmartin/terminaltables"
|
||||
|
||||
[tool.poetry.urls]
|
||||
"Bug Tracker" = "https://github.com/matthewdeanmartin/terminaltables/issues"
|
||||
"Change Log" = "https://github.com/matthewdeanmartin/terminaltables/blob/main/docs/CHANGES.MD"
|
||||
|
||||
[tool.poetry.scripts]
|
||||
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
# per vermin's estimation
|
||||
python = ">=2.6 || >=3.0"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
pytest = "==6.0.1"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry>=0.12"]
|
||||
build-backend = "poetry.masonry.api"
|
|
@ -1,7 +1,7 @@
|
|||
[tool.poetry]
|
||||
name = "terminaltables"
|
||||
version = "3.1.10"
|
||||
description = "Generate simple tables in terminals from a nested list of strings."
|
||||
name = "terminaltables3"
|
||||
version = "4.0.0"
|
||||
description = "Generate simple tables in terminals from a nested list of strings. Fork of terminaltables."
|
||||
authors = [
|
||||
"Robpol86 <robpol86@gmail.com>",
|
||||
"Matthew Martin <matthewdeanmartin@gmail.com>"
|
||||
|
@ -18,49 +18,74 @@ classifiers = [
|
|||
"Operating System :: Microsoft :: Windows",
|
||||
"Operating System :: POSIX :: Linux",
|
||||
"Operating System :: POSIX",
|
||||
"Programming Language :: Python :: 2.6",
|
||||
"Programming Language :: Python :: 2.7",
|
||||
"Programming Language :: Python :: 3.3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
"Programming Language :: Python :: 3.6",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: Implementation :: PyPy",
|
||||
"Topic :: Software Development :: Libraries",
|
||||
"Topic :: Terminals",
|
||||
"Topic :: Text Processing :: Markup",
|
||||
]
|
||||
packages = [
|
||||
{ include = "terminaltables" },
|
||||
{ include = "terminaltables3" },
|
||||
]
|
||||
include = [
|
||||
"terminaltables/**/*.py",
|
||||
"terminaltables3/**/*.py",
|
||||
]
|
||||
exclude = [
|
||||
]
|
||||
license = "MIT"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/matthewdeanmartin/terminaltables"
|
||||
homepage = "https://github.com/matthewdeanmartin/terminaltables"
|
||||
documentation = "https://github.com/matthewdeanmartin/terminaltables"
|
||||
repository = "https://github.com/matthewdeanmartin/terminaltables3"
|
||||
homepage = "https://github.com/matthewdeanmartin/terminaltables3"
|
||||
documentation = "https://github.com/matthewdeanmartin/terminaltables3"
|
||||
|
||||
[tool.poetry.urls]
|
||||
"Bug Tracker" = "https://github.com/matthewdeanmartin/terminaltables/issues"
|
||||
"Change Log" = "https://github.com/matthewdeanmartin/terminaltables/blob/master/CHANGELOG.md"
|
||||
"Bug Tracker" = "https://github.com/matthewdeanmartin/terminaltables3/issues"
|
||||
"Change Log" = "https://github.com/matthewdeanmartin/terminaltables3/blob/master/CHANGELOG.md"
|
||||
|
||||
[tool.poetry.scripts]
|
||||
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
# per vermin's estimation
|
||||
python = ">=2.6 || >=3.0"
|
||||
python = ">=3.8"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
pytest = "==6.0.1"
|
||||
# complementary deps
|
||||
colorama=">=0.3.7"
|
||||
colorclass=">=2.2.0"
|
||||
termcolor = "*"
|
||||
|
||||
# build deps
|
||||
pytest = ">=8.2.1"
|
||||
pytest-cov = ">=5.0.0"
|
||||
vermin = ">=1.6.0"
|
||||
tox = ">=4.15.0"
|
||||
isort = ">=5.13.2"
|
||||
bandit = ">=1.7.8"
|
||||
black = ">=24.4.2"
|
||||
pylint = ">=3.2.2"
|
||||
ruff = ">=0.4.5"
|
||||
mypy = ">=1.10.0"
|
||||
pillow = ">=10.3.0"
|
||||
pre-commit = ">=2"
|
||||
|
||||
# pytest = ">=7.4.3"
|
||||
pytest-xdist =">=3.5.0"
|
||||
pytest-randomly=">=3.15.0"
|
||||
pytest-sugar =">=0.9.7"
|
||||
|
||||
# pytest-snapshot = "*"
|
||||
# pytest-asyncio = "*"
|
||||
pytest-network= "*"
|
||||
|
||||
|
||||
# check-wheel-contents = "*" # requires <4
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry>=0.12"]
|
||||
build-backend = "poetry.masonry.api"
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
"""Generate simple tables in terminals from a nested list of strings.
|
||||
|
||||
Use SingleTable or DoubleTable instead of AsciiTable for box-drawing characters.
|
||||
|
||||
https://github.com/Robpol86/terminaltables
|
||||
https://pypi.python.org/pypi/terminaltables
|
||||
"""
|
||||
|
||||
from terminaltables.ascii_table import AsciiTable # noqa
|
||||
from terminaltables.github_table import GithubFlavoredMarkdownTable # noqa
|
||||
from terminaltables.other_tables import DoubleTable # noqa
|
||||
from terminaltables.other_tables import SingleTable # noqa
|
||||
from terminaltables.other_tables import PorcelainTable # noqa
|
||||
|
||||
__author__ = '@Robpol86'
|
||||
__license__ = 'MIT'
|
||||
__version__ = '3.1.0'
|
|
@ -1,177 +0,0 @@
|
|||
"""Additional simple tables defined here."""
|
||||
|
||||
from terminaltables.ascii_table import AsciiTable
|
||||
from terminaltables.terminal_io import IS_WINDOWS
|
||||
|
||||
|
||||
class UnixTable(AsciiTable):
|
||||
"""Draw a table using box-drawing characters on Unix platforms. Table borders won't have any gaps between lines.
|
||||
|
||||
Similar to the tables shown on PC BIOS boot messages, but not double-lined.
|
||||
"""
|
||||
|
||||
CHAR_F_INNER_HORIZONTAL = '\033(0\x71\033(B'
|
||||
CHAR_F_INNER_INTERSECT = '\033(0\x6e\033(B'
|
||||
CHAR_F_INNER_VERTICAL = '\033(0\x78\033(B'
|
||||
CHAR_F_OUTER_LEFT_INTERSECT = '\033(0\x74\033(B'
|
||||
CHAR_F_OUTER_LEFT_VERTICAL = '\033(0\x78\033(B'
|
||||
CHAR_F_OUTER_RIGHT_INTERSECT = '\033(0\x75\033(B'
|
||||
CHAR_F_OUTER_RIGHT_VERTICAL = '\033(0\x78\033(B'
|
||||
CHAR_H_INNER_HORIZONTAL = '\033(0\x71\033(B'
|
||||
CHAR_H_INNER_INTERSECT = '\033(0\x6e\033(B'
|
||||
CHAR_H_INNER_VERTICAL = '\033(0\x78\033(B'
|
||||
CHAR_H_OUTER_LEFT_INTERSECT = '\033(0\x74\033(B'
|
||||
CHAR_H_OUTER_LEFT_VERTICAL = '\033(0\x78\033(B'
|
||||
CHAR_H_OUTER_RIGHT_INTERSECT = '\033(0\x75\033(B'
|
||||
CHAR_H_OUTER_RIGHT_VERTICAL = '\033(0\x78\033(B'
|
||||
CHAR_INNER_HORIZONTAL = '\033(0\x71\033(B'
|
||||
CHAR_INNER_INTERSECT = '\033(0\x6e\033(B'
|
||||
CHAR_INNER_VERTICAL = '\033(0\x78\033(B'
|
||||
CHAR_OUTER_BOTTOM_HORIZONTAL = '\033(0\x71\033(B'
|
||||
CHAR_OUTER_BOTTOM_INTERSECT = '\033(0\x76\033(B'
|
||||
CHAR_OUTER_BOTTOM_LEFT = '\033(0\x6d\033(B'
|
||||
CHAR_OUTER_BOTTOM_RIGHT = '\033(0\x6a\033(B'
|
||||
CHAR_OUTER_LEFT_INTERSECT = '\033(0\x74\033(B'
|
||||
CHAR_OUTER_LEFT_VERTICAL = '\033(0\x78\033(B'
|
||||
CHAR_OUTER_RIGHT_INTERSECT = '\033(0\x75\033(B'
|
||||
CHAR_OUTER_RIGHT_VERTICAL = '\033(0\x78\033(B'
|
||||
CHAR_OUTER_TOP_HORIZONTAL = '\033(0\x71\033(B'
|
||||
CHAR_OUTER_TOP_INTERSECT = '\033(0\x77\033(B'
|
||||
CHAR_OUTER_TOP_LEFT = '\033(0\x6c\033(B'
|
||||
CHAR_OUTER_TOP_RIGHT = '\033(0\x6b\033(B'
|
||||
|
||||
@property
|
||||
def table(self):
|
||||
"""Return a large string of the entire table ready to be printed to the terminal."""
|
||||
ascii_table = super(UnixTable, self).table
|
||||
optimized = ascii_table.replace('\033(B\033(0', '')
|
||||
return optimized
|
||||
|
||||
|
||||
class WindowsTable(AsciiTable):
|
||||
"""Draw a table using box-drawing characters on Windows platforms. This uses Code Page 437. Single-line borders.
|
||||
|
||||
From: http://en.wikipedia.org/wiki/Code_page_437#Characters
|
||||
"""
|
||||
|
||||
CHAR_F_INNER_HORIZONTAL = b'\xc4'.decode('ibm437')
|
||||
CHAR_F_INNER_INTERSECT = b'\xc5'.decode('ibm437')
|
||||
CHAR_F_INNER_VERTICAL = b'\xb3'.decode('ibm437')
|
||||
CHAR_F_OUTER_LEFT_INTERSECT = b'\xc3'.decode('ibm437')
|
||||
CHAR_F_OUTER_LEFT_VERTICAL = b'\xb3'.decode('ibm437')
|
||||
CHAR_F_OUTER_RIGHT_INTERSECT = b'\xb4'.decode('ibm437')
|
||||
CHAR_F_OUTER_RIGHT_VERTICAL = b'\xb3'.decode('ibm437')
|
||||
CHAR_H_INNER_HORIZONTAL = b'\xc4'.decode('ibm437')
|
||||
CHAR_H_INNER_INTERSECT = b'\xc5'.decode('ibm437')
|
||||
CHAR_H_INNER_VERTICAL = b'\xb3'.decode('ibm437')
|
||||
CHAR_H_OUTER_LEFT_INTERSECT = b'\xc3'.decode('ibm437')
|
||||
CHAR_H_OUTER_LEFT_VERTICAL = b'\xb3'.decode('ibm437')
|
||||
CHAR_H_OUTER_RIGHT_INTERSECT = b'\xb4'.decode('ibm437')
|
||||
CHAR_H_OUTER_RIGHT_VERTICAL = b'\xb3'.decode('ibm437')
|
||||
CHAR_INNER_HORIZONTAL = b'\xc4'.decode('ibm437')
|
||||
CHAR_INNER_INTERSECT = b'\xc5'.decode('ibm437')
|
||||
CHAR_INNER_VERTICAL = b'\xb3'.decode('ibm437')
|
||||
CHAR_OUTER_BOTTOM_HORIZONTAL = b'\xc4'.decode('ibm437')
|
||||
CHAR_OUTER_BOTTOM_INTERSECT = b'\xc1'.decode('ibm437')
|
||||
CHAR_OUTER_BOTTOM_LEFT = b'\xc0'.decode('ibm437')
|
||||
CHAR_OUTER_BOTTOM_RIGHT = b'\xd9'.decode('ibm437')
|
||||
CHAR_OUTER_LEFT_INTERSECT = b'\xc3'.decode('ibm437')
|
||||
CHAR_OUTER_LEFT_VERTICAL = b'\xb3'.decode('ibm437')
|
||||
CHAR_OUTER_RIGHT_INTERSECT = b'\xb4'.decode('ibm437')
|
||||
CHAR_OUTER_RIGHT_VERTICAL = b'\xb3'.decode('ibm437')
|
||||
CHAR_OUTER_TOP_HORIZONTAL = b'\xc4'.decode('ibm437')
|
||||
CHAR_OUTER_TOP_INTERSECT = b'\xc2'.decode('ibm437')
|
||||
CHAR_OUTER_TOP_LEFT = b'\xda'.decode('ibm437')
|
||||
CHAR_OUTER_TOP_RIGHT = b'\xbf'.decode('ibm437')
|
||||
|
||||
|
||||
class WindowsTableDouble(AsciiTable):
|
||||
"""Draw a table using box-drawing characters on Windows platforms. This uses Code Page 437. Double-line borders."""
|
||||
|
||||
CHAR_F_INNER_HORIZONTAL = b'\xcd'.decode('ibm437')
|
||||
CHAR_F_INNER_INTERSECT = b'\xce'.decode('ibm437')
|
||||
CHAR_F_INNER_VERTICAL = b'\xba'.decode('ibm437')
|
||||
CHAR_F_OUTER_LEFT_INTERSECT = b'\xcc'.decode('ibm437')
|
||||
CHAR_F_OUTER_LEFT_VERTICAL = b'\xba'.decode('ibm437')
|
||||
CHAR_F_OUTER_RIGHT_INTERSECT = b'\xb9'.decode('ibm437')
|
||||
CHAR_F_OUTER_RIGHT_VERTICAL = b'\xba'.decode('ibm437')
|
||||
CHAR_H_INNER_HORIZONTAL = b'\xcd'.decode('ibm437')
|
||||
CHAR_H_INNER_INTERSECT = b'\xce'.decode('ibm437')
|
||||
CHAR_H_INNER_VERTICAL = b'\xba'.decode('ibm437')
|
||||
CHAR_H_OUTER_LEFT_INTERSECT = b'\xcc'.decode('ibm437')
|
||||
CHAR_H_OUTER_LEFT_VERTICAL = b'\xba'.decode('ibm437')
|
||||
CHAR_H_OUTER_RIGHT_INTERSECT = b'\xb9'.decode('ibm437')
|
||||
CHAR_H_OUTER_RIGHT_VERTICAL = b'\xba'.decode('ibm437')
|
||||
CHAR_INNER_HORIZONTAL = b'\xcd'.decode('ibm437')
|
||||
CHAR_INNER_INTERSECT = b'\xce'.decode('ibm437')
|
||||
CHAR_INNER_VERTICAL = b'\xba'.decode('ibm437')
|
||||
CHAR_OUTER_BOTTOM_HORIZONTAL = b'\xcd'.decode('ibm437')
|
||||
CHAR_OUTER_BOTTOM_INTERSECT = b'\xca'.decode('ibm437')
|
||||
CHAR_OUTER_BOTTOM_LEFT = b'\xc8'.decode('ibm437')
|
||||
CHAR_OUTER_BOTTOM_RIGHT = b'\xbc'.decode('ibm437')
|
||||
CHAR_OUTER_LEFT_INTERSECT = b'\xcc'.decode('ibm437')
|
||||
CHAR_OUTER_LEFT_VERTICAL = b'\xba'.decode('ibm437')
|
||||
CHAR_OUTER_RIGHT_INTERSECT = b'\xb9'.decode('ibm437')
|
||||
CHAR_OUTER_RIGHT_VERTICAL = b'\xba'.decode('ibm437')
|
||||
CHAR_OUTER_TOP_HORIZONTAL = b'\xcd'.decode('ibm437')
|
||||
CHAR_OUTER_TOP_INTERSECT = b'\xcb'.decode('ibm437')
|
||||
CHAR_OUTER_TOP_LEFT = b'\xc9'.decode('ibm437')
|
||||
CHAR_OUTER_TOP_RIGHT = b'\xbb'.decode('ibm437')
|
||||
|
||||
|
||||
class SingleTable(WindowsTable if IS_WINDOWS else UnixTable):
|
||||
"""Cross-platform table with single-line box-drawing characters.
|
||||
|
||||
:ivar iter table_data: List (empty or list of lists of strings) representing the table.
|
||||
:ivar str title: Optional title to show within the top border of the table.
|
||||
:ivar bool inner_column_border: Separates columns.
|
||||
:ivar bool inner_footing_row_border: Show a border before the last row.
|
||||
:ivar bool inner_heading_row_border: Show a border after the first row.
|
||||
:ivar bool inner_row_border: Show a border in between every row.
|
||||
:ivar bool outer_border: Show the top, left, right, and bottom border.
|
||||
:ivar dict justify_columns: Horizontal justification. Keys are column indexes (int). Values are right/left/center.
|
||||
:ivar int padding_left: Number of spaces to pad on the left side of every cell.
|
||||
:ivar int padding_right: Number of spaces to pad on the right side of every cell.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class DoubleTable(WindowsTableDouble):
|
||||
"""Cross-platform table with box-drawing characters. On Windows it's double borders, on Linux/OSX it's unicode.
|
||||
|
||||
:ivar iter table_data: List (empty or list of lists of strings) representing the table.
|
||||
:ivar str title: Optional title to show within the top border of the table.
|
||||
:ivar bool inner_column_border: Separates columns.
|
||||
:ivar bool inner_footing_row_border: Show a border before the last row.
|
||||
:ivar bool inner_heading_row_border: Show a border after the first row.
|
||||
:ivar bool inner_row_border: Show a border in between every row.
|
||||
:ivar bool outer_border: Show the top, left, right, and bottom border.
|
||||
:ivar dict justify_columns: Horizontal justification. Keys are column indexes (int). Values are right/left/center.
|
||||
:ivar int padding_left: Number of spaces to pad on the left side of every cell.
|
||||
:ivar int padding_right: Number of spaces to pad on the right side of every cell.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class PorcelainTable(AsciiTable):
|
||||
"""An AsciiTable stripped to a minimum.
|
||||
|
||||
Meant to be machine passable and roughly follow format set by git --porcelain option (hence the name).
|
||||
|
||||
:ivar iter table_data: List (empty or list of lists of strings) representing the table.
|
||||
"""
|
||||
|
||||
def __init__(self, table_data):
|
||||
"""Constructor.
|
||||
|
||||
:param iter table_data: List (empty or list of lists of strings) representing the table.
|
||||
"""
|
||||
# Porcelain table won't support title since it has no outer birders.
|
||||
super(PorcelainTable, self).__init__(table_data)
|
||||
|
||||
# Removes outer border, and inner footing and header row borders.
|
||||
self.inner_footing_row_border = False
|
||||
self.inner_heading_row_border = False
|
||||
self.outer_border = False
|
17
terminaltables3/__init__.py
Normal file
17
terminaltables3/__init__.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
"""Generate simple tables in terminals from a nested list of strings.
|
||||
|
||||
Use SingleTable or DoubleTable instead of AsciiTable for box-drawing characters.
|
||||
|
||||
https://github.com/Robpol86/terminaltables3
|
||||
https://pypi.python.org/pypi/terminaltables3
|
||||
"""
|
||||
|
||||
from terminaltables3.ascii_table import AsciiTable # noqa
|
||||
from terminaltables3.github_table import GithubFlavoredMarkdownTable # noqa
|
||||
from terminaltables3.other_tables import DoubleTable # noqa
|
||||
from terminaltables3.other_tables import PorcelainTable # noqa
|
||||
from terminaltables3.other_tables import SingleTable # noqa
|
||||
|
||||
__author__ = "@Robpol86"
|
||||
__license__ = "MIT"
|
||||
__version__ = "3.1.0"
|
|
@ -1,8 +1,12 @@
|
|||
"""AsciiTable is the main table class. To be inherited by other tables. Define convenience methods here."""
|
||||
|
||||
from terminaltables.base_table import BaseTable
|
||||
from terminaltables.terminal_io import terminal_size
|
||||
from terminaltables.width_and_alignment import column_max_width, max_dimensions, table_width
|
||||
from terminaltables3.base_table import BaseTable
|
||||
from terminaltables3.terminal_io import terminal_size
|
||||
from terminaltables3.width_and_alignment import (
|
||||
column_max_width,
|
||||
max_dimensions,
|
||||
table_width,
|
||||
)
|
||||
|
||||
|
||||
class AsciiTable(BaseTable):
|
||||
|
@ -20,7 +24,7 @@ class AsciiTable(BaseTable):
|
|||
:ivar int padding_right: Number of spaces to pad on the right side of every cell.
|
||||
"""
|
||||
|
||||
def column_max_width(self, column_number):
|
||||
def column_max_width(self, column_number: int) -> int:
|
||||
"""Return the maximum width of a column based on the current terminal width.
|
||||
|
||||
:param int column_number: The column number to query.
|
||||
|
@ -32,24 +36,28 @@ class AsciiTable(BaseTable):
|
|||
outer_border = 2 if self.outer_border else 0
|
||||
inner_border = 1 if self.inner_column_border else 0
|
||||
padding = self.padding_left + self.padding_right
|
||||
return column_max_width(inner_widths, column_number, outer_border, inner_border, padding)
|
||||
return column_max_width(
|
||||
inner_widths, column_number, outer_border, inner_border, padding
|
||||
)
|
||||
|
||||
@property
|
||||
def column_widths(self):
|
||||
def column_widths(self) -> list[int]:
|
||||
"""Return a list of integers representing the widths of each table column without padding."""
|
||||
if not self.table_data:
|
||||
return list()
|
||||
return []
|
||||
return max_dimensions(self.table_data)[0]
|
||||
|
||||
@property
|
||||
def ok(self): # Too late to change API. # pylint: disable=invalid-name
|
||||
def ok(self) -> bool: # Too late to change API. # pylint: disable=invalid-name
|
||||
"""Return True if the table fits within the terminal width, False if the table breaks."""
|
||||
return self.table_width <= terminal_size()[0]
|
||||
|
||||
@property
|
||||
def table_width(self):
|
||||
def table_width(self) -> int:
|
||||
"""Return the width of the table including padding and borders."""
|
||||
outer_widths = max_dimensions(self.table_data, self.padding_left, self.padding_right)[2]
|
||||
outer_widths = max_dimensions(
|
||||
self.table_data, self.padding_left, self.padding_right
|
||||
)[2]
|
||||
outer_border = 2 if self.outer_border else 0
|
||||
inner_border = 1 if self.inner_column_border else 0
|
||||
return table_width(outer_widths, outer_border, inner_border)
|
|
@ -1,10 +1,12 @@
|
|||
"""Base table class. Define just the bare minimum to build tables."""
|
||||
|
||||
from terminaltables.build import build_border, build_row, flatten
|
||||
from terminaltables.width_and_alignment import align_and_pad_cell, max_dimensions
|
||||
from typing import Generator, Optional, Sequence, Tuple
|
||||
|
||||
from terminaltables3.build import build_border, build_row, flatten
|
||||
from terminaltables3.width_and_alignment import align_and_pad_cell, max_dimensions
|
||||
|
||||
|
||||
class BaseTable(object):
|
||||
class BaseTable:
|
||||
"""Base table class.
|
||||
|
||||
:ivar iter table_data: List (empty or list of lists of strings) representing the table.
|
||||
|
@ -19,37 +21,39 @@ class BaseTable(object):
|
|||
:ivar int padding_right: Number of spaces to pad on the right side of every cell.
|
||||
"""
|
||||
|
||||
CHAR_F_INNER_HORIZONTAL = '-'
|
||||
CHAR_F_INNER_INTERSECT = '+'
|
||||
CHAR_F_INNER_VERTICAL = '|'
|
||||
CHAR_F_OUTER_LEFT_INTERSECT = '+'
|
||||
CHAR_F_OUTER_LEFT_VERTICAL = '|'
|
||||
CHAR_F_OUTER_RIGHT_INTERSECT = '+'
|
||||
CHAR_F_OUTER_RIGHT_VERTICAL = '|'
|
||||
CHAR_H_INNER_HORIZONTAL = '-'
|
||||
CHAR_H_INNER_INTERSECT = '+'
|
||||
CHAR_H_INNER_VERTICAL = '|'
|
||||
CHAR_H_OUTER_LEFT_INTERSECT = '+'
|
||||
CHAR_H_OUTER_LEFT_VERTICAL = '|'
|
||||
CHAR_H_OUTER_RIGHT_INTERSECT = '+'
|
||||
CHAR_H_OUTER_RIGHT_VERTICAL = '|'
|
||||
CHAR_INNER_HORIZONTAL = '-'
|
||||
CHAR_INNER_INTERSECT = '+'
|
||||
CHAR_INNER_VERTICAL = '|'
|
||||
CHAR_OUTER_BOTTOM_HORIZONTAL = '-'
|
||||
CHAR_OUTER_BOTTOM_INTERSECT = '+'
|
||||
CHAR_OUTER_BOTTOM_LEFT = '+'
|
||||
CHAR_OUTER_BOTTOM_RIGHT = '+'
|
||||
CHAR_OUTER_LEFT_INTERSECT = '+'
|
||||
CHAR_OUTER_LEFT_VERTICAL = '|'
|
||||
CHAR_OUTER_RIGHT_INTERSECT = '+'
|
||||
CHAR_OUTER_RIGHT_VERTICAL = '|'
|
||||
CHAR_OUTER_TOP_HORIZONTAL = '-'
|
||||
CHAR_OUTER_TOP_INTERSECT = '+'
|
||||
CHAR_OUTER_TOP_LEFT = '+'
|
||||
CHAR_OUTER_TOP_RIGHT = '+'
|
||||
CHAR_F_INNER_HORIZONTAL = "-"
|
||||
CHAR_F_INNER_INTERSECT = "+"
|
||||
CHAR_F_INNER_VERTICAL = "|"
|
||||
CHAR_F_OUTER_LEFT_INTERSECT = "+"
|
||||
CHAR_F_OUTER_LEFT_VERTICAL = "|"
|
||||
CHAR_F_OUTER_RIGHT_INTERSECT = "+"
|
||||
CHAR_F_OUTER_RIGHT_VERTICAL = "|"
|
||||
CHAR_H_INNER_HORIZONTAL = "-"
|
||||
CHAR_H_INNER_INTERSECT = "+"
|
||||
CHAR_H_INNER_VERTICAL = "|"
|
||||
CHAR_H_OUTER_LEFT_INTERSECT = "+"
|
||||
CHAR_H_OUTER_LEFT_VERTICAL = "|"
|
||||
CHAR_H_OUTER_RIGHT_INTERSECT = "+"
|
||||
CHAR_H_OUTER_RIGHT_VERTICAL = "|"
|
||||
CHAR_INNER_HORIZONTAL = "-"
|
||||
CHAR_INNER_INTERSECT = "+"
|
||||
CHAR_INNER_VERTICAL = "|"
|
||||
CHAR_OUTER_BOTTOM_HORIZONTAL = "-"
|
||||
CHAR_OUTER_BOTTOM_INTERSECT = "+"
|
||||
CHAR_OUTER_BOTTOM_LEFT = "+"
|
||||
CHAR_OUTER_BOTTOM_RIGHT = "+"
|
||||
CHAR_OUTER_LEFT_INTERSECT = "+"
|
||||
CHAR_OUTER_LEFT_VERTICAL = "|"
|
||||
CHAR_OUTER_RIGHT_INTERSECT = "+"
|
||||
CHAR_OUTER_RIGHT_VERTICAL = "|"
|
||||
CHAR_OUTER_TOP_HORIZONTAL = "-"
|
||||
CHAR_OUTER_TOP_INTERSECT = "+"
|
||||
CHAR_OUTER_TOP_LEFT = "+"
|
||||
CHAR_OUTER_TOP_RIGHT = "+"
|
||||
|
||||
def __init__(self, table_data, title=None):
|
||||
def __init__(
|
||||
self, table_data: Sequence[Sequence[str]], title: Optional[str] = None
|
||||
):
|
||||
"""Constructor.
|
||||
|
||||
:param iter table_data: List (empty or list of lists of strings) representing the table.
|
||||
|
@ -64,11 +68,13 @@ class BaseTable(object):
|
|||
self.inner_row_border = False
|
||||
self.outer_border = True
|
||||
|
||||
self.justify_columns = dict() # {0: 'right', 1: 'left', 2: 'center'}
|
||||
self.justify_columns = {} # {0: 'right', 1: 'left', 2: 'center'}
|
||||
self.padding_left = 1
|
||||
self.padding_right = 1
|
||||
|
||||
def horizontal_border(self, style, outer_widths):
|
||||
def horizontal_border(
|
||||
self, style: str, outer_widths: Sequence[int]
|
||||
) -> Tuple[str, ...]:
|
||||
"""Build any kind of horizontal border for the table.
|
||||
|
||||
:param str style: Type of border to return.
|
||||
|
@ -77,39 +83,45 @@ class BaseTable(object):
|
|||
:return: Prepared border as a tuple of strings.
|
||||
:rtype: tuple
|
||||
"""
|
||||
if style == 'top':
|
||||
if style == "top":
|
||||
horizontal = self.CHAR_OUTER_TOP_HORIZONTAL
|
||||
left = self.CHAR_OUTER_TOP_LEFT
|
||||
intersect = self.CHAR_OUTER_TOP_INTERSECT if self.inner_column_border else ''
|
||||
intersect = (
|
||||
self.CHAR_OUTER_TOP_INTERSECT if self.inner_column_border else ""
|
||||
)
|
||||
right = self.CHAR_OUTER_TOP_RIGHT
|
||||
title = self.title
|
||||
elif style == 'bottom':
|
||||
elif style == "bottom":
|
||||
horizontal = self.CHAR_OUTER_BOTTOM_HORIZONTAL
|
||||
left = self.CHAR_OUTER_BOTTOM_LEFT
|
||||
intersect = self.CHAR_OUTER_BOTTOM_INTERSECT if self.inner_column_border else ''
|
||||
intersect = (
|
||||
self.CHAR_OUTER_BOTTOM_INTERSECT if self.inner_column_border else ""
|
||||
)
|
||||
right = self.CHAR_OUTER_BOTTOM_RIGHT
|
||||
title = None
|
||||
elif style == 'heading':
|
||||
elif style == "heading":
|
||||
horizontal = self.CHAR_H_INNER_HORIZONTAL
|
||||
left = self.CHAR_H_OUTER_LEFT_INTERSECT if self.outer_border else ''
|
||||
intersect = self.CHAR_H_INNER_INTERSECT if self.inner_column_border else ''
|
||||
right = self.CHAR_H_OUTER_RIGHT_INTERSECT if self.outer_border else ''
|
||||
left = self.CHAR_H_OUTER_LEFT_INTERSECT if self.outer_border else ""
|
||||
intersect = self.CHAR_H_INNER_INTERSECT if self.inner_column_border else ""
|
||||
right = self.CHAR_H_OUTER_RIGHT_INTERSECT if self.outer_border else ""
|
||||
title = None
|
||||
elif style == 'footing':
|
||||
elif style == "footing":
|
||||
horizontal = self.CHAR_F_INNER_HORIZONTAL
|
||||
left = self.CHAR_F_OUTER_LEFT_INTERSECT if self.outer_border else ''
|
||||
intersect = self.CHAR_F_INNER_INTERSECT if self.inner_column_border else ''
|
||||
right = self.CHAR_F_OUTER_RIGHT_INTERSECT if self.outer_border else ''
|
||||
left = self.CHAR_F_OUTER_LEFT_INTERSECT if self.outer_border else ""
|
||||
intersect = self.CHAR_F_INNER_INTERSECT if self.inner_column_border else ""
|
||||
right = self.CHAR_F_OUTER_RIGHT_INTERSECT if self.outer_border else ""
|
||||
title = None
|
||||
else:
|
||||
horizontal = self.CHAR_INNER_HORIZONTAL
|
||||
left = self.CHAR_OUTER_LEFT_INTERSECT if self.outer_border else ''
|
||||
intersect = self.CHAR_INNER_INTERSECT if self.inner_column_border else ''
|
||||
right = self.CHAR_OUTER_RIGHT_INTERSECT if self.outer_border else ''
|
||||
left = self.CHAR_OUTER_LEFT_INTERSECT if self.outer_border else ""
|
||||
intersect = self.CHAR_INNER_INTERSECT if self.inner_column_border else ""
|
||||
right = self.CHAR_OUTER_RIGHT_INTERSECT if self.outer_border else ""
|
||||
title = None
|
||||
return build_border(outer_widths, horizontal, left, intersect, right, title)
|
||||
|
||||
def gen_row_lines(self, row, style, inner_widths, height):
|
||||
def gen_row_lines(
|
||||
self, row: Sequence[str], style: str, inner_widths: Sequence[int], height: int
|
||||
) -> Generator[Tuple[str, ...], None, None]:
|
||||
r"""Combine cells in row and group them into lines with vertical borders.
|
||||
|
||||
Caller is expected to pass yielded lines to ''.join() to combine them into a printable line. Caller must append
|
||||
|
@ -137,38 +149,44 @@ class BaseTable(object):
|
|||
|
||||
:return: Yields lines split into components in a list. Caller must ''.join() line.
|
||||
"""
|
||||
cells_in_row = list()
|
||||
cells_in_row = []
|
||||
|
||||
# Resize row if it doesn't have enough cells.
|
||||
if len(row) != len(inner_widths):
|
||||
row = row + [''] * (len(inner_widths) - len(row))
|
||||
row = row + [""] * (len(inner_widths) - len(row))
|
||||
|
||||
# Pad and align each cell. Split each cell into lines to support multi-line cells.
|
||||
for i, cell in enumerate(row):
|
||||
align = (self.justify_columns.get(i),)
|
||||
inner_dimensions = (inner_widths[i], height)
|
||||
padding = (self.padding_left, self.padding_right, 0, 0)
|
||||
cells_in_row.append(align_and_pad_cell(cell, align, inner_dimensions, padding))
|
||||
cells_in_row.append(
|
||||
align_and_pad_cell(cell, align, inner_dimensions, padding)
|
||||
)
|
||||
|
||||
# Determine border characters.
|
||||
if style == 'heading':
|
||||
left = self.CHAR_H_OUTER_LEFT_VERTICAL if self.outer_border else ''
|
||||
center = self.CHAR_H_INNER_VERTICAL if self.inner_column_border else ''
|
||||
right = self.CHAR_H_OUTER_RIGHT_VERTICAL if self.outer_border else ''
|
||||
elif style == 'footing':
|
||||
left = self.CHAR_F_OUTER_LEFT_VERTICAL if self.outer_border else ''
|
||||
center = self.CHAR_F_INNER_VERTICAL if self.inner_column_border else ''
|
||||
right = self.CHAR_F_OUTER_RIGHT_VERTICAL if self.outer_border else ''
|
||||
if style == "heading":
|
||||
left = self.CHAR_H_OUTER_LEFT_VERTICAL if self.outer_border else ""
|
||||
center = self.CHAR_H_INNER_VERTICAL if self.inner_column_border else ""
|
||||
right = self.CHAR_H_OUTER_RIGHT_VERTICAL if self.outer_border else ""
|
||||
elif style == "footing":
|
||||
left = self.CHAR_F_OUTER_LEFT_VERTICAL if self.outer_border else ""
|
||||
center = self.CHAR_F_INNER_VERTICAL if self.inner_column_border else ""
|
||||
right = self.CHAR_F_OUTER_RIGHT_VERTICAL if self.outer_border else ""
|
||||
else:
|
||||
left = self.CHAR_OUTER_LEFT_VERTICAL if self.outer_border else ''
|
||||
center = self.CHAR_INNER_VERTICAL if self.inner_column_border else ''
|
||||
right = self.CHAR_OUTER_RIGHT_VERTICAL if self.outer_border else ''
|
||||
left = self.CHAR_OUTER_LEFT_VERTICAL if self.outer_border else ""
|
||||
center = self.CHAR_INNER_VERTICAL if self.inner_column_border else ""
|
||||
right = self.CHAR_OUTER_RIGHT_VERTICAL if self.outer_border else ""
|
||||
|
||||
# Yield each line.
|
||||
for line in build_row(cells_in_row, left, center, right):
|
||||
yield line
|
||||
yield from build_row(cells_in_row, left, center, right)
|
||||
|
||||
def gen_table(self, inner_widths, inner_heights, outer_widths):
|
||||
def gen_table(
|
||||
self,
|
||||
inner_widths: Sequence[int],
|
||||
inner_heights: Sequence[int],
|
||||
outer_widths: Sequence[int],
|
||||
) -> Generator[Tuple[str, ...], None, None]:
|
||||
"""Combine everything and yield every line of the entire table with borders.
|
||||
|
||||
:param iter inner_widths: List of widths (no padding) for each column.
|
||||
|
@ -178,7 +196,7 @@ class BaseTable(object):
|
|||
"""
|
||||
# Yield top border.
|
||||
if self.outer_border:
|
||||
yield self.horizontal_border('top', outer_widths)
|
||||
yield self.horizontal_border("top", outer_widths)
|
||||
|
||||
# Yield table body.
|
||||
row_count = len(self.table_data)
|
||||
|
@ -186,32 +204,33 @@ class BaseTable(object):
|
|||
for i, row in enumerate(self.table_data):
|
||||
# Yield the row line by line (e.g. multi-line rows).
|
||||
if self.inner_heading_row_border and i == 0:
|
||||
style = 'heading'
|
||||
style = "heading"
|
||||
elif self.inner_footing_row_border and i == last_row_index:
|
||||
style = 'footing'
|
||||
style = "footing"
|
||||
else:
|
||||
style = 'row'
|
||||
for line in self.gen_row_lines(row, style, inner_widths, inner_heights[i]):
|
||||
yield line
|
||||
style = "row"
|
||||
yield from self.gen_row_lines(row, style, inner_widths, inner_heights[i])
|
||||
# If this is the last row then break. No separator needed.
|
||||
if i == last_row_index:
|
||||
break
|
||||
# Yield heading separator.
|
||||
if self.inner_heading_row_border and i == 0:
|
||||
yield self.horizontal_border('heading', outer_widths)
|
||||
yield self.horizontal_border("heading", outer_widths)
|
||||
# Yield footing separator.
|
||||
elif self.inner_footing_row_border and i == before_last_row_index:
|
||||
yield self.horizontal_border('footing', outer_widths)
|
||||
yield self.horizontal_border("footing", outer_widths)
|
||||
# Yield row separator.
|
||||
elif self.inner_row_border:
|
||||
yield self.horizontal_border('row', outer_widths)
|
||||
yield self.horizontal_border("row", outer_widths)
|
||||
|
||||
# Yield bottom border.
|
||||
if self.outer_border:
|
||||
yield self.horizontal_border('bottom', outer_widths)
|
||||
yield self.horizontal_border("bottom", outer_widths)
|
||||
|
||||
@property
|
||||
def table(self):
|
||||
def table(self) -> str:
|
||||
"""Return a large string of the entire table ready to be printed to the terminal."""
|
||||
dimensions = max_dimensions(self.table_data, self.padding_left, self.padding_right)[:3]
|
||||
dimensions = max_dimensions(
|
||||
self.table_data, self.padding_left, self.padding_right
|
||||
)[:3]
|
||||
return flatten(self.gen_table(*dimensions))
|
|
@ -1,9 +1,18 @@
|
|||
"""Combine cells into rows."""
|
||||
|
||||
from terminaltables.width_and_alignment import visible_width
|
||||
from typing import Generator, Iterator, Optional, Sequence, Union
|
||||
|
||||
from terminaltables3.width_and_alignment import visible_width
|
||||
|
||||
|
||||
def combine(line, left, intersect, right):
|
||||
def combine(
|
||||
line: Union[
|
||||
Generator[Union[int, str], None, None], Iterator[Optional[Union[int, str]]]
|
||||
],
|
||||
left: str,
|
||||
intersect: Optional[str],
|
||||
right: str,
|
||||
) -> Generator[int, None, None]:
|
||||
"""Zip borders between items in `line`.
|
||||
|
||||
e.g. ('l', '1', 'c', '2', 'c', '3', 'r')
|
||||
|
@ -41,15 +50,21 @@ def combine(line, left, intersect, right):
|
|||
yield intersect
|
||||
item = peek
|
||||
else:
|
||||
for i in line:
|
||||
yield i
|
||||
yield from line
|
||||
|
||||
# Yield right border.
|
||||
# Yield right border.
|
||||
if right:
|
||||
yield right
|
||||
|
||||
|
||||
def build_border(outer_widths, horizontal, left, intersect, right, title=None):
|
||||
def build_border(
|
||||
outer_widths: Sequence[int],
|
||||
horizontal: str,
|
||||
left: str,
|
||||
intersect: str,
|
||||
right: str,
|
||||
title: Optional[str] = None,
|
||||
):
|
||||
"""Build the top/bottom/middle row. Optionally embed the table title within the border.
|
||||
|
||||
Title is hidden if it doesn't fit between the left/right characters/edges.
|
||||
|
@ -86,9 +101,13 @@ def build_border(outer_widths, horizontal, left, intersect, right, title=None):
|
|||
|
||||
# Handle title fitting in the first column.
|
||||
if length == outer_widths[0]:
|
||||
return combine([title] + [horizontal * c for c in outer_widths[1:]], left, intersect, right)
|
||||
return combine(
|
||||
[title] + [horizontal * c for c in outer_widths[1:]], left, intersect, right
|
||||
)
|
||||
if length < outer_widths[0]:
|
||||
columns = [title + horizontal * (outer_widths[0] - length)] + [horizontal * c for c in outer_widths[1:]]
|
||||
columns = [title + horizontal * (outer_widths[0] - length)] + [
|
||||
horizontal * c for c in outer_widths[1:]
|
||||
]
|
||||
return combine(columns, left, intersect, right)
|
||||
|
||||
# Handle wide titles/narrow columns.
|
||||
|
@ -96,7 +115,9 @@ def build_border(outer_widths, horizontal, left, intersect, right, title=None):
|
|||
for width in combine(outer_widths, None, bool(intersect), None):
|
||||
# If title is taken care of.
|
||||
if length < 1:
|
||||
columns_and_intersects.append(intersect if width is True else horizontal * width)
|
||||
columns_and_intersects.append(
|
||||
intersect if width is True else horizontal * width
|
||||
)
|
||||
# If title's last character overrides an intersect character.
|
||||
elif width is True and length == 1:
|
||||
length = 0
|
||||
|
@ -105,7 +126,9 @@ def build_border(outer_widths, horizontal, left, intersect, right, title=None):
|
|||
length -= 1
|
||||
# If title's last character is within a column.
|
||||
elif width >= length:
|
||||
columns_and_intersects[0] += horizontal * (width - length) # Append horizontal chars to title.
|
||||
columns_and_intersects[0] += horizontal * (
|
||||
width - length
|
||||
) # Append horizontal chars to title.
|
||||
length = 0
|
||||
# If remainder of title won't fit in a column.
|
||||
else:
|
||||
|
@ -148,4 +171,4 @@ def flatten(table):
|
|||
:return: Joined rows/cells.
|
||||
:rtype: str
|
||||
"""
|
||||
return '\n'.join(''.join(r) for r in table)
|
||||
return "\n".join("".join(r) for r in table)
|
|
@ -1,7 +1,9 @@
|
|||
"""GithubFlavoredMarkdownTable class."""
|
||||
|
||||
from terminaltables.ascii_table import AsciiTable
|
||||
from terminaltables.build import combine
|
||||
from typing import Sequence
|
||||
|
||||
from terminaltables3.ascii_table import AsciiTable
|
||||
from terminaltables3.build import combine
|
||||
|
||||
|
||||
class GithubFlavoredMarkdownTable(AsciiTable):
|
||||
|
@ -13,13 +15,13 @@ class GithubFlavoredMarkdownTable(AsciiTable):
|
|||
:ivar dict justify_columns: Horizontal justification. Keys are column indexes (int). Values are right/left/center.
|
||||
"""
|
||||
|
||||
def __init__(self, table_data):
|
||||
def __init__(self, table_data: Sequence[Sequence[str]]):
|
||||
"""Constructor.
|
||||
|
||||
:param iter table_data: List (empty or list of lists of strings) representing the table.
|
||||
"""
|
||||
# Github flavored markdown table won't support title.
|
||||
super(GithubFlavoredMarkdownTable, self).__init__(table_data)
|
||||
super().__init__(table_data)
|
||||
|
||||
def horizontal_border(self, _, outer_widths):
|
||||
"""Handle the GitHub heading border.
|
||||
|
@ -38,16 +40,18 @@ class GithubFlavoredMarkdownTable(AsciiTable):
|
|||
intersect = self.CHAR_INNER_VERTICAL
|
||||
right = self.CHAR_OUTER_RIGHT_VERTICAL
|
||||
|
||||
columns = list()
|
||||
columns = []
|
||||
for i, width in enumerate(outer_widths):
|
||||
justify = self.justify_columns.get(i)
|
||||
width = max(3, width) # Width should be at least 3 so justification can be applied.
|
||||
if justify == 'left':
|
||||
columns.append(':' + horizontal * (width - 1))
|
||||
elif justify == 'right':
|
||||
columns.append(horizontal * (width - 1) + ':')
|
||||
elif justify == 'center':
|
||||
columns.append(':' + horizontal * (width - 2) + ':')
|
||||
width = max(
|
||||
3, width
|
||||
) # Width should be at least 3 so justification can be applied.
|
||||
if justify == "left":
|
||||
columns.append(":" + horizontal * (width - 1))
|
||||
elif justify == "right":
|
||||
columns.append(horizontal * (width - 1) + ":")
|
||||
elif justify == "center":
|
||||
columns.append(":" + horizontal * (width - 2) + ":")
|
||||
else:
|
||||
columns.append(horizontal * width)
|
||||
|
||||
|
@ -63,8 +67,7 @@ class GithubFlavoredMarkdownTable(AsciiTable):
|
|||
"""
|
||||
for i, row in enumerate(self.table_data):
|
||||
# Yield the row line by line (e.g. multi-line rows).
|
||||
for line in self.gen_row_lines(row, 'row', inner_widths, inner_heights[i]):
|
||||
yield line
|
||||
yield from self.gen_row_lines(row, "row", inner_widths, inner_heights[i])
|
||||
# Yield heading separator.
|
||||
if i == 0:
|
||||
yield self.horizontal_border(None, outer_widths)
|
173
terminaltables3/other_tables.py
Normal file
173
terminaltables3/other_tables.py
Normal file
|
@ -0,0 +1,173 @@
|
|||
"""Additional simple tables defined here."""
|
||||
|
||||
from terminaltables3.ascii_table import AsciiTable
|
||||
from terminaltables3.terminal_io import IS_WINDOWS
|
||||
|
||||
|
||||
class UnixTable(AsciiTable):
|
||||
"""Draw a table using box-drawing characters on Unix platforms. Table borders won't have any gaps between lines.
|
||||
|
||||
Similar to the tables shown on PC BIOS boot messages, but not double-lined.
|
||||
"""
|
||||
|
||||
CHAR_F_INNER_HORIZONTAL = "\033(0\x71\033(B"
|
||||
CHAR_F_INNER_INTERSECT = "\033(0\x6e\033(B"
|
||||
CHAR_F_INNER_VERTICAL = "\033(0\x78\033(B"
|
||||
CHAR_F_OUTER_LEFT_INTERSECT = "\033(0\x74\033(B"
|
||||
CHAR_F_OUTER_LEFT_VERTICAL = "\033(0\x78\033(B"
|
||||
CHAR_F_OUTER_RIGHT_INTERSECT = "\033(0\x75\033(B"
|
||||
CHAR_F_OUTER_RIGHT_VERTICAL = "\033(0\x78\033(B"
|
||||
CHAR_H_INNER_HORIZONTAL = "\033(0\x71\033(B"
|
||||
CHAR_H_INNER_INTERSECT = "\033(0\x6e\033(B"
|
||||
CHAR_H_INNER_VERTICAL = "\033(0\x78\033(B"
|
||||
CHAR_H_OUTER_LEFT_INTERSECT = "\033(0\x74\033(B"
|
||||
CHAR_H_OUTER_LEFT_VERTICAL = "\033(0\x78\033(B"
|
||||
CHAR_H_OUTER_RIGHT_INTERSECT = "\033(0\x75\033(B"
|
||||
CHAR_H_OUTER_RIGHT_VERTICAL = "\033(0\x78\033(B"
|
||||
CHAR_INNER_HORIZONTAL = "\033(0\x71\033(B"
|
||||
CHAR_INNER_INTERSECT = "\033(0\x6e\033(B"
|
||||
CHAR_INNER_VERTICAL = "\033(0\x78\033(B"
|
||||
CHAR_OUTER_BOTTOM_HORIZONTAL = "\033(0\x71\033(B"
|
||||
CHAR_OUTER_BOTTOM_INTERSECT = "\033(0\x76\033(B"
|
||||
CHAR_OUTER_BOTTOM_LEFT = "\033(0\x6d\033(B"
|
||||
CHAR_OUTER_BOTTOM_RIGHT = "\033(0\x6a\033(B"
|
||||
CHAR_OUTER_LEFT_INTERSECT = "\033(0\x74\033(B"
|
||||
CHAR_OUTER_LEFT_VERTICAL = "\033(0\x78\033(B"
|
||||
CHAR_OUTER_RIGHT_INTERSECT = "\033(0\x75\033(B"
|
||||
CHAR_OUTER_RIGHT_VERTICAL = "\033(0\x78\033(B"
|
||||
CHAR_OUTER_TOP_HORIZONTAL = "\033(0\x71\033(B"
|
||||
CHAR_OUTER_TOP_INTERSECT = "\033(0\x77\033(B"
|
||||
CHAR_OUTER_TOP_LEFT = "\033(0\x6c\033(B"
|
||||
CHAR_OUTER_TOP_RIGHT = "\033(0\x6b\033(B"
|
||||
|
||||
@property
|
||||
def table(self):
|
||||
"""Return a large string of the entire table ready to be printed to the terminal."""
|
||||
ascii_table = super().table
|
||||
optimized = ascii_table.replace("\033(B\033(0", "")
|
||||
return optimized
|
||||
|
||||
|
||||
class WindowsTable(AsciiTable):
|
||||
"""Draw a table using box-drawing characters on Windows platforms. This uses Code Page 437. Single-line borders.
|
||||
|
||||
From: http://en.wikipedia.org/wiki/Code_page_437#Characters
|
||||
"""
|
||||
|
||||
CHAR_F_INNER_HORIZONTAL = b"\xc4".decode("ibm437")
|
||||
CHAR_F_INNER_INTERSECT = b"\xc5".decode("ibm437")
|
||||
CHAR_F_INNER_VERTICAL = b"\xb3".decode("ibm437")
|
||||
CHAR_F_OUTER_LEFT_INTERSECT = b"\xc3".decode("ibm437")
|
||||
CHAR_F_OUTER_LEFT_VERTICAL = b"\xb3".decode("ibm437")
|
||||
CHAR_F_OUTER_RIGHT_INTERSECT = b"\xb4".decode("ibm437")
|
||||
CHAR_F_OUTER_RIGHT_VERTICAL = b"\xb3".decode("ibm437")
|
||||
CHAR_H_INNER_HORIZONTAL = b"\xc4".decode("ibm437")
|
||||
CHAR_H_INNER_INTERSECT = b"\xc5".decode("ibm437")
|
||||
CHAR_H_INNER_VERTICAL = b"\xb3".decode("ibm437")
|
||||
CHAR_H_OUTER_LEFT_INTERSECT = b"\xc3".decode("ibm437")
|
||||
CHAR_H_OUTER_LEFT_VERTICAL = b"\xb3".decode("ibm437")
|
||||
CHAR_H_OUTER_RIGHT_INTERSECT = b"\xb4".decode("ibm437")
|
||||
CHAR_H_OUTER_RIGHT_VERTICAL = b"\xb3".decode("ibm437")
|
||||
CHAR_INNER_HORIZONTAL = b"\xc4".decode("ibm437")
|
||||
CHAR_INNER_INTERSECT = b"\xc5".decode("ibm437")
|
||||
CHAR_INNER_VERTICAL = b"\xb3".decode("ibm437")
|
||||
CHAR_OUTER_BOTTOM_HORIZONTAL = b"\xc4".decode("ibm437")
|
||||
CHAR_OUTER_BOTTOM_INTERSECT = b"\xc1".decode("ibm437")
|
||||
CHAR_OUTER_BOTTOM_LEFT = b"\xc0".decode("ibm437")
|
||||
CHAR_OUTER_BOTTOM_RIGHT = b"\xd9".decode("ibm437")
|
||||
CHAR_OUTER_LEFT_INTERSECT = b"\xc3".decode("ibm437")
|
||||
CHAR_OUTER_LEFT_VERTICAL = b"\xb3".decode("ibm437")
|
||||
CHAR_OUTER_RIGHT_INTERSECT = b"\xb4".decode("ibm437")
|
||||
CHAR_OUTER_RIGHT_VERTICAL = b"\xb3".decode("ibm437")
|
||||
CHAR_OUTER_TOP_HORIZONTAL = b"\xc4".decode("ibm437")
|
||||
CHAR_OUTER_TOP_INTERSECT = b"\xc2".decode("ibm437")
|
||||
CHAR_OUTER_TOP_LEFT = b"\xda".decode("ibm437")
|
||||
CHAR_OUTER_TOP_RIGHT = b"\xbf".decode("ibm437")
|
||||
|
||||
|
||||
class WindowsTableDouble(AsciiTable):
|
||||
"""Draw a table using box-drawing characters on Windows platforms. This uses Code Page 437. Double-line borders."""
|
||||
|
||||
CHAR_F_INNER_HORIZONTAL = b"\xcd".decode("ibm437")
|
||||
CHAR_F_INNER_INTERSECT = b"\xce".decode("ibm437")
|
||||
CHAR_F_INNER_VERTICAL = b"\xba".decode("ibm437")
|
||||
CHAR_F_OUTER_LEFT_INTERSECT = b"\xcc".decode("ibm437")
|
||||
CHAR_F_OUTER_LEFT_VERTICAL = b"\xba".decode("ibm437")
|
||||
CHAR_F_OUTER_RIGHT_INTERSECT = b"\xb9".decode("ibm437")
|
||||
CHAR_F_OUTER_RIGHT_VERTICAL = b"\xba".decode("ibm437")
|
||||
CHAR_H_INNER_HORIZONTAL = b"\xcd".decode("ibm437")
|
||||
CHAR_H_INNER_INTERSECT = b"\xce".decode("ibm437")
|
||||
CHAR_H_INNER_VERTICAL = b"\xba".decode("ibm437")
|
||||
CHAR_H_OUTER_LEFT_INTERSECT = b"\xcc".decode("ibm437")
|
||||
CHAR_H_OUTER_LEFT_VERTICAL = b"\xba".decode("ibm437")
|
||||
CHAR_H_OUTER_RIGHT_INTERSECT = b"\xb9".decode("ibm437")
|
||||
CHAR_H_OUTER_RIGHT_VERTICAL = b"\xba".decode("ibm437")
|
||||
CHAR_INNER_HORIZONTAL = b"\xcd".decode("ibm437")
|
||||
CHAR_INNER_INTERSECT = b"\xce".decode("ibm437")
|
||||
CHAR_INNER_VERTICAL = b"\xba".decode("ibm437")
|
||||
CHAR_OUTER_BOTTOM_HORIZONTAL = b"\xcd".decode("ibm437")
|
||||
CHAR_OUTER_BOTTOM_INTERSECT = b"\xca".decode("ibm437")
|
||||
CHAR_OUTER_BOTTOM_LEFT = b"\xc8".decode("ibm437")
|
||||
CHAR_OUTER_BOTTOM_RIGHT = b"\xbc".decode("ibm437")
|
||||
CHAR_OUTER_LEFT_INTERSECT = b"\xcc".decode("ibm437")
|
||||
CHAR_OUTER_LEFT_VERTICAL = b"\xba".decode("ibm437")
|
||||
CHAR_OUTER_RIGHT_INTERSECT = b"\xb9".decode("ibm437")
|
||||
CHAR_OUTER_RIGHT_VERTICAL = b"\xba".decode("ibm437")
|
||||
CHAR_OUTER_TOP_HORIZONTAL = b"\xcd".decode("ibm437")
|
||||
CHAR_OUTER_TOP_INTERSECT = b"\xcb".decode("ibm437")
|
||||
CHAR_OUTER_TOP_LEFT = b"\xc9".decode("ibm437")
|
||||
CHAR_OUTER_TOP_RIGHT = b"\xbb".decode("ibm437")
|
||||
|
||||
|
||||
class SingleTable(WindowsTable if IS_WINDOWS else UnixTable):
|
||||
"""Cross-platform table with single-line box-drawing characters.
|
||||
|
||||
:ivar iter table_data: List (empty or list of lists of strings) representing the table.
|
||||
:ivar str title: Optional title to show within the top border of the table.
|
||||
:ivar bool inner_column_border: Separates columns.
|
||||
:ivar bool inner_footing_row_border: Show a border before the last row.
|
||||
:ivar bool inner_heading_row_border: Show a border after the first row.
|
||||
:ivar bool inner_row_border: Show a border in between every row.
|
||||
:ivar bool outer_border: Show the top, left, right, and bottom border.
|
||||
:ivar dict justify_columns: Horizontal justification. Keys are column indexes (int). Values are right/left/center.
|
||||
:ivar int padding_left: Number of spaces to pad on the left side of every cell.
|
||||
:ivar int padding_right: Number of spaces to pad on the right side of every cell.
|
||||
"""
|
||||
|
||||
|
||||
class DoubleTable(WindowsTableDouble):
|
||||
"""Cross-platform table with box-drawing characters. On Windows it's double borders, on Linux/OSX it's unicode.
|
||||
|
||||
:ivar iter table_data: List (empty or list of lists of strings) representing the table.
|
||||
:ivar str title: Optional title to show within the top border of the table.
|
||||
:ivar bool inner_column_border: Separates columns.
|
||||
:ivar bool inner_footing_row_border: Show a border before the last row.
|
||||
:ivar bool inner_heading_row_border: Show a border after the first row.
|
||||
:ivar bool inner_row_border: Show a border in between every row.
|
||||
:ivar bool outer_border: Show the top, left, right, and bottom border.
|
||||
:ivar dict justify_columns: Horizontal justification. Keys are column indexes (int). Values are right/left/center.
|
||||
:ivar int padding_left: Number of spaces to pad on the left side of every cell.
|
||||
:ivar int padding_right: Number of spaces to pad on the right side of every cell.
|
||||
"""
|
||||
|
||||
|
||||
class PorcelainTable(AsciiTable):
|
||||
"""An AsciiTable stripped to a minimum.
|
||||
|
||||
Meant to be machine passable and roughly follow format set by git --porcelain option (hence the name).
|
||||
|
||||
:ivar iter table_data: List (empty or list of lists of strings) representing the table.
|
||||
"""
|
||||
|
||||
def __init__(self, table_data):
|
||||
"""Constructor.
|
||||
|
||||
:param iter table_data: List (empty or list of lists of strings) representing the table.
|
||||
"""
|
||||
# Porcelain table won't support title since it has no outer birders.
|
||||
super().__init__(table_data)
|
||||
|
||||
# Removes outer border, and inner footing and header row borders.
|
||||
self.inner_footing_row_border = False
|
||||
self.inner_heading_row_border = False
|
||||
self.outer_border = False
|
|
@ -3,16 +3,17 @@
|
|||
import ctypes
|
||||
import struct
|
||||
import sys
|
||||
from typing import Tuple, Union
|
||||
|
||||
DEFAULT_HEIGHT = 24
|
||||
DEFAULT_WIDTH = 79
|
||||
INVALID_HANDLE_VALUE = -1
|
||||
IS_WINDOWS = sys.platform == 'win32'
|
||||
IS_WINDOWS = sys.platform == "win32"
|
||||
STD_ERROR_HANDLE = -12
|
||||
STD_OUTPUT_HANDLE = -11
|
||||
|
||||
|
||||
def get_console_info(kernel32, handle):
|
||||
def get_console_info(kernel32, handle: int) -> Tuple[int, int]:
|
||||
"""Get information about this current console window (Windows only).
|
||||
|
||||
https://github.com/Robpol86/colorclass/blob/ab42da59/colorclass/windows.py#L111
|
||||
|
@ -26,7 +27,7 @@ def get_console_info(kernel32, handle):
|
|||
:rtype: tuple
|
||||
"""
|
||||
if handle == INVALID_HANDLE_VALUE:
|
||||
raise OSError('Invalid handle.')
|
||||
raise OSError("Invalid handle.")
|
||||
|
||||
# Query Win32 API.
|
||||
lpcsbi = ctypes.create_string_buffer(22) # Populated by GetConsoleScreenBufferInfo.
|
||||
|
@ -34,12 +35,12 @@ def get_console_info(kernel32, handle):
|
|||
raise ctypes.WinError() # Subclass of OSError.
|
||||
|
||||
# Parse data.
|
||||
left, top, right, bottom = struct.unpack('hhhhHhhhhhh', lpcsbi.raw)[5:-2]
|
||||
left, top, right, bottom = struct.unpack("hhhhHhhhhhh", lpcsbi.raw)[5:-2]
|
||||
width, height = right - left, bottom - top
|
||||
return width, height
|
||||
|
||||
|
||||
def terminal_size(kernel32=None):
|
||||
def terminal_size(kernel32=None) -> Tuple[int, int]:
|
||||
"""Get the width and height of the terminal.
|
||||
|
||||
http://code.activestate.com/recipes/440694-determine-size-of-console-window-on-windows/
|
||||
|
@ -56,19 +57,23 @@ def terminal_size(kernel32=None):
|
|||
return get_console_info(kernel32, kernel32.GetStdHandle(STD_ERROR_HANDLE))
|
||||
except OSError:
|
||||
try:
|
||||
return get_console_info(kernel32, kernel32.GetStdHandle(STD_OUTPUT_HANDLE))
|
||||
return get_console_info(
|
||||
kernel32, kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
|
||||
)
|
||||
except OSError:
|
||||
return DEFAULT_WIDTH, DEFAULT_HEIGHT
|
||||
|
||||
try:
|
||||
device = __import__('fcntl').ioctl(0, __import__('termios').TIOCGWINSZ, '\0\0\0\0\0\0\0\0')
|
||||
except IOError:
|
||||
device = __import__("fcntl").ioctl(
|
||||
0, __import__("termios").TIOCGWINSZ, "\0\0\0\0\0\0\0\0"
|
||||
)
|
||||
except OSError:
|
||||
return DEFAULT_WIDTH, DEFAULT_HEIGHT
|
||||
height, width = struct.unpack('hhhh', device)[:2]
|
||||
height, width = struct.unpack("hhhh", device)[:2]
|
||||
return width, height
|
||||
|
||||
|
||||
def set_terminal_title(title, kernel32=None):
|
||||
def set_terminal_title(title: Union[str, bytes], kernel32=None) -> bool:
|
||||
"""Set the terminal title.
|
||||
|
||||
:param title: The title to set (string, unicode, bytes accepted).
|
||||
|
@ -78,7 +83,7 @@ def set_terminal_title(title, kernel32=None):
|
|||
:rtype: bool
|
||||
"""
|
||||
try:
|
||||
title_bytes = title.encode('utf-8')
|
||||
title_bytes = title.encode("utf-8")
|
||||
except AttributeError:
|
||||
title_bytes = title
|
||||
|
||||
|
@ -90,9 +95,8 @@ def set_terminal_title(title, kernel32=None):
|
|||
is_ascii = all(c < 128 for c in title) # bytes.
|
||||
if is_ascii:
|
||||
return kernel32.SetConsoleTitleA(title_bytes) != 0
|
||||
else:
|
||||
return kernel32.SetConsoleTitleW(title) != 0
|
||||
return kernel32.SetConsoleTitleW(title) != 0
|
||||
|
||||
# Linux/OSX.
|
||||
sys.stdout.write(b'\033]0;' + title_bytes + b'\007')
|
||||
sys.stdout.write(b"\033]0;" + title_bytes + b"\007")
|
||||
return True
|
|
@ -2,36 +2,37 @@
|
|||
|
||||
import re
|
||||
import unicodedata
|
||||
from typing import Sequence, Tuple
|
||||
|
||||
from terminaltables.terminal_io import terminal_size
|
||||
from terminaltables3.terminal_io import terminal_size
|
||||
|
||||
RE_COLOR_ANSI = re.compile(r'(\033\[[\d;]+m)')
|
||||
RE_COLOR_ANSI = re.compile(r"(\033\[[\d;]+m)")
|
||||
|
||||
|
||||
def visible_width(string):
|
||||
def visible_width(string: str) -> int:
|
||||
"""Get the visible width of a unicode string.
|
||||
|
||||
Some CJK unicode characters are more than one byte unlike ASCII and latin unicode characters.
|
||||
|
||||
From: https://github.com/Robpol86/terminaltables/pull/9
|
||||
From: https://github.com/Robpol86/terminaltables3/pull/9
|
||||
|
||||
:param str string: String to measure.
|
||||
|
||||
:return: String's width.
|
||||
:rtype: int
|
||||
"""
|
||||
if '\033' in string:
|
||||
string = RE_COLOR_ANSI.sub('', string)
|
||||
if "\033" in string:
|
||||
string = RE_COLOR_ANSI.sub("", string)
|
||||
|
||||
# Convert to unicode.
|
||||
try:
|
||||
string = string.decode('u8')
|
||||
string = string.decode("u8")
|
||||
except (AttributeError, UnicodeEncodeError):
|
||||
pass
|
||||
|
||||
width = 0
|
||||
for char in string:
|
||||
if unicodedata.east_asian_width(char) in ('F', 'W'):
|
||||
if unicodedata.east_asian_width(char) in ("F", "W"):
|
||||
width += 2
|
||||
else:
|
||||
width += 1
|
||||
|
@ -39,7 +40,13 @@ def visible_width(string):
|
|||
return width
|
||||
|
||||
|
||||
def align_and_pad_cell(string, align, inner_dimensions, padding, space=' '):
|
||||
def align_and_pad_cell(
|
||||
string: str,
|
||||
align: Tuple,
|
||||
inner_dimensions: Tuple,
|
||||
padding: Sequence[int],
|
||||
space: str = " ",
|
||||
) -> list[str]:
|
||||
"""Align a string horizontally and vertically. Also add additional padding in both dimensions.
|
||||
|
||||
:param str string: Input string to operate on.
|
||||
|
@ -51,37 +58,55 @@ def align_and_pad_cell(string, align, inner_dimensions, padding, space=' '):
|
|||
:return: Padded cell split into lines.
|
||||
:rtype: list
|
||||
"""
|
||||
if not hasattr(string, 'splitlines'):
|
||||
if not hasattr(string, "splitlines"):
|
||||
string = str(string)
|
||||
|
||||
# Handle trailing newlines or empty strings, str.splitlines() does not satisfy.
|
||||
lines = string.splitlines() or ['']
|
||||
if string.endswith('\n'):
|
||||
lines.append('')
|
||||
lines = string.splitlines() or [""]
|
||||
if string.endswith("\n"):
|
||||
lines.append("")
|
||||
|
||||
# Vertically align and pad.
|
||||
if 'bottom' in align:
|
||||
lines = ([''] * (inner_dimensions[1] - len(lines) + padding[2])) + lines + ([''] * padding[3])
|
||||
elif 'middle' in align:
|
||||
if "bottom" in align:
|
||||
lines = (
|
||||
([""] * (inner_dimensions[1] - len(lines) + padding[2]))
|
||||
+ lines
|
||||
+ ([""] * padding[3])
|
||||
)
|
||||
elif "middle" in align:
|
||||
delta = inner_dimensions[1] - len(lines)
|
||||
lines = ([''] * (delta // 2 + delta % 2 + padding[2])) + lines + ([''] * (delta // 2 + padding[3]))
|
||||
lines = (
|
||||
([""] * (delta // 2 + delta % 2 + padding[2]))
|
||||
+ lines
|
||||
+ ([""] * (delta // 2 + padding[3]))
|
||||
)
|
||||
else:
|
||||
lines = ([''] * padding[2]) + lines + ([''] * (inner_dimensions[1] - len(lines) + padding[3]))
|
||||
lines = (
|
||||
([""] * padding[2])
|
||||
+ lines
|
||||
+ ([""] * (inner_dimensions[1] - len(lines) + padding[3]))
|
||||
)
|
||||
|
||||
# Horizontally align and pad.
|
||||
for i, line in enumerate(lines):
|
||||
new_width = inner_dimensions[0] + len(line) - visible_width(line)
|
||||
if 'right' in align:
|
||||
if "right" in align:
|
||||
lines[i] = line.rjust(padding[0] + new_width, space) + (space * padding[1])
|
||||
elif 'center' in align:
|
||||
lines[i] = (space * padding[0]) + line.center(new_width, space) + (space * padding[1])
|
||||
elif "center" in align:
|
||||
lines[i] = (
|
||||
(space * padding[0])
|
||||
+ line.center(new_width, space)
|
||||
+ (space * padding[1])
|
||||
)
|
||||
else:
|
||||
lines[i] = (space * padding[0]) + line.ljust(new_width + padding[1], space)
|
||||
|
||||
return lines
|
||||
|
||||
|
||||
def max_dimensions(table_data, padding_left=0, padding_right=0, padding_top=0, padding_bottom=0):
|
||||
def max_dimensions(
|
||||
table_data, padding_left=0, padding_right=0, padding_top=0, padding_bottom=0
|
||||
):
|
||||
"""Get maximum widths of each column and maximum height of each row.
|
||||
|
||||
:param iter table_data: List of list of strings (unmodified table data).
|
||||
|
@ -99,12 +124,15 @@ def max_dimensions(table_data, padding_left=0, padding_right=0, padding_top=0, p
|
|||
# Find max width and heights.
|
||||
for j, row in enumerate(table_data):
|
||||
for i, cell in enumerate(row):
|
||||
if not hasattr(cell, 'count') or not hasattr(cell, 'splitlines'):
|
||||
if not hasattr(cell, "count") or not hasattr(cell, "splitlines"):
|
||||
cell = str(cell)
|
||||
if not cell:
|
||||
continue
|
||||
inner_heights[j] = max(inner_heights[j], cell.count('\n') + 1)
|
||||
inner_widths[i] = max(inner_widths[i], *[visible_width(l) for l in cell.splitlines()])
|
||||
inner_heights[j] = max(inner_heights[j], cell.count("\n") + 1)
|
||||
inner_widths[i] = max(
|
||||
inner_widths[i],
|
||||
*[visible_width(the_line) for the_line in cell.splitlines()]
|
||||
)
|
||||
|
||||
# Calculate with padding.
|
||||
outer_widths = [padding_left + i + padding_right for i in inner_widths]
|
||||
|
@ -113,7 +141,13 @@ def max_dimensions(table_data, padding_left=0, padding_right=0, padding_top=0, p
|
|||
return inner_widths, inner_heights, outer_widths, outer_heights
|
||||
|
||||
|
||||
def column_max_width(inner_widths, column_number, outer_border, inner_border, padding):
|
||||
def column_max_width(
|
||||
inner_widths: Sequence[int],
|
||||
column_number: int,
|
||||
outer_border: int,
|
||||
inner_border: int,
|
||||
padding: int,
|
||||
) -> int:
|
||||
"""Determine the maximum width of a column based on the current terminal width.
|
||||
|
||||
:param iter inner_widths: List of widths (no padding) for each column.
|
||||
|
@ -138,7 +172,9 @@ def column_max_width(inner_widths, column_number, outer_border, inner_border, pa
|
|||
return terminal_width - data_space - non_data_space
|
||||
|
||||
|
||||
def table_width(outer_widths, outer_border, inner_border):
|
||||
def table_width(
|
||||
outer_widths: Sequence[int], outer_border: int, inner_border: int
|
||||
) -> int:
|
||||
"""Determine the width of the entire table including borders and padding.
|
||||
|
||||
:param iter outer_widths: List of widths (with padding) for each column.
|
|
@ -2,4 +2,4 @@
|
|||
|
||||
import py
|
||||
|
||||
PROJECT_ROOT = py.path.local(__file__).dirpath().join('..')
|
||||
PROJECT_ROOT = py.path.local(__file__).dirpath().join("..")
|
||||
|
|
|
@ -14,7 +14,7 @@ except ImportError:
|
|||
|
||||
from tests import PROJECT_ROOT
|
||||
|
||||
STARTF_USESHOWWINDOW = getattr(subprocess, 'STARTF_USESHOWWINDOW', 1)
|
||||
STARTF_USESHOWWINDOW = getattr(subprocess, "STARTF_USESHOWWINDOW", 1)
|
||||
STILL_ACTIVE = 259
|
||||
SW_MAXIMIZE = 3
|
||||
|
||||
|
@ -23,24 +23,24 @@ class StartupInfo(ctypes.Structure):
|
|||
"""STARTUPINFO structure."""
|
||||
|
||||
_fields_ = [
|
||||
('cb', ctypes.c_ulong),
|
||||
('lpReserved', ctypes.c_char_p),
|
||||
('lpDesktop', ctypes.c_char_p),
|
||||
('lpTitle', ctypes.c_char_p),
|
||||
('dwX', ctypes.c_ulong),
|
||||
('dwY', ctypes.c_ulong),
|
||||
('dwXSize', ctypes.c_ulong),
|
||||
('dwYSize', ctypes.c_ulong),
|
||||
('dwXCountChars', ctypes.c_ulong),
|
||||
('dwYCountChars', ctypes.c_ulong),
|
||||
('dwFillAttribute', ctypes.c_ulong),
|
||||
('dwFlags', ctypes.c_ulong),
|
||||
('wShowWindow', ctypes.c_ushort),
|
||||
('cbReserved2', ctypes.c_ushort),
|
||||
('lpReserved2', ctypes.c_char_p),
|
||||
('hStdInput', ctypes.c_ulong),
|
||||
('hStdOutput', ctypes.c_ulong),
|
||||
('hStdError', ctypes.c_ulong),
|
||||
("cb", ctypes.c_ulong),
|
||||
("lpReserved", ctypes.c_char_p),
|
||||
("lpDesktop", ctypes.c_char_p),
|
||||
("lpTitle", ctypes.c_char_p),
|
||||
("dwX", ctypes.c_ulong),
|
||||
("dwY", ctypes.c_ulong),
|
||||
("dwXSize", ctypes.c_ulong),
|
||||
("dwYSize", ctypes.c_ulong),
|
||||
("dwXCountChars", ctypes.c_ulong),
|
||||
("dwYCountChars", ctypes.c_ulong),
|
||||
("dwFillAttribute", ctypes.c_ulong),
|
||||
("dwFlags", ctypes.c_ulong),
|
||||
("wShowWindow", ctypes.c_ushort),
|
||||
("cbReserved2", ctypes.c_ushort),
|
||||
("lpReserved2", ctypes.c_char_p),
|
||||
("hStdInput", ctypes.c_ulong),
|
||||
("hStdOutput", ctypes.c_ulong),
|
||||
("hStdError", ctypes.c_ulong),
|
||||
]
|
||||
|
||||
def __init__(self, maximize=False, title=None):
|
||||
|
@ -49,7 +49,7 @@ class StartupInfo(ctypes.Structure):
|
|||
:param bool maximize: Start process in new console window, maximized.
|
||||
:param bytes title: Set new window title to this instead of exe path.
|
||||
"""
|
||||
super(StartupInfo, self).__init__()
|
||||
super().__init__()
|
||||
self.cb = ctypes.sizeof(self)
|
||||
if maximize:
|
||||
self.dwFlags |= STARTF_USESHOWWINDOW
|
||||
|
@ -62,14 +62,14 @@ class ProcessInfo(ctypes.Structure):
|
|||
"""PROCESS_INFORMATION structure."""
|
||||
|
||||
_fields_ = [
|
||||
('hProcess', ctypes.c_void_p),
|
||||
('hThread', ctypes.c_void_p),
|
||||
('dwProcessId', ctypes.c_ulong),
|
||||
('dwThreadId', ctypes.c_ulong),
|
||||
("hProcess", ctypes.c_void_p),
|
||||
("hThread", ctypes.c_void_p),
|
||||
("dwProcessId", ctypes.c_ulong),
|
||||
("dwThreadId", ctypes.c_ulong),
|
||||
]
|
||||
|
||||
|
||||
class RunNewConsole(object):
|
||||
class RunNewConsole:
|
||||
"""Run the command in a new console window. Windows only. Use in a with statement.
|
||||
|
||||
subprocess sucks and really limits your access to the win32 API. Its implementation is half-assed. Using this so
|
||||
|
@ -84,20 +84,27 @@ class RunNewConsole(object):
|
|||
:param bytes title: Set new window title to this. Needed by user32.FindWindow.
|
||||
"""
|
||||
if title is None:
|
||||
title = 'pytest-{0}-{1}'.format(os.getpid(), random.randint(1000, 9999)).encode('ascii')
|
||||
title = "pytest-{}-{}".format(
|
||||
os.getpid(), random.randint(1000, 9999)
|
||||
).encode("ascii")
|
||||
self.startup_info = StartupInfo(maximize=maximized, title=title)
|
||||
self.process_info = ProcessInfo()
|
||||
self.command_str = subprocess.list2cmdline(command).encode('ascii')
|
||||
self._handles = list()
|
||||
self.command_str = subprocess.list2cmdline(command).encode("ascii")
|
||||
self._handles = []
|
||||
self._kernel32 = ctypes.LibraryLoader(ctypes.WinDLL).kernel32
|
||||
self._kernel32.GetExitCodeProcess.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_ulong)]
|
||||
self._kernel32.GetExitCodeProcess.argtypes = [
|
||||
ctypes.c_void_p,
|
||||
ctypes.POINTER(ctypes.c_ulong),
|
||||
]
|
||||
self._kernel32.GetExitCodeProcess.restype = ctypes.c_long
|
||||
|
||||
def __del__(self):
|
||||
"""Close win32 handles."""
|
||||
while self._handles:
|
||||
try:
|
||||
self._kernel32.CloseHandle(self._handles.pop(0)) # .pop() is thread safe.
|
||||
self._kernel32.CloseHandle(
|
||||
self._handles.pop(0)
|
||||
) # .pop() is thread safe.
|
||||
except IndexError:
|
||||
break
|
||||
|
||||
|
@ -111,9 +118,9 @@ class RunNewConsole(object):
|
|||
False, # bInheritHandles
|
||||
subprocess.CREATE_NEW_CONSOLE, # dwCreationFlags
|
||||
None, # lpEnvironment
|
||||
str(PROJECT_ROOT).encode('ascii'), # lpCurrentDirectory
|
||||
str(PROJECT_ROOT).encode("ascii"), # lpCurrentDirectory
|
||||
ctypes.byref(self.startup_info), # lpStartupInfo
|
||||
ctypes.byref(self.process_info) # lpProcessInformation
|
||||
ctypes.byref(self.process_info), # lpProcessInformation
|
||||
):
|
||||
raise ctypes.WinError()
|
||||
|
||||
|
@ -125,7 +132,9 @@ class RunNewConsole(object):
|
|||
self.hwnd = 0
|
||||
for _ in range(int(5 / 0.1)):
|
||||
# Takes time for console window to initialize.
|
||||
self.hwnd = ctypes.windll.user32.FindWindowA(None, self.startup_info.lpTitle)
|
||||
self.hwnd = ctypes.windll.user32.FindWindowA(
|
||||
None, self.startup_info.lpTitle
|
||||
)
|
||||
if self.hwnd:
|
||||
break
|
||||
time.sleep(0.1)
|
||||
|
@ -141,7 +150,9 @@ class RunNewConsole(object):
|
|||
status = ctypes.c_ulong(STILL_ACTIVE)
|
||||
while status.value == STILL_ACTIVE:
|
||||
time.sleep(0.1)
|
||||
if not self._kernel32.GetExitCodeProcess(self.process_info.hProcess, ctypes.byref(status)):
|
||||
if not self._kernel32.GetExitCodeProcess(
|
||||
self.process_info.hProcess, ctypes.byref(status)
|
||||
):
|
||||
raise ctypes.WinError()
|
||||
assert status.value == 0
|
||||
finally:
|
||||
|
@ -154,9 +165,11 @@ class RunNewConsole(object):
|
|||
:return: Yields region the new window is in (left, upper, right, lower).
|
||||
:rtype: tuple
|
||||
"""
|
||||
rect = ctypes.create_string_buffer(16) # To be written to by GetWindowRect. RECT structure.
|
||||
rect = ctypes.create_string_buffer(
|
||||
16
|
||||
) # To be written to by GetWindowRect. RECT structure.
|
||||
while ctypes.windll.user32.GetWindowRect(self.hwnd, rect):
|
||||
left, top, right, bottom = struct.unpack('llll', rect.raw)
|
||||
left, top, right, bottom = struct.unpack("llll", rect.raw)
|
||||
width, height = right - left, bottom - top
|
||||
assert width > 1
|
||||
assert height > 1
|
||||
|
@ -179,8 +192,7 @@ def iter_rows(pil_image):
|
|||
:rtype: tuple
|
||||
"""
|
||||
iterator = izip(*(iter(pil_image.getdata()),) * pil_image.width)
|
||||
for row in iterator:
|
||||
yield row
|
||||
yield from iterator
|
||||
|
||||
|
||||
def get_most_interesting_row(pil_image):
|
||||
|
@ -224,11 +236,13 @@ def count_subimages(screenshot, subimg):
|
|||
for x_pos in range(screenshot.width - si_width + 1):
|
||||
if row[x_pos] != si_pixel:
|
||||
continue # First pixel does not match.
|
||||
if row[x_pos:x_pos + si_width] != si_row:
|
||||
if row[x_pos : x_pos + si_width] != si_row:
|
||||
continue # Row does not match.
|
||||
# Found match for interesting row of subimg in screenshot.
|
||||
y_corrected = y_pos - si_y
|
||||
with screenshot.crop((x_pos, y_corrected, x_pos + si_width, y_corrected + si_height)) as cropped:
|
||||
with screenshot.crop(
|
||||
(x_pos, y_corrected, x_pos + si_width, y_corrected + si_height)
|
||||
) as cropped:
|
||||
if list(cropped.getdata()) == si_pixels:
|
||||
occurrences += 1
|
||||
|
||||
|
@ -248,11 +262,12 @@ def try_candidates(screenshot, subimg_candidates, expected_count):
|
|||
:rtype: int
|
||||
"""
|
||||
from PIL import Image
|
||||
|
||||
count_found = 0
|
||||
|
||||
for subimg_path in subimg_candidates:
|
||||
with Image.open(subimg_path) as rgba_s:
|
||||
with rgba_s.convert(mode='RGB') as subimg:
|
||||
with rgba_s.convert(mode="RGB") as subimg:
|
||||
# Make sure subimage isn't too large.
|
||||
assert subimg.width < 256
|
||||
assert subimg.height < 256
|
||||
|
@ -277,14 +292,17 @@ def screenshot_until_match(save_to, timeout, subimg_candidates, expected_count,
|
|||
:param iter gen: Generator yielding window position and size to crop screenshot to.
|
||||
"""
|
||||
from PIL import ImageGrab
|
||||
assert save_to.endswith('.png')
|
||||
|
||||
assert save_to.endswith(".png")
|
||||
stop_after = time.time() + timeout
|
||||
|
||||
# Take screenshots until subimage is found.
|
||||
while True:
|
||||
with ImageGrab.grab(next(gen)) as rgba:
|
||||
with rgba.convert(mode='RGB') as screenshot:
|
||||
count_found = try_candidates(screenshot, subimg_candidates, expected_count)
|
||||
with rgba.convert(mode="RGB") as screenshot:
|
||||
count_found = try_candidates(
|
||||
screenshot, subimg_candidates, expected_count
|
||||
)
|
||||
if count_found == expected_count or time.time() > stop_after:
|
||||
screenshot.save(save_to)
|
||||
assert count_found == expected_count
|
||||
|
|
|
@ -6,8 +6,8 @@ from textwrap import dedent
|
|||
import py
|
||||
import pytest
|
||||
|
||||
from terminaltables import AsciiTable
|
||||
from terminaltables.terminal_io import IS_WINDOWS
|
||||
from terminaltables3 import AsciiTable
|
||||
from terminaltables3.terminal_io import IS_WINDOWS
|
||||
from tests import PROJECT_ROOT
|
||||
from tests.screenshot import RunNewConsole, screenshot_until_match
|
||||
|
||||
|
@ -17,31 +17,31 @@ HERE = py.path.local(__file__).dirpath()
|
|||
def test_single_line():
|
||||
"""Test single-lined cells."""
|
||||
table_data = [
|
||||
['Name', 'Color', 'Type'],
|
||||
['Avocado', 'green', 'nut'],
|
||||
['Tomato', 'red', 'fruit'],
|
||||
['Lettuce', 'green', 'vegetable'],
|
||||
['Watermelon', 'green'],
|
||||
["Name", "Color", "Type"],
|
||||
["Avocado", "green", "nut"],
|
||||
["Tomato", "red", "fruit"],
|
||||
["Lettuce", "green", "vegetable"],
|
||||
["Watermelon", "green"],
|
||||
[],
|
||||
]
|
||||
table = AsciiTable(table_data, 'Example')
|
||||
table = AsciiTable(table_data, "Example")
|
||||
table.inner_footing_row_border = True
|
||||
table.justify_columns[0] = 'left'
|
||||
table.justify_columns[1] = 'center'
|
||||
table.justify_columns[2] = 'right'
|
||||
table.justify_columns[0] = "left"
|
||||
table.justify_columns[1] = "center"
|
||||
table.justify_columns[2] = "right"
|
||||
actual = table.table
|
||||
|
||||
expected = (
|
||||
'+Example-----+-------+-----------+\n'
|
||||
'| Name | Color | Type |\n'
|
||||
'+------------+-------+-----------+\n'
|
||||
'| Avocado | green | nut |\n'
|
||||
'| Tomato | red | fruit |\n'
|
||||
'| Lettuce | green | vegetable |\n'
|
||||
'| Watermelon | green | |\n'
|
||||
'+------------+-------+-----------+\n'
|
||||
'| | | |\n'
|
||||
'+------------+-------+-----------+'
|
||||
"+Example-----+-------+-----------+\n"
|
||||
"| Name | Color | Type |\n"
|
||||
"+------------+-------+-----------+\n"
|
||||
"| Avocado | green | nut |\n"
|
||||
"| Tomato | red | fruit |\n"
|
||||
"| Lettuce | green | vegetable |\n"
|
||||
"| Watermelon | green | |\n"
|
||||
"+------------+-------+-----------+\n"
|
||||
"| | | |\n"
|
||||
"+------------+-------+-----------+"
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
|
@ -49,22 +49,25 @@ def test_single_line():
|
|||
def test_multi_line():
|
||||
"""Test multi-lined cells."""
|
||||
table_data = [
|
||||
['Show', 'Characters'],
|
||||
['Rugrats', 'Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\nDil Pickles'],
|
||||
['South Park', 'Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick']
|
||||
["Show", "Characters"],
|
||||
[
|
||||
"Rugrats",
|
||||
"Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\nDil Pickles",
|
||||
],
|
||||
["South Park", "Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick"],
|
||||
]
|
||||
table = AsciiTable(table_data)
|
||||
|
||||
# Test defaults.
|
||||
actual = table.table
|
||||
expected = (
|
||||
'+------------+-------------------------------------------------------------------------------------+\n'
|
||||
'| Show | Characters |\n'
|
||||
'+------------+-------------------------------------------------------------------------------------+\n'
|
||||
'| Rugrats | Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, |\n'
|
||||
'| | Dil Pickles |\n'
|
||||
'| South Park | Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick |\n'
|
||||
'+------------+-------------------------------------------------------------------------------------+'
|
||||
"+------------+-------------------------------------------------------------------------------------+\n"
|
||||
"| Show | Characters |\n"
|
||||
"+------------+-------------------------------------------------------------------------------------+\n"
|
||||
"| Rugrats | Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, |\n"
|
||||
"| | Dil Pickles |\n"
|
||||
"| South Park | Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick |\n"
|
||||
"+------------+-------------------------------------------------------------------------------------+"
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
|
@ -72,52 +75,53 @@ def test_multi_line():
|
|||
table.inner_row_border = True
|
||||
actual = table.table
|
||||
expected = (
|
||||
'+------------+-------------------------------------------------------------------------------------+\n'
|
||||
'| Show | Characters |\n'
|
||||
'+------------+-------------------------------------------------------------------------------------+\n'
|
||||
'| Rugrats | Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, |\n'
|
||||
'| | Dil Pickles |\n'
|
||||
'+------------+-------------------------------------------------------------------------------------+\n'
|
||||
'| South Park | Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick |\n'
|
||||
'+------------+-------------------------------------------------------------------------------------+'
|
||||
"+------------+-------------------------------------------------------------------------------------+\n"
|
||||
"| Show | Characters |\n"
|
||||
"+------------+-------------------------------------------------------------------------------------+\n"
|
||||
"| Rugrats | Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, |\n"
|
||||
"| | Dil Pickles |\n"
|
||||
"+------------+-------------------------------------------------------------------------------------+\n"
|
||||
"| South Park | Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick |\n"
|
||||
"+------------+-------------------------------------------------------------------------------------+"
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
# Justify right.
|
||||
table.justify_columns = {1: 'right'}
|
||||
table.justify_columns = {1: "right"}
|
||||
actual = table.table
|
||||
expected = (
|
||||
'+------------+-------------------------------------------------------------------------------------+\n'
|
||||
'| Show | Characters |\n'
|
||||
'+------------+-------------------------------------------------------------------------------------+\n'
|
||||
'| Rugrats | Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, |\n'
|
||||
'| | Dil Pickles |\n'
|
||||
'+------------+-------------------------------------------------------------------------------------+\n'
|
||||
'| South Park | Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick |\n'
|
||||
'+------------+-------------------------------------------------------------------------------------+'
|
||||
"+------------+-------------------------------------------------------------------------------------+\n"
|
||||
"| Show | Characters |\n"
|
||||
"+------------+-------------------------------------------------------------------------------------+\n"
|
||||
"| Rugrats | Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, |\n"
|
||||
"| | Dil Pickles |\n"
|
||||
"+------------+-------------------------------------------------------------------------------------+\n"
|
||||
"| South Park | Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick |\n"
|
||||
"+------------+-------------------------------------------------------------------------------------+"
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.skipif(str(not IS_WINDOWS))
|
||||
@pytest.mark.skip # https://github.com/Robpol86/terminaltables/issues/44
|
||||
@pytest.mark.skip # https://github.com/Robpol86/terminaltables3/issues/44
|
||||
def test_windows_screenshot(tmpdir):
|
||||
"""Test on Windows in a new console window. Take a screenshot to verify it works.
|
||||
|
||||
:param tmpdir: pytest fixture.
|
||||
"""
|
||||
script = tmpdir.join('script.py')
|
||||
script = tmpdir.join("script.py")
|
||||
command = [sys.executable, str(script)]
|
||||
screenshot = PROJECT_ROOT.join('test_ascii_table.png')
|
||||
screenshot = PROJECT_ROOT.join("test_ascii_table.png")
|
||||
if screenshot.check():
|
||||
screenshot.remove()
|
||||
|
||||
# Generate script.
|
||||
script_template = dedent(u"""\
|
||||
script_template = dedent(
|
||||
"""\
|
||||
from __future__ import print_function
|
||||
import os, time
|
||||
from colorclass import Color, Windows
|
||||
from terminaltables import AsciiTable
|
||||
from terminaltables3 import AsciiTable
|
||||
Windows.enable(auto_colors=True)
|
||||
stop_after = time.time() + 20
|
||||
|
||||
|
@ -132,12 +136,13 @@ def test_windows_screenshot(tmpdir):
|
|||
print('Waiting for screenshot_until_match()...')
|
||||
while not os.path.exists(r'%s') and time.time() < stop_after:
|
||||
time.sleep(0.5)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
script_contents = script_template % str(screenshot)
|
||||
script.write(script_contents.encode('utf-8'), mode='wb')
|
||||
script.write(script_contents.encode("utf-8"), mode="wb")
|
||||
|
||||
# Setup expected.
|
||||
sub_images = [str(p) for p in HERE.listdir('sub_ascii_*.bmp')]
|
||||
sub_images = [str(p) for p in HERE.listdir("sub_ascii_*.bmp")]
|
||||
assert sub_images
|
||||
|
||||
# Run.
|
||||
|
|
|
@ -6,8 +6,8 @@ from textwrap import dedent
|
|||
import py
|
||||
import pytest
|
||||
|
||||
from terminaltables import DoubleTable
|
||||
from terminaltables.terminal_io import IS_WINDOWS
|
||||
from terminaltables3 import DoubleTable
|
||||
from terminaltables3.terminal_io import IS_WINDOWS
|
||||
from tests import PROJECT_ROOT
|
||||
from tests.screenshot import RunNewConsole, screenshot_until_match
|
||||
|
||||
|
@ -17,44 +17,35 @@ HERE = py.path.local(__file__).dirpath()
|
|||
def test_single_line():
|
||||
"""Test single-lined cells."""
|
||||
table_data = [
|
||||
['Name', 'Color', 'Type'],
|
||||
['Avocado', 'green', 'nut'],
|
||||
['Tomato', 'red', 'fruit'],
|
||||
['Lettuce', 'green', 'vegetable'],
|
||||
['Watermelon', 'green'],
|
||||
["Name", "Color", "Type"],
|
||||
["Avocado", "green", "nut"],
|
||||
["Tomato", "red", "fruit"],
|
||||
["Lettuce", "green", "vegetable"],
|
||||
["Watermelon", "green"],
|
||||
[],
|
||||
]
|
||||
table = DoubleTable(table_data, 'Example')
|
||||
table = DoubleTable(table_data, "Example")
|
||||
table.inner_footing_row_border = True
|
||||
table.justify_columns[0] = 'left'
|
||||
table.justify_columns[1] = 'center'
|
||||
table.justify_columns[2] = 'right'
|
||||
table.justify_columns[0] = "left"
|
||||
table.justify_columns[1] = "center"
|
||||
table.justify_columns[2] = "right"
|
||||
actual = table.table
|
||||
|
||||
expected = (
|
||||
u'\u2554Example\u2550\u2550\u2550\u2550\u2550\u2566\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2566\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n'
|
||||
|
||||
u'\u2551 Name \u2551 Color \u2551 Type \u2551\n'
|
||||
|
||||
u'\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256c\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u256c\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n'
|
||||
|
||||
u'\u2551 Avocado \u2551 green \u2551 nut \u2551\n'
|
||||
|
||||
u'\u2551 Tomato \u2551 red \u2551 fruit \u2551\n'
|
||||
|
||||
u'\u2551 Lettuce \u2551 green \u2551 vegetable \u2551\n'
|
||||
|
||||
u'\u2551 Watermelon \u2551 green \u2551 \u2551\n'
|
||||
|
||||
u'\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256c\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u256c\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n'
|
||||
|
||||
u'\u2551 \u2551 \u2551 \u2551\n'
|
||||
|
||||
u'\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2569\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2569\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d'
|
||||
"\u2554Example\u2550\u2550\u2550\u2550\u2550\u2566\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2566\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n"
|
||||
"\u2551 Name \u2551 Color \u2551 Type \u2551\n"
|
||||
"\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256c\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u256c\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n"
|
||||
"\u2551 Avocado \u2551 green \u2551 nut \u2551\n"
|
||||
"\u2551 Tomato \u2551 red \u2551 fruit \u2551\n"
|
||||
"\u2551 Lettuce \u2551 green \u2551 vegetable \u2551\n"
|
||||
"\u2551 Watermelon \u2551 green \u2551 \u2551\n"
|
||||
"\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256c\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u256c\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n"
|
||||
"\u2551 \u2551 \u2551 \u2551\n"
|
||||
"\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2569\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2569\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d"
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
|
@ -62,47 +53,44 @@ def test_single_line():
|
|||
def test_multi_line():
|
||||
"""Test multi-lined cells."""
|
||||
table_data = [
|
||||
['Show', 'Characters'],
|
||||
['Rugrats', 'Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\nDil Pickles'],
|
||||
['South Park', 'Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick']
|
||||
["Show", "Characters"],
|
||||
[
|
||||
"Rugrats",
|
||||
"Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\nDil Pickles",
|
||||
],
|
||||
["South Park", "Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick"],
|
||||
]
|
||||
table = DoubleTable(table_data)
|
||||
|
||||
# Test defaults.
|
||||
actual = table.table
|
||||
expected = (
|
||||
u'\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2566\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n'
|
||||
|
||||
u'\u2551 Show \u2551 Characters '
|
||||
u'\u2551\n'
|
||||
|
||||
u'\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256c\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n'
|
||||
|
||||
u'\u2551 Rugrats \u2551 Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, '
|
||||
u'\u2551\n'
|
||||
|
||||
u'\u2551 \u2551 Dil Pickles '
|
||||
u'\u2551\n'
|
||||
|
||||
u'\u2551 South Park \u2551 Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick '
|
||||
u'\u2551\n'
|
||||
|
||||
u'\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2569\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d'
|
||||
"\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2566\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n"
|
||||
"\u2551 Show \u2551 Characters "
|
||||
"\u2551\n"
|
||||
"\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256c\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n"
|
||||
"\u2551 Rugrats \u2551 Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, "
|
||||
"\u2551\n"
|
||||
"\u2551 \u2551 Dil Pickles "
|
||||
"\u2551\n"
|
||||
"\u2551 South Park \u2551 Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick "
|
||||
"\u2551\n"
|
||||
"\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2569\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d"
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
|
@ -110,114 +98,101 @@ def test_multi_line():
|
|||
table.inner_row_border = True
|
||||
actual = table.table
|
||||
expected = (
|
||||
u'\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2566\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n'
|
||||
|
||||
u'\u2551 Show \u2551 Characters '
|
||||
u'\u2551\n'
|
||||
|
||||
u'\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256c\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n'
|
||||
|
||||
u'\u2551 Rugrats \u2551 Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, '
|
||||
u'\u2551\n'
|
||||
|
||||
u'\u2551 \u2551 Dil Pickles '
|
||||
u'\u2551\n'
|
||||
|
||||
u'\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256c\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n'
|
||||
|
||||
u'\u2551 South Park \u2551 Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick '
|
||||
u'\u2551\n'
|
||||
|
||||
u'\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2569\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d'
|
||||
"\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2566\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n"
|
||||
"\u2551 Show \u2551 Characters "
|
||||
"\u2551\n"
|
||||
"\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256c\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n"
|
||||
"\u2551 Rugrats \u2551 Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, "
|
||||
"\u2551\n"
|
||||
"\u2551 \u2551 Dil Pickles "
|
||||
"\u2551\n"
|
||||
"\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256c\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n"
|
||||
"\u2551 South Park \u2551 Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick "
|
||||
"\u2551\n"
|
||||
"\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2569\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d"
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
# Justify right.
|
||||
table.justify_columns = {1: 'right'}
|
||||
table.justify_columns = {1: "right"}
|
||||
actual = table.table
|
||||
expected = (
|
||||
u'\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2566\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n'
|
||||
|
||||
u'\u2551 Show \u2551 Characters '
|
||||
u'\u2551\n'
|
||||
|
||||
u'\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256c\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n'
|
||||
|
||||
u'\u2551 Rugrats \u2551 Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, '
|
||||
u'\u2551\n'
|
||||
|
||||
u'\u2551 \u2551 Dil Pickles '
|
||||
u'\u2551\n'
|
||||
|
||||
u'\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256c\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n'
|
||||
|
||||
u'\u2551 South Park \u2551 Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick '
|
||||
u'\u2551\n'
|
||||
|
||||
u'\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2569\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'
|
||||
u'\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d'
|
||||
"\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2566\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n"
|
||||
"\u2551 Show \u2551 Characters "
|
||||
"\u2551\n"
|
||||
"\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256c\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n"
|
||||
"\u2551 Rugrats \u2551 Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, "
|
||||
"\u2551\n"
|
||||
"\u2551 \u2551 Dil Pickles "
|
||||
"\u2551\n"
|
||||
"\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256c\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n"
|
||||
"\u2551 South Park \u2551 Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick "
|
||||
"\u2551\n"
|
||||
"\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2569\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
|
||||
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d"
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.skipif(str(not IS_WINDOWS))
|
||||
@pytest.mark.skip # https://github.com/Robpol86/terminaltables/issues/44
|
||||
@pytest.mark.skip # https://github.com/Robpol86/terminaltables3/issues/44
|
||||
def test_windows_screenshot(tmpdir):
|
||||
"""Test on Windows in a new console window. Take a screenshot to verify it works.
|
||||
|
||||
:param tmpdir: pytest fixture.
|
||||
"""
|
||||
script = tmpdir.join('script.py')
|
||||
script = tmpdir.join("script.py")
|
||||
command = [sys.executable, str(script)]
|
||||
screenshot = PROJECT_ROOT.join('test_double_table.png')
|
||||
screenshot = PROJECT_ROOT.join("test_double_table.png")
|
||||
if screenshot.check():
|
||||
screenshot.remove()
|
||||
|
||||
# Generate script.
|
||||
script_template = dedent(u"""\
|
||||
script_template = dedent(
|
||||
"""\
|
||||
from __future__ import print_function
|
||||
import os, time
|
||||
from colorclass import Color, Windows
|
||||
from terminaltables import DoubleTable
|
||||
from terminaltables3 import DoubleTable
|
||||
Windows.enable(auto_colors=True)
|
||||
stop_after = time.time() + 20
|
||||
|
||||
|
@ -232,12 +207,13 @@ def test_windows_screenshot(tmpdir):
|
|||
print('Waiting for screenshot_until_match()...')
|
||||
while not os.path.exists(r'%s') and time.time() < stop_after:
|
||||
time.sleep(0.5)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
script_contents = script_template % str(screenshot)
|
||||
script.write(script_contents.encode('utf-8'), mode='wb')
|
||||
script.write(script_contents.encode("utf-8"), mode="wb")
|
||||
|
||||
# Setup expected.
|
||||
sub_images = [str(p) for p in HERE.listdir('sub_double_*.bmp')]
|
||||
sub_images = [str(p) for p in HERE.listdir("sub_double_*.bmp")]
|
||||
assert sub_images
|
||||
|
||||
# Run.
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
"""GithubFlavoredMarkdownTable end to end testing."""
|
||||
|
||||
from terminaltables import GithubFlavoredMarkdownTable
|
||||
from terminaltables3 import GithubFlavoredMarkdownTable
|
||||
|
||||
|
||||
def test_single_line():
|
||||
"""Test single-lined cells."""
|
||||
table_data = [
|
||||
['Name', 'Color', 'Type'],
|
||||
['Avocado', 'green', 'nut'],
|
||||
['Tomato', 'red', 'fruit'],
|
||||
['Lettuce', 'green', 'vegetable'],
|
||||
['Watermelon', 'green'],
|
||||
["Name", "Color", "Type"],
|
||||
["Avocado", "green", "nut"],
|
||||
["Tomato", "red", "fruit"],
|
||||
["Lettuce", "green", "vegetable"],
|
||||
["Watermelon", "green"],
|
||||
[],
|
||||
]
|
||||
table = GithubFlavoredMarkdownTable(table_data)
|
||||
table.inner_footing_row_border = True
|
||||
table.justify_columns[0] = 'left'
|
||||
table.justify_columns[1] = 'center'
|
||||
table.justify_columns[2] = 'right'
|
||||
table.justify_columns[0] = "left"
|
||||
table.justify_columns[1] = "center"
|
||||
table.justify_columns[2] = "right"
|
||||
actual = table.table
|
||||
|
||||
expected = (
|
||||
'| Name | Color | Type |\n'
|
||||
'|:-----------|:-----:|----------:|\n'
|
||||
'| Avocado | green | nut |\n'
|
||||
'| Tomato | red | fruit |\n'
|
||||
'| Lettuce | green | vegetable |\n'
|
||||
'| Watermelon | green | |\n'
|
||||
'| | | |'
|
||||
"| Name | Color | Type |\n"
|
||||
"|:-----------|:-----:|----------:|\n"
|
||||
"| Avocado | green | nut |\n"
|
||||
"| Tomato | red | fruit |\n"
|
||||
"| Lettuce | green | vegetable |\n"
|
||||
"| Watermelon | green | |\n"
|
||||
"| | | |"
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
|
@ -35,20 +35,23 @@ def test_single_line():
|
|||
def test_multi_line():
|
||||
"""Test multi-lined cells."""
|
||||
table_data = [
|
||||
['Show', 'Characters'],
|
||||
['Rugrats', 'Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\nDil Pickles'],
|
||||
['South Park', 'Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick']
|
||||
["Show", "Characters"],
|
||||
[
|
||||
"Rugrats",
|
||||
"Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\nDil Pickles",
|
||||
],
|
||||
["South Park", "Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick"],
|
||||
]
|
||||
table = GithubFlavoredMarkdownTable(table_data)
|
||||
|
||||
# Test defaults.
|
||||
actual = table.table
|
||||
expected = (
|
||||
'| Show | Characters |\n'
|
||||
'|------------|-------------------------------------------------------------------------------------|\n'
|
||||
'| Rugrats | Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, |\n'
|
||||
'| | Dil Pickles |\n'
|
||||
'| South Park | Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick |'
|
||||
"| Show | Characters |\n"
|
||||
"|------------|-------------------------------------------------------------------------------------|\n"
|
||||
"| Rugrats | Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, |\n"
|
||||
"| | Dil Pickles |\n"
|
||||
"| South Park | Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick |"
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
|
@ -56,22 +59,22 @@ def test_multi_line():
|
|||
table.inner_row_border = True
|
||||
actual = table.table
|
||||
expected = (
|
||||
'| Show | Characters |\n'
|
||||
'|------------|-------------------------------------------------------------------------------------|\n'
|
||||
'| Rugrats | Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, |\n'
|
||||
'| | Dil Pickles |\n'
|
||||
'| South Park | Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick |'
|
||||
"| Show | Characters |\n"
|
||||
"|------------|-------------------------------------------------------------------------------------|\n"
|
||||
"| Rugrats | Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, |\n"
|
||||
"| | Dil Pickles |\n"
|
||||
"| South Park | Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick |"
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
# Justify right.
|
||||
table.justify_columns = {1: 'right'}
|
||||
table.justify_columns = {1: "right"}
|
||||
actual = table.table
|
||||
expected = (
|
||||
'| Show | Characters |\n'
|
||||
'|------------|------------------------------------------------------------------------------------:|\n'
|
||||
'| Rugrats | Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, |\n'
|
||||
'| | Dil Pickles |\n'
|
||||
'| South Park | Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick |'
|
||||
"| Show | Characters |\n"
|
||||
"|------------|------------------------------------------------------------------------------------:|\n"
|
||||
"| Rugrats | Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, |\n"
|
||||
"| | Dil Pickles |\n"
|
||||
"| South Park | Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick |"
|
||||
)
|
||||
assert actual == expected
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
"""PorcelainTable end to end testing."""
|
||||
|
||||
from terminaltables import PorcelainTable
|
||||
from terminaltables3 import PorcelainTable
|
||||
|
||||
|
||||
def test_single_line():
|
||||
"""Test single-lined cells."""
|
||||
table_data = [
|
||||
['Name', 'Color', 'Type'],
|
||||
['Avocado', 'green', 'nut'],
|
||||
['Tomato', 'red', 'fruit'],
|
||||
['Lettuce', 'green', 'vegetable'],
|
||||
['Watermelon', 'green']
|
||||
["Name", "Color", "Type"],
|
||||
["Avocado", "green", "nut"],
|
||||
["Tomato", "red", "fruit"],
|
||||
["Lettuce", "green", "vegetable"],
|
||||
["Watermelon", "green"],
|
||||
]
|
||||
table = PorcelainTable(table_data)
|
||||
table.justify_columns[0] = 'left'
|
||||
table.justify_columns[1] = 'center'
|
||||
table.justify_columns[2] = 'right'
|
||||
table.justify_columns[0] = "left"
|
||||
table.justify_columns[1] = "center"
|
||||
table.justify_columns[2] = "right"
|
||||
actual = table.table
|
||||
|
||||
expected = (
|
||||
' Name | Color | Type \n'
|
||||
' Avocado | green | nut \n'
|
||||
' Tomato | red | fruit \n'
|
||||
' Lettuce | green | vegetable \n'
|
||||
' Watermelon | green | '
|
||||
" Name | Color | Type \n"
|
||||
" Avocado | green | nut \n"
|
||||
" Tomato | red | fruit \n"
|
||||
" Lettuce | green | vegetable \n"
|
||||
" Watermelon | green | "
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
|
@ -31,29 +31,32 @@ def test_single_line():
|
|||
def test_multi_line():
|
||||
"""Test multi-lined cells."""
|
||||
table_data = [
|
||||
['Show', 'Characters'],
|
||||
['Rugrats', 'Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\nDil Pickles'],
|
||||
['South Park', 'Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick']
|
||||
["Show", "Characters"],
|
||||
[
|
||||
"Rugrats",
|
||||
"Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\nDil Pickles",
|
||||
],
|
||||
["South Park", "Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick"],
|
||||
]
|
||||
table = PorcelainTable(table_data)
|
||||
|
||||
# Test defaults.
|
||||
actual = table.table
|
||||
expected = (
|
||||
' Show | Characters \n'
|
||||
' Rugrats | Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, \n'
|
||||
' | Dil Pickles \n'
|
||||
' South Park | Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick '
|
||||
" Show | Characters \n"
|
||||
" Rugrats | Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, \n"
|
||||
" | Dil Pickles \n"
|
||||
" South Park | Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick "
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
# Justify right.
|
||||
table.justify_columns = {1: 'right'}
|
||||
table.justify_columns = {1: "right"}
|
||||
actual = table.table
|
||||
expected = (
|
||||
' Show | Characters \n'
|
||||
' Rugrats | Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, \n'
|
||||
' | Dil Pickles \n'
|
||||
' South Park | Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick '
|
||||
" Show | Characters \n"
|
||||
" Rugrats | Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, \n"
|
||||
" | Dil Pickles \n"
|
||||
" South Park | Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick "
|
||||
)
|
||||
assert actual == expected
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
import pytest
|
||||
|
||||
from terminaltables import SingleTable
|
||||
from terminaltables.terminal_io import IS_WINDOWS
|
||||
from terminaltables3 import SingleTable
|
||||
from terminaltables3.terminal_io import IS_WINDOWS
|
||||
|
||||
pytestmark = pytest.mark.skipif(str(IS_WINDOWS))
|
||||
|
||||
|
@ -11,44 +11,35 @@ pytestmark = pytest.mark.skipif(str(IS_WINDOWS))
|
|||
def test_single_line():
|
||||
"""Test single-lined cells."""
|
||||
table_data = [
|
||||
['Name', 'Color', 'Type'],
|
||||
['Avocado', 'green', 'nut'],
|
||||
['Tomato', 'red', 'fruit'],
|
||||
['Lettuce', 'green', 'vegetable'],
|
||||
['Watermelon', 'green'],
|
||||
["Name", "Color", "Type"],
|
||||
["Avocado", "green", "nut"],
|
||||
["Tomato", "red", "fruit"],
|
||||
["Lettuce", "green", "vegetable"],
|
||||
["Watermelon", "green"],
|
||||
[],
|
||||
]
|
||||
table = SingleTable(table_data, 'Example')
|
||||
table = SingleTable(table_data, "Example")
|
||||
table.inner_footing_row_border = True
|
||||
table.justify_columns[0] = 'left'
|
||||
table.justify_columns[1] = 'center'
|
||||
table.justify_columns[2] = 'right'
|
||||
table.justify_columns[0] = "left"
|
||||
table.justify_columns[1] = "center"
|
||||
table.justify_columns[2] = "right"
|
||||
actual = table.table
|
||||
|
||||
expected = (
|
||||
'\033(0\x6c\033(BExample\033(0\x71\x71\x71\x71\x71\x77\x71\x71\x71\x71\x71\x71\x71\x77\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x6b\033(B\n'
|
||||
|
||||
'\033(0\x78\033(B Name \033(0\x78\033(B Color \033(0\x78\033(B Type \033(0\x78\033(B\n'
|
||||
|
||||
'\033(0\x74\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6e\x71\x71\x71\x71\x71\x71\x71\x6e\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x75\033(B\n'
|
||||
|
||||
'\033(0\x78\033(B Avocado \033(0\x78\033(B green \033(0\x78\033(B nut \033(0\x78\033(B\n'
|
||||
|
||||
'\033(0\x78\033(B Tomato \033(0\x78\033(B red \033(0\x78\033(B fruit \033(0\x78\033(B\n'
|
||||
|
||||
'\033(0\x78\033(B Lettuce \033(0\x78\033(B green \033(0\x78\033(B vegetable \033(0\x78\033(B\n'
|
||||
|
||||
'\033(0\x78\033(B Watermelon \033(0\x78\033(B green \033(0\x78\033(B \033(0\x78\033(B\n'
|
||||
|
||||
'\033(0\x74\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6e\x71\x71\x71\x71\x71\x71\x71\x6e\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x75\033(B\n'
|
||||
|
||||
'\033(0\x78\033(B \033(0\x78\033(B \033(0\x78\033(B \033(0\x78\033(B\n'
|
||||
|
||||
'\033(0\x6d\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x76\x71\x71\x71\x71\x71\x71\x71\x76\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x6a\033(B'
|
||||
"\033(0\x6c\033(BExample\033(0\x71\x71\x71\x71\x71\x77\x71\x71\x71\x71\x71\x71\x71\x77\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x6b\033(B\n"
|
||||
"\033(0\x78\033(B Name \033(0\x78\033(B Color \033(0\x78\033(B Type \033(0\x78\033(B\n"
|
||||
"\033(0\x74\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6e\x71\x71\x71\x71\x71\x71\x71\x6e\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x75\033(B\n"
|
||||
"\033(0\x78\033(B Avocado \033(0\x78\033(B green \033(0\x78\033(B nut \033(0\x78\033(B\n"
|
||||
"\033(0\x78\033(B Tomato \033(0\x78\033(B red \033(0\x78\033(B fruit \033(0\x78\033(B\n"
|
||||
"\033(0\x78\033(B Lettuce \033(0\x78\033(B green \033(0\x78\033(B vegetable \033(0\x78\033(B\n"
|
||||
"\033(0\x78\033(B Watermelon \033(0\x78\033(B green \033(0\x78\033(B \033(0\x78\033(B\n"
|
||||
"\033(0\x74\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6e\x71\x71\x71\x71\x71\x71\x71\x6e\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x75\033(B\n"
|
||||
"\033(0\x78\033(B \033(0\x78\033(B \033(0\x78\033(B \033(0\x78\033(B\n"
|
||||
"\033(0\x6d\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x76\x71\x71\x71\x71\x71\x71\x71\x76\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x6a\033(B"
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
|
@ -56,41 +47,38 @@ def test_single_line():
|
|||
def test_multi_line():
|
||||
"""Test multi-lined cells."""
|
||||
table_data = [
|
||||
['Show', 'Characters'],
|
||||
['Rugrats', 'Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\nDil Pickles'],
|
||||
['South Park', 'Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick']
|
||||
["Show", "Characters"],
|
||||
[
|
||||
"Rugrats",
|
||||
"Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\nDil Pickles",
|
||||
],
|
||||
["South Park", "Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick"],
|
||||
]
|
||||
table = SingleTable(table_data)
|
||||
|
||||
# Test defaults.
|
||||
actual = table.table
|
||||
expected = (
|
||||
'\033(0\x6c\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x77\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6b\033(B\n'
|
||||
|
||||
'\033(0\x78\033(B Show \033(0\x78\033(B Characters '
|
||||
' \033(0\x78\033(B\n'
|
||||
|
||||
'\033(0\x74\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6e\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x75\033(B\n'
|
||||
|
||||
'\033(0\x78\033(B Rugrats \033(0\x78\033(B Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille,'
|
||||
' Angelica Pickles, \033(0\x78\033(B\n'
|
||||
|
||||
'\033(0\x78\033(B \033(0\x78\033(B Dil Pickles '
|
||||
' \033(0\x78\033(B\n'
|
||||
|
||||
'\033(0\x78\033(B South Park \033(0\x78\033(B Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick '
|
||||
' \033(0\x78\033(B\n'
|
||||
|
||||
'\033(0\x6d\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x76\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6a\033(B'
|
||||
"\033(0\x6c\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x77\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6b\033(B\n"
|
||||
"\033(0\x78\033(B Show \033(0\x78\033(B Characters "
|
||||
" \033(0\x78\033(B\n"
|
||||
"\033(0\x74\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6e\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x75\033(B\n"
|
||||
"\033(0\x78\033(B Rugrats \033(0\x78\033(B Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille,"
|
||||
" Angelica Pickles, \033(0\x78\033(B\n"
|
||||
"\033(0\x78\033(B \033(0\x78\033(B Dil Pickles "
|
||||
" \033(0\x78\033(B\n"
|
||||
"\033(0\x78\033(B South Park \033(0\x78\033(B Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick "
|
||||
" \033(0\x78\033(B\n"
|
||||
"\033(0\x6d\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x76\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6a\033(B"
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
|
@ -98,74 +86,60 @@ def test_multi_line():
|
|||
table.inner_row_border = True
|
||||
actual = table.table
|
||||
expected = (
|
||||
'\033(0\x6c\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x77\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6b\033(B\n'
|
||||
|
||||
'\033(0\x78\033(B Show \033(0\x78\033(B Characters '
|
||||
' \033(0\x78\033(B\n'
|
||||
|
||||
'\033(0\x74\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6e\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x75\033(B\n'
|
||||
|
||||
'\033(0\x78\033(B Rugrats \033(0\x78\033(B Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille,'
|
||||
' Angelica Pickles, \033(0\x78\033(B\n'
|
||||
|
||||
'\033(0\x78\033(B \033(0\x78\033(B Dil Pickles '
|
||||
' \033(0\x78\033(B\n'
|
||||
|
||||
'\033(0\x74\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6e\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x75\033(B\n'
|
||||
|
||||
'\033(0\x78\033(B South Park \033(0\x78\033(B Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick '
|
||||
' \033(0\x78\033(B\n'
|
||||
|
||||
'\033(0\x6d\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x76\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6a\033(B'
|
||||
"\033(0\x6c\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x77\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6b\033(B\n"
|
||||
"\033(0\x78\033(B Show \033(0\x78\033(B Characters "
|
||||
" \033(0\x78\033(B\n"
|
||||
"\033(0\x74\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6e\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x75\033(B\n"
|
||||
"\033(0\x78\033(B Rugrats \033(0\x78\033(B Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille,"
|
||||
" Angelica Pickles, \033(0\x78\033(B\n"
|
||||
"\033(0\x78\033(B \033(0\x78\033(B Dil Pickles "
|
||||
" \033(0\x78\033(B\n"
|
||||
"\033(0\x74\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6e\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x75\033(B\n"
|
||||
"\033(0\x78\033(B South Park \033(0\x78\033(B Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick "
|
||||
" \033(0\x78\033(B\n"
|
||||
"\033(0\x6d\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x76\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6a\033(B"
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
# Justify right.
|
||||
table.justify_columns = {1: 'right'}
|
||||
table.justify_columns = {1: "right"}
|
||||
actual = table.table
|
||||
expected = (
|
||||
'\033(0\x6c\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x77\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6b\033(B\n'
|
||||
|
||||
'\033(0\x78\033(B Show \033(0\x78\033(B '
|
||||
' Characters \033(0\x78\033(B\n'
|
||||
|
||||
'\033(0\x74\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6e\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x75\033(B\n'
|
||||
|
||||
'\033(0\x78\033(B Rugrats \033(0\x78\033(B Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille,'
|
||||
' Angelica Pickles, \033(0\x78\033(B\n'
|
||||
|
||||
'\033(0\x78\033(B \033(0\x78\033(B '
|
||||
' Dil Pickles \033(0\x78\033(B\n'
|
||||
|
||||
'\033(0\x74\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6e\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x75\033(B\n'
|
||||
|
||||
'\033(0\x78\033(B South Park \033(0\x78\033(B Stan Marsh, Kyle Broflovski, '
|
||||
'Eric Cartman, Kenny McCormick \033(0\x78\033(B\n'
|
||||
|
||||
'\033(0\x6d\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x76\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71'
|
||||
'\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6a\033(B'
|
||||
"\033(0\x6c\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x77\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6b\033(B\n"
|
||||
"\033(0\x78\033(B Show \033(0\x78\033(B "
|
||||
" Characters \033(0\x78\033(B\n"
|
||||
"\033(0\x74\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6e\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x75\033(B\n"
|
||||
"\033(0\x78\033(B Rugrats \033(0\x78\033(B Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille,"
|
||||
" Angelica Pickles, \033(0\x78\033(B\n"
|
||||
"\033(0\x78\033(B \033(0\x78\033(B "
|
||||
" Dil Pickles \033(0\x78\033(B\n"
|
||||
"\033(0\x74\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6e\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x75\033(B\n"
|
||||
"\033(0\x78\033(B South Park \033(0\x78\033(B Stan Marsh, Kyle Broflovski, "
|
||||
"Eric Cartman, Kenny McCormick \033(0\x78\033(B\n"
|
||||
"\033(0\x6d\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x76\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71"
|
||||
"\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x6a\033(B"
|
||||
)
|
||||
assert actual == expected
|
||||
|
|
|
@ -6,8 +6,8 @@ from textwrap import dedent
|
|||
import py
|
||||
import pytest
|
||||
|
||||
from terminaltables import SingleTable
|
||||
from terminaltables.terminal_io import IS_WINDOWS
|
||||
from terminaltables3 import SingleTable
|
||||
from terminaltables3.terminal_io import IS_WINDOWS
|
||||
from tests import PROJECT_ROOT
|
||||
from tests.screenshot import RunNewConsole, screenshot_until_match
|
||||
|
||||
|
@ -18,44 +18,35 @@ pytestmark = pytest.mark.skipif(str(not IS_WINDOWS))
|
|||
def test_single_line():
|
||||
"""Test single-lined cells."""
|
||||
table_data = [
|
||||
['Name', 'Color', 'Type'],
|
||||
['Avocado', 'green', 'nut'],
|
||||
['Tomato', 'red', 'fruit'],
|
||||
['Lettuce', 'green', 'vegetable'],
|
||||
['Watermelon', 'green'],
|
||||
["Name", "Color", "Type"],
|
||||
["Avocado", "green", "nut"],
|
||||
["Tomato", "red", "fruit"],
|
||||
["Lettuce", "green", "vegetable"],
|
||||
["Watermelon", "green"],
|
||||
[],
|
||||
]
|
||||
table = SingleTable(table_data, 'Example')
|
||||
table = SingleTable(table_data, "Example")
|
||||
table.inner_footing_row_border = True
|
||||
table.justify_columns[0] = 'left'
|
||||
table.justify_columns[1] = 'center'
|
||||
table.justify_columns[2] = 'right'
|
||||
table.justify_columns[0] = "left"
|
||||
table.justify_columns[1] = "center"
|
||||
table.justify_columns[2] = "right"
|
||||
actual = table.table
|
||||
|
||||
expected = (
|
||||
u'\u250cExample\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n'
|
||||
|
||||
u'\u2502 Name \u2502 Color \u2502 Type \u2502\n'
|
||||
|
||||
u'\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n'
|
||||
|
||||
u'\u2502 Avocado \u2502 green \u2502 nut \u2502\n'
|
||||
|
||||
u'\u2502 Tomato \u2502 red \u2502 fruit \u2502\n'
|
||||
|
||||
u'\u2502 Lettuce \u2502 green \u2502 vegetable \u2502\n'
|
||||
|
||||
u'\u2502 Watermelon \u2502 green \u2502 \u2502\n'
|
||||
|
||||
u'\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n'
|
||||
|
||||
u'\u2502 \u2502 \u2502 \u2502\n'
|
||||
|
||||
u'\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518'
|
||||
"\u250cExample\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n"
|
||||
"\u2502 Name \u2502 Color \u2502 Type \u2502\n"
|
||||
"\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n"
|
||||
"\u2502 Avocado \u2502 green \u2502 nut \u2502\n"
|
||||
"\u2502 Tomato \u2502 red \u2502 fruit \u2502\n"
|
||||
"\u2502 Lettuce \u2502 green \u2502 vegetable \u2502\n"
|
||||
"\u2502 Watermelon \u2502 green \u2502 \u2502\n"
|
||||
"\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n"
|
||||
"\u2502 \u2502 \u2502 \u2502\n"
|
||||
"\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
|
@ -63,47 +54,44 @@ def test_single_line():
|
|||
def test_multi_line():
|
||||
"""Test multi-lined cells."""
|
||||
table_data = [
|
||||
['Show', 'Characters'],
|
||||
['Rugrats', 'Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\nDil Pickles'],
|
||||
['South Park', 'Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick']
|
||||
["Show", "Characters"],
|
||||
[
|
||||
"Rugrats",
|
||||
"Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\nDil Pickles",
|
||||
],
|
||||
["South Park", "Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick"],
|
||||
]
|
||||
table = SingleTable(table_data)
|
||||
|
||||
# Test defaults.
|
||||
actual = table.table
|
||||
expected = (
|
||||
u'\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n'
|
||||
|
||||
u'\u2502 Show \u2502 Characters '
|
||||
u'\u2502\n'
|
||||
|
||||
u'\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n'
|
||||
|
||||
u'\u2502 Rugrats \u2502 Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, '
|
||||
u'\u2502\n'
|
||||
|
||||
u'\u2502 \u2502 Dil Pickles '
|
||||
u'\u2502\n'
|
||||
|
||||
u'\u2502 South Park \u2502 Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick '
|
||||
u'\u2502\n'
|
||||
|
||||
u'\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518'
|
||||
"\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n"
|
||||
"\u2502 Show \u2502 Characters "
|
||||
"\u2502\n"
|
||||
"\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n"
|
||||
"\u2502 Rugrats \u2502 Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, "
|
||||
"\u2502\n"
|
||||
"\u2502 \u2502 Dil Pickles "
|
||||
"\u2502\n"
|
||||
"\u2502 South Park \u2502 Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick "
|
||||
"\u2502\n"
|
||||
"\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
|
@ -111,114 +99,101 @@ def test_multi_line():
|
|||
table.inner_row_border = True
|
||||
actual = table.table
|
||||
expected = (
|
||||
u'\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n'
|
||||
|
||||
u'\u2502 Show \u2502 Characters '
|
||||
u'\u2502\n'
|
||||
|
||||
u'\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n'
|
||||
|
||||
u'\u2502 Rugrats \u2502 Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, '
|
||||
u'\u2502\n'
|
||||
|
||||
u'\u2502 \u2502 Dil Pickles '
|
||||
u'\u2502\n'
|
||||
|
||||
u'\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n'
|
||||
|
||||
u'\u2502 South Park \u2502 Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick '
|
||||
u'\u2502\n'
|
||||
|
||||
u'\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518'
|
||||
"\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n"
|
||||
"\u2502 Show \u2502 Characters "
|
||||
"\u2502\n"
|
||||
"\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n"
|
||||
"\u2502 Rugrats \u2502 Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, "
|
||||
"\u2502\n"
|
||||
"\u2502 \u2502 Dil Pickles "
|
||||
"\u2502\n"
|
||||
"\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n"
|
||||
"\u2502 South Park \u2502 Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick "
|
||||
"\u2502\n"
|
||||
"\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
# Justify right.
|
||||
table.justify_columns = {1: 'right'}
|
||||
table.justify_columns = {1: "right"}
|
||||
actual = table.table
|
||||
expected = (
|
||||
u'\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n'
|
||||
|
||||
u'\u2502 Show \u2502 Characters '
|
||||
u'\u2502\n'
|
||||
|
||||
u'\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n'
|
||||
|
||||
u'\u2502 Rugrats \u2502 Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, '
|
||||
u'\u2502\n'
|
||||
|
||||
u'\u2502 \u2502 Dil Pickles '
|
||||
u'\u2502\n'
|
||||
|
||||
u'\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n'
|
||||
|
||||
u'\u2502 South Park \u2502 Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick '
|
||||
u'\u2502\n'
|
||||
|
||||
u'\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
|
||||
u'\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518'
|
||||
"\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n"
|
||||
"\u2502 Show \u2502 Characters "
|
||||
"\u2502\n"
|
||||
"\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n"
|
||||
"\u2502 Rugrats \u2502 Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles, "
|
||||
"\u2502\n"
|
||||
"\u2502 \u2502 Dil Pickles "
|
||||
"\u2502\n"
|
||||
"\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n"
|
||||
"\u2502 South Park \u2502 Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick "
|
||||
"\u2502\n"
|
||||
"\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
||||
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.skipif(str(not IS_WINDOWS))
|
||||
@pytest.mark.skip # https://github.com/Robpol86/terminaltables/issues/44
|
||||
@pytest.mark.skip # https://github.com/Robpol86/terminaltables3/issues/44
|
||||
def test_windows_screenshot(tmpdir):
|
||||
"""Test on Windows in a new console window. Take a screenshot to verify it works.
|
||||
|
||||
:param tmpdir: pytest fixture.
|
||||
"""
|
||||
script = tmpdir.join('script.py')
|
||||
script = tmpdir.join("script.py")
|
||||
command = [sys.executable, str(script)]
|
||||
screenshot = PROJECT_ROOT.join('test_single_table.png')
|
||||
screenshot = PROJECT_ROOT.join("test_single_table.png")
|
||||
if screenshot.check():
|
||||
screenshot.remove()
|
||||
|
||||
# Generate script.
|
||||
script_template = dedent(u"""\
|
||||
script_template = dedent(
|
||||
"""\
|
||||
from __future__ import print_function
|
||||
import os, time
|
||||
from colorclass import Color, Windows
|
||||
from terminaltables import SingleTable
|
||||
from terminaltables3 import SingleTable
|
||||
Windows.enable(auto_colors=True)
|
||||
stop_after = time.time() + 20
|
||||
|
||||
|
@ -233,12 +208,13 @@ def test_windows_screenshot(tmpdir):
|
|||
print('Waiting for screenshot_until_match()...')
|
||||
while not os.path.exists(r'%s') and time.time() < stop_after:
|
||||
time.sleep(0.5)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
script_contents = script_template % str(screenshot)
|
||||
script.write(script_contents.encode('utf-8'), mode='wb')
|
||||
script.write(script_contents.encode("utf-8"), mode="wb")
|
||||
|
||||
# Setup expected.
|
||||
sub_images = [str(p) for p in HERE.listdir('sub_single_*.bmp')]
|
||||
sub_images = [str(p) for p in HERE.listdir("sub_single_*.bmp")]
|
||||
assert sub_images
|
||||
|
||||
# Run.
|
||||
|
|
|
@ -2,19 +2,22 @@
|
|||
|
||||
import pytest
|
||||
|
||||
from terminaltables.other_tables import AsciiTable
|
||||
from terminaltables3.other_tables import AsciiTable
|
||||
|
||||
SINGLE_LINE = (
|
||||
('Name', 'Color', 'Type'),
|
||||
('Avocado', 'green', 'nut'),
|
||||
('Tomato', 'red', 'fruit'),
|
||||
('Lettuce', 'green', 'vegetable'),
|
||||
("Name", "Color", "Type"),
|
||||
("Avocado", "green", "nut"),
|
||||
("Tomato", "red", "fruit"),
|
||||
("Lettuce", "green", "vegetable"),
|
||||
)
|
||||
|
||||
MULTI_LINE = (
|
||||
('Show', 'Characters'),
|
||||
('Rugrats', 'Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\nDil Pickles'),
|
||||
('South Park', 'Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick'),
|
||||
("Show", "Characters"),
|
||||
(
|
||||
"Rugrats",
|
||||
"Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\nDil Pickles",
|
||||
),
|
||||
("South Park", "Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick"),
|
||||
)
|
||||
|
||||
|
||||
|
@ -24,20 +27,25 @@ def patch(monkeypatch):
|
|||
|
||||
:param monkeypatch: pytest fixture.
|
||||
"""
|
||||
monkeypatch.setattr('terminaltables.ascii_table.terminal_size', lambda: (79, 24))
|
||||
monkeypatch.setattr('terminaltables.width_and_alignment.terminal_size', lambda: (79, 24))
|
||||
monkeypatch.setattr("terminaltables3.ascii_table.terminal_size", lambda: (79, 24))
|
||||
monkeypatch.setattr(
|
||||
"terminaltables3.width_and_alignment.terminal_size", lambda: (79, 24)
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('table_data,column_number,expected', [
|
||||
([], 0, IndexError),
|
||||
([[]], 0, IndexError),
|
||||
([['']], 1, IndexError),
|
||||
(SINGLE_LINE, 0, 55),
|
||||
(SINGLE_LINE, 1, 53),
|
||||
(SINGLE_LINE, 2, 57),
|
||||
(MULTI_LINE, 0, -11),
|
||||
(MULTI_LINE, 1, 62),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"table_data,column_number,expected",
|
||||
[
|
||||
([], 0, IndexError),
|
||||
([[]], 0, IndexError),
|
||||
([[""]], 1, IndexError),
|
||||
(SINGLE_LINE, 0, 55),
|
||||
(SINGLE_LINE, 1, 53),
|
||||
(SINGLE_LINE, 2, 57),
|
||||
(MULTI_LINE, 0, -11),
|
||||
(MULTI_LINE, 1, 62),
|
||||
],
|
||||
)
|
||||
def test_column_max_width(table_data, column_number, expected):
|
||||
"""Test method in class.
|
||||
|
||||
|
@ -47,7 +55,7 @@ def test_column_max_width(table_data, column_number, expected):
|
|||
"""
|
||||
table = AsciiTable(table_data)
|
||||
|
||||
if expected == IndexError:
|
||||
if expected is IndexError:
|
||||
with pytest.raises(IndexError):
|
||||
table.column_max_width(column_number)
|
||||
return
|
||||
|
@ -58,22 +66,25 @@ def test_column_max_width(table_data, column_number, expected):
|
|||
|
||||
def test_column_widths():
|
||||
"""Test method in class."""
|
||||
assert AsciiTable([]).column_widths == list()
|
||||
assert AsciiTable([]).column_widths == []
|
||||
|
||||
table = AsciiTable(SINGLE_LINE)
|
||||
actual = table.column_widths
|
||||
assert actual == [7, 5, 9]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('table_data,terminal_width,expected', [
|
||||
([], None, True),
|
||||
([[]], None, True),
|
||||
([['']], None, True),
|
||||
(SINGLE_LINE, None, True),
|
||||
(SINGLE_LINE, 30, False),
|
||||
(MULTI_LINE, None, False),
|
||||
(MULTI_LINE, 100, True),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"table_data,terminal_width,expected",
|
||||
[
|
||||
([], None, True),
|
||||
([[]], None, True),
|
||||
([[""]], None, True),
|
||||
(SINGLE_LINE, None, True),
|
||||
(SINGLE_LINE, 30, False),
|
||||
(MULTI_LINE, None, False),
|
||||
(MULTI_LINE, 100, True),
|
||||
],
|
||||
)
|
||||
def test_ok(monkeypatch, table_data, terminal_width, expected):
|
||||
"""Test method in class.
|
||||
|
||||
|
@ -83,20 +94,25 @@ def test_ok(monkeypatch, table_data, terminal_width, expected):
|
|||
:param bool expected: Expected return value.
|
||||
"""
|
||||
if terminal_width is not None:
|
||||
monkeypatch.setattr('terminaltables.ascii_table.terminal_size', lambda: (terminal_width, 24))
|
||||
monkeypatch.setattr(
|
||||
"terminaltables3.ascii_table.terminal_size", lambda: (terminal_width, 24)
|
||||
)
|
||||
table = AsciiTable(table_data)
|
||||
actual = table.ok
|
||||
assert actual is expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('table_data,expected', [
|
||||
([], 2),
|
||||
([[]], 2),
|
||||
([['']], 4),
|
||||
([[' ']], 5),
|
||||
(SINGLE_LINE, 31),
|
||||
(MULTI_LINE, 100),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"table_data,expected",
|
||||
[
|
||||
([], 2),
|
||||
([[]], 2),
|
||||
([[""]], 4),
|
||||
([[" "]], 5),
|
||||
(SINGLE_LINE, 31),
|
||||
(MULTI_LINE, 100),
|
||||
],
|
||||
)
|
||||
def test_table_width(table_data, expected):
|
||||
"""Test method in class.
|
||||
|
||||
|
|
0
tests/test_base_table/__init__.py
Normal file
0
tests/test_base_table/__init__.py
Normal file
|
@ -2,47 +2,47 @@
|
|||
|
||||
import pytest
|
||||
|
||||
from terminaltables.base_table import BaseTable
|
||||
from terminaltables3.base_table import BaseTable
|
||||
|
||||
|
||||
@pytest.mark.parametrize('style', ['heading', 'footing', 'row'])
|
||||
@pytest.mark.parametrize("style", ["heading", "footing", "row"])
|
||||
def test_single_line(style):
|
||||
"""Test with single-line row.
|
||||
|
||||
:param str style: Passed to method.
|
||||
"""
|
||||
row = ['Row One Column One', 'Two', 'Three']
|
||||
row = ["Row One Column One", "Two", "Three"]
|
||||
table = BaseTable([row])
|
||||
actual = [tuple(i) for i in table.gen_row_lines(row, style, [18, 3, 5], 1)]
|
||||
expected = [
|
||||
('|', ' Row One Column One ', '|', ' Two ', '|', ' Three ', '|'),
|
||||
("|", " Row One Column One ", "|", " Two ", "|", " Three ", "|"),
|
||||
]
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('style', ['heading', 'footing', 'row'])
|
||||
@pytest.mark.parametrize("style", ["heading", "footing", "row"])
|
||||
def test_multi_line(style):
|
||||
"""Test with multi-line row.
|
||||
|
||||
:param str style: Passed to method.
|
||||
"""
|
||||
row = ['Row One\nColumn One', 'Two', 'Three']
|
||||
row = ["Row One\nColumn One", "Two", "Three"]
|
||||
table = BaseTable([row])
|
||||
actual = [tuple(i) for i in table.gen_row_lines(row, style, [10, 3, 5], 2)]
|
||||
expected = [
|
||||
('|', ' Row One ', '|', ' Two ', '|', ' Three ', '|'),
|
||||
('|', ' Column One ', '|', ' ', '|', ' ', '|'),
|
||||
("|", " Row One ", "|", " Two ", "|", " Three ", "|"),
|
||||
("|", " Column One ", "|", " ", "|", " ", "|"),
|
||||
]
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('style', ['heading', 'footing', 'row'])
|
||||
@pytest.mark.parametrize("style", ["heading", "footing", "row"])
|
||||
def test_no_padding_no_borders(style):
|
||||
"""Test without padding or borders.
|
||||
|
||||
:param str style: Passed to method.
|
||||
"""
|
||||
row = ['Row One\nColumn One', 'Two', 'Three']
|
||||
row = ["Row One\nColumn One", "Two", "Three"]
|
||||
table = BaseTable([row])
|
||||
table.inner_column_border = False
|
||||
table.outer_border = False
|
||||
|
@ -50,28 +50,28 @@ def test_no_padding_no_borders(style):
|
|||
table.padding_right = 0
|
||||
actual = [tuple(i) for i in table.gen_row_lines(row, style, [10, 3, 5], 2)]
|
||||
expected = [
|
||||
('Row One ', 'Two', 'Three'),
|
||||
('Column One', ' ', ' '),
|
||||
("Row One ", "Two", "Three"),
|
||||
("Column One", " ", " "),
|
||||
]
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('style', ['heading', 'footing', 'row'])
|
||||
@pytest.mark.parametrize("style", ["heading", "footing", "row"])
|
||||
def test_uneven(style):
|
||||
"""Test with row missing cells.
|
||||
|
||||
:param str style: Passed to method.
|
||||
"""
|
||||
row = ['Row One Column One']
|
||||
row = ["Row One Column One"]
|
||||
table = BaseTable([row])
|
||||
actual = [tuple(i) for i in table.gen_row_lines(row, style, [18, 3, 5], 1)]
|
||||
expected = [
|
||||
('|', ' Row One Column One ', '|', ' ', '|', ' ', '|'),
|
||||
("|", " Row One Column One ", "|", " ", "|", " ", "|"),
|
||||
]
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('style', ['heading', 'footing', 'row'])
|
||||
@pytest.mark.parametrize("style", ["heading", "footing", "row"])
|
||||
def test_empty_table(style):
|
||||
"""Test empty table.
|
||||
|
||||
|
@ -81,6 +81,6 @@ def test_empty_table(style):
|
|||
table = BaseTable([row])
|
||||
actual = [tuple(i) for i in table.gen_row_lines(row, style, [], 0)]
|
||||
expected = [
|
||||
('|', '|'),
|
||||
("|", "|"),
|
||||
]
|
||||
assert actual == expected
|
||||
|
|
|
@ -2,15 +2,17 @@
|
|||
|
||||
import pytest
|
||||
|
||||
from terminaltables.base_table import BaseTable
|
||||
from terminaltables.build import flatten
|
||||
from terminaltables.width_and_alignment import max_dimensions
|
||||
from terminaltables3.base_table import BaseTable
|
||||
from terminaltables3.build import flatten
|
||||
from terminaltables3.width_and_alignment import max_dimensions
|
||||
|
||||
|
||||
@pytest.mark.parametrize('inner_heading_row_border', [True, False])
|
||||
@pytest.mark.parametrize('inner_footing_row_border', [True, False])
|
||||
@pytest.mark.parametrize('inner_row_border', [True, False])
|
||||
def test_inner_row_borders(inner_heading_row_border, inner_footing_row_border, inner_row_border):
|
||||
@pytest.mark.parametrize("inner_heading_row_border", [True, False])
|
||||
@pytest.mark.parametrize("inner_footing_row_border", [True, False])
|
||||
@pytest.mark.parametrize("inner_row_border", [True, False])
|
||||
def test_inner_row_borders(
|
||||
inner_heading_row_border, inner_footing_row_border, inner_row_border
|
||||
):
|
||||
"""Test heading/footing/row borders.
|
||||
|
||||
:param bool inner_heading_row_border: Passed to table.
|
||||
|
@ -18,142 +20,145 @@ def test_inner_row_borders(inner_heading_row_border, inner_footing_row_border, i
|
|||
:param bool inner_row_border: Passed to table.
|
||||
"""
|
||||
table_data = [
|
||||
['Name', 'Color', 'Type'],
|
||||
['Avocado', 'green', 'nut'],
|
||||
['Tomato', 'red', 'fruit'],
|
||||
['Lettuce', 'green', 'vegetable'],
|
||||
["Name", "Color", "Type"],
|
||||
["Avocado", "green", "nut"],
|
||||
["Tomato", "red", "fruit"],
|
||||
["Lettuce", "green", "vegetable"],
|
||||
]
|
||||
table = BaseTable(table_data)
|
||||
table.inner_heading_row_border = inner_heading_row_border
|
||||
table.inner_footing_row_border = inner_footing_row_border
|
||||
table.inner_row_border = inner_row_border
|
||||
inner_widths, inner_heights, outer_widths = max_dimensions(table_data, table.padding_left, table.padding_right)[:3]
|
||||
inner_widths, inner_heights, outer_widths = max_dimensions(
|
||||
table_data, table.padding_left, table.padding_right
|
||||
)[:3]
|
||||
actual = flatten(table.gen_table(inner_widths, inner_heights, outer_widths))
|
||||
|
||||
# Determine expected.
|
||||
if inner_row_border:
|
||||
expected = (
|
||||
'+---------+-------+-----------+\n'
|
||||
'| Name | Color | Type |\n'
|
||||
'+---------+-------+-----------+\n'
|
||||
'| Avocado | green | nut |\n'
|
||||
'+---------+-------+-----------+\n'
|
||||
'| Tomato | red | fruit |\n'
|
||||
'+---------+-------+-----------+\n'
|
||||
'| Lettuce | green | vegetable |\n'
|
||||
'+---------+-------+-----------+'
|
||||
"+---------+-------+-----------+\n"
|
||||
"| Name | Color | Type |\n"
|
||||
"+---------+-------+-----------+\n"
|
||||
"| Avocado | green | nut |\n"
|
||||
"+---------+-------+-----------+\n"
|
||||
"| Tomato | red | fruit |\n"
|
||||
"+---------+-------+-----------+\n"
|
||||
"| Lettuce | green | vegetable |\n"
|
||||
"+---------+-------+-----------+"
|
||||
)
|
||||
elif inner_heading_row_border and inner_footing_row_border:
|
||||
expected = (
|
||||
'+---------+-------+-----------+\n'
|
||||
'| Name | Color | Type |\n'
|
||||
'+---------+-------+-----------+\n'
|
||||
'| Avocado | green | nut |\n'
|
||||
'| Tomato | red | fruit |\n'
|
||||
'+---------+-------+-----------+\n'
|
||||
'| Lettuce | green | vegetable |\n'
|
||||
'+---------+-------+-----------+'
|
||||
"+---------+-------+-----------+\n"
|
||||
"| Name | Color | Type |\n"
|
||||
"+---------+-------+-----------+\n"
|
||||
"| Avocado | green | nut |\n"
|
||||
"| Tomato | red | fruit |\n"
|
||||
"+---------+-------+-----------+\n"
|
||||
"| Lettuce | green | vegetable |\n"
|
||||
"+---------+-------+-----------+"
|
||||
)
|
||||
elif inner_heading_row_border:
|
||||
expected = (
|
||||
'+---------+-------+-----------+\n'
|
||||
'| Name | Color | Type |\n'
|
||||
'+---------+-------+-----------+\n'
|
||||
'| Avocado | green | nut |\n'
|
||||
'| Tomato | red | fruit |\n'
|
||||
'| Lettuce | green | vegetable |\n'
|
||||
'+---------+-------+-----------+'
|
||||
"+---------+-------+-----------+\n"
|
||||
"| Name | Color | Type |\n"
|
||||
"+---------+-------+-----------+\n"
|
||||
"| Avocado | green | nut |\n"
|
||||
"| Tomato | red | fruit |\n"
|
||||
"| Lettuce | green | vegetable |\n"
|
||||
"+---------+-------+-----------+"
|
||||
)
|
||||
elif inner_footing_row_border:
|
||||
expected = (
|
||||
'+---------+-------+-----------+\n'
|
||||
'| Name | Color | Type |\n'
|
||||
'| Avocado | green | nut |\n'
|
||||
'| Tomato | red | fruit |\n'
|
||||
'+---------+-------+-----------+\n'
|
||||
'| Lettuce | green | vegetable |\n'
|
||||
'+---------+-------+-----------+'
|
||||
"+---------+-------+-----------+\n"
|
||||
"| Name | Color | Type |\n"
|
||||
"| Avocado | green | nut |\n"
|
||||
"| Tomato | red | fruit |\n"
|
||||
"+---------+-------+-----------+\n"
|
||||
"| Lettuce | green | vegetable |\n"
|
||||
"+---------+-------+-----------+"
|
||||
)
|
||||
else:
|
||||
expected = (
|
||||
'+---------+-------+-----------+\n'
|
||||
'| Name | Color | Type |\n'
|
||||
'| Avocado | green | nut |\n'
|
||||
'| Tomato | red | fruit |\n'
|
||||
'| Lettuce | green | vegetable |\n'
|
||||
'+---------+-------+-----------+'
|
||||
"+---------+-------+-----------+\n"
|
||||
"| Name | Color | Type |\n"
|
||||
"| Avocado | green | nut |\n"
|
||||
"| Tomato | red | fruit |\n"
|
||||
"| Lettuce | green | vegetable |\n"
|
||||
"+---------+-------+-----------+"
|
||||
)
|
||||
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('outer_border', [True, False])
|
||||
@pytest.mark.parametrize("outer_border", [True, False])
|
||||
def test_outer_borders(outer_border):
|
||||
"""Test left/right/top/bottom table borders.
|
||||
|
||||
:param bool outer_border: Passed to table.
|
||||
"""
|
||||
table_data = [
|
||||
['Name', 'Color', 'Type'],
|
||||
['Avocado', 'green', 'nut'],
|
||||
['Tomato', 'red', 'fruit'],
|
||||
['Lettuce', 'green', 'vegetable'],
|
||||
["Name", "Color", "Type"],
|
||||
["Avocado", "green", "nut"],
|
||||
["Tomato", "red", "fruit"],
|
||||
["Lettuce", "green", "vegetable"],
|
||||
]
|
||||
table = BaseTable(table_data, 'Example Table')
|
||||
table = BaseTable(table_data, "Example Table")
|
||||
table.outer_border = outer_border
|
||||
inner_widths, inner_heights, outer_widths = max_dimensions(table_data, table.padding_left, table.padding_right)[:3]
|
||||
inner_widths, inner_heights, outer_widths = max_dimensions(
|
||||
table_data, table.padding_left, table.padding_right
|
||||
)[:3]
|
||||
actual = flatten(table.gen_table(inner_widths, inner_heights, outer_widths))
|
||||
|
||||
# Determine expected.
|
||||
if outer_border:
|
||||
expected = (
|
||||
'+Example Table----+-----------+\n'
|
||||
'| Name | Color | Type |\n'
|
||||
'+---------+-------+-----------+\n'
|
||||
'| Avocado | green | nut |\n'
|
||||
'| Tomato | red | fruit |\n'
|
||||
'| Lettuce | green | vegetable |\n'
|
||||
'+---------+-------+-----------+'
|
||||
"+Example Table----+-----------+\n"
|
||||
"| Name | Color | Type |\n"
|
||||
"+---------+-------+-----------+\n"
|
||||
"| Avocado | green | nut |\n"
|
||||
"| Tomato | red | fruit |\n"
|
||||
"| Lettuce | green | vegetable |\n"
|
||||
"+---------+-------+-----------+"
|
||||
)
|
||||
else:
|
||||
expected = (
|
||||
' Name | Color | Type \n'
|
||||
'---------+-------+-----------\n'
|
||||
' Avocado | green | nut \n'
|
||||
' Tomato | red | fruit \n'
|
||||
' Lettuce | green | vegetable '
|
||||
" Name | Color | Type \n"
|
||||
"---------+-------+-----------\n"
|
||||
" Avocado | green | nut \n"
|
||||
" Tomato | red | fruit \n"
|
||||
" Lettuce | green | vegetable "
|
||||
)
|
||||
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('mode', ['row', 'one', 'blank', 'empty', 'none'])
|
||||
@pytest.mark.parametrize('bare', [False, True])
|
||||
@pytest.mark.parametrize("mode", ["row", "one", "blank", "empty", "none"])
|
||||
@pytest.mark.parametrize("bare", [False, True])
|
||||
def test_one_no_rows(mode, bare):
|
||||
"""Test with one or no rows.
|
||||
|
||||
:param str mode: Type of table contents to test.
|
||||
:param bool bare: Disable padding/borders.
|
||||
"""
|
||||
if mode == 'row':
|
||||
if mode == "row":
|
||||
table_data = [
|
||||
['Avocado', 'green', 'nut'],
|
||||
["Avocado", "green", "nut"],
|
||||
]
|
||||
elif mode == 'one':
|
||||
elif mode == "one":
|
||||
table_data = [
|
||||
['Avocado'],
|
||||
["Avocado"],
|
||||
]
|
||||
elif mode == 'blank':
|
||||
elif mode == "blank":
|
||||
table_data = [
|
||||
[''],
|
||||
[""],
|
||||
]
|
||||
elif mode == 'empty':
|
||||
elif mode == "empty":
|
||||
table_data = [
|
||||
[],
|
||||
]
|
||||
else:
|
||||
table_data = [
|
||||
]
|
||||
table_data = []
|
||||
table = BaseTable(table_data)
|
||||
if bare:
|
||||
table.inner_column_border = False
|
||||
|
@ -163,63 +168,40 @@ def test_one_no_rows(mode, bare):
|
|||
table.outer_border = False
|
||||
table.padding_left = 0
|
||||
table.padding_right = 0
|
||||
inner_widths, inner_heights, outer_widths = max_dimensions(table_data, table.padding_left, table.padding_right)[:3]
|
||||
inner_widths, inner_heights, outer_widths = max_dimensions(
|
||||
table_data, table.padding_left, table.padding_right
|
||||
)[:3]
|
||||
actual = flatten(table.gen_table(inner_widths, inner_heights, outer_widths))
|
||||
|
||||
# Determine expected.
|
||||
if mode == 'row':
|
||||
if mode == "row":
|
||||
if bare:
|
||||
expected = (
|
||||
'Avocadogreennut'
|
||||
)
|
||||
expected = "Avocadogreennut"
|
||||
else:
|
||||
expected = (
|
||||
'+---------+-------+-----+\n'
|
||||
'| Avocado | green | nut |\n'
|
||||
'+---------+-------+-----+'
|
||||
"+---------+-------+-----+\n"
|
||||
"| Avocado | green | nut |\n"
|
||||
"+---------+-------+-----+"
|
||||
)
|
||||
elif mode == 'one':
|
||||
elif mode == "one":
|
||||
if bare:
|
||||
expected = (
|
||||
'Avocado'
|
||||
)
|
||||
expected = "Avocado"
|
||||
else:
|
||||
expected = (
|
||||
'+---------+\n'
|
||||
'| Avocado |\n'
|
||||
'+---------+'
|
||||
)
|
||||
elif mode == 'blank': # Remember there's still padding.
|
||||
expected = "+---------+\n" "| Avocado |\n" "+---------+"
|
||||
elif mode == "blank": # Remember there's still padding.
|
||||
if bare:
|
||||
expected = (
|
||||
''
|
||||
)
|
||||
expected = ""
|
||||
else:
|
||||
expected = (
|
||||
'+--+\n'
|
||||
'| |\n'
|
||||
'+--+'
|
||||
)
|
||||
elif mode == 'empty':
|
||||
expected = "+--+\n" "| |\n" "+--+"
|
||||
elif mode == "empty":
|
||||
if bare:
|
||||
expected = (
|
||||
''
|
||||
)
|
||||
expected = ""
|
||||
else:
|
||||
expected = (
|
||||
'++\n'
|
||||
'||\n'
|
||||
'++'
|
||||
)
|
||||
expected = "++\n" "||\n" "++"
|
||||
else:
|
||||
if bare:
|
||||
expected = (
|
||||
''
|
||||
)
|
||||
expected = ""
|
||||
else:
|
||||
expected = (
|
||||
'++\n'
|
||||
'++'
|
||||
)
|
||||
expected = "++\n" "++"
|
||||
|
||||
assert actual == expected
|
||||
|
|
|
@ -2,47 +2,49 @@
|
|||
|
||||
import pytest
|
||||
|
||||
from terminaltables.base_table import BaseTable
|
||||
from terminaltables.width_and_alignment import max_dimensions
|
||||
from terminaltables3.base_table import BaseTable
|
||||
from terminaltables3.width_and_alignment import max_dimensions
|
||||
|
||||
SINGLE_LINE = (
|
||||
('Name', 'Color', 'Type'),
|
||||
('Avocado', 'green', 'nut'),
|
||||
('Tomato', 'red', 'fruit'),
|
||||
('Lettuce', 'green', 'vegetable'),
|
||||
("Name", "Color", "Type"),
|
||||
("Avocado", "green", "nut"),
|
||||
("Tomato", "red", "fruit"),
|
||||
("Lettuce", "green", "vegetable"),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('inner_column_border', [True, False])
|
||||
@pytest.mark.parametrize('style', ['top', 'bottom'])
|
||||
@pytest.mark.parametrize("inner_column_border", [True, False])
|
||||
@pytest.mark.parametrize("style", ["top", "bottom"])
|
||||
def test_top_bottom(inner_column_border, style):
|
||||
"""Test top and bottom borders.
|
||||
|
||||
:param bool inner_column_border: Passed to table class.
|
||||
:param str style: Passed to method.
|
||||
"""
|
||||
table = BaseTable(SINGLE_LINE, 'Example')
|
||||
table = BaseTable(SINGLE_LINE, "Example")
|
||||
table.inner_column_border = inner_column_border
|
||||
outer_widths = max_dimensions(table.table_data, table.padding_left, table.padding_right)[2]
|
||||
outer_widths = max_dimensions(
|
||||
table.table_data, table.padding_left, table.padding_right
|
||||
)[2]
|
||||
|
||||
# Determine expected.
|
||||
if style == 'top' and inner_column_border:
|
||||
expected = '+Example--+-------+-----------+'
|
||||
elif style == 'top':
|
||||
expected = '+Example--------------------+'
|
||||
elif style == 'bottom' and inner_column_border:
|
||||
expected = '+---------+-------+-----------+'
|
||||
if style == "top" and inner_column_border:
|
||||
expected = "+Example--+-------+-----------+"
|
||||
elif style == "top":
|
||||
expected = "+Example--------------------+"
|
||||
elif style == "bottom" and inner_column_border:
|
||||
expected = "+---------+-------+-----------+"
|
||||
else:
|
||||
expected = '+---------------------------+'
|
||||
expected = "+---------------------------+"
|
||||
|
||||
# Test.
|
||||
actual = ''.join(table.horizontal_border(style, outer_widths))
|
||||
actual = "".join(table.horizontal_border(style, outer_widths))
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('inner_column_border', [True, False])
|
||||
@pytest.mark.parametrize('outer_border', [True, False])
|
||||
@pytest.mark.parametrize('style', ['heading', 'footing'])
|
||||
@pytest.mark.parametrize("inner_column_border", [True, False])
|
||||
@pytest.mark.parametrize("outer_border", [True, False])
|
||||
@pytest.mark.parametrize("style", ["heading", "footing"])
|
||||
def test_heading_footing(inner_column_border, outer_border, style):
|
||||
"""Test heading and footing borders.
|
||||
|
||||
|
@ -53,25 +55,43 @@ def test_heading_footing(inner_column_border, outer_border, style):
|
|||
table = BaseTable(SINGLE_LINE)
|
||||
table.inner_column_border = inner_column_border
|
||||
table.outer_border = outer_border
|
||||
outer_widths = max_dimensions(table.table_data, table.padding_left, table.padding_right)[2]
|
||||
outer_widths = max_dimensions(
|
||||
table.table_data, table.padding_left, table.padding_right
|
||||
)[2]
|
||||
|
||||
# Determine expected.
|
||||
if style == 'heading' and outer_border:
|
||||
expected = '+---------+-------+-----------+' if inner_column_border else '+---------------------------+'
|
||||
elif style == 'heading':
|
||||
expected = '---------+-------+-----------' if inner_column_border else '---------------------------'
|
||||
elif style == 'footing' and outer_border:
|
||||
expected = '+---------+-------+-----------+' if inner_column_border else '+---------------------------+'
|
||||
if style == "heading" and outer_border:
|
||||
expected = (
|
||||
"+---------+-------+-----------+"
|
||||
if inner_column_border
|
||||
else "+---------------------------+"
|
||||
)
|
||||
elif style == "heading":
|
||||
expected = (
|
||||
"---------+-------+-----------"
|
||||
if inner_column_border
|
||||
else "---------------------------"
|
||||
)
|
||||
elif style == "footing" and outer_border:
|
||||
expected = (
|
||||
"+---------+-------+-----------+"
|
||||
if inner_column_border
|
||||
else "+---------------------------+"
|
||||
)
|
||||
else:
|
||||
expected = '---------+-------+-----------' if inner_column_border else '---------------------------'
|
||||
expected = (
|
||||
"---------+-------+-----------"
|
||||
if inner_column_border
|
||||
else "---------------------------"
|
||||
)
|
||||
|
||||
# Test.
|
||||
actual = ''.join(table.horizontal_border(style, outer_widths))
|
||||
actual = "".join(table.horizontal_border(style, outer_widths))
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('inner_column_border', [True, False])
|
||||
@pytest.mark.parametrize('outer_border', [True, False])
|
||||
@pytest.mark.parametrize("inner_column_border", [True, False])
|
||||
@pytest.mark.parametrize("outer_border", [True, False])
|
||||
def test_row(inner_column_border, outer_border):
|
||||
"""Test inner borders.
|
||||
|
||||
|
@ -81,18 +101,20 @@ def test_row(inner_column_border, outer_border):
|
|||
table = BaseTable(SINGLE_LINE)
|
||||
table.inner_column_border = inner_column_border
|
||||
table.outer_border = outer_border
|
||||
outer_widths = max_dimensions(table.table_data, table.padding_left, table.padding_right)[2]
|
||||
outer_widths = max_dimensions(
|
||||
table.table_data, table.padding_left, table.padding_right
|
||||
)[2]
|
||||
|
||||
# Determine expected.
|
||||
if inner_column_border and outer_border:
|
||||
expected = '+---------+-------+-----------+'
|
||||
expected = "+---------+-------+-----------+"
|
||||
elif inner_column_border:
|
||||
expected = '---------+-------+-----------'
|
||||
expected = "---------+-------+-----------"
|
||||
elif outer_border:
|
||||
expected = '+---------------------------+'
|
||||
expected = "+---------------------------+"
|
||||
else:
|
||||
expected = '---------------------------'
|
||||
expected = "---------------------------"
|
||||
|
||||
# Test.
|
||||
actual = ''.join(table.horizontal_border('row', outer_widths))
|
||||
actual = "".join(table.horizontal_border("row", outer_widths))
|
||||
assert actual == expected
|
||||
|
|
|
@ -1,32 +1,31 @@
|
|||
# coding: utf-8
|
||||
"""Test property in BaseTable class."""
|
||||
|
||||
from colorama import Fore
|
||||
from colorclass import Color
|
||||
from termcolor import colored
|
||||
|
||||
from terminaltables.base_table import BaseTable
|
||||
from terminaltables3.base_table import BaseTable
|
||||
|
||||
|
||||
def test_ascii():
|
||||
"""Test with ASCII characters."""
|
||||
table_data = [
|
||||
['Name', 'Color', 'Type'],
|
||||
['Avocado', 'green', 'nut'],
|
||||
['Tomato', 'red', 'fruit'],
|
||||
['Lettuce', 'green', 'vegetable'],
|
||||
["Name", "Color", "Type"],
|
||||
["Avocado", "green", "nut"],
|
||||
["Tomato", "red", "fruit"],
|
||||
["Lettuce", "green", "vegetable"],
|
||||
]
|
||||
table = BaseTable(table_data)
|
||||
actual = table.table
|
||||
|
||||
expected = (
|
||||
'+---------+-------+-----------+\n'
|
||||
'| Name | Color | Type |\n'
|
||||
'+---------+-------+-----------+\n'
|
||||
'| Avocado | green | nut |\n'
|
||||
'| Tomato | red | fruit |\n'
|
||||
'| Lettuce | green | vegetable |\n'
|
||||
'+---------+-------+-----------+'
|
||||
"+---------+-------+-----------+\n"
|
||||
"| Name | Color | Type |\n"
|
||||
"+---------+-------+-----------+\n"
|
||||
"| Avocado | green | nut |\n"
|
||||
"| Tomato | red | fruit |\n"
|
||||
"| Lettuce | green | vegetable |\n"
|
||||
"+---------+-------+-----------+"
|
||||
)
|
||||
|
||||
assert actual == expected
|
||||
|
@ -44,13 +43,13 @@ def test_int():
|
|||
actual = table.table
|
||||
|
||||
expected = (
|
||||
'+1234567890+---+\n'
|
||||
'| 100 | 10 | 1 |\n'
|
||||
'+-----+----+---+\n'
|
||||
'| 0 | 3 | 6 |\n'
|
||||
'| 1 | 4 | 7 |\n'
|
||||
'| 2 | 5 | 8 |\n'
|
||||
'+-----+----+---+'
|
||||
"+1234567890+---+\n"
|
||||
"| 100 | 10 | 1 |\n"
|
||||
"+-----+----+---+\n"
|
||||
"| 0 | 3 | 6 |\n"
|
||||
"| 1 | 4 | 7 |\n"
|
||||
"| 2 | 5 | 8 |\n"
|
||||
"+-----+----+---+"
|
||||
)
|
||||
|
||||
assert actual == expected
|
||||
|
@ -68,13 +67,13 @@ def test_float():
|
|||
actual = table.table
|
||||
|
||||
expected = (
|
||||
'+0.12345678--+-------+\n'
|
||||
'| 1.0 | 22.0 | 333.0 |\n'
|
||||
'+-----+------+-------+\n'
|
||||
'| 0.1 | 3.1 | 6.1 |\n'
|
||||
'| 1.1 | 4.1 | 7.1 |\n'
|
||||
'| 2.1 | 5.1 | 8.1 |\n'
|
||||
'+-----+------+-------+'
|
||||
"+0.12345678--+-------+\n"
|
||||
"| 1.0 | 22.0 | 333.0 |\n"
|
||||
"+-----+------+-------+\n"
|
||||
"| 0.1 | 3.1 | 6.1 |\n"
|
||||
"| 1.1 | 4.1 | 7.1 |\n"
|
||||
"| 2.1 | 5.1 | 8.1 |\n"
|
||||
"+-----+------+-------+"
|
||||
)
|
||||
|
||||
assert actual == expected
|
||||
|
@ -92,13 +91,13 @@ def test_bool_none():
|
|||
actual = table.table
|
||||
|
||||
expected = (
|
||||
'+True---+-------+-------+\n'
|
||||
'| True | False | None |\n'
|
||||
'+-------+-------+-------+\n'
|
||||
'| True | False | None |\n'
|
||||
'| False | None | True |\n'
|
||||
'| None | True | False |\n'
|
||||
'+-------+-------+-------+'
|
||||
"+True---+-------+-------+\n"
|
||||
"| True | False | None |\n"
|
||||
"+-------+-------+-------+\n"
|
||||
"| True | False | None |\n"
|
||||
"| False | None | True |\n"
|
||||
"| None | True | False |\n"
|
||||
"+-------+-------+-------+"
|
||||
)
|
||||
|
||||
assert actual == expected
|
||||
|
@ -107,20 +106,20 @@ def test_bool_none():
|
|||
def test_cjk():
|
||||
"""Test with CJK characters."""
|
||||
table_data = [
|
||||
['CJK'],
|
||||
['蓝色'],
|
||||
['世界你好'],
|
||||
["CJK"],
|
||||
["蓝色"],
|
||||
["世界你好"],
|
||||
]
|
||||
table = BaseTable(table_data)
|
||||
actual = table.table
|
||||
|
||||
expected = (
|
||||
'+----------+\n'
|
||||
'| CJK |\n'
|
||||
'+----------+\n'
|
||||
'| 蓝色 |\n'
|
||||
'| 世界你好 |\n'
|
||||
'+----------+'
|
||||
"+----------+\n"
|
||||
"| CJK |\n"
|
||||
"+----------+\n"
|
||||
"| 蓝色 |\n"
|
||||
"| 世界你好 |\n"
|
||||
"+----------+"
|
||||
)
|
||||
|
||||
assert actual == expected
|
||||
|
@ -129,20 +128,15 @@ def test_cjk():
|
|||
def test_rtl():
|
||||
"""Test with RTL characters."""
|
||||
table_data = [
|
||||
['RTL'],
|
||||
['שלום'],
|
||||
['معرب'],
|
||||
["RTL"],
|
||||
["שלום"],
|
||||
["معرب"],
|
||||
]
|
||||
table = BaseTable(table_data)
|
||||
actual = table.table
|
||||
|
||||
expected = (
|
||||
'+------+\n'
|
||||
'| RTL |\n'
|
||||
'+------+\n'
|
||||
'| שלום |\n'
|
||||
'| معرب |\n'
|
||||
'+------+'
|
||||
"+------+\n" "| RTL |\n" "+------+\n" "| שלום |\n" "| معرب |\n" "+------+"
|
||||
)
|
||||
|
||||
assert actual == expected
|
||||
|
@ -151,22 +145,22 @@ def test_rtl():
|
|||
def test_rtl_large():
|
||||
"""Test large table of RTL characters."""
|
||||
table_data = [
|
||||
['اكتب', 'اللون', 'اسم'],
|
||||
['البندق', 'أخضر', 'أفوكادو'],
|
||||
['ثمرة', 'أحمر', 'بندورة'],
|
||||
['الخضروات', 'أخضر', 'الخس'],
|
||||
["اكتب", "اللون", "اسم"],
|
||||
["البندق", "أخضر", "أفوكادو"],
|
||||
["ثمرة", "أحمر", "بندورة"],
|
||||
["الخضروات", "أخضر", "الخس"],
|
||||
]
|
||||
table = BaseTable(table_data, 'جوجل المترجم')
|
||||
table = BaseTable(table_data, "جوجل المترجم")
|
||||
actual = table.table
|
||||
|
||||
expected = (
|
||||
'+جوجل المترجم------+---------+\n'
|
||||
'| اكتب | اللون | اسم |\n'
|
||||
'+----------+-------+---------+\n'
|
||||
'| البندق | أخضر | أفوكادو |\n'
|
||||
'| ثمرة | أحمر | بندورة |\n'
|
||||
'| الخضروات | أخضر | الخس |\n'
|
||||
'+----------+-------+---------+'
|
||||
"+جوجل المترجم------+---------+\n"
|
||||
"| اكتب | اللون | اسم |\n"
|
||||
"+----------+-------+---------+\n"
|
||||
"| البندق | أخضر | أفوكادو |\n"
|
||||
"| ثمرة | أحمر | بندورة |\n"
|
||||
"| الخضروات | أخضر | الخس |\n"
|
||||
"+----------+-------+---------+"
|
||||
)
|
||||
|
||||
assert actual == expected
|
||||
|
@ -175,22 +169,42 @@ def test_rtl_large():
|
|||
def test_color():
|
||||
"""Test with color characters."""
|
||||
table_data = [
|
||||
['ansi', '\033[31mRed\033[39m', '\033[32mGreen\033[39m', '\033[34mBlue\033[39m'],
|
||||
['colorclass', Color('{red}Red{/red}'), Color('{green}Green{/green}'), Color('{blue}Blue{/blue}')],
|
||||
['colorama', Fore.RED + 'Red' + Fore.RESET, Fore.GREEN + 'Green' + Fore.RESET, Fore.BLUE + 'Blue' + Fore.RESET],
|
||||
['termcolor', colored('Red', 'red'), colored('Green', 'green'), colored('Blue', 'blue')],
|
||||
[
|
||||
"ansi",
|
||||
"\033[31mRed\033[39m",
|
||||
"\033[32mGreen\033[39m",
|
||||
"\033[34mBlue\033[39m",
|
||||
],
|
||||
[
|
||||
"colorclass",
|
||||
Color("{red}Red{/red}"),
|
||||
Color("{green}Green{/green}"),
|
||||
Color("{blue}Blue{/blue}"),
|
||||
],
|
||||
[
|
||||
"colorama",
|
||||
Fore.RED + "Red" + Fore.RESET,
|
||||
Fore.GREEN + "Green" + Fore.RESET,
|
||||
Fore.BLUE + "Blue" + Fore.RESET,
|
||||
],
|
||||
[
|
||||
"termcolor",
|
||||
colored("Red", "red"),
|
||||
colored("Green", "green"),
|
||||
colored("Blue", "blue"),
|
||||
],
|
||||
]
|
||||
table = BaseTable(table_data)
|
||||
table.inner_heading_row_border = False
|
||||
actual = table.table
|
||||
|
||||
expected = (
|
||||
u'+------------+-----+-------+------+\n'
|
||||
u'| ansi | \033[31mRed\033[39m | \033[32mGreen\033[39m | \033[34mBlue\033[39m |\n'
|
||||
u'| colorclass | \033[31mRed\033[39m | \033[32mGreen\033[39m | \033[34mBlue\033[39m |\n'
|
||||
u'| colorama | \033[31mRed\033[39m | \033[32mGreen\033[39m | \033[34mBlue\033[39m |\n'
|
||||
u'| termcolor | \033[31mRed\033[0m | \033[32mGreen\033[0m | \033[34mBlue\033[0m |\n'
|
||||
u'+------------+-----+-------+------+'
|
||||
"+------------+-----+-------+------+\n"
|
||||
"| ansi | \033[31mRed\033[39m | \033[32mGreen\033[39m | \033[34mBlue\033[39m |\n"
|
||||
"| colorclass | \033[31mRed\033[39m | \033[32mGreen\033[39m | \033[34mBlue\033[39m |\n"
|
||||
"| colorama | \033[31mRed\033[39m | \033[32mGreen\033[39m | \033[34mBlue\033[39m |\n"
|
||||
"| termcolor | \033[31mRed\033[0m | \033[32mGreen\033[0m | \033[34mBlue\033[0m |\n"
|
||||
"+------------+-----+-------+------+"
|
||||
)
|
||||
|
||||
assert actual == expected
|
||||
|
|
0
tests/test_build/__init__.py
Normal file
0
tests/test_build/__init__.py
Normal file
|
@ -1,4 +1,3 @@
|
|||
# coding: utf-8
|
||||
"""Test function in module."""
|
||||
|
||||
import pytest
|
||||
|
@ -6,16 +5,19 @@ from colorama import Fore, Style
|
|||
from colorclass import Color
|
||||
from termcolor import colored
|
||||
|
||||
from terminaltables.build import build_border
|
||||
from terminaltables3.build import build_border
|
||||
|
||||
|
||||
@pytest.mark.parametrize('outer_widths,horizontal,left,intersect,right,expected', [
|
||||
([5, 6, 7], '-', '<', '+', '>', '<-----+------+------->'),
|
||||
([1, 1, 1], '-', '', '', '', '---'),
|
||||
([1, 1, 1], '', '', '', '', ''),
|
||||
([1], '-', '<', '+', '>', '<->'),
|
||||
([], '-', '<', '+', '>', '<>'),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"outer_widths,horizontal,left,intersect,right,expected",
|
||||
[
|
||||
([5, 6, 7], "-", "<", "+", ">", "<-----+------+------->"),
|
||||
([1, 1, 1], "-", "", "", "", "---"),
|
||||
([1, 1, 1], "", "", "", "", ""),
|
||||
([1], "-", "<", "+", ">", "<->"),
|
||||
([], "-", "<", "+", ">", "<>"),
|
||||
],
|
||||
)
|
||||
def test_no_title(outer_widths, horizontal, left, intersect, right, expected):
|
||||
"""Test without title.
|
||||
|
||||
|
@ -27,26 +29,25 @@ def test_no_title(outer_widths, horizontal, left, intersect, right, expected):
|
|||
:param str expected: Expected output.
|
||||
"""
|
||||
actual = build_border(outer_widths, horizontal, left, intersect, right)
|
||||
assert ''.join(actual) == expected
|
||||
assert "".join(actual) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('outer_widths,intersect,expected', [
|
||||
([20], '+', 'Applications--------'),
|
||||
([20], '', 'Applications--------'),
|
||||
|
||||
([15, 5], '+', 'Applications---+-----'),
|
||||
([15, 5], '', 'Applications--------'),
|
||||
|
||||
([12], '+', 'Applications'),
|
||||
([12], '', 'Applications'),
|
||||
|
||||
([12, 1], '+', 'Applications+-'),
|
||||
([12, 1], '', 'Applications-'),
|
||||
|
||||
([12, 0], '+', 'Applications+'),
|
||||
([12, 0], '', 'Applications'),
|
||||
])
|
||||
@pytest.mark.parametrize('left,right', [('', ''), ('<', '>')])
|
||||
@pytest.mark.parametrize(
|
||||
"outer_widths,intersect,expected",
|
||||
[
|
||||
([20], "+", "Applications--------"),
|
||||
([20], "", "Applications--------"),
|
||||
([15, 5], "+", "Applications---+-----"),
|
||||
([15, 5], "", "Applications--------"),
|
||||
([12], "+", "Applications"),
|
||||
([12], "", "Applications"),
|
||||
([12, 1], "+", "Applications+-"),
|
||||
([12, 1], "", "Applications-"),
|
||||
([12, 0], "+", "Applications+"),
|
||||
([12, 0], "", "Applications"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("left,right", [("", ""), ("<", ">")])
|
||||
def test_first_column_fit(outer_widths, left, intersect, right, expected):
|
||||
"""Test with title that fits in the first column.
|
||||
|
||||
|
@ -58,23 +59,28 @@ def test_first_column_fit(outer_widths, left, intersect, right, expected):
|
|||
"""
|
||||
if left and right:
|
||||
expected = left + expected + right
|
||||
actual = build_border(outer_widths, '-', left, intersect, right, title='Applications')
|
||||
assert ''.join(actual) == expected
|
||||
actual = build_border(
|
||||
outer_widths, "-", left, intersect, right, title="Applications"
|
||||
)
|
||||
assert "".join(actual) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('outer_widths,expected', [
|
||||
([20], 'Applications--------'),
|
||||
([10, 10], 'Applications--------'),
|
||||
([5, 5, 5, 5], 'Applications--------'),
|
||||
([3, 2, 3, 2, 3, 2, 3, 2], 'Applications--------'),
|
||||
([1] * 20, 'Applications--------'),
|
||||
([10, 5], 'Applications---'),
|
||||
([9, 5], 'Applications--'),
|
||||
([8, 5], 'Applications-'),
|
||||
([7, 5], 'Applications'),
|
||||
([6, 5], '-----------'),
|
||||
])
|
||||
@pytest.mark.parametrize('left,right', [('', ''), ('<', '>')])
|
||||
@pytest.mark.parametrize(
|
||||
"outer_widths,expected",
|
||||
[
|
||||
([20], "Applications--------"),
|
||||
([10, 10], "Applications--------"),
|
||||
([5, 5, 5, 5], "Applications--------"),
|
||||
([3, 2, 3, 2, 3, 2, 3, 2], "Applications--------"),
|
||||
([1] * 20, "Applications--------"),
|
||||
([10, 5], "Applications---"),
|
||||
([9, 5], "Applications--"),
|
||||
([8, 5], "Applications-"),
|
||||
([7, 5], "Applications"),
|
||||
([6, 5], "-----------"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("left,right", [("", ""), ("<", ">")])
|
||||
def test_no_intersect(outer_widths, left, right, expected):
|
||||
"""Test with no column dividers.
|
||||
|
||||
|
@ -85,37 +91,39 @@ def test_no_intersect(outer_widths, left, right, expected):
|
|||
"""
|
||||
if left and right:
|
||||
expected = left + expected + right
|
||||
actual = build_border(outer_widths, '-', left, '', right, title='Applications')
|
||||
assert ''.join(actual) == expected
|
||||
actual = build_border(outer_widths, "-", left, "", right, title="Applications")
|
||||
assert "".join(actual) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('outer_widths,expected', [
|
||||
([20], 'Applications--------'),
|
||||
([0, 20], 'Applications---------'),
|
||||
([20, 0], 'Applications--------+'),
|
||||
([0, 0, 20], 'Applications----------'),
|
||||
([20, 0, 0], 'Applications--------++'),
|
||||
|
||||
([10, 10], 'Applications---------'),
|
||||
([11, 9], 'Applications---------'),
|
||||
([12, 8], 'Applications+--------'),
|
||||
([13, 7], 'Applications-+-------'),
|
||||
|
||||
([5, 5, 5, 5], 'Applications-----+-----'),
|
||||
([4, 4, 6, 6], 'Applications----+------'),
|
||||
([3, 3, 7, 7], 'Applications---+-------'),
|
||||
([2, 2, 7, 9], 'Applications-+---------'),
|
||||
([1, 1, 9, 9], 'Applications-+---------'),
|
||||
|
||||
([2, 2, 2, 2, 2, 2, 2], 'Applications--+--+--'),
|
||||
([1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 'Applications-+-+-+-'),
|
||||
([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'Applications++++++++'),
|
||||
|
||||
([2, 2, 2, 2], '--+--+--+--'),
|
||||
([1, 1, 1, 1, 1], '-+-+-+-+-'),
|
||||
([0, 0, 0, 0, 0, 0, 0, 0, 0, 0], '+++++++++'),
|
||||
])
|
||||
@pytest.mark.parametrize('left,right', [('', ''), ('<', '>')])
|
||||
@pytest.mark.parametrize(
|
||||
"outer_widths,expected",
|
||||
[
|
||||
([20], "Applications--------"),
|
||||
([0, 20], "Applications---------"),
|
||||
([20, 0], "Applications--------+"),
|
||||
([0, 0, 20], "Applications----------"),
|
||||
([20, 0, 0], "Applications--------++"),
|
||||
([10, 10], "Applications---------"),
|
||||
([11, 9], "Applications---------"),
|
||||
([12, 8], "Applications+--------"),
|
||||
([13, 7], "Applications-+-------"),
|
||||
([5, 5, 5, 5], "Applications-----+-----"),
|
||||
([4, 4, 6, 6], "Applications----+------"),
|
||||
([3, 3, 7, 7], "Applications---+-------"),
|
||||
([2, 2, 7, 9], "Applications-+---------"),
|
||||
([1, 1, 9, 9], "Applications-+---------"),
|
||||
([2, 2, 2, 2, 2, 2, 2], "Applications--+--+--"),
|
||||
([1, 1, 1, 1, 1, 1, 1, 1, 1, 1], "Applications-+-+-+-"),
|
||||
(
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
"Applications++++++++",
|
||||
),
|
||||
([2, 2, 2, 2], "--+--+--+--"),
|
||||
([1, 1, 1, 1, 1], "-+-+-+-+-"),
|
||||
([0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "+++++++++"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("left,right", [("", ""), ("<", ">")])
|
||||
def test_intersect(outer_widths, left, right, expected):
|
||||
"""Test with column dividers.
|
||||
|
||||
|
@ -126,48 +134,51 @@ def test_intersect(outer_widths, left, right, expected):
|
|||
"""
|
||||
if left and right:
|
||||
expected = left + expected + right
|
||||
actual = build_border(outer_widths, '-', left, '+', right, title='Applications')
|
||||
assert ''.join(actual) == expected
|
||||
actual = build_border(outer_widths, "-", left, "+", right, title="Applications")
|
||||
assert "".join(actual) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('outer_widths,intersect,expected', [
|
||||
([12], '+', u'蓝色--------'),
|
||||
([12], '', u'蓝色--------'),
|
||||
([7, 5], '+', u'蓝色---+-----'),
|
||||
([7, 5], '', u'蓝色--------'),
|
||||
([4], '+', u'蓝色'),
|
||||
([4], '', u'蓝色'),
|
||||
([4, 1], '+', u'蓝色+-'),
|
||||
([4, 1], '', u'蓝色-'),
|
||||
([4, 0], '+', u'蓝色+'),
|
||||
([4, 0], '', u'蓝色'),
|
||||
([12], '', u'蓝色--------'),
|
||||
([6, 6], '', u'蓝色--------'),
|
||||
([3, 3, 3, 3], '', u'蓝色--------'),
|
||||
([2, 1, 2, 1, 2, 1, 2, 1], '', u'蓝色--------'),
|
||||
([1] * 12, '', u'蓝色--------'),
|
||||
([2, 4], '', u'蓝色--'),
|
||||
([1, 4], '', u'蓝色-'),
|
||||
([1, 3], '', u'蓝色'),
|
||||
([1, 2], '', u'---'),
|
||||
([2], '', u'--'),
|
||||
([12], '+', u'蓝色--------'),
|
||||
([0, 12], '+', u'蓝色---------'),
|
||||
([12, 0], '+', u'蓝色--------+'),
|
||||
([0, 0, 12], '+', u'蓝色----------'),
|
||||
([12, 0, 0], '+', u'蓝色--------++'),
|
||||
([3, 3], '+', u'蓝色---'),
|
||||
([4, 2], '+', u'蓝色+--'),
|
||||
([5, 1], '+', u'蓝色-+-'),
|
||||
([3, 3, 3, 3], '+', u'蓝色---+---+---'),
|
||||
([2, 2, 4, 4], '+', u'蓝色-+----+----'),
|
||||
([1, 1, 5, 5], '+', u'蓝色-----+-----'),
|
||||
([2, 2, 2, 2], '+', u'蓝色-+--+--'),
|
||||
([1, 1, 1, 1, 1], '+', u'蓝色-+-+-'),
|
||||
([0, 0, 0, 0, 0, 0, 0], '+', u'蓝色++'),
|
||||
([1, 1], '+', u'-+-'),
|
||||
])
|
||||
@pytest.mark.parametrize('left,right', [('', ''), ('<', '>')])
|
||||
@pytest.mark.parametrize(
|
||||
"outer_widths,intersect,expected",
|
||||
[
|
||||
([12], "+", "蓝色--------"),
|
||||
([12], "", "蓝色--------"),
|
||||
([7, 5], "+", "蓝色---+-----"),
|
||||
([7, 5], "", "蓝色--------"),
|
||||
([4], "+", "蓝色"),
|
||||
([4], "", "蓝色"),
|
||||
([4, 1], "+", "蓝色+-"),
|
||||
([4, 1], "", "蓝色-"),
|
||||
([4, 0], "+", "蓝色+"),
|
||||
([4, 0], "", "蓝色"),
|
||||
([12], "", "蓝色--------"),
|
||||
([6, 6], "", "蓝色--------"),
|
||||
([3, 3, 3, 3], "", "蓝色--------"),
|
||||
([2, 1, 2, 1, 2, 1, 2, 1], "", "蓝色--------"),
|
||||
([1] * 12, "", "蓝色--------"),
|
||||
([2, 4], "", "蓝色--"),
|
||||
([1, 4], "", "蓝色-"),
|
||||
([1, 3], "", "蓝色"),
|
||||
([1, 2], "", "---"),
|
||||
([2], "", "--"),
|
||||
([12], "+", "蓝色--------"),
|
||||
([0, 12], "+", "蓝色---------"),
|
||||
([12, 0], "+", "蓝色--------+"),
|
||||
([0, 0, 12], "+", "蓝色----------"),
|
||||
([12, 0, 0], "+", "蓝色--------++"),
|
||||
([3, 3], "+", "蓝色---"),
|
||||
([4, 2], "+", "蓝色+--"),
|
||||
([5, 1], "+", "蓝色-+-"),
|
||||
([3, 3, 3, 3], "+", "蓝色---+---+---"),
|
||||
([2, 2, 4, 4], "+", "蓝色-+----+----"),
|
||||
([1, 1, 5, 5], "+", "蓝色-----+-----"),
|
||||
([2, 2, 2, 2], "+", "蓝色-+--+--"),
|
||||
([1, 1, 1, 1, 1], "+", "蓝色-+-+-"),
|
||||
([0, 0, 0, 0, 0, 0, 0], "+", "蓝色++"),
|
||||
([1, 1], "+", "-+-"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("left,right", [("", ""), ("<", ">")])
|
||||
def test_cjk(outer_widths, left, intersect, right, expected):
|
||||
"""Test with CJK characters in title.
|
||||
|
||||
|
@ -179,48 +190,51 @@ def test_cjk(outer_widths, left, intersect, right, expected):
|
|||
"""
|
||||
if left and right:
|
||||
expected = left + expected + right
|
||||
actual = build_border(outer_widths, '-', left, intersect, right, title=u'蓝色')
|
||||
assert ''.join(actual) == expected
|
||||
actual = build_border(outer_widths, "-", left, intersect, right, title="蓝色")
|
||||
assert "".join(actual) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('outer_widths,intersect,expected', [
|
||||
([12], '+', u'معرب--------'),
|
||||
([12], '', u'معرب--------'),
|
||||
([7, 5], '+', u'معرب---+-----'),
|
||||
([7, 5], '', u'معرب--------'),
|
||||
([4], '+', u'معرب'),
|
||||
([4], '', u'معرب'),
|
||||
([4, 1], '+', u'معرب+-'),
|
||||
([4, 1], '', u'معرب-'),
|
||||
([4, 0], '+', u'معرب+'),
|
||||
([4, 0], '', u'معرب'),
|
||||
([12], '', u'معرب--------'),
|
||||
([6, 6], '', u'معرب--------'),
|
||||
([3, 3, 3, 3], '', u'معرب--------'),
|
||||
([2, 1, 2, 1, 2, 1, 2, 1], '', u'معرب--------'),
|
||||
([1] * 12, '', u'معرب--------'),
|
||||
([2, 4], '', u'معرب--'),
|
||||
([1, 4], '', u'معرب-'),
|
||||
([1, 3], '', u'معرب'),
|
||||
([1, 2], '', u'---'),
|
||||
([2], '', u'--'),
|
||||
([12], '+', u'معرب--------'),
|
||||
([0, 12], '+', u'معرب---------'),
|
||||
([12, 0], '+', u'معرب--------+'),
|
||||
([0, 0, 12], '+', u'معرب----------'),
|
||||
([12, 0, 0], '+', u'معرب--------++'),
|
||||
([3, 3], '+', u'معرب---'),
|
||||
([4, 2], '+', u'معرب+--'),
|
||||
([5, 1], '+', u'معرب-+-'),
|
||||
([3, 3, 3, 3], '+', u'معرب---+---+---'),
|
||||
([2, 2, 4, 4], '+', u'معرب-+----+----'),
|
||||
([1, 1, 5, 5], '+', u'معرب-----+-----'),
|
||||
([2, 2, 2, 2], '+', u'معرب-+--+--'),
|
||||
([1, 1, 1, 1, 1], '+', u'معرب-+-+-'),
|
||||
([0, 0, 0, 0, 0, 0, 0], '+', u'معرب++'),
|
||||
([1, 1], '+', u'-+-'),
|
||||
])
|
||||
@pytest.mark.parametrize('left,right', [('', ''), ('<', '>')])
|
||||
@pytest.mark.parametrize(
|
||||
"outer_widths,intersect,expected",
|
||||
[
|
||||
([12], "+", "معرب--------"),
|
||||
([12], "", "معرب--------"),
|
||||
([7, 5], "+", "معرب---+-----"),
|
||||
([7, 5], "", "معرب--------"),
|
||||
([4], "+", "معرب"),
|
||||
([4], "", "معرب"),
|
||||
([4, 1], "+", "معرب+-"),
|
||||
([4, 1], "", "معرب-"),
|
||||
([4, 0], "+", "معرب+"),
|
||||
([4, 0], "", "معرب"),
|
||||
([12], "", "معرب--------"),
|
||||
([6, 6], "", "معرب--------"),
|
||||
([3, 3, 3, 3], "", "معرب--------"),
|
||||
([2, 1, 2, 1, 2, 1, 2, 1], "", "معرب--------"),
|
||||
([1] * 12, "", "معرب--------"),
|
||||
([2, 4], "", "معرب--"),
|
||||
([1, 4], "", "معرب-"),
|
||||
([1, 3], "", "معرب"),
|
||||
([1, 2], "", "---"),
|
||||
([2], "", "--"),
|
||||
([12], "+", "معرب--------"),
|
||||
([0, 12], "+", "معرب---------"),
|
||||
([12, 0], "+", "معرب--------+"),
|
||||
([0, 0, 12], "+", "معرب----------"),
|
||||
([12, 0, 0], "+", "معرب--------++"),
|
||||
([3, 3], "+", "معرب---"),
|
||||
([4, 2], "+", "معرب+--"),
|
||||
([5, 1], "+", "معرب-+-"),
|
||||
([3, 3, 3, 3], "+", "معرب---+---+---"),
|
||||
([2, 2, 4, 4], "+", "معرب-+----+----"),
|
||||
([1, 1, 5, 5], "+", "معرب-----+-----"),
|
||||
([2, 2, 2, 2], "+", "معرب-+--+--"),
|
||||
([1, 1, 1, 1, 1], "+", "معرب-+-+-"),
|
||||
([0, 0, 0, 0, 0, 0, 0], "+", "معرب++"),
|
||||
([1, 1], "+", "-+-"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("left,right", [("", ""), ("<", ">")])
|
||||
def test_rtl(outer_widths, left, intersect, right, expected):
|
||||
"""Test with RTL characters in title.
|
||||
|
||||
|
@ -232,53 +246,59 @@ def test_rtl(outer_widths, left, intersect, right, expected):
|
|||
"""
|
||||
if left and right:
|
||||
expected = left + expected + right
|
||||
actual = build_border(outer_widths, '-', left, intersect, right, title=u'معرب')
|
||||
assert ''.join(actual) == expected
|
||||
actual = build_border(outer_widths, "-", left, intersect, right, title="معرب")
|
||||
assert "".join(actual) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('outer_widths,intersect,expected', [
|
||||
([12], '+', '\x1b[34mTEST\x1b[0m--------'),
|
||||
([12], '', '\x1b[34mTEST\x1b[0m--------'),
|
||||
([7, 5], '+', '\x1b[34mTEST\x1b[0m---+-----'),
|
||||
([7, 5], '', '\x1b[34mTEST\x1b[0m--------'),
|
||||
([4], '+', '\x1b[34mTEST\x1b[0m'),
|
||||
([4], '', '\x1b[34mTEST\x1b[0m'),
|
||||
([4, 1], '+', '\x1b[34mTEST\x1b[0m+-'),
|
||||
([4, 1], '', '\x1b[34mTEST\x1b[0m-'),
|
||||
([4, 0], '+', '\x1b[34mTEST\x1b[0m+'),
|
||||
([4, 0], '', '\x1b[34mTEST\x1b[0m'),
|
||||
([12], '', '\x1b[34mTEST\x1b[0m--------'),
|
||||
([6, 6], '', '\x1b[34mTEST\x1b[0m--------'),
|
||||
([3, 3, 3, 3], '', '\x1b[34mTEST\x1b[0m--------'),
|
||||
([2, 1, 2, 1, 2, 1, 2, 1], '', '\x1b[34mTEST\x1b[0m--------'),
|
||||
([1] * 12, '', '\x1b[34mTEST\x1b[0m--------'),
|
||||
([2, 4], '', '\x1b[34mTEST\x1b[0m--'),
|
||||
([1, 4], '', '\x1b[34mTEST\x1b[0m-'),
|
||||
([1, 3], '', '\x1b[34mTEST\x1b[0m'),
|
||||
([1, 2], '', '---'),
|
||||
([12], '+', '\x1b[34mTEST\x1b[0m--------'),
|
||||
([0, 12], '+', '\x1b[34mTEST\x1b[0m---------'),
|
||||
([12, 0], '+', '\x1b[34mTEST\x1b[0m--------+'),
|
||||
([0, 0, 12], '+', '\x1b[34mTEST\x1b[0m----------'),
|
||||
([12, 0, 0], '+', '\x1b[34mTEST\x1b[0m--------++'),
|
||||
([3, 3], '+', '\x1b[34mTEST\x1b[0m---'),
|
||||
([4, 2], '+', '\x1b[34mTEST\x1b[0m+--'),
|
||||
([5, 1], '+', '\x1b[34mTEST\x1b[0m-+-'),
|
||||
([3, 3, 3, 3], '+', '\x1b[34mTEST\x1b[0m---+---+---'),
|
||||
([2, 2, 4, 4], '+', '\x1b[34mTEST\x1b[0m-+----+----'),
|
||||
([1, 1, 5, 5], '+', '\x1b[34mTEST\x1b[0m-----+-----'),
|
||||
([2, 2, 2, 2], '+', '\x1b[34mTEST\x1b[0m-+--+--'),
|
||||
([1, 1, 1, 1, 1], '+', '\x1b[34mTEST\x1b[0m-+-+-'),
|
||||
([0, 0, 0, 0, 0, 0, 0], '+', '\x1b[34mTEST\x1b[0m++'),
|
||||
([1, 1], '+', '-+-'),
|
||||
])
|
||||
@pytest.mark.parametrize('left,right', [('', ''), ('<', '>')])
|
||||
@pytest.mark.parametrize('title', [
|
||||
'\x1b[34mTEST\x1b[0m',
|
||||
Color('{blue}TEST{/all}'),
|
||||
Fore.BLUE + 'TEST' + Style.RESET_ALL,
|
||||
colored('TEST', 'blue'),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"outer_widths,intersect,expected",
|
||||
[
|
||||
([12], "+", "\x1b[34mTEST\x1b[0m--------"),
|
||||
([12], "", "\x1b[34mTEST\x1b[0m--------"),
|
||||
([7, 5], "+", "\x1b[34mTEST\x1b[0m---+-----"),
|
||||
([7, 5], "", "\x1b[34mTEST\x1b[0m--------"),
|
||||
([4], "+", "\x1b[34mTEST\x1b[0m"),
|
||||
([4], "", "\x1b[34mTEST\x1b[0m"),
|
||||
([4, 1], "+", "\x1b[34mTEST\x1b[0m+-"),
|
||||
([4, 1], "", "\x1b[34mTEST\x1b[0m-"),
|
||||
([4, 0], "+", "\x1b[34mTEST\x1b[0m+"),
|
||||
([4, 0], "", "\x1b[34mTEST\x1b[0m"),
|
||||
([12], "", "\x1b[34mTEST\x1b[0m--------"),
|
||||
([6, 6], "", "\x1b[34mTEST\x1b[0m--------"),
|
||||
([3, 3, 3, 3], "", "\x1b[34mTEST\x1b[0m--------"),
|
||||
([2, 1, 2, 1, 2, 1, 2, 1], "", "\x1b[34mTEST\x1b[0m--------"),
|
||||
([1] * 12, "", "\x1b[34mTEST\x1b[0m--------"),
|
||||
([2, 4], "", "\x1b[34mTEST\x1b[0m--"),
|
||||
([1, 4], "", "\x1b[34mTEST\x1b[0m-"),
|
||||
([1, 3], "", "\x1b[34mTEST\x1b[0m"),
|
||||
([1, 2], "", "---"),
|
||||
([12], "+", "\x1b[34mTEST\x1b[0m--------"),
|
||||
([0, 12], "+", "\x1b[34mTEST\x1b[0m---------"),
|
||||
([12, 0], "+", "\x1b[34mTEST\x1b[0m--------+"),
|
||||
([0, 0, 12], "+", "\x1b[34mTEST\x1b[0m----------"),
|
||||
([12, 0, 0], "+", "\x1b[34mTEST\x1b[0m--------++"),
|
||||
([3, 3], "+", "\x1b[34mTEST\x1b[0m---"),
|
||||
([4, 2], "+", "\x1b[34mTEST\x1b[0m+--"),
|
||||
([5, 1], "+", "\x1b[34mTEST\x1b[0m-+-"),
|
||||
([3, 3, 3, 3], "+", "\x1b[34mTEST\x1b[0m---+---+---"),
|
||||
([2, 2, 4, 4], "+", "\x1b[34mTEST\x1b[0m-+----+----"),
|
||||
([1, 1, 5, 5], "+", "\x1b[34mTEST\x1b[0m-----+-----"),
|
||||
([2, 2, 2, 2], "+", "\x1b[34mTEST\x1b[0m-+--+--"),
|
||||
([1, 1, 1, 1, 1], "+", "\x1b[34mTEST\x1b[0m-+-+-"),
|
||||
([0, 0, 0, 0, 0, 0, 0], "+", "\x1b[34mTEST\x1b[0m++"),
|
||||
([1, 1], "+", "-+-"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("left,right", [("", ""), ("<", ">")])
|
||||
@pytest.mark.parametrize(
|
||||
"title",
|
||||
[
|
||||
"\x1b[34mTEST\x1b[0m",
|
||||
Color("{blue}TEST{/all}"),
|
||||
Fore.BLUE + "TEST" + Style.RESET_ALL,
|
||||
colored("TEST", "blue"),
|
||||
],
|
||||
)
|
||||
def test_colors(outer_widths, left, intersect, right, title, expected):
|
||||
"""Test with color title characters.
|
||||
|
||||
|
@ -291,16 +311,19 @@ def test_colors(outer_widths, left, intersect, right, title, expected):
|
|||
"""
|
||||
if left and right:
|
||||
expected = left + expected + right
|
||||
actual = build_border(outer_widths, '-', left, intersect, right, title=title)
|
||||
assert ''.join(actual) == expected
|
||||
actual = build_border(outer_widths, "-", left, intersect, right, title=title)
|
||||
assert "".join(actual) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('outer_widths,title,expected', [
|
||||
([3, 3, 3], 123, '<123+---+--->'),
|
||||
([3, 3, 3], 0.9, '<0.9+---+--->'),
|
||||
([3, 3, 3], True, '<True---+--->'),
|
||||
([3, 3, 3], False, '<False--+--->'),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"outer_widths,title,expected",
|
||||
[
|
||||
([3, 3, 3], 123, "<123+---+--->"),
|
||||
([3, 3, 3], 0.9, "<0.9+---+--->"),
|
||||
([3, 3, 3], True, "<True---+--->"),
|
||||
([3, 3, 3], False, "<False--+--->"),
|
||||
],
|
||||
)
|
||||
def test_non_string(outer_widths, title, expected):
|
||||
"""Test with non-string values.
|
||||
|
||||
|
@ -308,5 +331,5 @@ def test_non_string(outer_widths, title, expected):
|
|||
:param title: Title in border.
|
||||
:param str expected: Expected output.
|
||||
"""
|
||||
actual = build_border(outer_widths, '-', '<', '+', '>', title=title)
|
||||
assert ''.join(actual) == expected
|
||||
actual = build_border(outer_widths, "-", "<", "+", ">", title=title)
|
||||
assert "".join(actual) == expected
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
"""Test function in module."""
|
||||
|
||||
from terminaltables.build import build_row
|
||||
from terminaltables3.build import build_row
|
||||
|
||||
|
||||
def test_one_line():
|
||||
"""Test with one line cells."""
|
||||
row = [
|
||||
['Left Cell'], ['Center Cell'], ['Right Cell'],
|
||||
["Left Cell"],
|
||||
["Center Cell"],
|
||||
["Right Cell"],
|
||||
]
|
||||
actual = [tuple(i) for i in build_row(row, '>', '|', '<')]
|
||||
actual = [tuple(i) for i in build_row(row, ">", "|", "<")]
|
||||
expected = [
|
||||
('>', 'Left Cell', '|', 'Center Cell', '|', 'Right Cell', '<'),
|
||||
(">", "Left Cell", "|", "Center Cell", "|", "Right Cell", "<"),
|
||||
]
|
||||
assert actual == expected
|
||||
|
||||
|
@ -19,24 +21,22 @@ def test_two_line():
|
|||
"""Test with two line cells."""
|
||||
row = [
|
||||
[
|
||||
'Left ',
|
||||
'Cell1',
|
||||
"Left ",
|
||||
"Cell1",
|
||||
],
|
||||
|
||||
[
|
||||
'Center',
|
||||
'Cell2 ',
|
||||
"Center",
|
||||
"Cell2 ",
|
||||
],
|
||||
|
||||
[
|
||||
'Right',
|
||||
'Cell3',
|
||||
"Right",
|
||||
"Cell3",
|
||||
],
|
||||
]
|
||||
actual = [tuple(i) for i in build_row(row, '>', '|', '<')]
|
||||
actual = [tuple(i) for i in build_row(row, ">", "|", "<")]
|
||||
expected = [
|
||||
('>', 'Left ', '|', 'Center', '|', 'Right', '<'),
|
||||
('>', 'Cell1', '|', 'Cell2 ', '|', 'Cell3', '<'),
|
||||
(">", "Left ", "|", "Center", "|", "Right", "<"),
|
||||
(">", "Cell1", "|", "Cell2 ", "|", "Cell3", "<"),
|
||||
]
|
||||
assert actual == expected
|
||||
|
||||
|
@ -45,60 +45,58 @@ def test_three_line():
|
|||
"""Test with three line cells."""
|
||||
row = [
|
||||
[
|
||||
'Left ',
|
||||
'Cell1',
|
||||
' ',
|
||||
"Left ",
|
||||
"Cell1",
|
||||
" ",
|
||||
],
|
||||
|
||||
[
|
||||
'Center',
|
||||
'Cell2 ',
|
||||
' ',
|
||||
"Center",
|
||||
"Cell2 ",
|
||||
" ",
|
||||
],
|
||||
|
||||
[
|
||||
'Right',
|
||||
'Cell3',
|
||||
' ',
|
||||
"Right",
|
||||
"Cell3",
|
||||
" ",
|
||||
],
|
||||
]
|
||||
actual = [tuple(i) for i in build_row(row, '>', '|', '<')]
|
||||
actual = [tuple(i) for i in build_row(row, ">", "|", "<")]
|
||||
expected = [
|
||||
('>', 'Left ', '|', 'Center', '|', 'Right', '<'),
|
||||
('>', 'Cell1', '|', 'Cell2 ', '|', 'Cell3', '<'),
|
||||
('>', ' ', '|', ' ', '|', ' ', '<'),
|
||||
(">", "Left ", "|", "Center", "|", "Right", "<"),
|
||||
(">", "Cell1", "|", "Cell2 ", "|", "Cell3", "<"),
|
||||
(">", " ", "|", " ", "|", " ", "<"),
|
||||
]
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_single():
|
||||
"""Test with single cell."""
|
||||
actual = [tuple(i) for i in build_row([['Cell']], '>', '|', '<')]
|
||||
actual = [tuple(i) for i in build_row([["Cell"]], ">", "|", "<")]
|
||||
expected = [
|
||||
('>', 'Cell', '<'),
|
||||
(">", "Cell", "<"),
|
||||
]
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_empty():
|
||||
"""Test with empty cell."""
|
||||
actual = [tuple(i) for i in build_row([['']], '>', '|', '<')]
|
||||
actual = [tuple(i) for i in build_row([[""]], ">", "|", "<")]
|
||||
expected = [
|
||||
('>', '', '<'),
|
||||
(">", "", "<"),
|
||||
]
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_no_cells():
|
||||
"""Test with no cells."""
|
||||
actual = [tuple(i) for i in build_row([[]], '>', '|', '<')]
|
||||
actual = [tuple(i) for i in build_row([[]], ">", "|", "<")]
|
||||
expected = [
|
||||
('>', '<'),
|
||||
(">", "<"),
|
||||
]
|
||||
assert actual == expected
|
||||
|
||||
actual = [tuple(i) for i in build_row([], '>', '|', '<')]
|
||||
actual = [tuple(i) for i in build_row([], ">", "|", "<")]
|
||||
expected = [
|
||||
('>', '<'),
|
||||
(">", "<"),
|
||||
]
|
||||
assert actual == expected
|
||||
|
|
|
@ -2,36 +2,36 @@
|
|||
|
||||
import pytest
|
||||
|
||||
from terminaltables.build import combine
|
||||
from terminaltables3.build import combine
|
||||
|
||||
|
||||
@pytest.mark.parametrize('generator', [False, True])
|
||||
@pytest.mark.parametrize("generator", [False, True])
|
||||
def test_borders(generator):
|
||||
"""Test with borders.
|
||||
|
||||
:param bool generator: Test with generator instead of list.
|
||||
"""
|
||||
line = ['One', 'Two', 'Three']
|
||||
actual = list(combine(iter(line) if generator else line, '>', '|', '<'))
|
||||
assert actual == ['>', 'One', '|', 'Two', '|', 'Three', '<']
|
||||
line = ["One", "Two", "Three"]
|
||||
actual = list(combine(iter(line) if generator else line, ">", "|", "<"))
|
||||
assert actual == [">", "One", "|", "Two", "|", "Three", "<"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('generator', [False, True])
|
||||
@pytest.mark.parametrize("generator", [False, True])
|
||||
def test_no_border(generator):
|
||||
"""Test without borders.
|
||||
|
||||
:param bool generator: Test with generator instead of list.
|
||||
"""
|
||||
line = ['One', 'Two', 'Three']
|
||||
actual = list(combine(iter(line) if generator else line, '', '', ''))
|
||||
assert actual == ['One', 'Two', 'Three']
|
||||
line = ["One", "Two", "Three"]
|
||||
actual = list(combine(iter(line) if generator else line, "", "", ""))
|
||||
assert actual == ["One", "Two", "Three"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('generator', [False, True])
|
||||
@pytest.mark.parametrize("generator", [False, True])
|
||||
def test_no_items(generator):
|
||||
"""Test with empty list.
|
||||
|
||||
:param bool generator: Test with generator instead of list.
|
||||
"""
|
||||
actual = list(combine(iter([]) if generator else [], '>', '|', '<'))
|
||||
assert actual == ['>', '<']
|
||||
actual = list(combine(iter([]) if generator else [], ">", "|", "<"))
|
||||
assert actual == [">", "<"]
|
||||
|
|
|
@ -1,25 +1,24 @@
|
|||
"""Test function in module."""
|
||||
|
||||
from terminaltables.build import flatten
|
||||
from terminaltables3.build import flatten
|
||||
|
||||
|
||||
def test_one_line():
|
||||
"""Test with one line cells."""
|
||||
table = [
|
||||
['>', 'Left Cell', '|', 'Center Cell', '|', 'Right Cell', '<'],
|
||||
[">", "Left Cell", "|", "Center Cell", "|", "Right Cell", "<"],
|
||||
]
|
||||
actual = flatten(table)
|
||||
expected = '>Left Cell|Center Cell|Right Cell<'
|
||||
expected = ">Left Cell|Center Cell|Right Cell<"
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_two_line():
|
||||
"""Test with two line cells."""
|
||||
table = [
|
||||
['>', 'Left ', '|', 'Center', '|', 'Right', '<'],
|
||||
['>', 'Cell1', '|', 'Cell2 ', '|', 'Cell3', '<'],
|
||||
[">", "Left ", "|", "Center", "|", "Right", "<"],
|
||||
[">", "Cell1", "|", "Cell2 ", "|", "Cell3", "<"],
|
||||
]
|
||||
actual = flatten(table)
|
||||
expected = ('>Left |Center|Right<\n'
|
||||
'>Cell1|Cell2 |Cell3<')
|
||||
expected = ">Left |Center|Right<\n" ">Cell1|Cell2 |Cell3<"
|
||||
assert actual == expected
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
"""Test example scripts."""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
@ -11,17 +9,19 @@ import pytest
|
|||
from tests import PROJECT_ROOT
|
||||
|
||||
|
||||
@pytest.mark.parametrize('filename', map('example{0}.py'.format, (1, 2, 3)))
|
||||
@pytest.mark.parametrize("filename", map("example{}.py".format, (1, 2, 3)))
|
||||
def test(filename):
|
||||
"""Test with subprocess.
|
||||
|
||||
:param str filename: Example script filename to run.
|
||||
"""
|
||||
command = [sys.executable, str(PROJECT_ROOT.join(filename))]
|
||||
env = dict(os.environ, PYTHONIOENCODING='utf-8')
|
||||
env = dict(os.environ, PYTHONIOENCODING="utf-8")
|
||||
|
||||
# Run.
|
||||
proc = subprocess.Popen(command, env=env, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
|
||||
proc = subprocess.Popen(
|
||||
command, env=env, stderr=subprocess.STDOUT, stdout=subprocess.PIPE
|
||||
)
|
||||
output = proc.communicate()[0]
|
||||
|
||||
# Verify.
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
"""Common objects used by tests in directory."""
|
||||
|
||||
from terminaltables import terminal_io
|
||||
from terminaltables3 import terminal_io
|
||||
|
||||
|
||||
class MockKernel32(object):
|
||||
class MockKernel32:
|
||||
"""Mock kernel32."""
|
||||
|
||||
def __init__(self, stderr=terminal_io.INVALID_HANDLE_VALUE, stdout=terminal_io.INVALID_HANDLE_VALUE):
|
||||
def __init__(
|
||||
self,
|
||||
stderr=terminal_io.INVALID_HANDLE_VALUE,
|
||||
stdout=terminal_io.INVALID_HANDLE_VALUE,
|
||||
):
|
||||
"""Constructor."""
|
||||
self.stderr = stderr
|
||||
self.stdout = stdout
|
||||
self.csbi_err = b'x\x00)#\x00\x00\x87\x05\x07\x00\x00\x00j\x05w\x00\x87\x05x\x00J\x00' # 119 x 29
|
||||
self.csbi_out = b'L\x00,\x01\x00\x00*\x01\x07\x00\x00\x00\x0e\x01K\x00*\x01L\x00L\x00' # 75 x 28
|
||||
self.csbi_err = b"x\x00)#\x00\x00\x87\x05\x07\x00\x00\x00j\x05w\x00\x87\x05x\x00J\x00" # 119 x 29
|
||||
self.csbi_out = b"L\x00,\x01\x00\x00*\x01\x07\x00\x00\x00\x0e\x01K\x00*\x01L\x00L\x00" # 75 x 28
|
||||
self.setConsoleTitleA_called = False
|
||||
self.setConsoleTitleW_called = False
|
||||
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
# coding: utf-8
|
||||
"""Test function in module."""
|
||||
|
||||
import ctypes
|
||||
|
||||
import pytest
|
||||
|
||||
from terminaltables.terminal_io import get_console_info, INVALID_HANDLE_VALUE, IS_WINDOWS
|
||||
from terminaltables3.terminal_io import (
|
||||
get_console_info,
|
||||
INVALID_HANDLE_VALUE,
|
||||
IS_WINDOWS,
|
||||
)
|
||||
|
||||
from tests.test_terminal_io import MockKernel32
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# coding: utf-8
|
||||
"""Test function in module."""
|
||||
|
||||
import sys
|
||||
|
@ -7,7 +6,7 @@ from textwrap import dedent
|
|||
import py
|
||||
import pytest
|
||||
|
||||
from terminaltables.terminal_io import IS_WINDOWS, set_terminal_title
|
||||
from terminaltables3.terminal_io import IS_WINDOWS, set_terminal_title
|
||||
|
||||
from tests import PROJECT_ROOT
|
||||
from tests.screenshot import RunNewConsole, screenshot_until_match
|
||||
|
@ -15,9 +14,10 @@ from tests.test_terminal_io import MockKernel32
|
|||
|
||||
HERE = py.path.local(__file__).dirpath()
|
||||
|
||||
|
||||
@pytest.mark.skip("Fails on windows, I didn't touch it")
|
||||
@pytest.mark.parametrize('is_windows', [False, True])
|
||||
@pytest.mark.parametrize('mode', ['ascii', 'unicode', 'bytes'])
|
||||
@pytest.mark.parametrize("is_windows", [False, True])
|
||||
@pytest.mark.parametrize("mode", ["ascii", "unicode", "bytes"])
|
||||
def test(monkeypatch, is_windows, mode):
|
||||
"""Test function.
|
||||
|
||||
|
@ -25,16 +25,16 @@ def test(monkeypatch, is_windows, mode):
|
|||
:param bool is_windows: Monkeypatch terminal_io.IS_WINDOWS
|
||||
:param str mode: Scenario to test for.
|
||||
"""
|
||||
monkeypatch.setattr('terminaltables.terminal_io.IS_WINDOWS', is_windows)
|
||||
monkeypatch.setattr("terminaltables3.terminal_io.IS_WINDOWS", is_windows)
|
||||
kernel32 = MockKernel32()
|
||||
|
||||
# Title.
|
||||
if mode == 'ascii':
|
||||
title = 'Testing terminaltables.'
|
||||
elif mode == 'unicode':
|
||||
title = u'Testing terminaltables with unicode: 世界你好蓝色'
|
||||
if mode == "ascii":
|
||||
title = "Testing terminaltables3."
|
||||
elif mode == "unicode":
|
||||
title = "Testing terminaltables3 with unicode: 世界你好蓝色"
|
||||
else:
|
||||
title = b'Testing terminaltables with bytes.'
|
||||
title = b"Testing terminaltables3 with bytes."
|
||||
|
||||
# Run.
|
||||
assert set_terminal_title(title, kernel32)
|
||||
|
@ -42,10 +42,10 @@ def test(monkeypatch, is_windows, mode):
|
|||
return
|
||||
|
||||
# Verify.
|
||||
if mode == 'ascii':
|
||||
if mode == "ascii":
|
||||
assert kernel32.setConsoleTitleA_called
|
||||
assert not kernel32.setConsoleTitleW_called
|
||||
elif mode == 'unicode':
|
||||
elif mode == "unicode":
|
||||
assert not kernel32.setConsoleTitleA_called
|
||||
assert kernel32.setConsoleTitleW_called
|
||||
else:
|
||||
|
@ -54,35 +54,36 @@ def test(monkeypatch, is_windows, mode):
|
|||
|
||||
|
||||
@pytest.mark.skipif(str(not IS_WINDOWS))
|
||||
@pytest.mark.parametrize('mode', ['ascii', 'unicode', 'bytes'])
|
||||
@pytest.mark.skip # https://github.com/Robpol86/terminaltables/issues/44
|
||||
@pytest.mark.parametrize("mode", ["ascii", "unicode", "bytes"])
|
||||
@pytest.mark.skip # https://github.com/Robpol86/terminaltables3/issues/44
|
||||
def test_windows_screenshot(tmpdir, mode):
|
||||
"""Test function on Windows in a new console window. Take a screenshot to verify it works.
|
||||
|
||||
:param tmpdir: pytest fixture.
|
||||
:param str mode: Scenario to test for.
|
||||
"""
|
||||
script = tmpdir.join('script.py')
|
||||
script = tmpdir.join("script.py")
|
||||
command = [sys.executable, str(script)]
|
||||
change_title = tmpdir.join('change_title')
|
||||
screenshot = PROJECT_ROOT.join('test_terminal_io_{0}.png'.format(mode))
|
||||
change_title = tmpdir.join("change_title")
|
||||
screenshot = PROJECT_ROOT.join(f"test_terminal_io_{mode}.png")
|
||||
if screenshot.check():
|
||||
screenshot.remove()
|
||||
|
||||
# Determine title.
|
||||
if mode == 'ascii':
|
||||
if mode == "ascii":
|
||||
title = "'test ASCII test'"
|
||||
elif mode == 'unicode':
|
||||
title = u"u'test 世界你好蓝色 test'"
|
||||
elif mode == "unicode":
|
||||
title = "u'test 世界你好蓝色 test'"
|
||||
else:
|
||||
title = "b'test ASCII test'"
|
||||
|
||||
# Generate script.
|
||||
script_template = dedent(u"""\
|
||||
script_template = dedent(
|
||||
"""\
|
||||
# coding: utf-8
|
||||
from __future__ import print_function
|
||||
import os, time
|
||||
from terminaltables.terminal_io import set_terminal_title
|
||||
from terminaltables3.terminal_io import set_terminal_title
|
||||
stop_after = time.time() + 20
|
||||
|
||||
print('Waiting for FindWindowA() in RunNewConsole.__enter__()...')
|
||||
|
@ -93,15 +94,18 @@ def test_windows_screenshot(tmpdir, mode):
|
|||
print('Waiting for screenshot_until_match()...')
|
||||
while not os.path.exists(r'{screenshot}') and time.time() < stop_after:
|
||||
time.sleep(0.5)
|
||||
""")
|
||||
script_contents = script_template.format(change_title=str(change_title), title=title, screenshot=str(screenshot))
|
||||
script.write(script_contents.encode('utf-8'), mode='wb')
|
||||
"""
|
||||
)
|
||||
script_contents = script_template.format(
|
||||
change_title=str(change_title), title=title, screenshot=str(screenshot)
|
||||
)
|
||||
script.write(script_contents.encode("utf-8"), mode="wb")
|
||||
|
||||
# Setup expected.
|
||||
if mode == 'unicode':
|
||||
sub_images = [str(p) for p in HERE.listdir('sub_title_cjk_*.bmp')]
|
||||
if mode == "unicode":
|
||||
sub_images = [str(p) for p in HERE.listdir("sub_title_cjk_*.bmp")]
|
||||
else:
|
||||
sub_images = [str(p) for p in HERE.listdir('sub_title_ascii_*.bmp')]
|
||||
sub_images = [str(p) for p in HERE.listdir("sub_title_ascii_*.bmp")]
|
||||
assert sub_images
|
||||
|
||||
# Run.
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
# coding: utf-8
|
||||
"""Test function in module."""
|
||||
|
||||
import pytest
|
||||
|
||||
from terminaltables.terminal_io import DEFAULT_HEIGHT, DEFAULT_WIDTH, INVALID_HANDLE_VALUE, IS_WINDOWS, terminal_size
|
||||
from terminaltables3.terminal_io import (
|
||||
DEFAULT_HEIGHT,
|
||||
DEFAULT_WIDTH,
|
||||
INVALID_HANDLE_VALUE,
|
||||
IS_WINDOWS,
|
||||
terminal_size,
|
||||
)
|
||||
|
||||
from tests.test_terminal_io import MockKernel32
|
||||
|
||||
|
||||
@pytest.mark.parametrize('stderr', [1, INVALID_HANDLE_VALUE])
|
||||
@pytest.mark.parametrize('stdout', [2, INVALID_HANDLE_VALUE])
|
||||
@pytest.mark.parametrize("stderr", [1, INVALID_HANDLE_VALUE])
|
||||
@pytest.mark.parametrize("stdout", [2, INVALID_HANDLE_VALUE])
|
||||
def test_windows(monkeypatch, stderr, stdout):
|
||||
"""Test function with IS_WINDOWS=True.
|
||||
|
||||
|
@ -17,7 +22,7 @@ def test_windows(monkeypatch, stderr, stdout):
|
|||
:param int stderr: Mock handle value.
|
||||
:param int stdout: Mock handle value.
|
||||
"""
|
||||
monkeypatch.setattr('terminaltables.terminal_io.IS_WINDOWS', True)
|
||||
monkeypatch.setattr("terminaltables3.terminal_io.IS_WINDOWS", True)
|
||||
|
||||
kernel32 = MockKernel32(stderr=stderr, stdout=stdout)
|
||||
width, height = terminal_size(kernel32)
|
||||
|
@ -48,7 +53,7 @@ def test_nix(monkeypatch):
|
|||
assert height == DEFAULT_HEIGHT
|
||||
|
||||
# Test mocked.
|
||||
monkeypatch.setattr('fcntl.ioctl', lambda *_: b'\x1d\x00w\x00\xca\x02\x96\x01')
|
||||
monkeypatch.setattr("fcntl.ioctl", lambda *_: b"\x1d\x00w\x00\xca\x02\x96\x01")
|
||||
width, height = terminal_size()
|
||||
assert width == 119
|
||||
assert height == 29
|
||||
|
|
0
tests/test_width_and_alignment/__init__.py
Normal file
0
tests/test_width_and_alignment/__init__.py
Normal file
|
@ -1,4 +1,3 @@
|
|||
# coding: utf-8
|
||||
"""Test function in module."""
|
||||
|
||||
import pytest
|
||||
|
@ -6,75 +5,74 @@ from colorama import Fore
|
|||
from colorclass import Color
|
||||
from termcolor import colored
|
||||
|
||||
from terminaltables.width_and_alignment import align_and_pad_cell
|
||||
from terminaltables3.width_and_alignment import align_and_pad_cell
|
||||
|
||||
|
||||
@pytest.mark.parametrize('string,align,width,expected', [
|
||||
('test', '', 4, ['test']),
|
||||
(123, '', 3, ['123']),
|
||||
(0.9, '', 3, ['0.9']),
|
||||
(None, '', 4, ['None']),
|
||||
(True, '', 4, ['True']),
|
||||
(False, '', 5, ['False']),
|
||||
(Color('{blue}Test{/blue}'), '', 4, ['\x1b[34mTest\x1b[39m']),
|
||||
(Fore.BLUE + 'Test' + Fore.RESET, '', 4, ['\x1b[34mTest\x1b[39m']),
|
||||
(colored('Test', 'blue'), '', 4, ['\x1b[34mTest\x1b[0m']),
|
||||
('蓝色', '', 4, ['蓝色']),
|
||||
(u'שלום', '', 4, [u'\u05e9\u05dc\u05d5\u05dd']),
|
||||
(u'معرب', '', 4, [u'\u0645\u0639\u0631\u0628']),
|
||||
|
||||
('test', '', 5, ['test ']),
|
||||
(123, '', 4, ['123 ']),
|
||||
(0.9, '', 4, ['0.9 ']),
|
||||
(None, '', 5, ['None ']),
|
||||
(True, '', 5, ['True ']),
|
||||
(False, '', 6, ['False ']),
|
||||
(Color('{blue}Test{/blue}'), '', 5, ['\x1b[34mTest\x1b[39m ']),
|
||||
(Fore.BLUE + 'Test' + Fore.RESET, '', 5, ['\x1b[34mTest\x1b[39m ']),
|
||||
(colored('Test', 'blue'), '', 5, ['\x1b[34mTest\x1b[0m ']),
|
||||
('蓝色', '', 5, ['蓝色 ']),
|
||||
(u'שלום', '', 5, [u'\u05e9\u05dc\u05d5\u05dd ']),
|
||||
(u'معرب', '', 5, [u'\u0645\u0639\u0631\u0628 ']),
|
||||
|
||||
('test', 'left', 5, ['test ']),
|
||||
(123, 'left', 4, ['123 ']),
|
||||
(0.9, 'left', 4, ['0.9 ']),
|
||||
(None, 'left', 5, ['None ']),
|
||||
(True, 'left', 5, ['True ']),
|
||||
(False, 'left', 6, ['False ']),
|
||||
(Color('{blue}Test{/blue}'), 'left', 5, ['\x1b[34mTest\x1b[39m ']),
|
||||
(Fore.BLUE + 'Test' + Fore.RESET, 'left', 5, ['\x1b[34mTest\x1b[39m ']),
|
||||
(colored('Test', 'blue'), 'left', 5, ['\x1b[34mTest\x1b[0m ']),
|
||||
('蓝色', 'left', 5, ['蓝色 ']),
|
||||
(u'שלום', 'left', 5, [u'\u05e9\u05dc\u05d5\u05dd ']),
|
||||
(u'معرب', 'left', 5, [u'\u0645\u0639\u0631\u0628 ']),
|
||||
|
||||
('test', 'right', 5, [' test']),
|
||||
(123, 'right', 4, [' 123']),
|
||||
(0.9, 'right', 4, [' 0.9']),
|
||||
(None, 'right', 5, [' None']),
|
||||
(True, 'right', 5, [' True']),
|
||||
(False, 'right', 6, [' False']),
|
||||
(Color('{blue}Test{/blue}'), 'right', 5, [' \x1b[34mTest\x1b[39m']),
|
||||
(Fore.BLUE + 'Test' + Fore.RESET, 'right', 5, [' \x1b[34mTest\x1b[39m']),
|
||||
(colored('Test', 'blue'), 'right', 5, [' \x1b[34mTest\x1b[0m']),
|
||||
('蓝色', 'right', 5, [' 蓝色']),
|
||||
(u'שלום', 'right', 5, [u' \u05e9\u05dc\u05d5\u05dd']),
|
||||
(u'معرب', 'right', 5, [u' \u0645\u0639\u0631\u0628']),
|
||||
|
||||
('test', 'center', 6, [' test ']),
|
||||
(123, 'center', 5, [' 123 ']),
|
||||
(0.9, 'center', 5, [' 0.9 ']),
|
||||
(None, 'center', 6, [' None ']),
|
||||
(True, 'center', 6, [' True ']),
|
||||
(False, 'center', 7, [' False ']),
|
||||
(Color('{blue}Test{/blue}'), 'center', 6, [' \x1b[34mTest\x1b[39m ']),
|
||||
(Fore.BLUE + 'Test' + Fore.RESET, 'center', 6, [' \x1b[34mTest\x1b[39m ']),
|
||||
(colored('Test', 'blue'), 'center', 6, [' \x1b[34mTest\x1b[0m ']),
|
||||
('蓝色', 'center', 6, [' 蓝色 ']),
|
||||
(u'שלום', 'center', 6, [u' \u05e9\u05dc\u05d5\u05dd ']),
|
||||
(u'معرب', 'center', 6, [u' \u0645\u0639\u0631\u0628 ']),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"string,align,width,expected",
|
||||
[
|
||||
("test", "", 4, ["test"]),
|
||||
(123, "", 3, ["123"]),
|
||||
(0.9, "", 3, ["0.9"]),
|
||||
(None, "", 4, ["None"]),
|
||||
(True, "", 4, ["True"]),
|
||||
(False, "", 5, ["False"]),
|
||||
(Color("{blue}Test{/blue}"), "", 4, ["\x1b[34mTest\x1b[39m"]),
|
||||
(Fore.BLUE + "Test" + Fore.RESET, "", 4, ["\x1b[34mTest\x1b[39m"]),
|
||||
(colored("Test", "blue"), "", 4, ["\x1b[34mTest\x1b[0m"]),
|
||||
("蓝色", "", 4, ["蓝色"]),
|
||||
("שלום", "", 4, ["\u05e9\u05dc\u05d5\u05dd"]),
|
||||
("معرب", "", 4, ["\u0645\u0639\u0631\u0628"]),
|
||||
("test", "", 5, ["test "]),
|
||||
(123, "", 4, ["123 "]),
|
||||
(0.9, "", 4, ["0.9 "]),
|
||||
(None, "", 5, ["None "]),
|
||||
(True, "", 5, ["True "]),
|
||||
(False, "", 6, ["False "]),
|
||||
(Color("{blue}Test{/blue}"), "", 5, ["\x1b[34mTest\x1b[39m "]),
|
||||
(Fore.BLUE + "Test" + Fore.RESET, "", 5, ["\x1b[34mTest\x1b[39m "]),
|
||||
(colored("Test", "blue"), "", 5, ["\x1b[34mTest\x1b[0m "]),
|
||||
("蓝色", "", 5, ["蓝色 "]),
|
||||
("שלום", "", 5, ["\u05e9\u05dc\u05d5\u05dd "]),
|
||||
("معرب", "", 5, ["\u0645\u0639\u0631\u0628 "]),
|
||||
("test", "left", 5, ["test "]),
|
||||
(123, "left", 4, ["123 "]),
|
||||
(0.9, "left", 4, ["0.9 "]),
|
||||
(None, "left", 5, ["None "]),
|
||||
(True, "left", 5, ["True "]),
|
||||
(False, "left", 6, ["False "]),
|
||||
(Color("{blue}Test{/blue}"), "left", 5, ["\x1b[34mTest\x1b[39m "]),
|
||||
(Fore.BLUE + "Test" + Fore.RESET, "left", 5, ["\x1b[34mTest\x1b[39m "]),
|
||||
(colored("Test", "blue"), "left", 5, ["\x1b[34mTest\x1b[0m "]),
|
||||
("蓝色", "left", 5, ["蓝色 "]),
|
||||
("שלום", "left", 5, ["\u05e9\u05dc\u05d5\u05dd "]),
|
||||
("معرب", "left", 5, ["\u0645\u0639\u0631\u0628 "]),
|
||||
("test", "right", 5, [" test"]),
|
||||
(123, "right", 4, [" 123"]),
|
||||
(0.9, "right", 4, [" 0.9"]),
|
||||
(None, "right", 5, [" None"]),
|
||||
(True, "right", 5, [" True"]),
|
||||
(False, "right", 6, [" False"]),
|
||||
(Color("{blue}Test{/blue}"), "right", 5, [" \x1b[34mTest\x1b[39m"]),
|
||||
(Fore.BLUE + "Test" + Fore.RESET, "right", 5, [" \x1b[34mTest\x1b[39m"]),
|
||||
(colored("Test", "blue"), "right", 5, [" \x1b[34mTest\x1b[0m"]),
|
||||
("蓝色", "right", 5, [" 蓝色"]),
|
||||
("שלום", "right", 5, [" \u05e9\u05dc\u05d5\u05dd"]),
|
||||
("معرب", "right", 5, [" \u0645\u0639\u0631\u0628"]),
|
||||
("test", "center", 6, [" test "]),
|
||||
(123, "center", 5, [" 123 "]),
|
||||
(0.9, "center", 5, [" 0.9 "]),
|
||||
(None, "center", 6, [" None "]),
|
||||
(True, "center", 6, [" True "]),
|
||||
(False, "center", 7, [" False "]),
|
||||
(Color("{blue}Test{/blue}"), "center", 6, [" \x1b[34mTest\x1b[39m "]),
|
||||
(Fore.BLUE + "Test" + Fore.RESET, "center", 6, [" \x1b[34mTest\x1b[39m "]),
|
||||
(colored("Test", "blue"), "center", 6, [" \x1b[34mTest\x1b[0m "]),
|
||||
("蓝色", "center", 6, [" 蓝色 "]),
|
||||
("שלום", "center", 6, [" \u05e9\u05dc\u05d5\u05dd "]),
|
||||
("معرب", "center", 6, [" \u0645\u0639\u0631\u0628 "]),
|
||||
],
|
||||
)
|
||||
def test_width(string, align, width, expected):
|
||||
"""Test width and horizontal alignment.
|
||||
|
||||
|
@ -87,47 +85,61 @@ def test_width(string, align, width, expected):
|
|||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('string,align,height,expected', [
|
||||
('test', '', 1, ['test']),
|
||||
(Color('{blue}Test{/blue}'), '', 1, ['\x1b[34mTest\x1b[39m']),
|
||||
(Fore.BLUE + 'Test' + Fore.RESET, '', 1, ['\x1b[34mTest\x1b[39m']),
|
||||
(colored('Test', 'blue'), '', 1, ['\x1b[34mTest\x1b[0m']),
|
||||
('蓝色', '', 1, ['蓝色']),
|
||||
(u'שלום', '', 1, [u'\u05e9\u05dc\u05d5\u05dd']),
|
||||
(u'معرب', '', 1, [u'\u0645\u0639\u0631\u0628']),
|
||||
|
||||
('test', '', 2, ['test', ' ']),
|
||||
(Color('{blue}Test{/blue}'), '', 2, ['\x1b[34mTest\x1b[39m', ' ']),
|
||||
(Fore.BLUE + 'Test' + Fore.RESET, '', 2, ['\x1b[34mTest\x1b[39m', ' ']),
|
||||
(colored('Test', 'blue'), '', 2, ['\x1b[34mTest\x1b[0m', ' ']),
|
||||
('蓝色', '', 2, ['蓝色', ' ']),
|
||||
(u'שלום', '', 2, [u'\u05e9\u05dc\u05d5\u05dd', ' ']),
|
||||
(u'معرب', '', 2, [u'\u0645\u0639\u0631\u0628', ' ']),
|
||||
|
||||
('test', 'top', 2, ['test', ' ']),
|
||||
(Color('{blue}Test{/blue}'), 'top', 2, ['\x1b[34mTest\x1b[39m', ' ']),
|
||||
(Fore.BLUE + 'Test' + Fore.RESET, 'top', 2, ['\x1b[34mTest\x1b[39m', ' ']),
|
||||
(colored('Test', 'blue'), 'top', 2, ['\x1b[34mTest\x1b[0m', ' ']),
|
||||
('蓝色', 'top', 2, ['蓝色', ' ']),
|
||||
(u'שלום', 'top', 2, [u'\u05e9\u05dc\u05d5\u05dd', ' ']),
|
||||
(u'معرب', 'top', 2, [u'\u0645\u0639\u0631\u0628', ' ']),
|
||||
|
||||
('test', 'bottom', 2, [' ', 'test']),
|
||||
(Color('{blue}Test{/blue}'), 'bottom', 2, [' ', '\x1b[34mTest\x1b[39m']),
|
||||
(Fore.BLUE + 'Test' + Fore.RESET, 'bottom', 2, [' ', '\x1b[34mTest\x1b[39m']),
|
||||
(colored('Test', 'blue'), 'bottom', 2, [' ', '\x1b[34mTest\x1b[0m']),
|
||||
('蓝色', 'bottom', 2, [' ', '蓝色']),
|
||||
(u'שלום', 'bottom', 2, [' ', u'\u05e9\u05dc\u05d5\u05dd']),
|
||||
(u'معرب', 'bottom', 2, [' ', u'\u0645\u0639\u0631\u0628']),
|
||||
|
||||
('test', 'middle', 3, [' ', 'test', ' ']),
|
||||
(Color('{blue}Test{/blue}'), 'middle', 3, [' ', '\x1b[34mTest\x1b[39m', ' ']),
|
||||
(Fore.BLUE + 'Test' + Fore.RESET, 'middle', 3, [' ', '\x1b[34mTest\x1b[39m', ' ']),
|
||||
(colored('Test', 'blue'), 'middle', 3, [' ', '\x1b[34mTest\x1b[0m', ' ']),
|
||||
('蓝色', 'middle', 3, [' ', '蓝色', ' ']),
|
||||
(u'שלום', 'middle', 3, [' ', u'\u05e9\u05dc\u05d5\u05dd', ' ']),
|
||||
(u'معرب', 'middle', 3, [' ', u'\u0645\u0639\u0631\u0628', ' ']),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"string,align,height,expected",
|
||||
[
|
||||
("test", "", 1, ["test"]),
|
||||
(Color("{blue}Test{/blue}"), "", 1, ["\x1b[34mTest\x1b[39m"]),
|
||||
(Fore.BLUE + "Test" + Fore.RESET, "", 1, ["\x1b[34mTest\x1b[39m"]),
|
||||
(colored("Test", "blue"), "", 1, ["\x1b[34mTest\x1b[0m"]),
|
||||
("蓝色", "", 1, ["蓝色"]),
|
||||
("שלום", "", 1, ["\u05e9\u05dc\u05d5\u05dd"]),
|
||||
("معرب", "", 1, ["\u0645\u0639\u0631\u0628"]),
|
||||
("test", "", 2, ["test", " "]),
|
||||
(Color("{blue}Test{/blue}"), "", 2, ["\x1b[34mTest\x1b[39m", " "]),
|
||||
(Fore.BLUE + "Test" + Fore.RESET, "", 2, ["\x1b[34mTest\x1b[39m", " "]),
|
||||
(colored("Test", "blue"), "", 2, ["\x1b[34mTest\x1b[0m", " "]),
|
||||
("蓝色", "", 2, ["蓝色", " "]),
|
||||
("שלום", "", 2, ["\u05e9\u05dc\u05d5\u05dd", " "]),
|
||||
("معرب", "", 2, ["\u0645\u0639\u0631\u0628", " "]),
|
||||
("test", "top", 2, ["test", " "]),
|
||||
(Color("{blue}Test{/blue}"), "top", 2, ["\x1b[34mTest\x1b[39m", " "]),
|
||||
(Fore.BLUE + "Test" + Fore.RESET, "top", 2, ["\x1b[34mTest\x1b[39m", " "]),
|
||||
(colored("Test", "blue"), "top", 2, ["\x1b[34mTest\x1b[0m", " "]),
|
||||
("蓝色", "top", 2, ["蓝色", " "]),
|
||||
("שלום", "top", 2, ["\u05e9\u05dc\u05d5\u05dd", " "]),
|
||||
("معرب", "top", 2, ["\u0645\u0639\u0631\u0628", " "]),
|
||||
("test", "bottom", 2, [" ", "test"]),
|
||||
(Color("{blue}Test{/blue}"), "bottom", 2, [" ", "\x1b[34mTest\x1b[39m"]),
|
||||
(
|
||||
Fore.BLUE + "Test" + Fore.RESET,
|
||||
"bottom",
|
||||
2,
|
||||
[" ", "\x1b[34mTest\x1b[39m"],
|
||||
),
|
||||
(colored("Test", "blue"), "bottom", 2, [" ", "\x1b[34mTest\x1b[0m"]),
|
||||
("蓝色", "bottom", 2, [" ", "蓝色"]),
|
||||
("שלום", "bottom", 2, [" ", "\u05e9\u05dc\u05d5\u05dd"]),
|
||||
("معرب", "bottom", 2, [" ", "\u0645\u0639\u0631\u0628"]),
|
||||
("test", "middle", 3, [" ", "test", " "]),
|
||||
(
|
||||
Color("{blue}Test{/blue}"),
|
||||
"middle",
|
||||
3,
|
||||
[" ", "\x1b[34mTest\x1b[39m", " "],
|
||||
),
|
||||
(
|
||||
Fore.BLUE + "Test" + Fore.RESET,
|
||||
"middle",
|
||||
3,
|
||||
[" ", "\x1b[34mTest\x1b[39m", " "],
|
||||
),
|
||||
(colored("Test", "blue"), "middle", 3, [" ", "\x1b[34mTest\x1b[0m", " "]),
|
||||
("蓝色", "middle", 3, [" ", "蓝色", " "]),
|
||||
("שלום", "middle", 3, [" ", "\u05e9\u05dc\u05d5\u05dd", " "]),
|
||||
("معرب", "middle", 3, [" ", "\u0645\u0639\u0631\u0628", " "]),
|
||||
],
|
||||
)
|
||||
def test_height(string, align, height, expected):
|
||||
"""Test height and vertical alignment.
|
||||
|
||||
|
@ -140,57 +152,68 @@ def test_height(string, align, height, expected):
|
|||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('string,align,expected', [
|
||||
('', '', ['.......', '.......', '.......', '.......', '.......']),
|
||||
('\n', '', ['.......', '.......', '.......', '.......', '.......']),
|
||||
('a\nb\nc', '', ['.......', '.a.....', '.b.....', '.c.....', '.......']),
|
||||
('test', '', ['.......', '.test..', '.......', '.......', '.......']),
|
||||
|
||||
('', 'left', ['.......', '.......', '.......', '.......', '.......']),
|
||||
('\n', 'left', ['.......', '.......', '.......', '.......', '.......']),
|
||||
('a\nb\nc', 'left', ['.......', '.a.....', '.b.....', '.c.....', '.......']),
|
||||
('test', 'left', ['.......', '.test..', '.......', '.......', '.......']),
|
||||
|
||||
('', 'right', ['.......', '.......', '.......', '.......', '.......']),
|
||||
('\n', 'right', ['.......', '.......', '.......', '.......', '.......']),
|
||||
('a\nb\nc', 'right', ['.......', '.....a.', '.....b.', '.....c.', '.......']),
|
||||
('test', 'right', ['.......', '..test.', '.......', '.......', '.......']),
|
||||
|
||||
('', 'center', ['.......', '.......', '.......', '.......', '.......']),
|
||||
('\n', 'center', ['.......', '.......', '.......', '.......', '.......']),
|
||||
('a\nb\nc', 'center', ['.......', '...a...', '...b...', '...c...', '.......']),
|
||||
('test', 'center', ['.......', '..test.', '.......', '.......', '.......']),
|
||||
|
||||
('', 'top', ['.......', '.......', '.......', '.......', '.......']),
|
||||
('\n', 'top', ['.......', '.......', '.......', '.......', '.......']),
|
||||
('a\nb\nc', 'top', ['.......', '.a.....', '.b.....', '.c.....', '.......']),
|
||||
('test', 'top', ['.......', '.test..', '.......', '.......', '.......']),
|
||||
|
||||
('', 'bottom', ['.......', '.......', '.......', '.......', '.......']),
|
||||
('\n', 'bottom', ['.......', '.......', '.......', '.......', '.......']),
|
||||
('a\nb\nc', 'bottom', ['.......', '.a.....', '.b.....', '.c.....', '.......']),
|
||||
('test', 'bottom', ['.......', '.......', '.......', '.test..', '.......']),
|
||||
|
||||
('', 'middle', ['.......', '.......', '.......', '.......', '.......']),
|
||||
('\n', 'middle', ['.......', '.......', '.......', '.......', '.......']),
|
||||
('a\nb\nc', 'middle', ['.......', '.a.....', '.b.....', '.c.....', '.......']),
|
||||
('test', 'middle', ['.......', '.......', '.test..', '.......', '.......']),
|
||||
|
||||
(
|
||||
u'蓝色\nשלום\nمعرب',
|
||||
'',
|
||||
['.......', u'.蓝色..', u'.\u05e9\u05dc\u05d5\u05dd..', u'.\u0645\u0639\u0631\u0628..', '.......']
|
||||
),
|
||||
|
||||
(
|
||||
'\n'.join((Color('{blue}Test{/blue}'), Fore.BLUE + 'Test' + Fore.RESET, colored('Test', 'blue'))),
|
||||
'',
|
||||
['.......', '.\x1b[34mTest\x1b[39m..', '.\x1b[34mTest\x1b[39m..', '.\x1b[34mTest\x1b[0m..', '.......']
|
||||
),
|
||||
|
||||
# (Color('{blue}A\nB{/blue}'), '', '.......\n.\x1b[34mA\x1b[39m.....\n.\x1b[34mB\x1b[39m.....\n.......\n.......'),
|
||||
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"string,align,expected",
|
||||
[
|
||||
("", "", [".......", ".......", ".......", ".......", "......."]),
|
||||
("\n", "", [".......", ".......", ".......", ".......", "......."]),
|
||||
("a\nb\nc", "", [".......", ".a.....", ".b.....", ".c.....", "......."]),
|
||||
("test", "", [".......", ".test..", ".......", ".......", "......."]),
|
||||
("", "left", [".......", ".......", ".......", ".......", "......."]),
|
||||
("\n", "left", [".......", ".......", ".......", ".......", "......."]),
|
||||
("a\nb\nc", "left", [".......", ".a.....", ".b.....", ".c.....", "......."]),
|
||||
("test", "left", [".......", ".test..", ".......", ".......", "......."]),
|
||||
("", "right", [".......", ".......", ".......", ".......", "......."]),
|
||||
("\n", "right", [".......", ".......", ".......", ".......", "......."]),
|
||||
("a\nb\nc", "right", [".......", ".....a.", ".....b.", ".....c.", "......."]),
|
||||
("test", "right", [".......", "..test.", ".......", ".......", "......."]),
|
||||
("", "center", [".......", ".......", ".......", ".......", "......."]),
|
||||
("\n", "center", [".......", ".......", ".......", ".......", "......."]),
|
||||
("a\nb\nc", "center", [".......", "...a...", "...b...", "...c...", "......."]),
|
||||
("test", "center", [".......", "..test.", ".......", ".......", "......."]),
|
||||
("", "top", [".......", ".......", ".......", ".......", "......."]),
|
||||
("\n", "top", [".......", ".......", ".......", ".......", "......."]),
|
||||
("a\nb\nc", "top", [".......", ".a.....", ".b.....", ".c.....", "......."]),
|
||||
("test", "top", [".......", ".test..", ".......", ".......", "......."]),
|
||||
("", "bottom", [".......", ".......", ".......", ".......", "......."]),
|
||||
("\n", "bottom", [".......", ".......", ".......", ".......", "......."]),
|
||||
("a\nb\nc", "bottom", [".......", ".a.....", ".b.....", ".c.....", "......."]),
|
||||
("test", "bottom", [".......", ".......", ".......", ".test..", "......."]),
|
||||
("", "middle", [".......", ".......", ".......", ".......", "......."]),
|
||||
("\n", "middle", [".......", ".......", ".......", ".......", "......."]),
|
||||
("a\nb\nc", "middle", [".......", ".a.....", ".b.....", ".c.....", "......."]),
|
||||
("test", "middle", [".......", ".......", ".test..", ".......", "......."]),
|
||||
(
|
||||
"蓝色\nשלום\nمعرب",
|
||||
"",
|
||||
[
|
||||
".......",
|
||||
".蓝色..",
|
||||
".\u05e9\u05dc\u05d5\u05dd..",
|
||||
".\u0645\u0639\u0631\u0628..",
|
||||
".......",
|
||||
],
|
||||
),
|
||||
(
|
||||
"\n".join(
|
||||
(
|
||||
Color("{blue}Test{/blue}"),
|
||||
Fore.BLUE + "Test" + Fore.RESET,
|
||||
colored("Test", "blue"),
|
||||
)
|
||||
),
|
||||
"",
|
||||
[
|
||||
".......",
|
||||
".\x1b[34mTest\x1b[39m..",
|
||||
".\x1b[34mTest\x1b[39m..",
|
||||
".\x1b[34mTest\x1b[0m..",
|
||||
".......",
|
||||
],
|
||||
),
|
||||
# (Color('{blue}A\nB{/blue}'), '', '.......\n.\x1b[34mA\x1b[39m.....\n.\x1b[34mB\x1b[39m.....\n.......\n.......'),
|
||||
],
|
||||
)
|
||||
def test_odd_width_height_pad_space(string, align, expected):
|
||||
"""Test odd number width, height, padding, and dots for whitespaces.
|
||||
|
||||
|
@ -198,5 +221,5 @@ def test_odd_width_height_pad_space(string, align, expected):
|
|||
:param str align: Alignment in any dimension but one at a time.
|
||||
:param list expected: Expected output string.
|
||||
"""
|
||||
actual = align_and_pad_cell(string, (align,), (5, 3), (1, 1, 1, 1), '.')
|
||||
actual = align_and_pad_cell(string, (align,), (5, 3), (1, 1, 1, 1), ".")
|
||||
assert actual == expected
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import pytest
|
||||
|
||||
from terminaltables.width_and_alignment import column_max_width, max_dimensions
|
||||
from terminaltables3.width_and_alignment import column_max_width, max_dimensions
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
|
@ -11,27 +11,35 @@ def patch(monkeypatch):
|
|||
|
||||
:param monkeypatch: pytest fixture.
|
||||
"""
|
||||
monkeypatch.setattr('terminaltables.width_and_alignment.terminal_size', lambda: (79, 24))
|
||||
monkeypatch.setattr(
|
||||
"terminaltables3.width_and_alignment.terminal_size", lambda: (79, 24)
|
||||
)
|
||||
|
||||
|
||||
def test_empty():
|
||||
"""Test with zero-length cells."""
|
||||
assert column_max_width(max_dimensions([['']])[0], 0, 0, 0, 0) == 79
|
||||
assert column_max_width(max_dimensions([['', '', '']])[0], 0, 0, 0, 0) == 79
|
||||
assert column_max_width(max_dimensions([['', '', ''], ['', '', '']])[0], 0, 0, 0, 0) == 79
|
||||
assert column_max_width(max_dimensions([[""]])[0], 0, 0, 0, 0) == 79
|
||||
assert column_max_width(max_dimensions([["", "", ""]])[0], 0, 0, 0, 0) == 79
|
||||
assert (
|
||||
column_max_width(max_dimensions([["", "", ""], ["", "", ""]])[0], 0, 0, 0, 0)
|
||||
== 79
|
||||
)
|
||||
|
||||
assert column_max_width(max_dimensions([['']])[0], 0, 2, 1, 2) == 75
|
||||
assert column_max_width(max_dimensions([['', '', '']])[0], 0, 2, 1, 2) == 69
|
||||
assert column_max_width(max_dimensions([['', '', ''], ['', '', '']])[0], 0, 2, 1, 2) == 69
|
||||
assert column_max_width(max_dimensions([[""]])[0], 0, 2, 1, 2) == 75
|
||||
assert column_max_width(max_dimensions([["", "", ""]])[0], 0, 2, 1, 2) == 69
|
||||
assert (
|
||||
column_max_width(max_dimensions([["", "", ""], ["", "", ""]])[0], 0, 2, 1, 2)
|
||||
== 69
|
||||
)
|
||||
|
||||
|
||||
def test_single_line():
|
||||
"""Test with single-line cells."""
|
||||
table_data = [
|
||||
['Name', 'Color', 'Type'],
|
||||
['Avocado', 'green', 'nut'],
|
||||
['Tomato', 'red', 'fruit'],
|
||||
['Lettuce', 'green', 'vegetable'],
|
||||
["Name", "Color", "Type"],
|
||||
["Avocado", "green", "nut"],
|
||||
["Tomato", "red", "fruit"],
|
||||
["Lettuce", "green", "vegetable"],
|
||||
]
|
||||
inner_widths = max_dimensions(table_data)[0]
|
||||
|
||||
|
@ -72,11 +80,11 @@ def test_single_line():
|
|||
assert column_max_width(inner_widths, 2, outer, inner, padding) == 48
|
||||
|
||||
table_data = [
|
||||
['Name', 'Color', 'Type'],
|
||||
['Avocado', 'green', 'nut'],
|
||||
['Tomato', 'red', 'fruit'],
|
||||
['Lettuce', 'green', 'vegetable'],
|
||||
['Watermelon', 'green', 'fruit'],
|
||||
["Name", "Color", "Type"],
|
||||
["Avocado", "green", "nut"],
|
||||
["Tomato", "red", "fruit"],
|
||||
["Lettuce", "green", "vegetable"],
|
||||
["Watermelon", "green", "fruit"],
|
||||
]
|
||||
inner_widths = max_dimensions(table_data)[0]
|
||||
outer, inner, padding = 2, 1, 2
|
||||
|
@ -91,10 +99,15 @@ def test_multi_line(monkeypatch):
|
|||
:param monkeypatch: pytest fixture.
|
||||
"""
|
||||
table_data = [
|
||||
['Show', 'Characters'],
|
||||
['Rugrats', ('Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\n'
|
||||
'Susie Carmichael, Dil Pickles, Kimi Finster, Spike')],
|
||||
['South Park', 'Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick']
|
||||
["Show", "Characters"],
|
||||
[
|
||||
"Rugrats",
|
||||
(
|
||||
"Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\n"
|
||||
"Susie Carmichael, Dil Pickles, Kimi Finster, Spike"
|
||||
),
|
||||
],
|
||||
["South Park", "Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick"],
|
||||
]
|
||||
inner_widths = max_dimensions(table_data)[0]
|
||||
outer, inner, padding = 2, 1, 2
|
||||
|
@ -102,6 +115,8 @@ def test_multi_line(monkeypatch):
|
|||
assert column_max_width(inner_widths, 0, outer, inner, padding) == -11
|
||||
assert column_max_width(inner_widths, 1, outer, inner, padding) == 62
|
||||
|
||||
monkeypatch.setattr('terminaltables.width_and_alignment.terminal_size', lambda: (100, 24))
|
||||
monkeypatch.setattr(
|
||||
"terminaltables3.width_and_alignment.terminal_size", lambda: (100, 24)
|
||||
)
|
||||
assert column_max_width(inner_widths, 0, outer, inner, padding) == 10
|
||||
assert column_max_width(inner_widths, 1, outer, inner, padding) == 83
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# coding: utf-8
|
||||
"""Test function in module."""
|
||||
|
||||
import pytest
|
||||
|
@ -6,18 +5,20 @@ from colorama import Fore
|
|||
from colorclass import Color
|
||||
from termcolor import colored
|
||||
|
||||
from terminaltables.width_and_alignment import max_dimensions
|
||||
from terminaltables3.width_and_alignment import max_dimensions
|
||||
|
||||
|
||||
@pytest.mark.parametrize('table_data,expected_w,expected_h', [
|
||||
([[]], [], [0]),
|
||||
([['']], [0], [0]),
|
||||
([['', '']], [0, 0], [0]),
|
||||
|
||||
([[], []], [], [0, 0]),
|
||||
([[''], ['']], [0], [0, 0]),
|
||||
([['', ''], ['', '']], [0, 0], [0, 0]),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"table_data,expected_w,expected_h",
|
||||
[
|
||||
([[]], [], [0]),
|
||||
([[""]], [0], [0]),
|
||||
([["", ""]], [0, 0], [0]),
|
||||
([[], []], [], [0, 0]),
|
||||
([[""], [""]], [0], [0, 0]),
|
||||
([["", ""], ["", ""]], [0, 0], [0, 0]),
|
||||
],
|
||||
)
|
||||
def test_zero_length(table_data, expected_w, expected_h):
|
||||
"""Test zero-length or empty tables.
|
||||
|
||||
|
@ -32,40 +33,60 @@ def test_zero_length(table_data, expected_w, expected_h):
|
|||
def test_single_line():
|
||||
"""Test widths."""
|
||||
table_data = [
|
||||
['Name', 'Color', 'Type'],
|
||||
['Avocado', 'green', 'nut'],
|
||||
['Tomato', 'red', 'fruit'],
|
||||
['Lettuce', 'green', 'vegetable'],
|
||||
["Name", "Color", "Type"],
|
||||
["Avocado", "green", "nut"],
|
||||
["Tomato", "red", "fruit"],
|
||||
["Lettuce", "green", "vegetable"],
|
||||
]
|
||||
assert max_dimensions(table_data, 1, 1) == ([7, 5, 9], [1, 1, 1, 1], [9, 7, 11], [1, 1, 1, 1])
|
||||
assert max_dimensions(table_data, 1, 1) == (
|
||||
[7, 5, 9],
|
||||
[1, 1, 1, 1],
|
||||
[9, 7, 11],
|
||||
[1, 1, 1, 1],
|
||||
)
|
||||
|
||||
table_data.append(['Watermelon', 'green', 'fruit'])
|
||||
assert max_dimensions(table_data, 2, 2) == ([10, 5, 9], [1, 1, 1, 1, 1], [14, 9, 13], [1, 1, 1, 1, 1])
|
||||
table_data.append(["Watermelon", "green", "fruit"])
|
||||
assert max_dimensions(table_data, 2, 2) == (
|
||||
[10, 5, 9],
|
||||
[1, 1, 1, 1, 1],
|
||||
[14, 9, 13],
|
||||
[1, 1, 1, 1, 1],
|
||||
)
|
||||
|
||||
|
||||
def test_multi_line():
|
||||
"""Test heights."""
|
||||
table_data = [
|
||||
['One\nTwo', 'Buckle\nMy\nShoe'],
|
||||
["One\nTwo", "Buckle\nMy\nShoe"],
|
||||
]
|
||||
assert max_dimensions(table_data, 0, 0, 1, 1) == ([3, 6], [3], [3, 6], [5])
|
||||
|
||||
table_data = [
|
||||
['Show', 'Characters'],
|
||||
['Rugrats', ('Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\n'
|
||||
'Susie Carmichael, Dil Pickles, Kimi Finster, Spike')],
|
||||
['South Park', 'Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick']
|
||||
["Show", "Characters"],
|
||||
[
|
||||
"Rugrats",
|
||||
(
|
||||
"Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\n"
|
||||
"Susie Carmichael, Dil Pickles, Kimi Finster, Spike"
|
||||
),
|
||||
],
|
||||
["South Park", "Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick"],
|
||||
]
|
||||
assert max_dimensions(table_data, 0, 0, 2, 2) == ([10, 83], [1, 2, 1], [10, 83], [5, 6, 5])
|
||||
assert max_dimensions(table_data, 0, 0, 2, 2) == (
|
||||
[10, 83],
|
||||
[1, 2, 1],
|
||||
[10, 83],
|
||||
[5, 6, 5],
|
||||
)
|
||||
|
||||
|
||||
def test_trailing_newline():
|
||||
r"""Test with trailing \n."""
|
||||
table_data = [
|
||||
['Row One\n<blank>'],
|
||||
['<blank>\nRow Two'],
|
||||
['Row Three\n'],
|
||||
['\nRow Four'],
|
||||
["Row One\n<blank>"],
|
||||
["<blank>\nRow Two"],
|
||||
["Row Three\n"],
|
||||
["\nRow Four"],
|
||||
]
|
||||
assert max_dimensions(table_data) == ([9], [2, 2, 2, 2], [9], [2, 2, 2, 2])
|
||||
|
||||
|
@ -73,21 +94,21 @@ def test_trailing_newline():
|
|||
def test_colors_cjk_rtl():
|
||||
"""Test color text, CJK characters, and RTL characters."""
|
||||
table_data = [
|
||||
[Color('{blue}Test{/blue}')],
|
||||
[Fore.BLUE + 'Test' + Fore.RESET],
|
||||
[colored('Test', 'blue')],
|
||||
[Color("{blue}Test{/blue}")],
|
||||
[Fore.BLUE + "Test" + Fore.RESET],
|
||||
[colored("Test", "blue")],
|
||||
]
|
||||
assert max_dimensions(table_data) == ([4], [1, 1, 1], [4], [1, 1, 1])
|
||||
|
||||
table_data = [
|
||||
['蓝色'],
|
||||
['世界你好'],
|
||||
["蓝色"],
|
||||
["世界你好"],
|
||||
]
|
||||
assert max_dimensions(table_data) == ([8], [1, 1], [8], [1, 1])
|
||||
|
||||
table_data = [
|
||||
['שלום'],
|
||||
['معرب'],
|
||||
["שלום"],
|
||||
["معرب"],
|
||||
]
|
||||
assert max_dimensions(table_data) == ([4], [1, 1], [4], [1, 1])
|
||||
|
||||
|
|
|
@ -1,26 +1,28 @@
|
|||
"""Test function in module."""
|
||||
|
||||
from terminaltables.width_and_alignment import max_dimensions, table_width
|
||||
from terminaltables3.width_and_alignment import max_dimensions, table_width
|
||||
|
||||
|
||||
def test_empty():
|
||||
"""Test with zero-length cells."""
|
||||
assert table_width(max_dimensions([['']])[2], 0, 0) == 0
|
||||
assert table_width(max_dimensions([['', '', '']])[2], 0, 0) == 0
|
||||
assert table_width(max_dimensions([['', '', ''], ['', '', '']])[2], 0, 0) == 0
|
||||
assert table_width(max_dimensions([[""]])[2], 0, 0) == 0
|
||||
assert table_width(max_dimensions([["", "", ""]])[2], 0, 0) == 0
|
||||
assert table_width(max_dimensions([["", "", ""], ["", "", ""]])[2], 0, 0) == 0
|
||||
|
||||
assert table_width(max_dimensions([['']], 1, 1)[2], 2, 1) == 4
|
||||
assert table_width(max_dimensions([['', '', '']], 1, 1)[2], 2, 1) == 10
|
||||
assert table_width(max_dimensions([['', '', ''], ['', '', '']], 1, 1)[2], 2, 1) == 10
|
||||
assert table_width(max_dimensions([[""]], 1, 1)[2], 2, 1) == 4
|
||||
assert table_width(max_dimensions([["", "", ""]], 1, 1)[2], 2, 1) == 10
|
||||
assert (
|
||||
table_width(max_dimensions([["", "", ""], ["", "", ""]], 1, 1)[2], 2, 1) == 10
|
||||
)
|
||||
|
||||
|
||||
def test_single_line():
|
||||
"""Test with single-line cells."""
|
||||
table_data = [
|
||||
['Name', 'Color', 'Type'],
|
||||
['Avocado', 'green', 'nut'],
|
||||
['Tomato', 'red', 'fruit'],
|
||||
['Lettuce', 'green', 'vegetable'],
|
||||
["Name", "Color", "Type"],
|
||||
["Avocado", "green", "nut"],
|
||||
["Tomato", "red", "fruit"],
|
||||
["Lettuce", "green", "vegetable"],
|
||||
]
|
||||
|
||||
# '| Lettuce | green | vegetable |'
|
||||
|
@ -48,11 +50,11 @@ def test_single_line():
|
|||
assert table_width(outer_widths, outer, inner) == 40
|
||||
|
||||
table_data = [
|
||||
['Name', 'Color', 'Type'],
|
||||
['Avocado', 'green', 'nut'],
|
||||
['Tomato', 'red', 'fruit'],
|
||||
['Lettuce', 'green', 'vegetable'],
|
||||
['Watermelon', 'green', 'fruit'],
|
||||
["Name", "Color", "Type"],
|
||||
["Avocado", "green", "nut"],
|
||||
["Tomato", "red", "fruit"],
|
||||
["Lettuce", "green", "vegetable"],
|
||||
["Watermelon", "green", "fruit"],
|
||||
]
|
||||
outer, inner, outer_widths = 2, 1, max_dimensions(table_data, 1, 1)[2]
|
||||
assert table_width(outer_widths, outer, inner) == 34
|
||||
|
@ -61,10 +63,15 @@ def test_single_line():
|
|||
def test_multi_line():
|
||||
"""Test with multi-line cells."""
|
||||
table_data = [
|
||||
['Show', 'Characters'],
|
||||
['Rugrats', ('Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\n'
|
||||
'Susie Carmichael, Dil Pickles, Kimi Finster, Spike')],
|
||||
['South Park', 'Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick']
|
||||
["Show", "Characters"],
|
||||
[
|
||||
"Rugrats",
|
||||
(
|
||||
"Tommy Pickles, Chuckie Finster, Phillip DeVille, Lillian DeVille, Angelica Pickles,\n"
|
||||
"Susie Carmichael, Dil Pickles, Kimi Finster, Spike"
|
||||
),
|
||||
],
|
||||
["South Park", "Stan Marsh, Kyle Broflovski, Eric Cartman, Kenny McCormick"],
|
||||
]
|
||||
outer, inner, outer_widths = 2, 1, max_dimensions(table_data, 1, 1)[2]
|
||||
assert table_width(outer_widths, outer, inner) == 100
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# coding: utf-8
|
||||
"""Test function in module."""
|
||||
|
||||
import pytest
|
||||
|
@ -6,50 +5,49 @@ from colorama import Fore
|
|||
from colorclass import Color
|
||||
from termcolor import colored
|
||||
|
||||
from terminaltables.width_and_alignment import visible_width
|
||||
from terminaltables3.width_and_alignment import visible_width
|
||||
|
||||
|
||||
@pytest.mark.parametrize('string,expected', [
|
||||
# str
|
||||
('hello, world', 12),
|
||||
('世界你好', 8),
|
||||
('蓝色', 4),
|
||||
('שלום', 4),
|
||||
('معرب', 4),
|
||||
('hello 世界', 10),
|
||||
|
||||
# str+ansi
|
||||
('\x1b[34mhello, world\x1b[39m', 12),
|
||||
('\x1b[34m世界你好\x1b[39m', 8),
|
||||
('\x1b[34m蓝色\x1b[39m', 4),
|
||||
('\x1b[34mשלום\x1b[39m', 4),
|
||||
('\x1b[34mمعرب\x1b[39m', 4),
|
||||
('\x1b[34mhello 世界\x1b[39m', 10),
|
||||
|
||||
# colorclass
|
||||
(Color(u'{blue}hello, world{/blue}'), 12),
|
||||
(Color(u'{blue}世界你好{/blue}'), 8),
|
||||
(Color(u'{blue}蓝色{/blue}'), 4),
|
||||
(Color(u'{blue}שלום{/blue}'), 4),
|
||||
(Color(u'{blue}معرب{/blue}'), 4),
|
||||
(Color(u'{blue}hello 世界{/blue}'), 10),
|
||||
|
||||
# colorama
|
||||
(Fore.BLUE + 'hello, world' + Fore.RESET, 12),
|
||||
(Fore.BLUE + '世界你好' + Fore.RESET, 8),
|
||||
(Fore.BLUE + '蓝色' + Fore.RESET, 4),
|
||||
(Fore.BLUE + 'שלום' + Fore.RESET, 4),
|
||||
(Fore.BLUE + 'معرب' + Fore.RESET, 4),
|
||||
(Fore.BLUE + 'hello 世界' + Fore.RESET, 10),
|
||||
|
||||
# termcolor
|
||||
(colored('hello, world', 'blue'), 12),
|
||||
(colored('世界你好', 'blue'), 8),
|
||||
(colored('蓝色', 'blue'), 4),
|
||||
(colored('שלום', 'blue'), 4),
|
||||
(colored('معرب', 'blue'), 4),
|
||||
(colored('hello 世界', 'blue'), 10),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"string,expected",
|
||||
[
|
||||
# str
|
||||
("hello, world", 12),
|
||||
("世界你好", 8),
|
||||
("蓝色", 4),
|
||||
("שלום", 4),
|
||||
("معرب", 4),
|
||||
("hello 世界", 10),
|
||||
# str+ansi
|
||||
("\x1b[34mhello, world\x1b[39m", 12),
|
||||
("\x1b[34m世界你好\x1b[39m", 8),
|
||||
("\x1b[34m蓝色\x1b[39m", 4),
|
||||
("\x1b[34mשלום\x1b[39m", 4),
|
||||
("\x1b[34mمعرب\x1b[39m", 4),
|
||||
("\x1b[34mhello 世界\x1b[39m", 10),
|
||||
# colorclass
|
||||
(Color("{blue}hello, world{/blue}"), 12),
|
||||
(Color("{blue}世界你好{/blue}"), 8),
|
||||
(Color("{blue}蓝色{/blue}"), 4),
|
||||
(Color("{blue}שלום{/blue}"), 4),
|
||||
(Color("{blue}معرب{/blue}"), 4),
|
||||
(Color("{blue}hello 世界{/blue}"), 10),
|
||||
# colorama
|
||||
(Fore.BLUE + "hello, world" + Fore.RESET, 12),
|
||||
(Fore.BLUE + "世界你好" + Fore.RESET, 8),
|
||||
(Fore.BLUE + "蓝色" + Fore.RESET, 4),
|
||||
(Fore.BLUE + "שלום" + Fore.RESET, 4),
|
||||
(Fore.BLUE + "معرب" + Fore.RESET, 4),
|
||||
(Fore.BLUE + "hello 世界" + Fore.RESET, 10),
|
||||
# termcolor
|
||||
(colored("hello, world", "blue"), 12),
|
||||
(colored("世界你好", "blue"), 8),
|
||||
(colored("蓝色", "blue"), 4),
|
||||
(colored("שלום", "blue"), 4),
|
||||
(colored("معرب", "blue"), 4),
|
||||
(colored("hello 世界", "blue"), 10),
|
||||
],
|
||||
)
|
||||
def test(string, expected):
|
||||
"""Test function with different color libraries.
|
||||
|
||||
|
|
65
tox.ini
65
tox.ini
|
@ -2,39 +2,23 @@
|
|||
name = terminaltables
|
||||
|
||||
[tox]
|
||||
envlist = lint,py{34,27,26}
|
||||
envlist = py{38,39,310,311,312,313}
|
||||
|
||||
[testenv]
|
||||
commands =
|
||||
python -c "import os, sys; sys.platform == 'win32' and os.system('easy_install pillow')"
|
||||
py.test --cov-report term-missing --cov-report xml --cov {[general]name} --cov-config tox.ini {posargs:tests}
|
||||
python -c "import os, sys; sys.version_info[:3] <= (3, 12, 0) and os.system('pip install pillow')"
|
||||
py.test --cov-report term-missing --cov-report xml --cov {[general]name} {posargs:tests}
|
||||
deps =
|
||||
colorama==0.3.7
|
||||
colorclass==2.2.0
|
||||
pytest-cov==2.4.0
|
||||
termcolor==1.1.0
|
||||
colorama>=0.3.7
|
||||
colorclass>=2.2.0
|
||||
pytest-cov>=2.4.0
|
||||
termcolor>=1.1.0
|
||||
passenv =
|
||||
WINDIR
|
||||
setenv =
|
||||
PYTHON_EGG_CACHE = {envtmpdir}
|
||||
usedevelop = True
|
||||
|
||||
[testenv:lint]
|
||||
commands =
|
||||
python setup.py check --strict
|
||||
python setup.py check --strict -m
|
||||
python setup.py check --strict -s
|
||||
python setup.py check_version
|
||||
flake8 --application-import-names={[general]name},tests
|
||||
pylint --rcfile=tox.ini setup.py {[general]name}
|
||||
deps =
|
||||
flake8-docstrings==1.0.3
|
||||
flake8-import-order==0.12
|
||||
flake8==3.3.0
|
||||
pep8-naming==0.4.1
|
||||
pydocstyle==1.1.1
|
||||
pylint==1.6.5
|
||||
|
||||
[testenv:docs]
|
||||
changedir = {toxinidir}/docs
|
||||
commands =
|
||||
|
@ -55,25 +39,24 @@ passenv =
|
|||
HOME
|
||||
HOSTNAME
|
||||
SSH_AUTH_SOCK
|
||||
TRAVIS*
|
||||
USER
|
||||
usedevelop = False
|
||||
;
|
||||
;[flake8]
|
||||
;exclude = .tox/*,build/*,docs/*,env/*,get-pip.py
|
||||
;import-order-style = smarkets
|
||||
;max-line-length = 120
|
||||
;statistics = True
|
||||
|
||||
[flake8]
|
||||
exclude = .tox/*,build/*,docs/*,env/*,get-pip.py
|
||||
import-order-style = smarkets
|
||||
max-line-length = 120
|
||||
statistics = True
|
||||
;[pylint]
|
||||
;disable =
|
||||
; locally-disabled,
|
||||
; too-few-public-methods,
|
||||
; too-many-instance-attributes,
|
||||
;ignore = .tox/*,build/*,docs/*,env/*,get-pip.py
|
||||
;max-args = 6
|
||||
;max-line-length = 120
|
||||
;reports = no
|
||||
|
||||
[pylint]
|
||||
disable =
|
||||
locally-disabled,
|
||||
too-few-public-methods,
|
||||
too-many-instance-attributes,
|
||||
ignore = .tox/*,build/*,docs/*,env/*,get-pip.py
|
||||
max-args = 6
|
||||
max-line-length = 120
|
||||
reports = no
|
||||
|
||||
[run]
|
||||
branch = True
|
||||
;[run]
|
||||
;branch = True
|
||||
|
|
Loading…
Add table
Reference in a new issue