aiomisc 17.5.2__tar.gz → 17.5.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. {aiomisc-17.5.2 → aiomisc-17.5.6}/PKG-INFO +1 -1
  2. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/log.py +10 -8
  3. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/version.py +2 -2
  4. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc_log/__init__.py +50 -39
  5. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc_log/enum.py +3 -3
  6. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc_log/formatter/color.py +1 -5
  7. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc_log/formatter/rich.py +14 -8
  8. {aiomisc-17.5.2 → aiomisc-17.5.6}/pyproject.toml +1 -1
  9. {aiomisc-17.5.2 → aiomisc-17.5.6}/COPYING +0 -0
  10. {aiomisc-17.5.2 → aiomisc-17.5.6}/README.rst +0 -0
  11. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/__init__.py +0 -0
  12. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/_context_vars.py +0 -0
  13. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/aggregate.py +0 -0
  14. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/backoff.py +0 -0
  15. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/circuit_breaker.py +0 -0
  16. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/compat.py +0 -0
  17. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/context.py +0 -0
  18. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/counters.py +0 -0
  19. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/cron.py +0 -0
  20. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/entrypoint.py +0 -0
  21. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/io.py +0 -0
  22. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/iterator_wrapper.py +0 -0
  23. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/periodic.py +0 -0
  24. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/plugins/__init__.py +0 -0
  25. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/plugins/__main__.py +0 -0
  26. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/pool.py +0 -0
  27. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/process_pool.py +0 -0
  28. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/py.typed +0 -0
  29. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/recurring.py +0 -0
  30. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/service/__init__.py +0 -0
  31. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/service/aiohttp.py +0 -0
  32. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/service/asgi.py +0 -0
  33. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/service/base.py +0 -0
  34. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/service/carbon.py +0 -0
  35. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/service/cron.py +0 -0
  36. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/service/grpc_server.py +0 -0
  37. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/service/periodic.py +0 -0
  38. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/service/process.py +0 -0
  39. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/service/profiler.py +0 -0
  40. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/service/raven.py +0 -0
  41. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/service/sdwatchdog.py +0 -0
  42. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/service/tcp.py +0 -0
  43. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/service/tls.py +0 -0
  44. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/service/tracer.py +0 -0
  45. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/service/udp.py +0 -0
  46. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/service/uvicorn.py +0 -0
  47. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/signal.py +0 -0
  48. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/thread_pool.py +0 -0
  49. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/timeout.py +0 -0
  50. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/utils.py +0 -0
  51. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc/worker_pool.py +0 -0
  52. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc_log/formatter/__init__.py +0 -0
  53. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc_log/formatter/journald.py +0 -0
  54. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc_log/formatter/json.py +0 -0
  55. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc_log/py.typed +0 -0
  56. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc_worker/__init__.py +0 -0
  57. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc_worker/__main__.py +0 -0
  58. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc_worker/forking.py +0 -0
  59. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc_worker/process.py +0 -0
  60. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc_worker/process_inner.py +0 -0
  61. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc_worker/protocol.py +0 -0
  62. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc_worker/py.typed +0 -0
  63. {aiomisc-17.5.2 → aiomisc-17.5.6}/aiomisc_worker/worker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: aiomisc
3
- Version: 17.5.2
3
+ Version: 17.5.6
4
4
  Summary: aiomisc - miscellaneous utils for asyncio
5
5
  Home-page: https://github.com/aiokitchen/aiomisc
6
6
  License: MIT
@@ -7,7 +7,9 @@ import traceback
7
7
  from contextlib import suppress
8
8
  from functools import partial
9
9
  from socket import socket
10
- from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union
10
+ from typing import (
11
+ Any, Callable, Dict, Iterable, List, Optional, Tuple, Type, Union,
12
+ )
11
13
  from weakref import finalize
12
14
 
13
15
  import aiomisc_log
@@ -75,9 +77,7 @@ def wrap_logging_handler(
75
77
  return buffered_handler
76
78
 
77
79
 
78
- class UnhandledLoopHook(aiomisc_log.UnhandledHookBase):
79
- LOGGER_NAME = "asyncio.unhandled"
80
-
80
+ class UnhandledLoopHook(aiomisc_log.UnhandledHook):
81
81
  @staticmethod
82
82
  def _fill_transport_extra(
83
83
  transport: Optional[asyncio.Transport],
@@ -109,8 +109,8 @@ class UnhandledLoopHook(aiomisc_log.UnhandledHookBase):
109
109
  protocol: Optional[asyncio.Protocol] = context.pop("protocol", None)
110
110
  transport: Optional[asyncio.Transport] = context.pop("transport", None)
111
111
  sock: Optional[socket] = context.pop("socket", None)
112
- source_traceback: List[traceback.FrameSummary] = context.pop(
113
- "source_traceback", None,
112
+ source_traceback: List[traceback.FrameSummary] = (
113
+ context.pop("source_traceback", None) or []
114
114
  )
115
115
 
116
116
  if exception is None:
@@ -141,15 +141,16 @@ def basic_config(
141
141
  buffered: bool = True, buffer_size: int = 1024,
142
142
  flush_interval: Union[int, float] = 0.2,
143
143
  loop: Optional[asyncio.AbstractEventLoop] = None,
144
+ handlers: Iterable[logging.Handler] = (),
144
145
  **kwargs: Any,
145
146
  ) -> None:
146
147
  loop = loop or asyncio.get_event_loop()
147
- unhandled_hook = UnhandledLoopHook()
148
+ unhandled_hook = UnhandledLoopHook(logger_name="asyncio.unhandled")
148
149
 
149
150
  def wrap_handler(handler: logging.Handler) -> logging.Handler:
150
151
  nonlocal buffer_size, buffered, loop, unhandled_hook
151
152
 
152
- unhandled_hook.set_handler(handler)
153
+ unhandled_hook.add_handler(handler)
153
154
 
154
155
  if buffered:
155
156
  return wrap_logging_handler(
@@ -164,6 +165,7 @@ def basic_config(
164
165
  level=level,
165
166
  log_format=log_format,
166
167
  handler_wrapper=wrap_handler,
168
+ handlers=handlers,
167
169
  **kwargs,
168
170
  )
169
171
 
@@ -2,5 +2,5 @@
2
2
  # BY: poem-plugins "git" plugin
3
3
  # NEVER EDIT THIS FILE MANUALLY
4
4
 
5
- version_info = (17, 5, 2)
6
- __version__ = "17.5.2"
5
+ version_info = (17, 5, 6)
6
+ __version__ = "17.5.6"
@@ -2,8 +2,11 @@ import logging
2
2
  import logging.handlers
3
3
  import os
4
4
  import sys
5
+ from contextvars import ContextVar
6
+ from dataclasses import dataclass
7
+ from itertools import chain
5
8
  from types import TracebackType
6
- from typing import Any, Callable, Optional, Type, Union
9
+ from typing import Any, Callable, Iterable, Optional, Type, Union
7
10
 
8
11
  from .enum import LogFormat, LogLevel
9
12
  from .formatter import (
@@ -11,17 +14,10 @@ from .formatter import (
11
14
  )
12
15
 
13
16
 
14
- LOG_LEVEL: Optional[Any] = None
15
- LOG_FORMAT: Optional[Any] = None
16
-
17
- try:
18
- import contextvars
19
- LOG_LEVEL = contextvars.ContextVar("LOG_LEVEL", default=logging.INFO)
20
- LOG_FORMAT = contextvars.ContextVar(
21
- "LOG_FORMAT", default=LogFormat.default(),
22
- )
23
- except ImportError:
24
- pass
17
+ LOG_LEVEL: ContextVar = ContextVar("LOG_LEVEL", default=logging.INFO)
18
+ LOG_FORMAT: ContextVar = ContextVar(
19
+ "LOG_FORMAT", default=LogFormat.default(),
20
+ )
25
21
 
26
22
 
27
23
  DEFAULT_FORMAT = "%(levelname)s:%(name)s:%(message)s"
@@ -30,12 +26,13 @@ DEFAULT_FORMAT = "%(levelname)s:%(name)s:%(message)s"
30
26
  def create_logging_handler(
31
27
  log_format: LogFormat = LogFormat.color,
32
28
  date_format: Optional[str] = None, **kwargs: Any,
33
- ) -> logging.Handler:
29
+ ) -> Optional[logging.Handler]:
34
30
 
35
- if LOG_FORMAT is not None:
36
- LOG_FORMAT.set(log_format)
31
+ LOG_FORMAT.set(log_format)
37
32
 
38
- if log_format == LogFormat.stream:
33
+ if log_format == LogFormat.disabled:
34
+ return None
35
+ elif log_format == LogFormat.stream:
39
36
  handler: logging.Handler = logging.StreamHandler()
40
37
  if date_format and date_format is not Ellipsis:
41
38
  formatter = logging.Formatter(
@@ -90,24 +87,25 @@ def pass_wrapper(handler: logging.Handler) -> logging.Handler:
90
87
  return handler
91
88
 
92
89
 
90
+ @dataclass
93
91
  class UnhandledHookBase:
94
- __slots__ = "logger",
95
-
96
- LOGGER_NAME: str = "unhandled"
97
92
  logger: logging.Logger
93
+ logger_name: str = "unhandled"
94
+ logger_default_message: str = "Unhandled exception"
98
95
 
99
- def __init__(self) -> None:
100
- self.logger = logging.getLogger().getChild(self.LOGGER_NAME)
101
- self.logger.propagate = False
102
96
 
103
- def set_handler(self, handler: logging.Handler) -> None:
104
- self.logger.handlers.clear()
105
- self.logger.handlers.append(handler)
97
+ class UnhandledHook(UnhandledHookBase):
98
+ def __init__(self, **kwargs: Any) -> None:
99
+ logger = logging.getLogger().getChild(self.logger_name)
100
+ logger.propagate = False
101
+ logger.handlers.clear()
102
+ super().__init__(logger=logger, **kwargs)
106
103
 
104
+ def add_handler(self, handler: logging.Handler) -> None:
105
+ self.logger.handlers.append(handler)
107
106
 
108
- class UnhandledHook(UnhandledHookBase):
109
- MESSAGE: str = "Unhandled exception"
110
107
 
108
+ class UnhandledPythonHook(UnhandledHook):
111
109
  def __call__(
112
110
  self,
113
111
  exc_type: Type[BaseException],
@@ -115,49 +113,62 @@ class UnhandledHook(UnhandledHookBase):
115
113
  exc_traceback: TracebackType,
116
114
  ) -> None:
117
115
  self.logger.exception(
118
- self.MESSAGE, exc_info=(exc_type, exc_value, exc_traceback),
116
+ self.logger_default_message,
117
+ exc_info=(exc_type, exc_value, exc_traceback),
119
118
  )
120
119
 
121
120
 
122
121
  def basic_config(
123
- level: Union[int, str] = logging.INFO,
122
+ level: Union[int, str] = LogLevel.info,
124
123
  log_format: Union[str, LogFormat] = LogFormat.color,
125
124
  handler_wrapper: HandlerWrapperType = pass_wrapper,
125
+ handlers: Iterable[logging.Handler] = (),
126
126
  **kwargs: Any,
127
127
  ) -> None:
128
128
 
129
129
  if isinstance(level, str):
130
130
  level = LogLevel[level]
131
131
 
132
- logging.basicConfig()
133
- logger = logging.getLogger()
134
- logger.handlers.clear()
132
+ logging.basicConfig(handlers=[], level=logging.NOTSET)
133
+ root_logger = logging.getLogger()
134
+ root_logger.handlers.clear()
135
135
 
136
136
  if isinstance(log_format, str):
137
137
  log_format = LogFormat[log_format]
138
138
 
139
- raw_handler = create_logging_handler(log_format, **kwargs)
140
- unhandled_hook = UnhandledHook()
139
+ unhandled_hook = UnhandledPythonHook()
141
140
  sys.excepthook = unhandled_hook # type: ignore
142
141
 
143
- handler = handler_wrapper(raw_handler)
142
+ logging_handlers = list(
143
+ map(
144
+ handler_wrapper,
145
+ filter(
146
+ None,
147
+ chain(
148
+ [create_logging_handler(log_format, **kwargs)],
149
+ handlers,
150
+ ),
151
+ ),
152
+ ),
153
+ )
144
154
 
145
- if LOG_LEVEL is not None:
146
- LOG_LEVEL.set(level)
155
+ LOG_LEVEL.set(level)
147
156
 
148
157
  # noinspection PyArgumentList
149
158
  logging.basicConfig(
150
159
  level=int(level),
151
- handlers=[handler],
160
+ handlers=logging_handlers,
152
161
  )
153
162
 
154
- unhandled_hook.set_handler(raw_handler)
163
+ for handler in logging_handlers:
164
+ unhandled_hook.add_handler(handler)
155
165
 
156
166
 
157
167
  __all__ = (
158
168
  "LogFormat",
159
169
  "LogLevel",
160
170
  "basic_config",
171
+ "create_logging_handler",
161
172
  "LOG_FORMAT",
162
173
  "LOG_LEVEL",
163
174
  )
@@ -12,15 +12,15 @@ except ImportError:
12
12
  return False
13
13
 
14
14
  try:
15
- import rich
16
-
17
- RICH_INSTALLED = bool(rich)
15
+ import rich as _ # noqa
16
+ RICH_INSTALLED = True
18
17
  except ImportError:
19
18
  RICH_INSTALLED = False
20
19
 
21
20
 
22
21
  @unique
23
22
  class LogFormat(IntEnum):
23
+ disabled = -1
24
24
  stream = 0
25
25
  color = 1
26
26
  json = 2
@@ -11,11 +11,7 @@ def color_formatter(
11
11
  stream: Optional[IO[str]] = None,
12
12
  date_format: Optional[str] = None, **_: Any,
13
13
  ) -> logging.Handler:
14
-
15
- date_format = (
16
- date_format if date_format is not None else DateFormat.color.value
17
- )
18
-
14
+ date_format = date_format or DateFormat.color.value
19
15
  stream = stream or sys.stderr
20
16
  handler = logging.StreamHandler(stream)
21
17
 
@@ -1,29 +1,35 @@
1
1
  import logging
2
- import sys
3
2
  from typing import IO, Any, Optional
4
3
 
5
4
  from aiomisc_log.enum import DateFormat
6
5
 
7
6
 
8
7
  try:
9
- from rich.console import Console
8
+ from rich import reconfigure
10
9
  from rich.logging import RichHandler
11
10
 
12
11
  def rich_formatter(
13
12
  date_format: Optional[str] = None, stream: Optional[IO[str]] = None,
14
- rich_tracebacks: bool = False, **_: Any,
13
+ **kwargs: Any,
15
14
  ) -> logging.Handler:
16
- handler = RichHandler(
17
- console=Console(file=stream or sys.stderr),
18
- log_time_format=date_format or DateFormat.rich.value,
19
- rich_tracebacks=rich_tracebacks,
15
+ kwargs.setdefault("rich_tracebacks", False)
16
+ kwargs.setdefault(
17
+ "log_time_format", date_format or DateFormat.rich.value,
20
18
  )
19
+
20
+ if "console" not in kwargs:
21
+ if stream is None:
22
+ reconfigure(stderr=True)
23
+ else:
24
+ reconfigure(file=stream)
25
+
26
+ handler = RichHandler(**kwargs)
21
27
  formatter = logging.Formatter("%(message)s")
22
28
  handler.setFormatter(formatter)
23
29
  return handler
24
30
  except ImportError:
25
31
  def rich_formatter(
26
32
  date_format: Optional[str] = None, stream: Optional[IO[str]] = None,
27
- rich_tracebacks: bool = False, **_: Any,
33
+ **kwargs: Any,
28
34
  ) -> logging.Handler:
29
35
  raise ImportError("You must install \"rich\" library for use it")
@@ -1,7 +1,7 @@
1
1
  [tool.poetry]
2
2
  name = "aiomisc"
3
3
  # This is a dummy version which will be rewritten with poem-plugins
4
- version = "17.5.2"
4
+ version = "17.5.6"
5
5
  description = "aiomisc - miscellaneous utils for asyncio"
6
6
  authors = ["Dmitry Orlov <me@mosquito.su>"]
7
7
  readme = "README.rst"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes