[med-svn] [Git][python-team/packages/enlighten][upstream] New upstream version 1.11.1
Andreas Tille (@tille)
gitlab at salsa.debian.org
Thu Nov 3 12:46:15 GMT 2022
Andreas Tille pushed to branch upstream at Debian Python Team / packages / enlighten
Commits:
dc9fc186 by Andreas Tille at 2022-11-03T13:43:18+01:00
New upstream version 1.11.1
- - - - -
30 changed files:
- .github/workflows/tests.yml
- + .sourcery.yaml
- README.rst
- doc/api.rst
- doc/conf.py
- doc/examples.rst
- doc/index.rst
- doc/patterns.rst
- enlighten/__init__.py
- enlighten/_basecounter.py
- enlighten/_basemanager.py
- enlighten/_counter.py
- enlighten/_manager.py
- enlighten/_statusbar.py
- enlighten/_util.py
- enlighten/counter.py
- enlighten/manager.py
- examples/basic.py
- examples/context_manager.py
- examples/floats.py
- examples/ftp_downloader.py
- examples/multicolored.py
- pylintrc
- setup.cfg
- setup.py
- setup_helpers.py
- tests/__init__.py
- tests/test_manager.py
- tests/test_util.py
- tox.ini
Changes:
=====================================
.github/workflows/tests.yml
=====================================
@@ -49,10 +49,10 @@ jobs:
toxenv: el7
- python-version: pypy-2.7
- toxenv: pypy
+ toxenv: pypy27
- - python-version: pypy3
- toxenv: pypy3
+ - python-version: pypy-3.9
+ toxenv: pypy39
- python-version: '3.11-dev'
optional: true
=====================================
.sourcery.yaml
=====================================
@@ -0,0 +1,9 @@
+refactor:
+ skip:
+ - replace-interpolation-with-fstring # Python 3.6+
+ - use-contextlib-suppress # Python 3.4+ (Possibly less efficient)
+ - use-fstring-for-concatenation # Python 3.6+
+ - use-named-expression # Python 3.8+
+
+clone_detection:
+ min_lines: 4
\ No newline at end of file
=====================================
README.rst
=====================================
@@ -190,7 +190,7 @@ Advanced
To maintain multiple progress bars simultaneously or write to the console, a manager is required.
-Advanced output will only work when the output stream, ``sys.stdout`` by default,
+Advanced output will only work when the output stream, ``sys.__stdout__`` by default,
is attached to a TTY. get_manager_ can be used to get a manager instance.
It will return a disabled Manager_ instance if the stream is not attached to a TTY
and an enabled instance if it is.
=====================================
doc/api.rst
=====================================
@@ -1,5 +1,5 @@
..
- Copyright 2017 - 2020 Avram Lubkin, All Rights Reserved
+ Copyright 2017 - 2021 Avram Lubkin, All Rights Reserved
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
=====================================
doc/conf.py
=====================================
@@ -36,7 +36,7 @@ extensions = ['sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinx.ext.napoleon']
-if not os.environ.get('READTHEDOCS') == 'True':
+if os.environ.get('READTHEDOCS') != 'True':
extensions.append('sphinxcontrib.spelling')
# Add any paths that contain templates here, relative to this directory.
@@ -53,7 +53,7 @@ master_doc = 'index'
# General information about the project.
project = 'Enlighten'
-copyright = '2017 - 2021, Avram Lubkin'
+copyright = '2017 - 2022, Avram Lubkin'
author = 'Avram Lubkin'
# The version info for the project you're documenting, acts as replacement for
@@ -70,7 +70,7 @@ release = version
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
-language = None
+language = 'en'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
=====================================
doc/examples.rst
=====================================
@@ -1,5 +1,5 @@
..
- Copyright 2017 - 2021 Avram Lubkin, All Rights Reserved
+ Copyright 2017 - 2022 Avram Lubkin, All Rights Reserved
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -31,7 +31,7 @@ Advanced
To maintain multiple progress bars simultaneously or write to the console, a manager is required.
-Advanced output will only work when the output stream, :py:data:`sys.stdout` by default,
+Advanced output will only work when the output stream, :py:data:`sys.__stdout__` by default,
is attached to a TTY. :py:func:`~enlighten.get_manager` can be used to get a manager instance.
It will return a disabled :py:class:`~enlighten.Manager` instance if the stream is not attached to a TTY
and an enabled instance if it is.
=====================================
doc/index.rst
=====================================
@@ -1,5 +1,5 @@
..
- Copyright 2017 Avram Lubkin, All Rights Reserved
+ Copyright 2017 - 2021 Avram Lubkin, All Rights Reserved
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
=====================================
doc/patterns.rst
=====================================
@@ -1,5 +1,5 @@
..
- Copyright 2017 - 2021 Avram Lubkin, All Rights Reserved
+ Copyright 2017 - 2022 Avram Lubkin, All Rights Reserved
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -35,7 +35,7 @@ The :py:func:`~enlighten.get_manager` function slightly simplifies this
import enlighten
# Example configuration object
- config = {'stream': None, # Defaults to sys.stdout
+ config = {'stream': None, # Defaults to sys.__stdout__
'useCounter': False}
manager = enlighten.get_manager(stream=config['stream'], enabled=config['useCounter'])
=====================================
enlighten/__init__.py
=====================================
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2017 - 2021 Avram Lubkin, All Rights Reserved
+# Copyright 2017 - 2022 Avram Lubkin, All Rights Reserved
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -16,7 +16,7 @@ from enlighten.manager import Manager, get_manager
from enlighten._util import EnlightenWarning, Justify
-__version__ = '1.10.2'
+__version__ = '1.11.1'
__all__ = ['Counter', 'EnlightenWarning', 'Justify', 'Manager',
'StatusBar', 'SubCounter', 'get_manager', 'NotebookManager']
=====================================
enlighten/_basecounter.py
=====================================
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2017 - 2020 Avram Lubkin, All Rights Reserved
+# Copyright 2017 - 2022 Avram Lubkin, All Rights Reserved
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -104,12 +104,8 @@ class BaseCounter(object):
If no color is specified for this instance, the content is returned unmodified
"""
- # No color specified
- if self._color is None:
- return content
-
- # Used spec cached by color.setter
- return self._color[1](content)
+ # Used spec cached by color.setter if available
+ return content if self._color is None else self._color[1](content)
def update(self, *args, **kwargs):
"""
=====================================
enlighten/_basemanager.py
=====================================
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2017 - 2021 Avram Lubkin, All Rights Reserved
+# Copyright 2017 - 2022 Avram Lubkin, All Rights Reserved
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -26,7 +26,7 @@ class BaseManager(object):
Args:
stream(:py:term:`file object`): Output stream. If :py:data:`None`,
- defaults to :py:data:`sys.stdout`
+ defaults to :py:data:`sys.__stdout__`
status_bar_class(:py:term:`class`): Status bar class (Default: :py:class:`StatusBar`)
counter_class(:py:term:`class`): Progress bar class (Default: :py:class:`Counter`)
set_scroll(bool): Enable scroll area redefinition (Default: :py:data:`True`)
@@ -54,7 +54,7 @@ class BaseManager(object):
self.no_resize = kwargs.pop('no_resize', False)
self.set_scroll = kwargs.pop('set_scroll', True)
self.status_bar_class = kwargs.pop('status_bar_class', StatusBar)
- self.stream = kwargs.pop('stream', sys.stdout)
+ self.stream = kwargs.pop('stream', sys.__stdout__)
self.threaded = kwargs.pop('threaded', None)
self._width = kwargs.pop('width', None)
=====================================
enlighten/_counter.py
=====================================
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2017 - 2021 Avram Lubkin, All Rights Reserved
+# Copyright 2017 - 2022 Avram Lubkin, All Rights Reserved
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -183,7 +183,7 @@ class Counter(PrintableCounter):
A :py:class:`Counter` instance can be created with the :py:meth:`Manager.counter` method
or, when a standalone progress bar for simple applications is required, the :py:class:`Counter`
- class can be called directly. The output stream will default to :py:data:`sys.stdout` unless
+ class can be called directly. The output stream will default to :py:data:`sys.__stdout__` unless
``stream`` is set.
.. note::
@@ -433,7 +433,7 @@ class Counter(PrintableCounter):
"""
# pylint: disable=too-many-instance-attributes
- __slots__ = ('all_fields', 'bar_format', 'counter_format', 'desc', 'fields', 'manager',
+ __slots__ = ('all_fields', 'bar_format', 'counter_format', 'desc', 'fields',
'offset', 'series', 'total', 'unit', '_fields', '_subcounters')
_repr_attrs = ('desc', 'total', 'count', 'unit', 'color')
@@ -508,11 +508,7 @@ class Counter(PrintableCounter):
fields['count_%d' % num] = Float(count) if force_float else count
- if self.total and bar_fields:
- subPercentage = count / float(self.total)
- else:
- subPercentage = 0.0
-
+ subPercentage = count / float(self.total) if self.total and bar_fields else 0.0
if bar_fields:
fields['percentage_%d' % num] = subPercentage * 100
@@ -696,13 +692,8 @@ class Counter(PrintableCounter):
percentage = self.count / float(self.total)
rate = fields['rate']
- # Get eta
- if rate:
- # Use iterations so a counter running backwards is accurate
- fields['eta'] = format_time((self.total - iterations) / rate)
- else:
- fields['eta'] = u'?'
-
+ # Get eta. Use iterations so a counter running backwards is accurate
+ fields['eta'] = format_time((self.total - iterations) / rate) if rate else u'?'
fields['percentage'] = percentage * 100
# Have to go through subcounters here so the fields are available
=====================================
enlighten/_manager.py
=====================================
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2017 - 2021 Avram Lubkin, All Rights Reserved
+# Copyright 2017 - 2022 Avram Lubkin, All Rights Reserved
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -30,7 +30,7 @@ class Manager(BaseManager):
Args:
stream(:py:term:`file object`): Output stream. If :py:data:`None`,
- defaults to :py:data:`sys.stdout`
+ defaults to :py:data:`sys.__stdout__`
status_bar_class(:py:term:`class`): Status bar class (Default: :py:class:`StatusBar`)
counter_class(:py:term:`class`): Progress bar class (Default: :py:class:`Counter`)
set_scroll(bool): Enable scroll area redefinition (Default: :py:data:`True`)
@@ -57,9 +57,8 @@ class Manager(BaseManager):
the primary output stream. The cursor position in the companion stream will be
moved in coordination with the primary stream.
- If the value is :py:data:`None`, :py:data:`sys.stdout` and :py:data:`sys.stderr` will
- be used as companion streams. Unless explicitly
- specified, a stream which is not attached to a TTY (the case when
+ If the value is :py:data:`None`, the companion stream will be dynamically determined.
+ Unless explicitly specified, a stream which is not attached to a TTY (the case when
redirected to a file), will not be used as a companion stream.
"""
=====================================
enlighten/_statusbar.py
=====================================
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2017 - 2020 Avram Lubkin, All Rights Reserved
+# Copyright 2017 - 2021 Avram Lubkin, All Rights Reserved
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
=====================================
enlighten/_util.py
=====================================
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright 2017 - 2020 Avram Lubkin, All Rights Reserved
+# Copyright 2017 - 2022 Avram Lubkin, All Rights Reserved
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -19,10 +19,17 @@ import re
import sys
import warnings
-from blessed.colorspace import RGB_256TABLE
+from blessed.colorspace import RGB_256TABLE, X11_COLORNAMES_TO_RGB
from blessed.sequences import iter_parse
+try:
+ from functools import lru_cache
+except ImportError: # pragma: no cover(Python 2)
+ # lru_cache was added in Python 3.2
+ from backports.functools_lru_cache import lru_cache
+
+
try:
BASESTRING = basestring
except NameError:
@@ -136,25 +143,23 @@ class Lookahead:
return self
def __next__(self):
- if self.buffer:
- return self.buffer.pop(0)
- return next(self.iterator)
+ return self.buffer.pop(0) if self.buffer else next(self.iterator)
# Python 2
next = __next__
- def lookahead(self, start, stop=None):
- """
- Args:
- start(int): Positive integer index of first value
- stop(int): Positive integer index to end before (not returned)
-
- Retrieve next value(s) in iterator.
+ def __getitem__(self, key):
- start and stop roughly behave like slice notation, but must be positive
- """
+ if isinstance(key, int):
+ first = last = key
+ elif isinstance(key, slice):
+ first = key.start or 0
+ last = max(first, (key.stop or 0) - 1)
+ else:
+ raise TypeError('Index or slice notation is required')
- last = max(start, (stop or 0) - 1)
+ if first < 0:
+ raise ValueError('Negative indexes are not supported')
while last >= len(self.buffer):
try:
@@ -162,10 +167,7 @@ class Lookahead:
except StopIteration:
break
- if stop is None:
- return self.buffer[start]
-
- return self.buffer[start:stop]
+ return self.buffer.__getitem__(key)
class Span(list):
@@ -269,8 +271,7 @@ class HTMLConverter(object):
last_added = to_out[-1] if to_out else None
# Look for normal to close span
- if value == normal[0] and \
- normal[1:] == [val[0] for val in parsed.lookahead(0, self.normal_rem or None)]:
+ if value == normal[0] and normal[1:] == [val[0] for val in parsed[: self.normal_rem]]:
# Clear rest of normal
for _ in range(self.normal_rem):
@@ -323,6 +324,38 @@ class HTMLConverter(object):
4: ('enlighten-underline', {'text-decoration': 'underline'}),
}
+ @property
+ @lru_cache()
+ def rgb_to_colors(self):
+ """
+ Dictionary for translating known RGB values into X11 names
+ """
+
+ rtn = {}
+ for key, val in sorted(X11_COLORNAMES_TO_RGB.items()):
+ val = '#%02x%02x%02x' % val
+ if val not in rtn:
+ rtn[val] = key
+
+ return rtn
+
+ def _color256_lookup(self, idx):
+ """
+ Look up RGB values and attempt to get names in the 256 color space
+ """
+
+ rgb = str(RGB_256TABLE[idx])
+
+ # Some terminals use 256 color syntax for basic colors
+ if 0 <= idx <= 7: # pragma: no cover(Non-standard Terminal)
+ name = CGA_COLORS[idx]
+ elif 8 <= idx <= 15: # pragma: no cover(Non-standard Terminal)
+ name = 'bright-%s' % CGA_COLORS[idx - 8]
+ else:
+ name = self.rgb_to_colors.get((rgb[1:3], rgb[3:5], rgb[5:7]), rgb[1:])
+ return name, rgb
+
+ @lru_cache(maxsize=256)
def _parse_style(self, value, cap): # pylint: disable=too-many-return-statements
r"""
Args:
@@ -337,12 +370,14 @@ class HTMLConverter(object):
# Parse RGB color foreground
if cap is caps['color_rgb']:
rgb = '#%02x%02x%02x' % tuple(int(num) for num in RE_COLOR_RGB.match(value).groups())
- return 'enlighten-fg-%s' % rgb[1:], {'color': rgb}
+ name = self.rgb_to_colors.get(rgb, rgb[1:])
+ return 'enlighten-fg-%s' % name, {'color': rgb}
# Parse RGB color background
if cap is caps['on_color_rgb']:
rgb = '#%02x%02x%02x' % tuple(int(num) for num in RE_ON_COLOR_RGB.match(value).groups())
- return 'enlighten-bg-%s' % rgb[1:], {'background-color': rgb}
+ name = self.rgb_to_colors.get(rgb, rgb[1:])
+ return 'enlighten-bg-%s' % name, {'background-color': rgb}
# Weird and inconsistent bug that seems to affect Python <= 3.5
# Matches set_a_attributes3 instead of more specific color 256 patterns
@@ -354,13 +389,13 @@ class HTMLConverter(object):
# Parse 256 color foreground
if cap is caps['color256']:
- rgb = str(RGB_256TABLE[int(RE_COLOR_256.match(value).group(1))])
- return 'enlighten-fg-%s' % rgb[1:], {'color': rgb}
+ name, rgb = self._color256_lookup(int(RE_COLOR_256.match(value).group(1)))
+ return 'enlighten-fg-%s' % name, {'color': rgb}
# Parse 256 color background
if cap is caps['on_color256']:
- rgb = str(RGB_256TABLE[int(RE_ON_COLOR_256.match(value).group(1))])
- return 'enlighten-bg-%s' % rgb[1:], {'background-color': rgb}
+ name, rgb = self._color256_lookup(int(RE_ON_COLOR_256.match(value).group(1)))
+ return 'enlighten-bg-%s' % name, {'background-color': rgb}
# Parse text attributes
if cap is caps['set_a_attributes1']:
=====================================
enlighten/counter.py
=====================================
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2017 - 2020 Avram Lubkin, All Rights Reserved
+# Copyright 2017 - 2022 Avram Lubkin, All Rights Reserved
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -21,13 +21,14 @@ from enlighten.manager import get_manager
# Counter is defined here to avoid circular dependencies
class Counter(_Counter): # pylint: disable=missing-docstring
+ # pylint: disable=too-many-instance-attributes
__doc__ = _Counter.__doc__
def __init__(self, **kwargs):
- manager = kwargs.get('manager', None)
- stream = kwargs.pop('stream', sys.stdout)
+ manager = kwargs.get('manager')
+ stream = kwargs.pop('stream', sys.__stdout__)
if manager is None:
manager = get_manager(stream=stream, counter_class=self.__class__, set_scroll=False)
=====================================
enlighten/manager.py
=====================================
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2017 - 2021 Avram Lubkin, All Rights Reserved
+# Copyright 2017 - 2022 Avram Lubkin, All Rights Reserved
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -29,7 +29,7 @@ def get_manager(stream=None, counter_class=Counter, **kwargs):
"""
Args:
stream(:py:term:`file object`): Output stream. If :py:data:`None`,
- defaults to :py:data:`sys.stdout`
+ defaults to :py:data:`sys.__stdout__`
counter_class(:py:term:`class`): Progress bar class (Default: :py:class:`Counter`)
kwargs(Dict[str, Any]): Any additional :py:term:`keyword arguments<keyword argument>`
will passed to the manager class.
@@ -49,7 +49,7 @@ def get_manager(stream=None, counter_class=Counter, **kwargs):
if IN_NOTEBOOK:
return NotebookManager(stream=stream, counter_class=counter_class, **kwargs)
- stream = sys.stdout if stream is None else stream
+ stream = sys.__stdout__ if stream is None else stream
isatty = hasattr(stream, 'isatty') and stream.isatty()
kwargs['enabled'] = isatty and kwargs.get('enabled', True)
return Manager(stream=stream, counter_class=counter_class, **kwargs)
=====================================
examples/basic.py
=====================================
@@ -1,4 +1,4 @@
-# Copyright 2017 Avram Lubkin, All Rights Reserved
+# Copyright 2017 - 2020 Avram Lubkin, All Rights Reserved
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
=====================================
examples/context_manager.py
=====================================
@@ -1,4 +1,4 @@
-# Copyright 2017 Avram Lubkin, All Rights Reserved
+# Copyright 2017 - 2020 Avram Lubkin, All Rights Reserved
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
=====================================
examples/floats.py
=====================================
@@ -1,4 +1,4 @@
-# Copyright 2017 Avram Lubkin, All Rights Reserved
+# Copyright 2017 - 2020 Avram Lubkin, All Rights Reserved
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
=====================================
examples/ftp_downloader.py
=====================================
@@ -1,4 +1,4 @@
-# Copyright 2018 Avram Lubkin, All Rights Reserved
+# Copyright 2018 - 2021 Avram Lubkin, All Rights Reserved
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
=====================================
examples/multicolored.py
=====================================
@@ -1,4 +1,4 @@
-# Copyright 2019 - 2021 Avram Lubkin, All Rights Reserved
+# Copyright 2019 - 2022 Avram Lubkin, All Rights Reserved
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -105,7 +105,7 @@ def run_tests(manager, tests=100):
if result == 7:
LOGGER.error("Test %d did not complete", num)
errors.update()
- elif result in (5, 6):
+ elif result in {5, 6}:
LOGGER.error("Test %d failed", num)
failures.update()
else:
=====================================
pylintrc
=====================================
@@ -1,16 +1,30 @@
[REPORTS]
+
+# 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=colorized
+
[FORMAT]
+
# Use max line length of 100
max-line-length=100
+# Regexp for a line that is allowed to be longer than the limit.
+# URLs and pure strings
+ignore-long-lines=^\s*(# )?<?https?://\S+>?$|^\s*[f|r|u]?b?[\"\'\`].+[\"\'\`]$
+
+
[DESIGN]
+
# Maximum number of branch for function / method body.
max-branches=15
+
[BASIC]
+
# As far as I can tell, PEP-8 (Nov 1, 2013) does not specify
# a specific naming convention for variables and arguments
# prefer mixedcase, starting with a lowercase or underscore
@@ -19,7 +33,22 @@ variable-rgx=[a-z_][A-Za-z0-9_]{1,29}[A-Za-z0-9_]$
# Good variable names which should always be accepted, separated by a comma.
good-names=e,_
+# Regular expression which should only match function or class names that do
+# not require a docstring.
+no-docstring-rgx=__.*__
+
+
[MESSAGES CONTROL]
+
+# 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=
consider-using-f-string, # Python 2
redundant-u-string-prefix, # Python 2
@@ -27,10 +56,13 @@ disable=
too-few-public-methods,
useless-object-inheritance, # Python 2
+
[SIMILARITIES]
+
# Minimum lines number of a similarity.
min-similarity-lines=8
+
[SPELLING]
# Spelling dictionary name. Available dictionaries: en_US (myspell).
=====================================
setup.cfg
=====================================
@@ -10,11 +10,11 @@ python_files = test_*.py
testpaths = tests
[flake8]
-max-line-length = 100
+max-line-length = 110
exclude = .svn,CVS,.bzr,.hg,.git,__pycache__,.tox,.eggs,*.egg,build,notes
[pycodestyle]
-max-line-length = 100
+max-line-length = 110
[coverage:run]
branch = True
=====================================
setup.py
=====================================
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-# Copyright 2017 - 2021 Avram Lubkin, All Rights Reserved
+# Copyright 2017 - 2022 Avram Lubkin, All Rights Reserved
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -17,7 +17,11 @@ from setuptools import setup, find_packages
from setup_helpers import get_version, readme
-INSTALL_REQUIRES = ['blessed>=1.17.7', 'prefixed>=0.3.2']
+INSTALL_REQUIRES = [
+ 'blessed>=1.17.7',
+ 'prefixed>=0.3.2',
+ 'backports.functools-lru-cache; python_version < "3.2"'
+]
TESTS_REQUIRE = ['mock; python_version < "3.3"']
# Additional requirements
=====================================
setup_helpers.py
=====================================
@@ -1,4 +1,4 @@
-# Copyright 2017 - 2020 Avram Lubkin, All Rights Reserved
+# Copyright 2017 - 2022 Avram Lubkin, All Rights Reserved
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -8,9 +8,11 @@
Functions to help with build and setup
"""
+import datetime
import io
import os
import re
+import subprocess
import sys
@@ -107,6 +109,95 @@ def check_rst2html(path):
return 0
+def check_copyrights():
+ """
+ Check files recursively to ensure year of last change is in copyright line
+ """
+
+ this_year = str(datetime.date.today().year)
+ changed_now = []
+
+ # Get list of changed files
+ process = subprocess.run(
+ ('git', 'status', '--porcelain=1'), stdout=subprocess.PIPE, check=True, text=True
+ )
+ for entry in process.stdout.splitlines():
+ filename = entry[3:].strip()
+
+ # Get changes for file
+ process = subprocess.run(
+ ('git', 'diff', '-U0', filename), stdout=subprocess.PIPE, check=True, text=True
+ )
+
+ # Find files with changes that aren't only for copyright
+ for line in process.stdout.splitlines():
+ if line[0] != '+' or line[:3] == '+++': # Ignore anything but the new contents
+ continue
+
+ if re.search(r'copyright.*20\d\d', line, re.IGNORECASE): # Ignore copyright line
+ continue
+
+ changed_now.append(filename)
+ break
+
+ # Look for copyright lines
+ process = subprocess.run(
+ ('git', 'grep', '-i', 'copyright'), stdout=subprocess.PIPE, check=True, text=True
+ )
+
+ rtn = 0
+ for entry in process.stdout.splitlines():
+
+ modified = None
+
+ # Get the year in the copyright line
+ match = re.match(r'([^:]+):.*(20\d\d)', entry)
+ if match:
+ filename, year = match.groups()
+
+ # If files is in current changes, use this year
+ if filename in changed_now:
+ modified = this_year
+
+ # Otherwise, try to get the year of last commit that wasn't only updating copyright
+ else:
+ git_log = subprocess.run(
+ ('git', '--no-pager', 'log', '-U0', filename),
+ stdout=subprocess.PIPE, check=True, text=True
+ )
+
+ for line in git_log.stdout.splitlines():
+
+ # Get year
+ if line.startswith('Date: '):
+ modified = line.split()[5]
+
+ # Skip blank line and lines that aren't changes
+ if not line.strip() or line[0] != '+' or line[:3] == '+++':
+ continue
+
+ # Stop looking on the first line we hit that isn't a copyright
+ if re.search(r'copyright.*20\d\d', line, re.IGNORECASE) is None:
+ break
+
+ # Special case for Sphinx configuration
+ if filename == 'doc/conf.py' and modified != this_year:
+
+ # Get the latest change date for docs
+ process = subprocess.run(
+ ('git', 'log', '-1', '--pretty=format:%cs', 'doc/*.rst'),
+ stdout=subprocess.PIPE, check=True, text=True
+ )
+ modified = process.stdout[:4]
+
+ # Compare modified date to copyright year
+ if modified and modified != year:
+ rtn = 1
+ print('%s [%s]' % (entry, modified))
+
+ return rtn
+
+
if __name__ == '__main__':
# Do nothing if no arguments were given
@@ -131,6 +222,10 @@ if __name__ == '__main__':
sys.exit('Missing filename for ReST to HTML check')
sys.exit(check_rst2html(sys.argv[2]))
+ # Print misspelled word list
+ if sys.argv[1] == 'copyright':
+ sys.exit(check_copyrights())
+
# Unknown option
else:
sys.stderr.write('Unknown option: %s' % sys.argv[1])
=====================================
tests/__init__.py
=====================================
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2017 - 2018 Avram Lubkin, All Rights Reserved
+# Copyright 2017 - 2022 Avram Lubkin, All Rights Reserved
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -24,23 +24,15 @@ from enlighten._basecounter import BaseCounter
from enlighten._counter import Counter
from enlighten._statusbar import StatusBar
-# pylint: disable=import-error
+
if sys.version_info[:2] < (3, 3):
import mock
else:
from unittest import mock # noqa: F401 # pylint: disable=no-name-in-module
-if sys.version_info[0] < 3:
- from StringIO import StringIO
- PY2 = True
-else:
- from io import StringIO
- PY2 = False
-
-# pylint: enable=import-error
-
-OUTPUT = StringIO()
+PY2 = sys.version_info[0] < 3
+OUTPUT = io.StringIO()
os.environ['TERM'] = 'xterm-256color' # Default to xterm-256color
=====================================
tests/test_manager.py
=====================================
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2017 - 2021 Avram Lubkin, All Rights Reserved
+# Copyright 2017 - 2022 Avram Lubkin, All Rights Reserved
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -39,7 +39,7 @@ class TestManager(TestCase):
def test_init_safe(self):
with redirect_output('stdout', self.tty.stdout):
# Companion stream is stderr if stream is stdout
- manager = enlighten.Manager()
+ manager = enlighten.Manager(stream=sys.stdout)
self.assertIs(manager.stream, sys.stdout)
self.assertIs(manager.term.stream, sys.stdout)
@@ -52,8 +52,8 @@ class TestManager(TestCase):
mock_stderr.isatty.return_value = True
manager = enlighten.Manager(stream=sys.__stdout__)
- self.assertIs(manager.stream, sys.stdout)
- self.assertIs(manager.term.stream, sys.stdout)
+ self.assertIs(manager.stream, sys.__stdout__)
+ self.assertIs(manager.term.stream, sys.__stdout__)
self.assertIs(manager.companion_stream, mock_stderr)
self.assertIs(manager.companion_term.stream, mock_stderr)
@@ -86,7 +86,7 @@ class TestManager(TestCase):
# Need to mock isatty() for some build and test environments
with mock.patch.object(sys, 'stderr') as mock_stderr:
mock_stderr.isatty.return_value = True
- manager = enlighten.Manager()
+ manager = enlighten.Manager(stream=sys.stdout)
self.assertIs(manager.stream, sys.stdout)
self.assertIs(manager.term.stream, sys.stdout)
@@ -136,7 +136,7 @@ class TestManager(TestCase):
def test_repr(self):
manager = enlighten.Manager()
- self.assertEqual(repr(manager), "Manager(stream=%r)" % sys.stdout)
+ self.assertEqual(repr(manager), "Manager(stream=%r)" % sys.__stdout__)
def test_counter_and_remove(self):
# pylint: disable=no-member,assigning-non-slot
@@ -986,8 +986,8 @@ class TestGetManager(TestCase):
def test_get_manager_tty(self):
# stdout is attached to a tty
- with redirect_output('stdout', self.tty.stdout):
- self.assertTrue(sys.stdout.isatty())
+ with redirect_output('__stdout__', self.tty.stdout):
+ self.assertTrue(sys.__stdout__.isatty())
manager = enlighten.get_manager(unit='knights')
self.assertIsInstance(manager, _manager.Manager)
self.assertTrue('unit' in manager.defaults)
@@ -999,8 +999,8 @@ class TestGetManager(TestCase):
def test_get_manager_no_tty(self):
# stdout is not attached to a tty
- with redirect_output('stdout', OUTPUT):
- self.assertFalse(sys.stdout.isatty())
+ with redirect_output('__stdout__', OUTPUT):
+ self.assertFalse(sys.__stdout__.isatty())
manager = enlighten.get_manager(unit='knights')
self.assertIsInstance(manager, _manager.Manager)
self.assertTrue('unit' in manager.defaults)
=====================================
tests/test_util.py
=====================================
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2017 - 2020 Avram Lubkin, All Rights Reserved
+# Copyright 2017 - 2022 Avram Lubkin, All Rights Reserved
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -63,29 +63,42 @@ class TestLookahead(TestCase):
self.assertEqual([next(wrapped) for _ in range(10)], list(range(10)))
- def test_lookahead(self):
- """Verify lookahead() behavior"""
+ def test_getitem(self):
+ """Verify __getitem__ behavior"""
wrapped = Lookahead(iter(range(10)))
- self.assertEqual(wrapped.lookahead(0), 0)
- self.assertEqual(wrapped.lookahead(4), 4)
- self.assertEqual(wrapped.lookahead(2, 4), [2, 3])
- self.assertEqual(wrapped.lookahead(8, 12), [8, 9])
+ self.assertEqual(wrapped[0], 0)
+ self.assertEqual(wrapped[4], 4)
+ self.assertEqual(wrapped[2: 4], [2, 3])
+ self.assertEqual(wrapped[8: 12], [8, 9])
- def test_lookahead_iteration(self):
- """lookahead() output changes as iteration proceeds"""
+ with self.assertRaisesRegex(TypeError, 'Index or slice notation is required'):
+ wrapped['named_key'] # pylint: disable=pointless-statement
+
+ with self.assertRaisesRegex(ValueError, 'Negative indexes are not supported'):
+ wrapped[-1] # pylint: disable=pointless-statement
+
+ def test_buffer(self):
+ """Output changes as iteration proceeds"""
wrapped = Lookahead(iter(range(10)))
self.assertEqual(next(wrapped), 0)
- self.assertEqual(wrapped.lookahead(0), 1)
+ self.assertEqual(wrapped[0], 1)
self.assertEqual(next(wrapped), 1)
- self.assertEqual(wrapped.lookahead(4), 6)
+ self.assertEqual(wrapped[4], 6)
self.assertEqual(next(wrapped), 2)
- self.assertEqual(wrapped.lookahead(2, 4), [5, 6])
+ self.assertEqual(wrapped[2: 4], [5, 6])
self.assertEqual(next(wrapped), 3)
- self.assertEqual(wrapped.lookahead(8, 12), [])
+ self.assertEqual(wrapped[8: 12], [])
+
+ def test_step_notation(self):
+ """Slice notation is supported"""
+
+ wrapped = Lookahead(iter(range(10)))
+
+ self.assertEqual(wrapped[: 6: 2], [0, 2, 4])
class TestHTMLConverter(TestCase):
@@ -99,7 +112,7 @@ class TestHTMLConverter(TestCase):
def setUpClass(cls):
cls.tty = MockTTY()
cls.term = blessed.Terminal(
- stream=cls.tty.stdout, kind='xterm-256color', force_styling=True
+ stream=cls.tty.stdout, force_styling=True
)
cls.term.number_of_colors = 1 << 24
@@ -117,22 +130,22 @@ class TestHTMLConverter(TestCase):
out = self.converter.to_html(self.term.blue_on_aquamarine('blue_on_aquam'))
self.assertEqual(
out,
- '<pre><span class="enlighten-fg-blue enlighten-bg-7fffd4">blue_on_aquam</span></pre>'
+ u'<pre><span class="enlighten-fg-blue enlighten-bg-aquamarine">blue_on_aquam</span></pre>'
)
self.assertEqual(self.converter._styles['enlighten-fg-blue'], {'color': '#0000ee'})
self.assertEqual(
- self.converter._styles['enlighten-bg-7fffd4'], {'background-color': '#7fffd4'}
+ self.converter._styles['enlighten-bg-aquamarine'], {'background-color': '#7fffd4'}
)
# RGB color on CGA color
out = self.converter.to_html(self.term.aquamarine_on_blue('aquam_on_blue'))
self.assertEqual(
out,
- '<pre><span class="enlighten-fg-7fffd4 enlighten-bg-blue">aquam_on_blue</span></pre>'
+ u'<pre><span class="enlighten-fg-aquamarine enlighten-bg-blue">aquam_on_blue</span></pre>'
)
- self.assertEqual(self.converter._styles['enlighten-fg-7fffd4'], {'color': '#7fffd4'})
+ self.assertEqual(self.converter._styles['enlighten-fg-aquamarine'], {'color': '#7fffd4'})
self.assertEqual(
self.converter._styles['enlighten-bg-blue'], {'background-color': '#0000ee'}
)
@@ -199,20 +212,6 @@ class TestHTMLConverter(TestCase):
self.converter._styles['enlighten-underline'], {'text-decoration': 'underline'}
)
- # Blink
- out = self.converter.to_html(self.term.blink('blink'))
- self.assertEqual(out, '<pre><span class="enlighten-blink">blink</span></pre>')
-
- self.assertEqual(
- self.converter._additional_styles,
- {'@keyframes enlighten-blink-animation {\n to {\n visibility: hidden;\n }\n}'}
- )
-
- self.assertEqual(
- self.converter._styles['enlighten-blink'],
- {'animation': 'enlighten-blink-animation 1s steps(5, start) infinite'}
- )
-
def test_unsupported(self):
"""Verify unsupported does not produce classes"""
@@ -247,7 +246,7 @@ class TestHTMLConverter(TestCase):
out = self.converter.to_html(self.term.blue_on_aquamarine(self.term.blue('blue_on_aquam')))
self.assertEqual(
out,
- '<pre><span class="enlighten-fg-blue enlighten-bg-7fffd4">blue_on_aquam</span></pre>'
+ u'<pre><span class="enlighten-fg-blue enlighten-bg-aquamarine">blue_on_aquam</span></pre>'
)
def test_style_output(self):
@@ -257,7 +256,7 @@ class TestHTMLConverter(TestCase):
self.assertEqual(
out,
- '<pre><span class="enlighten-fg-red enlighten-bg-708090">red_on_slategrey</span></pre>'
+ u'<pre><span class="enlighten-fg-red enlighten-bg-slategray">red_on_slategrey</span></pre>'
)
style = '''\
@@ -265,7 +264,7 @@ class TestHTMLConverter(TestCase):
.enlighten-fg-red {
color: #cd0000;
}
- .enlighten-bg-708090 {
+ .enlighten-bg-slategray {
background-color: #708090;
}
</style>
@@ -273,12 +272,25 @@ class TestHTMLConverter(TestCase):
self.assertEqual(self.converter.style, dedent(style))
- def test_style_output_additional(self):
- """Verify style section output with additional sections"""
+ def test_blink(self):
+ """Blink requires an additional style section"""
+
+ if not self.term.blink:
+ self.skipTest('blink is not supported by this terminal')
out = self.converter.to_html(self.term.blink('blink'))
self.assertEqual(out, '<pre><span class="enlighten-blink">blink</span></pre>')
+ self.assertEqual(
+ self.converter._additional_styles,
+ {'@keyframes enlighten-blink-animation {\n to {\n visibility: hidden;\n }\n}'}
+ )
+
+ self.assertEqual(
+ self.converter._styles['enlighten-blink'],
+ {'animation': 'enlighten-blink-animation 1s steps(5, start) infinite'}
+ )
+
style = '''\
<style>
.enlighten-blink {
=====================================
tox.ini
=====================================
@@ -2,15 +2,17 @@
ignore_basepython_conflict = True
envlist =
lint
+ copyright
coverage
docs
el7
- py{27,35,36,37,38,39,py,py3}
+ py{27,36,37,38,39,py27,py38}
[base]
deps =
blessed
prefixed
+ py{27,py27}: backports.functools-lru-cache
[ipython]
deps =
@@ -26,7 +28,7 @@ ignore_errors = True
deps =
{[base]deps}
- py{27,py}: mock
+ py{27,py27}: mock
commands =
{envpython} -m unittest discover -s {toxinidir}/tests {posargs}
@@ -39,6 +41,7 @@ deps =
prefixed == 0.3.2
# setuptools == 0.9.8 (Doesn't support PEP 508)
setuptools == 20.2.2
+ backports.functools-lru-cache == 1.2.1
[testenv:flake8]
skip_install = True
@@ -73,6 +76,13 @@ commands =
{envpython} -m nbqa flake8 tests
{envpython} -m nbqa pylint tests
+[testenv:copyright]
+skip_install = True
+ignore_errors = True
+
+commands =
+ {envpython} setup_helpers.py copyright
+
[testenv:lint]
skip_install = True
ignore_errors = True
View it on GitLab: https://salsa.debian.org/python-team/packages/enlighten/-/commit/dc9fc186bc38d53b1161aabde827c4e19d08c269
--
View it on GitLab: https://salsa.debian.org/python-team/packages/enlighten/-/commit/dc9fc186bc38d53b1161aabde827c4e19d08c269
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20221103/49b47f45/attachment-0001.htm>
More information about the debian-med-commit
mailing list