Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v1.4 #33

Merged
merged 8 commits into from Feb 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion .appveyor.yml
@@ -1,6 +1,5 @@
environment:
global:
POETRY_PREVIEW: 1
RANDOM_SEED: 0
matrix:
- PYTHON_MAJOR: 3
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -3,6 +3,7 @@
*.egg-info
__pycache__
.ipynb_checkpoints
setup.py

# Temporary OS files
Icon*
Expand Down
1 change: 0 additions & 1 deletion .travis.yml
Expand Up @@ -13,7 +13,6 @@ cache:

env:
global:
- POETRY_PREVIEW=1
- RANDOM_SEED=0

before_install:
Expand Down
4 changes: 2 additions & 2 deletions .verchew.ini
Expand Up @@ -6,12 +6,12 @@ version = GNU Make
[Python]

cli = python
version = 3.8 || 3.7 || 3.6
version = 3.6 || 3.7 || 3.8

[Poetry]

cli = poetry
version = 1.0 || 0.12
version = 1

[Graphviz]

Expand Down
6 changes: 5 additions & 1 deletion CHANGELOG.md
@@ -1,3 +1,7 @@
# 1.4 (2020-02-15)

- Deprecated `reset=True` option for `log.init()` in favor of a separate `log.reset()` function.

# 1.3 (2019-11-27)

- Added support for Python 3.8.
Expand Down Expand Up @@ -70,4 +74,4 @@

# 0.1 (2018-03-03)

- Initial release.
- Initial release.
6 changes: 3 additions & 3 deletions Makefile
Expand Up @@ -41,7 +41,7 @@ DEPENDENCIES := $(VIRTUAL_ENV)/.poetry-$(shell bin/checksum pyproject.toml poetr
install: $(DEPENDENCIES) .cache

$(DEPENDENCIES): poetry.lock
@ poetry config virtualenvs.in-project true || poetry config settings.virtualenvs.in-project true
@ poetry config virtualenvs.in-project true
poetry install
@ touch $@

Expand Down Expand Up @@ -146,8 +146,8 @@ docs/*.png: $(MODULES)
- mv -f classes_$(PACKAGE).png docs/classes.png
- mv -f packages_$(PACKAGE).png docs/packages.png

.PHONY: mkdocs-live
mkdocs-live: mkdocs
.PHONY: mkdocs-serve
mkdocs-serve: mkdocs
eval "sleep 3; bin/open http://127.0.0.1:8000" &
poetry run mkdocs serve

Expand Down
13 changes: 8 additions & 5 deletions bin/checksum
Expand Up @@ -6,14 +6,17 @@ import sys


def run(paths):
hash_md5 = hashlib.md5()
sha = hashlib.sha1()

for path in paths:
with open(path, 'rb') as f:
for chunk in iter(lambda: f.read(4096), b''):
hash_md5.update(chunk)
try:
with open(path, 'rb') as f:
for chunk in iter(lambda: f.read(4096), b''):
sha.update(chunk)
except IOError:
sha.update(path.encode())

print(hash_md5.hexdigest())
print(sha.hexdigest())


if __name__ == '__main__':
Expand Down
95 changes: 41 additions & 54 deletions bin/verchew
Expand Up @@ -34,28 +34,31 @@ import logging
import os
import re
import sys
import warnings
from collections import OrderedDict
from subprocess import PIPE, STDOUT, Popen
from typing import Any, Dict


PY2 = sys.version_info[0] == 2
try:
import configparser # Python 3
except ImportError:
import ConfigParser as configparser # Python 2

if PY2:
import ConfigParser as configparser
else:
import configparser # type: ignore
__version__ = '1.6.2'

__version__ = '2.0.1'
PY2 = sys.version_info[0] == 2

CONFIG_FILENAMES = ['verchew.ini', '.verchew.ini', '.verchewrc', '.verchew']
CONFIG_FILENAMES = [
'verchew.ini',
'.verchew.ini',
'.verchewrc',
'.verchew',
]

SAMPLE_CONFIG = """
[Python]

cli = python
version = Python 3.5 || Python 3.6
versions = Python 3.5 | Python 3.6

[Legacy Python]

Expand All @@ -76,7 +79,12 @@ optional = true

""".strip()

STYLE = {"~": "✔", "*": "⭑", "?": "⚠", "x": "✘"}
STYLE = {
"~": "✔",
"*": "⭑",
"?": "⚠",
"x": "✘",
}

COLOR = {
"x": "\033[91m", # red
Expand Down Expand Up @@ -114,25 +122,18 @@ def parse_args():

version = "%(prog)s v" + __version__
parser.add_argument('--version', action='version', version=version)
parser.add_argument(
'-r', '--root', metavar='PATH', help="specify a custom project root directory"
)
parser.add_argument(
'--init', action='store_true', help="generate a sample configuration file"
)
parser.add_argument(
'--exit-code',
action='store_true',
help="return a non-zero exit code on failure",
)
parser.add_argument('-r', '--root', metavar='PATH',
help="specify a custom project root directory")
parser.add_argument('--init', action='store_true',
help="generate a sample configuration file")
parser.add_argument('--exit-code', action='store_true',
help="return a non-zero exit code on failure")

group = parser.add_mutually_exclusive_group()
group.add_argument(
'-v', '--verbose', action='count', default=0, help="enable verbose logging"
)
group.add_argument(
'-q', '--quiet', action='store_true', help="suppress all output on success"
)
group.add_argument('-v', '--verbose', action='count', default=0,
help="enable verbose logging")
group.add_argument('-q', '--quiet', action='store_true',
help="suppress all output on success")

args = parser.parse_args()

Expand Down Expand Up @@ -185,7 +186,7 @@ def generate_config(root=None, filenames=None):


def parse_config(path):
data: Dict[str, Any] = OrderedDict()
data = OrderedDict()

log.info("Parsing config file: %s", path)
config = configparser.ConfigParser()
Expand All @@ -197,23 +198,9 @@ def parse_config(path):
data[section][name] = value

for name in data:
if 'versions' in data[name]:
warnings.warn(
"'versions' is deprecated, use 'version' instead", DeprecationWarning
)
version = data[name].pop('versions') or ""
else:
version = data[name].get('version') or ""

if ' | ' in version:
warnings.warn(
"'|' is deprecated, use '||' to separate multiple versions",
DeprecationWarning,
)
version = version.replace(' | ', ' || ')

data[name]['version'] = version
data[name]['patterns'] = [v.strip() for v in version.split('||')]
versions = data[name].get('versions', data[name].pop('version', ""))
data[name]['versions'] = versions
data[name]['patterns'] = [v.strip() for v in versions.split('|')]

return data

Expand All @@ -232,14 +219,15 @@ def check_dependencies(config):
break
else:
if settings.get('optional'):
show(_("?") + " EXPECTED: {0}".format(settings['version']))
show(_("?") + " EXPECTED: {0}".format(settings['versions']))
success.append(_("?"))
else:
if QUIET:
print(
"Unmatched {0} version: {1}".format(name, settings['version'])
)
show(_("x") + " EXPECTED: {0}".format(settings['version']))
print("Unmatched {0} version: {1}".format(
name,
settings['versions'],
))
show(_("x") + " EXPECTED: {0}".format(settings['versions']))
success.append(_("x"))
if settings.get('message'):
show(_("*") + " MESSAGE: {0}".format(settings['message']))
Expand All @@ -259,8 +247,7 @@ def get_version(program, argument=None):

show("$ {0}".format(" ".join(args)))
output = call(args)
lines = output.splitlines()
show(lines[0] if lines else "<nothing>")
show(output.splitlines()[0] if output else "<nothing>")

return output

Expand Down Expand Up @@ -302,7 +289,7 @@ def show(text, start='', end='\n', head=False):
if log.getEffectiveLevel() < logging.WARNING:
log.info(text)
else:
formatted = start + text + end
formatted = (start + text + end)
if PY2:
formatted = formatted.encode('utf-8')
sys.stdout.write(formatted)
Expand Down
9 changes: 5 additions & 4 deletions docs/extras.md
Expand Up @@ -42,13 +42,14 @@ log.silence('werkzeug', 'requests', allow_warning=True)
Finally, if another package has already set the logging format or level, that can be reset so that `minilog` takes over:

```python
log.init(…, reset=True)
log.reset()
log.init(…)
```

# Records

In addition to the standard [`LogRecord`](https://docs.python.org/3/library/logging.html#logrecord-attributes) attributes, the following additional patterns are available:

| Logging Format | Description
| --- | --- |
| `%(relpath)s` | Full pathname of the source file where the logging call was issued relative to the current working directory. |
| Logging Format | Description |
| -------------- | ------------------------------------------------------------------------------------------------------------- |
| `%(relpath)s` | Full pathname of the source file where the logging call was issued relative to the current working directory. |
6 changes: 4 additions & 2 deletions log/__init__.py
@@ -1,7 +1,9 @@
# pylint: disable=wildcard-import

from logging import DEBUG, ERROR, INFO, WARNING

from .helpers import init, install_additional_formats, silence
from .logger import * # pylint: disable=wildcard-import
from .helpers import *
from .logger import *

WARN = WARNING

Expand Down
5 changes: 5 additions & 0 deletions log/filters.py
Expand Up @@ -20,3 +20,8 @@ def filter(self, record):


relpath_format_filter = RelpathFormatFilter()


def install(logger):
for handler in logger.handlers:
handler.addFilter(relpath_format_filter)
35 changes: 23 additions & 12 deletions log/helpers.py
@@ -1,9 +1,12 @@
"""Wrappers to eliminate boilerplate `logging` activities."""

import logging
import warnings
from importlib import reload

from . import state
from .filters import relpath_format_filter
from . import filters, state

__all__ = ['reset', 'init', 'silence']

VERBOSITY_TO_LEVEL = {
0: logging.ERROR,
Expand All @@ -13,10 +16,23 @@
}


def init(*, reset=False, debug=False, verbosity=None, **kwargs):
if reset:
for handler in logging.root.handlers[:]:
logging.root.removeHandler(handler)
def reset():
logging.shutdown()
reload(logging)


def init(*, debug=False, verbosity=None, **kwargs):
if 'reset' in kwargs: # pragma: no cover
warnings.warn(
(
"'reset' option will be removed in the next major version."
" Use 'log.reset()' instead."
),
DeprecationWarning,
)
should_reset = kwargs.pop('reset')
if should_reset:
reset()

custom_format = kwargs.get('format')
if debug:
Expand All @@ -37,16 +53,11 @@ def init(*, reset=False, debug=False, verbosity=None, **kwargs):
for handler in logging.root.handlers:
handler.setFormatter(formatter)

install_additional_formats(logging.root)
filters.install(logging.root)

state.initialized = True


def install_additional_formats(logger):
for handler in logger.handlers:
handler.addFilter(relpath_format_filter)


def silence(*names, allow_info=False, allow_warning=False, allow_error=False):
if allow_info:
level = logging.INFO
Expand Down
2 changes: 2 additions & 0 deletions log/logger.py
Expand Up @@ -5,6 +5,8 @@

from . import utils

__all__ = ['log', 'debug', 'info', 'warning', 'error', 'critical', 'exception']


def log(level, message, *args, **kwargs):
utils.create_logger_record(level, message, *args, **kwargs)
Expand Down
13 changes: 1 addition & 12 deletions log/tests/conftest.py
Expand Up @@ -12,18 +12,7 @@ def pytest_configure(config):
logging.basicConfig(level=logging.DEBUG)

terminal = config.pluginmanager.getplugin('terminal')
base = terminal.TerminalReporter

class QuietReporter(base): # type: ignore
"""Reporter that only shows dots when running tests."""

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.verbosity = 0
self.showlongtestinfo = False
self.showfspath = False

terminal.TerminalReporter = QuietReporter
terminal.TerminalReporter.showfspath = False


@pytest.fixture(autouse=True)
Expand Down