Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/workflows/check-pull-request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Check-pull-request

on: [pull_request]

jobs:
Check:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.5, 3.6, 3.7, 3.8]

steps:
- uses: actions/checkout@master

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
pip3 install -e .[dev]

- name: Run checks
run: ./precommit.py

- name: Coveralls Parallel
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.github_token }}
flag-name: run-${{ matrix.test_number }}
parallel: true

Finish:
needs: Check
runs-on: ubuntu-latest
steps:
- name: Coveralls Finished
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel-finished: true
35 changes: 35 additions & 0 deletions .github/workflows/check-push.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Check-push

on:
push:
branches:
- master

jobs:
Execute:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.5, 3.6, 3.7, 3.8]

steps:
- uses: actions/checkout@master

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python3 -m pip install --upgrade pip
pip3 install -e .[dev]
pip3 install coveralls

- name: Run checks
run: ./precommit.py

- name: Upload coverage to coveralls
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: coveralls
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ venv
*.egg-info
.tox
dist/
.coverage
16 changes: 16 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
logthis
=======

.. image:: https://github.com/Parquery/logthis/workflows/Check-push/badge.svg
:target: https://github.com/Parquery/logthis/actions?query=workflow%3ACheck-push
:alt: Check status

.. image:: https://coveralls.io/repos/github/Parquery/logthis/badge.svg?branch=master
:target: https://coveralls.io/github/Parquery/logthis
:alt: Test coverage

.. image:: https://badge.fury.io/py/logthis.svg
:target: https://pypi.org/project/logthis/
:alt: PyPI - version

.. image:: https://img.shields.io/pypi/pyversions/logthis.svg
:target: https://pypi.org/project/logthis/
:alt: PyPI - Python Version

logthis is a singleton, two-level, colorful, thread-safe, knob-free, logging library for in-house software.

* **singleton**: There is no object to create. There are only two logging functions, ``say()`` and ``err()``.
Expand Down
47 changes: 27 additions & 20 deletions logthis/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
#!/usr/bin/env python3
"""
Provide singleton, two-level, colorful, thread-safe, knob-free, logging for in-house software.

"""
"""Provide singleton, two-level, colorful, thread-safe, knob-free, logging for in-house software."""
import datetime
import inspect
import os
Expand All @@ -14,9 +11,14 @@
class State:
"""Represent the global logging state."""

lock = threading.Lock()
stdout = sys.stdout
stderr = sys.stderr
def __init__(self) -> None:
"""Initialize with the default values."""
self.lock = threading.Lock()
self.stdout = sys.stdout
self.stderr = sys.stderr


_GLOBAL_STATE = State()


class Colors:
Expand Down Expand Up @@ -82,66 +84,71 @@ def filename_line(skip: int = 2) -> Tuple[str, int]:
return filename, parentframe.f_lineno


def say(message: str) -> None:
def say(message: str, state: State = _GLOBAL_STATE, utcnow: datetime.datetime = datetime.datetime.utcnow()) -> None:
"""
Print a formatted log message to STDOUT and flush.

:param message: to be displayed

:param state: state object to use; the default is the singleton
:param utcnow: current timestamp
"""
with State.lock:
with state.lock:
filename, line = filename_line()
State.stdout.write(say_as_text(filename=filename, line=line, message=message))
State.stdout.flush()
state.stdout.write(say_as_text(filename=filename, line=line, message=message, utcnow=utcnow))
state.stdout.flush()


def say_as_text(filename: str, line: int, message: str) -> str:
def say_as_text(filename: str, line: int, message: str, utcnow: datetime.datetime = datetime.datetime.utcnow()) -> str:
"""
Generate 'say' message as a string.

:param filename: path to the script, usually you want to pass __file__
:param line: line number in the script, usually you want to pass inspect.currentframe().f_lineno
:param message: to be displayed
:param utcnow: current timestamp
:return: whole formatted message which the 'say' function will display

"""
return "{blue}{fname}: {line:5d}: {dt}:{endcolor} {msg}\n".format(
blue=Colors.kForeBlue,
fname=filename,
line=line,
dt=datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%SZ"),
dt=utcnow.strftime("%Y-%m-%d %H:%M:%SZ"),
msg=message,
endcolor=Colors.kConsoleDefault)


def err(message: str) -> None:
def err(message: str, state: State = _GLOBAL_STATE, utcnow: datetime.datetime = datetime.datetime.utcnow()) -> None:
"""
Print a formatted log message to STDERR and flush.

:param message: to be displayed
:param state: state object to use; default is the singleton
:param utcnow: current timestamp

"""
filename, line = filename_line()

with State.lock:
State.stderr.write(err_as_text(filename=filename, line=line, message=message))
State.stderr.flush()
with state.lock:
state.stderr.write(err_as_text(filename=filename, line=line, message=message, utcnow=utcnow))
state.stderr.flush()


def err_as_text(filename: str, line: int, message: str) -> str:
def err_as_text(filename: str, line: int, message: str, utcnow: datetime.datetime = datetime.datetime.utcnow()) -> str:
"""
Generate 'err' message as a string.

:param filename: path to the script, usually you want to pass __file__
:param line: line number in the script, usually you want to pass inspect.currentframe().f_lineno
:param message: to be displayed
:param utcnow: current timestamp
:return: whole formatted message which the 'err' function will display

"""
return "{red}{fname}: {line:5d}: {dt}:{endcolor} {msg}\n".format(
red=Colors.kForeRed,
fname=filename,
line=line,
dt=datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%SZ"),
dt=utcnow.strftime("%Y-%m-%d %H:%M:%SZ"),
msg=message,
endcolor=Colors.kConsoleDefault)
Loading