Skip to content

Commit

Permalink
Merge pull request #7 from es7s/dev
Browse files Browse the repository at this point in the history
💎 REFACTOR: verbose logging
  • Loading branch information
delameter authored Nov 10, 2023
2 parents ac6d325 + 0183240 commit c7f1d70
Show file tree
Hide file tree
Showing 31 changed files with 243 additions and 8,568 deletions.
2 changes: 1 addition & 1 deletion .env.dist
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION=0.11.0
VERSION=0.12.0
PYPI_USERNAME=__token__
PYPI_PASSWORD= #api token for primary repo
PYPI_PASSWORD_DEV= #api token for dev repo
Expand Down
10 changes: 5 additions & 5 deletions .gitmessage
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
#🌱 NEW:
#🐞 FIX:
#💎 REFINE:
#💎 REFACTOR:

#🔩 ADJUST:
#🙈 BULK:
#🍒 CHERRYPICK:
#♻️ CI/CD:
#⌛ DRAFT:
#📙 DOCS:
#🚧 INIT
#⛔ LOCAL:
#🔧 MAINTAIN:
#🚀 RELEASE:
#❌ REMOVAL:
#☢️ REVERT:
#❌ REMOVAL:
#💡 RESEARCH:
#💥 REWORK:
#🔨 SQUASH: [00]
Expand All @@ -24,8 +24,8 @@


##-----------------------------------------------------------------------------
#@ es7s/gitmessage rev. 15 es7s projects commit message templates
## Apr-2022 A. Shavykin <[email protected]>
#@ es7s/gitmessage rev. 16 es7s projects commit message templates
## Jul-2022 A. Shavykin <[email protected]>
##-----------------------------------------------------------------------------
## To make git use new commit template run (in repo's directory):
##
Expand Down
8 changes: 5 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ include ${DOTENV_DIST}
export
VERSION ?= 0.0.0

NOW := $(shell date '+%Y-%b-%0e.%H%M%S.%3N')
NOW := $(shell LC_TIME=en_US.UTF-8 date --rfc-3339=seconds)
BOLD := $(shell tput -Txterm bold)
GREEN := $(shell tput -Txterm setaf 2)
YELLOW := $(shell tput -Txterm setaf 3)
Expand All @@ -52,8 +52,9 @@ reinit-venv: ## > Prepare environment for module building <venv>
rm -vrf ${VENV_PATH}
if [ ! -f .env.build ] ; then cp -u ${DOTENV_DIST} ${DOTENV} && sed -i -Ee '/^VERSION=/d' ${DOTENV} ; fi
${HOST_DEFAULT_PYTHON} -m venv ${VENV_PATH}
${HOST_DEFAULT_PYTHON} -m pip install pipx
${VENV_PATH}/bin/pip install -r requirements.txt -r requirements-dev.txt
${VENV_PATH}/bin/pip install -e .
${VENV_PATH}/bin/pip install -r requirements-dev.txt
${VENV_PATH}/bin/python -m $(PROJECT_NAME) --version

all: ## Prepare, run tests, generate docs and reports, build module
all: reinit-build test coverage build
Expand Down Expand Up @@ -88,6 +89,7 @@ set-version: show-version
sed -E -i "s/^VERSION.+/VERSION=$$VERSION/" ${DOTENV_DIST}
sed -E -i "s/^version.+/version = $$VERSION/" setup.cfg
sed -E -i "s/^__version__.+/__version__ = \"$$VERSION\"/" ${PROJECT_NAME}/_version.py
sed -E -i 's/^(__updated__).+/\1 = "${NOW}"/w/dev/stdout' ${PROJECT_NAME}/_version.py | cut -f2 -d'"'
echo "Updated version: ${GREEN}$$VERSION${RESET}"

purge-cache: ## Clean up pycache
Expand Down
32 changes: 18 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
<div align="center">
<img src="https://user-images.githubusercontent.com/50381946/211150260-a91aa0c7-f79b-459c-8a37-a92da96a86a2.png" width="96" height="96"><br>
<img src="https://user-images.githubusercontent.com/50381946/219900319-d335e85f-5449-4bcf-8f3b-b56eb88f2246.png" width="400" height="64">
</div>

<div align="center">
<img src="https://img.shields.io/badge/python-3.10-3776AB?logo=python&logoColor=white&labelColor=333333">
<h1 align="center">
<!-- es7s/macedon -->
<a href="##"><img align="left" src="https://s3.eu-north-1.amazonaws.com/dp2.dl/readme/es7s/macedon/logo.png?v=2" width="64" height="64"></a>
<a href="##"><img align="center" src="https://s3.eu-north-1.amazonaws.com/dp2.dl/readme/es7s/macedon/label.png" width="200" height="64"></a>
<a href="##"><img align="right" src="https://s3.eu-north-1.amazonaws.com/dp2.dl/readme/empty.png" width="64" height="64"></a>
</h1>
<div align="right">
<a href="##"><img src="https://img.shields.io/badge/python-3.10-3776AB?logo=python&logoColor=white&labelColor=333333"></a>
<a href="https://pepy.tech/project/macedon/"><img alt="Downloads" src="https://pepy.tech/badge/macedon"></a>
<br>
<a href="https://pypi.org/project/macedon/"><img alt="PyPI" src="https://img.shields.io/pypi/v/macedon"></a>
<a href='https://coveralls.io/github/es7s/macedon?branch=master'><img src='https://coveralls.io/repos/github/es7s/macedon/badge.svg?branch=master' alt='Coverage Status' /></a>
<a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
<a href="##"><img src="https://wakatime.com/badge/user/8eb9e217-791b-436f-b729-81eb63e84b08/project/1d26a427-aecb-4192-965d-119e9a86cdd9.svg"></a>
</div>
<h1> </h1>
<br>


Multi-threaded CLI web service availability verifier. Takes a list of endpoints with optional input dataset, performs series of HTTP requests and displays the results.
Expand Down Expand Up @@ -42,7 +43,7 @@ Necessity to have a fast and configurable endpoint testing tool at fingertips.
-n, --amount INTEGER How many times each request will be performed. [default: 1]
-d, --delay FLOAT Seconds to wait between requests. [default: 0]
-t, --timeout FLOAT Seconds to wait for the response. [default: 10]
-i, --insecure Skip certificate verifying on HTTPS connections.
-i, --insecure Ignore invalid/expired certificates when performing HTTPS requests.
-f, --file FILENAME Execute request(s) from a specified file, or from stdin, if FILENAME specified as '-'.
The file should contain a list of endpoints in the format '{method} {url}', one per
line. Another (partially) supported format is JetBrains HTTP Client format (see
Expand All @@ -56,12 +57,15 @@ Necessity to have a fast and configurable endpoint testing tool at fingertips.
terminated under normal conditions, regardless of an actual HTTP codes; but it can
still die with a non-zero code upon invalid option syntax, etc).
-c, --color / -C, --no-color Force output colorizing using ANSI escape sequences or disable it unconditionally. If
omitted, the application determine it automatically by checking if the output device
omitted, the application determines it automatically by checking if the output device
is a terminal emulator with SGR support.
--show-id Print a column with request serial number.
--show-error Print a column with error details (when applicable).
-v, --verbose Print more details: -v for request and error details, -vv for error stack traces and
worker threads diagnostic messages, -vvv for input file/response tracing. [0<=x<=3]
--show-error Print a column with network (not HTTP) error messages, when applicable.
-v, --verbose Increase verbosity:
-v for request details and exceptions;
-vv for request/response contents and stack traces;
-vvv for thread state transition messages.
-V, --version Show the version and exit.
--help Show this message and exit.


Expand Down
3 changes: 2 additions & 1 deletion macedon/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
# (c) 2022-2023 A. Shavykin <[email protected]>
# -----------------------------------------------------------------------------

from ._version import __version__
from ._version import __version__, __updated__

APP_NAME = "macedon"
APP_VERSION = __version__
APP_UPDATED = __updated__
16 changes: 16 additions & 0 deletions macedon/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
from dataclasses import dataclass, field
from threading import Event, Lock

import click
import psutil
import pytermor as pt
from requests.structures import CaseInsensitiveDict

_state: State | None = None
Expand Down Expand Up @@ -92,3 +94,17 @@ class Task:
method: str = "GET"
headers: CaseInsensitiveDict = None
body: str = None


class FixedWidthStringWrapper(pt.StringReplacerChain):
def __init__(self, width: int = 80):
super().__init__(
"(?s).+",
pt.StringReplacer(R"\s+", " "),
pt.StringReplacer(fR"(.{{{width}}})", r"\1\n"),
)


class HiddenIntRange(click.IntRange):
def _describe_range(self) -> str:
return ""
3 changes: 2 additions & 1 deletion macedon/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
# (c) 2022-2023 A. Shavykin <[email protected]>
# -----------------------------------------------------------------------------

__version__ = "0.11.0"
__version__ = "0.12.0"
__updated__ = "2023-11-09 14:09:23+03:00"
79 changes: 62 additions & 17 deletions macedon/entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@
import sys

import click
import es7s_commons
import urllib3
from click import pass_context
from es7s_commons import format_path, format_attrs
from urllib3.exceptions import InsecureRequestWarning

import pytermor as pt
from . import APP_NAME, APP_VERSION
from ._common import Options, destroy_state, init_state, get_state
from . import APP_NAME, APP_VERSION, APP_UPDATED
from ._common import Options, destroy_state, init_state, get_state, HiddenIntRange
from .fileparser import destroy_parser, init_parser
from .io import destroy_io, init_io
from .logger import destroy_logger, init_logger, get_logger
Expand All @@ -39,11 +42,11 @@ def shutdown():


def exit_gracefully(signal_code: int, *args):
get_logger().debug(f"{signal.Signals(signal_code).name} ({signal_code}) received")
get_logger().info(f"{signal.Signals(signal_code).name} ({signal_code}) received")
if not _shutdown_started:
shutdown()
return
os._exit(0)
os._exit(0) # noqa


class ClickCommand(click.Command):
Expand Down Expand Up @@ -98,7 +101,7 @@ class ClickCommand(click.Command):
"--insecure",
is_flag=True,
default=Options.insecure,
help="Skip certificate verifying on HTTPS connections.",
help="Ignore invalid/expired certificates when performing HTTPS requests.",
)
@click.option(
"-f",
Expand Down Expand Up @@ -131,7 +134,7 @@ class ClickCommand(click.Command):
is_flag=True,
default=Options.color,
help="Force output colorizing using ANSI escape sequences or disable it "
"unconditionally. If omitted, the application determine it automatically "
"unconditionally. If omitted, the application determines it automatically "
"by checking if the output device is a terminal emulator with SGR support.",
)
@click.option(
Expand All @@ -144,19 +147,33 @@ class ClickCommand(click.Command):
"--show-error",
is_flag=True,
default=Options.show_error,
help="Print a column with error details (when applicable).",
help="Print a column with network (not HTTP) error messages, when applicable.",
)
@click.option(
"-v",
"--verbose",
count=True,
type=click.types.IntRange(min=0, max=3, clamp=True),
type=HiddenIntRange(min=0, max=3, clamp=True),
default=Options.verbose,
help="Print more details: -v for request and error details, -vv for "
"error stack traces and worker threads diagnostic messages, -vvv "
"for input file/response tracing.",
help="""\b
Increase verbosity:
-v for request details and exceptions;
-vv for request/response contents and stack traces;
-vvv for thread state transition messages.""",
)
def callback(**kwargs):
@click.option(
"--version",
"-V",
"mode_version",
count=True,
is_eager=True,
help="Show the version and exit.",
)
def callback(mode_version: bool, **kwargs):
if mode_version:
invoke_version(value=mode_version, **kwargs)
return

options = Options(**kwargs)
_init(options)

Expand All @@ -166,6 +183,34 @@ def callback(**kwargs):
_destroy(options)


@pass_context
def invoke_version(ctx: click.Context, value: int, **kwargs):
if not value or ctx.resilient_parsing:
return
vfmt = lambda s: pt.Fragment(s, "green")
ufmt = lambda s: pt.Fragment(s, "gray")

pt.echo(f"{APP_NAME:>12s} {vfmt(APP_VERSION):<14s} {ufmt(APP_UPDATED)}")
pt.echo(f"{'pytermor':>12s} {vfmt(pt.__version__):<14s} {ufmt(pt.__updated__)}")
pt.echo(
f"{'es7s-commons':>12s} {vfmt(es7s_commons.PKG_VERSION):<14s} {ufmt(es7s_commons.PKG_UPDATED)}"
)

def _echo_path(label: str, path: str):
pt.echo(
pt.Composite(
pt.Text(label + ":", width=17),
format_path(path, color=True, repr=False),
)
)

if value > 1:
pt.echo()
_echo_path("Executable", sys.executable)
_echo_path("Entrypoint", __file__)
ctx.exit()


def _init(options: Options):
urllib3.disable_warnings(InsecureRequestWarning)

Expand Down Expand Up @@ -193,12 +238,12 @@ def _destroy(options: Options):
if exit_code:
exit(exit_code)


def _log_init_info(options: Options):
logger = get_logger()
logger.debug(
logger.info(
f"{APP_NAME} {APP_VERSION} "
f"PID={os.getpid()} PPID={os.getppid()} "
f"UID={os.getuid()} CWD={os.getcwd()}"
+ format_attrs(dict(PID=os.getpid(), PPID=os.getppid(), UID=os.getuid(), CWD=os.getcwd()))
)
logger.debug(f"Args: {sys.argv!r}")
logger.debug(f"Options: {options!r}")
logger.debug(f"Args: {format_attrs(sys.argv)}")
logger.debug(repr(options))
Loading

0 comments on commit c7f1d70

Please sign in to comment.