fastapi-startkit 0.1.1__tar.gz → 0.1.3__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 (105) hide show
  1. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/PKG-INFO +2 -2
  2. fastapi_startkit-0.1.3/fastapi_startkit/application.py +132 -0
  3. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/configuration/Configuration.py +1 -6
  4. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/configuration/providers/ConfigurationProvider.py +0 -3
  5. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/container/container.py +27 -13
  6. fastapi_startkit-0.1.3/fastapi_startkit/facades/Facade.py +4 -0
  7. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/loader/Loader.py +1 -1
  8. fastapi_startkit-0.1.3/fastapi_startkit/logging/ChannelFactory.py +20 -0
  9. fastapi_startkit-0.1.3/fastapi_startkit/logging/Logger.py +2 -0
  10. fastapi_startkit-0.1.3/fastapi_startkit/logging/__init__.py +1 -0
  11. fastapi_startkit-0.1.3/fastapi_startkit/logging/channels/BaseChannel.py +60 -0
  12. fastapi_startkit-0.1.3/fastapi_startkit/logging/channels/DailyChannel.py +17 -0
  13. fastapi_startkit-0.1.3/fastapi_startkit/logging/channels/MultiBaseChannel.py +64 -0
  14. fastapi_startkit-0.1.3/fastapi_startkit/logging/channels/SingleChannel.py +14 -0
  15. fastapi_startkit-0.1.3/fastapi_startkit/logging/channels/SlackChannel.py +19 -0
  16. fastapi_startkit-0.1.3/fastapi_startkit/logging/channels/StackChannel.py +30 -0
  17. fastapi_startkit-0.1.3/fastapi_startkit/logging/channels/SyslogChannel.py +14 -0
  18. fastapi_startkit-0.1.3/fastapi_startkit/logging/channels/TerminalChannel.py +14 -0
  19. fastapi_startkit-0.1.3/fastapi_startkit/logging/channels/__init__.py +8 -0
  20. fastapi_startkit-0.1.3/fastapi_startkit/logging/configs/logging.py +20 -0
  21. fastapi_startkit-0.1.3/fastapi_startkit/logging/drivers/BaseDriver.py +25 -0
  22. fastapi_startkit-0.1.3/fastapi_startkit/logging/drivers/LogSingleDriver.py +84 -0
  23. fastapi_startkit-0.1.3/fastapi_startkit/logging/drivers/LogSlackDriver.py +94 -0
  24. fastapi_startkit-0.1.3/fastapi_startkit/logging/drivers/LogSyslogDriver.py +48 -0
  25. fastapi_startkit-0.1.3/fastapi_startkit/logging/drivers/LogTerminalDriver.py +60 -0
  26. fastapi_startkit-0.1.3/fastapi_startkit/logging/drivers/__init__.py +5 -0
  27. fastapi_startkit-0.1.3/fastapi_startkit/logging/factory.py +15 -0
  28. fastapi_startkit-0.1.3/fastapi_startkit/logging/listeners.py +15 -0
  29. fastapi_startkit-0.1.3/fastapi_startkit/logging/managers/LoggingManager.py +11 -0
  30. fastapi_startkit-0.1.3/fastapi_startkit/logging/managers/__init__.py +1 -0
  31. fastapi_startkit-0.1.3/fastapi_startkit/logging/providers/LoggingProvider.py +36 -0
  32. fastapi_startkit-0.1.3/fastapi_startkit/logging/providers/__init__.py +1 -0
  33. fastapi_startkit-0.1.3/fastapi_startkit/providers/Provider.py +21 -0
  34. fastapi_startkit-0.1.3/fastapi_startkit/providers/__init__.py +3 -0
  35. fastapi_startkit-0.1.3/fastapi_startkit/tests/configurations/test_config_merge.py +54 -0
  36. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/utils/structures.py +8 -9
  37. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/pyproject.toml +2 -2
  38. fastapi_startkit-0.1.1/fastapi_startkit/application.py +0 -40
  39. fastapi_startkit-0.1.1/fastapi_startkit/facades/Facade.py +0 -5
  40. fastapi_startkit-0.1.1/fastapi_startkit/providers/ConfigurationProvider.py +0 -13
  41. fastapi_startkit-0.1.1/fastapi_startkit/providers/Provider.py +0 -14
  42. fastapi_startkit-0.1.1/fastapi_startkit/providers/__init__.py +0 -4
  43. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/__init__.py +0 -0
  44. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/configuration/__init__.py +0 -0
  45. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/configuration/helpers.py +0 -0
  46. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/configuration/providers/__init__.py +0 -0
  47. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/container/__init__.py +0 -0
  48. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/environment/environment.py +0 -0
  49. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/exceptions/DD.py +0 -0
  50. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/exceptions/ExceptionHandler.py +0 -0
  51. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/exceptions/__init__.py +0 -0
  52. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/exceptions/exceptionite/__init__.py +0 -0
  53. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/exceptions/exceptionite/blocks.py +0 -0
  54. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/exceptions/exceptionite/controllers.py +0 -0
  55. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/exceptions/exceptionite/solutions.py +0 -0
  56. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/exceptions/exceptionite/tabs.py +0 -0
  57. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/exceptions/exceptions.py +0 -0
  58. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/exceptions/handlers/DumpExceptionHandler.py +0 -0
  59. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/exceptions/handlers/HttpExceptionHandler.py +0 -0
  60. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/exceptions/handlers/ModelNotFoundHandler.py +0 -0
  61. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Auth.py +0 -0
  62. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Auth.pyi +0 -0
  63. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Broadcast.py +0 -0
  64. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Cache.py +0 -0
  65. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Config.py +0 -0
  66. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Config.pyi +0 -0
  67. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Dump.py +0 -0
  68. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Dump.pyi +0 -0
  69. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Gate.py +0 -0
  70. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Gate.pyi +0 -0
  71. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Hash.py +0 -0
  72. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Hash.pyi +0 -0
  73. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Loader.py +0 -0
  74. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Loader.pyi +0 -0
  75. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Mail.py +0 -0
  76. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Mail.pyi +0 -0
  77. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Notification.py +0 -0
  78. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Notification.pyi +0 -0
  79. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Queue.py +0 -0
  80. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Queue.pyi +0 -0
  81. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/RateLimiter.py +0 -0
  82. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/RateLimiter.pyi +0 -0
  83. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Request.py +0 -0
  84. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Request.pyi +0 -0
  85. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Response.py +0 -0
  86. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Response.pyi +0 -0
  87. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Session.py +0 -0
  88. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Session.pyi +0 -0
  89. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Storage.py +0 -0
  90. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Storage.pyi +0 -0
  91. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Url.py +0 -0
  92. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/Url.pyi +0 -0
  93. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/View.py +0 -0
  94. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/View.pyi +0 -0
  95. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/facades/__init__.py +0 -0
  96. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/loader/__init__.py +0 -0
  97. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/utils/__init__.py +0 -0
  98. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/utils/collections.py +0 -0
  99. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/utils/console.py +0 -0
  100. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/utils/data/mime.types +0 -0
  101. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/utils/filesystem.py +0 -0
  102. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/utils/http.py +0 -0
  103. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/utils/location.py +0 -0
  104. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/utils/str.py +0 -0
  105. {fastapi_startkit-0.1.1 → fastapi_startkit-0.1.3}/fastapi_startkit/utils/time.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-startkit
3
- Version: 0.1.1
4
- Summary: Core Masonite components (Container, Config, Loader)
3
+ Version: 0.1.3
4
+ Summary: Fastapi_Startkit components
5
5
  Author: Bedram Tamang
6
6
  Author-email: tmgbedu@gmail.com
7
7
  Requires-Python: >=3.12,<4.0
@@ -0,0 +1,132 @@
1
+ import os
2
+ from typing import Type, Callable, Any
3
+
4
+ from fastapi import FastAPI, APIRouter
5
+ from starlette.middleware.base import BaseHTTPMiddleware
6
+
7
+ from .container import Container
8
+ from .environment.environment import LoadEnvironment
9
+ from .configuration.providers import ConfigurationProvider
10
+
11
+ def app() -> 'Container':
12
+ return Container.instance()
13
+
14
+ class Application(Container):
15
+ DEFAULT_PROVIDERS = [
16
+ ConfigurationProvider,
17
+ ]
18
+
19
+ def __init__(self, base_path: str = None, providers=None):
20
+ super().__init__()
21
+
22
+ self.base_path: str = base_path
23
+ self.providers = self.DEFAULT_PROVIDERS + (providers or [])
24
+ self.published_resources = {}
25
+
26
+ # Set global singleton
27
+ Container.set_instance(self)
28
+
29
+ # Boot application
30
+ self.load_environment()
31
+ self.configure_paths()
32
+ self.register_providers()
33
+
34
+ self._fastapi = FastAPI()
35
+ self.load_providers()
36
+
37
+ def register_providers(self):
38
+ providers = []
39
+ for provider_data in self.providers:
40
+ config = {}
41
+ if isinstance(provider_data, tuple):
42
+ provider_class, config = provider_data
43
+ else:
44
+ provider_class = provider_data
45
+
46
+ provider = provider_class(self, config=config)
47
+ provider.register()
48
+ providers.append(provider)
49
+
50
+ self.providers = providers
51
+ return self
52
+
53
+ def load_providers(self):
54
+ for provider in self.providers:
55
+ self.resolve(provider.boot)
56
+ return self
57
+
58
+ def use_fastapi(self, fastapi: FastAPI):
59
+ self._fastapi = fastapi
60
+ return self
61
+
62
+ def get(self, path: str, **kwargs) -> Callable:
63
+ return self._fastapi.get(path, **kwargs)
64
+
65
+ def post(self, path: str, **kwargs) -> Callable:
66
+ return self._fastapi.post(path, **kwargs)
67
+
68
+ def put(self, path: str, **kwargs) -> Callable:
69
+ return self._fastapi.put(path, **kwargs)
70
+
71
+ def delete(self, path: str, **kwargs) -> Callable:
72
+ return self._fastapi.delete(path, **kwargs)
73
+
74
+ def patch(self, path: str, **kwargs) -> Callable:
75
+ return self._fastapi.patch(path, **kwargs)
76
+
77
+ def options(self, path: str, **kwargs) -> Callable:
78
+ return self._fastapi.options(path, **kwargs)
79
+
80
+ def head(self, path: str, **kwargs) -> Callable:
81
+ return self._fastapi.head(path, **kwargs)
82
+
83
+ def trace(self, path: str, **kwargs) -> Callable:
84
+ return self._fastapi.trace(path, **kwargs)
85
+
86
+ # Include routers
87
+ def include_router(self, router: APIRouter, **kwargs):
88
+ self._fastapi.include_router(router, **kwargs)
89
+ return self
90
+
91
+ # Add middleware
92
+ def add_middleware(self, middleware_class: Type[BaseHTTPMiddleware], **options):
93
+ self._fastapi.add_middleware(middleware_class, **options)
94
+ return self
95
+
96
+ # Add event handlers (startup/shutdown)
97
+ def add_event_handler(self, event_type: str, func: Callable[..., Any]):
98
+ self._fastapi.add_event_handler(event_type, func)
99
+ return self
100
+
101
+ # Mount sub-apps
102
+ def mount(self, path: str, app_instance: FastAPI, **kwargs):
103
+ self._fastapi.mount(path, app_instance, **kwargs)
104
+ return self
105
+
106
+ # Add custom exception handlers
107
+ def add_exception_handler(self, exc_class_or_status_code: Any, handler: Callable[..., Any]):
108
+ self._fastapi.add_exception_handler(exc_class_or_status_code, handler)
109
+ return self
110
+
111
+ @property
112
+ def fastapi(self) -> FastAPI:
113
+ return self._fastapi
114
+
115
+ def __call__(self, *args, **kwargs):
116
+ return self._fastapi
117
+
118
+ def load_environment(self):
119
+ LoadEnvironment(base_path=self.base_path)
120
+
121
+ def configure_paths(self):
122
+ self.bind('config.location', os.path.join(self.base_path, "config"))
123
+
124
+ def use_config_path(self, path: str = None):
125
+ self.bind('config.location', path)
126
+
127
+ return self
128
+
129
+ def use_storage_path(self, path: str = None):
130
+ self.bind('storage.location', path)
131
+
132
+ return self
@@ -33,11 +33,6 @@ class Configuration:
33
33
  for name, value in params.items():
34
34
  self._config[f"{module_name}.{name.lower()}"] = value
35
35
 
36
- # check loaded configuration
37
- if not self._config.get("application"):
38
- raise InvalidConfigurationLocation(
39
- f"Config directory {config_root} does not contain required configuration files."
40
- )
41
36
 
42
37
  def merge_with(self, path, external_config):
43
38
  """Merge external config at key with project config at same key. It's especially
@@ -53,7 +48,7 @@ class Configuration:
53
48
  )
54
49
  if isinstance(external_config, str):
55
50
  # config is a path and should be loaded
56
- params = Loader.get_parameters(external_config)
51
+ params = Loader().get_parameters(external_config)
57
52
  else:
58
53
  params = external_config
59
54
  base_config = {name.lower(): value for name, value in params.items()}
@@ -4,9 +4,6 @@ from ..Configuration import Configuration
4
4
 
5
5
 
6
6
  class ConfigurationProvider(Provider):
7
- def __init__(self, application):
8
- self.application = application
9
-
10
7
  def register(self):
11
8
  config = Configuration(self.application)
12
9
  config.load()
@@ -15,19 +15,33 @@ class Container:
15
15
  Performs bindings and resolving of objects to and from the container.
16
16
  """
17
17
 
18
- objects = {}
19
- strict = False
20
- override = True
21
- resolve_parameters = {}
22
- remember = False
23
- _hooks = {
24
- "make": {},
25
- "bind": {},
26
- "resolve": {},
27
- }
28
-
29
- swaps = {}
30
- _remembered = {}
18
+ _instance = None
19
+
20
+ @classmethod
21
+ def set_instance(cls, instance):
22
+ cls._instance = instance
23
+
24
+ @classmethod
25
+ def instance(cls):
26
+ if cls._instance is None:
27
+ raise RuntimeError("Container not initialized")
28
+ return cls._instance
29
+
30
+
31
+ def __init__(self):
32
+ if not hasattr(self, 'objects'):
33
+ self.objects = {}
34
+ self.strict = False
35
+ self.override = True
36
+ self.resolve_parameters = {}
37
+ self.remember = False
38
+ self._hooks = {
39
+ "make": {},
40
+ "bind": {},
41
+ "resolve": {},
42
+ }
43
+ self.swaps = {}
44
+ self._remembered = {}
31
45
 
32
46
  def bind(self, name, class_obj):
33
47
  """Bind classes into the container with a key value pair.
@@ -0,0 +1,4 @@
1
+ class Facade(type):
2
+ def __getattr__(self, attribute, *args, **kwargs):
3
+ from ..application import app
4
+ return getattr(app().make(self.key), attribute)
@@ -25,7 +25,7 @@ class Loader:
25
25
  module_paths = list(map(as_filepath, files_or_directories))
26
26
  for module_loader, name, _ in pkgutil.iter_modules(module_paths):
27
27
  module = load(
28
- f"{os.path.relpath(module_loader.path)}.{name}",
28
+ f"{module_loader.path}/{name}.py",
29
29
  raise_exception=raise_exception,
30
30
  )
31
31
  _modules.update({name: module})
@@ -0,0 +1,20 @@
1
+ from .channels import SingleChannel, DailyChannel, SlackChannel, StackChannel, SyslogChannel, TerminalChannel
2
+
3
+ class ChannelFactory:
4
+
5
+ channels = {
6
+ 'single': SingleChannel,
7
+ 'daily': DailyChannel,
8
+ 'slack': SlackChannel,
9
+ 'stack': StackChannel,
10
+ 'syslog': SyslogChannel,
11
+ 'terminal': TerminalChannel
12
+ }
13
+
14
+ @classmethod
15
+ def make(cls, channel):
16
+ return cls.channels.get(channel)
17
+
18
+ @classmethod
19
+ def register(cls, channel_dictionary):
20
+ cls.channels.update(channel_dictionary)
@@ -0,0 +1,2 @@
1
+ class Logger:
2
+ pass
@@ -0,0 +1 @@
1
+ from .Logger import Logger
@@ -0,0 +1,60 @@
1
+ import pendulum
2
+ from fastapi_startkit.facades import Config
3
+
4
+ class BaseChannel:
5
+
6
+ def get_time(self):
7
+
8
+ return pendulum.now().in_tz(Config.get('logging.channels.timezone', 'UTC'))
9
+
10
+ def emergency(self, message, *args, **kwargs):
11
+ if not self.driver.should_run('emergency', self.max_level):
12
+ return
13
+
14
+ return self.driver.emergency(message, *args, **kwargs)
15
+
16
+ def alert(self, message, *args, **kwargs):
17
+ if not self.driver.should_run('alert', self.max_level):
18
+ return
19
+
20
+ return self.driver.alert(message, *args, **kwargs)
21
+
22
+ def critical(self, message, *args, **kwargs):
23
+ if not self.driver.should_run('critical', self.max_level):
24
+ return
25
+
26
+ return self.driver.critical(message, *args, **kwargs)
27
+
28
+ def error(self, message, *args, **kwargs):
29
+ if not self.driver.should_run('error', self.max_level):
30
+ return
31
+
32
+ return self.driver.error(message, *args, **kwargs)
33
+
34
+ def warning(self, message, *args, **kwargs):
35
+ if not self.driver.should_run('warning', self.max_level):
36
+ return
37
+
38
+ return self.driver.warning(message, *args, **kwargs)
39
+
40
+ def notice(self, message, *args, **kwargs):
41
+ if not self.driver.should_run('notice', self.max_level):
42
+ return
43
+
44
+ return self.driver.notice(message, *args, **kwargs)
45
+
46
+ def info(self, message, *args, **kwargs):
47
+ if not self.driver.should_run('info', self.max_level):
48
+ return
49
+
50
+ return self.driver.info(message, *args, **kwargs)
51
+
52
+ def debug(self, message, *args, **kwargs):
53
+ if not self.driver.should_run('debug', self.max_level):
54
+ return
55
+
56
+ return self.driver.debug(message, *args, **kwargs)
57
+
58
+ def channel(self, channel):
59
+ from ..ChannelFactory import ChannelFactory
60
+ return ChannelFactory().make(channel)()
@@ -0,0 +1,17 @@
1
+ from ..factory import DriverFactory
2
+ from fastapi_startkit.facades import Config
3
+ from fastapi_startkit.utils.filesystem import make_directory
4
+ import os
5
+ from .BaseChannel import BaseChannel
6
+
7
+ class DailyChannel(BaseChannel):
8
+
9
+ def __init__(self, driver=None, path=None):
10
+ path = path or Config.get('logging.channels.daily.path')
11
+ path = os.path.join(path, self.get_time().to_date_string() + '.log')
12
+ self.max_level = Config.get('logging.channels.daily.level')
13
+ make_directory(path)
14
+ self.driver = DriverFactory.make(driver or Config.get('logging.channels.daily.driver'))(path=path, max_level=self.max_level)
15
+
16
+ def debug(self, message, *args, **kwargs):
17
+ return self.driver.debug(message, *args, **kwargs)
@@ -0,0 +1,64 @@
1
+ import pendulum
2
+ from fastapi_startkit.facades import Config
3
+
4
+ class MultiBaseChannel:
5
+
6
+ def get_time(self):
7
+ return pendulum.now().in_tz(Config.get('logging.channels.timezone', 'UTC'))
8
+
9
+ def emergency(self, message, *args, **kwargs):
10
+ for channel in self.channels:
11
+ if not channel.driver.should_run('emergency', channel.max_level):
12
+ continue
13
+
14
+ channel.driver.emergency(message, *args, **kwargs)
15
+
16
+ def alert(self, message, *args, **kwargs):
17
+ for channel in self.channels:
18
+ if not channel.driver.should_run('alert', channel.max_level):
19
+ continue
20
+
21
+ channel.driver.alert(message, *args, **kwargs)
22
+
23
+ def critical(self, message, *args, **kwargs):
24
+ for channel in self.channels:
25
+ if not channel.driver.should_run('critical', channel.max_level):
26
+ continue
27
+
28
+ channel.driver.critical(message, *args, **kwargs)
29
+
30
+ def error(self, message, *args, **kwargs):
31
+ for channel in self.channels:
32
+ if not channel.driver.should_run('error', channel.max_level):
33
+ continue
34
+
35
+ channel.driver.error(message, *args, **kwargs)
36
+
37
+ def warning(self, message, *args, **kwargs):
38
+ for channel in self.channels:
39
+ if not channel.driver.should_run('warning', channel.max_level):
40
+ continue
41
+
42
+ channel.driver.warning(message, *args, **kwargs)
43
+
44
+ def notice(self, message, *args, **kwargs):
45
+ for channel in self.channels:
46
+ if not channel.driver.should_run('notice', channel.max_level):
47
+ continue
48
+
49
+ channel.driver.notice(message, *args, **kwargs)
50
+
51
+ def info(self, message, *args, **kwargs):
52
+ for channel in self.channels:
53
+ if not channel.driver.should_run('info', channel.max_level):
54
+ continue
55
+
56
+ channel.driver.info(message, *args, **kwargs)
57
+
58
+ def debug(self, message, *args, **kwargs):
59
+ for channel in self.channels:
60
+ if not channel.driver.should_run('debug', channel.max_level):
61
+ continue
62
+
63
+ channel.driver.debug(message, *args, **kwargs)
64
+
@@ -0,0 +1,14 @@
1
+ from ..factory import DriverFactory
2
+ from fastapi_startkit.facades import Config
3
+ from fastapi_startkit.utils.filesystem import make_directory
4
+ import os
5
+ import pendulum
6
+ from .BaseChannel import BaseChannel
7
+
8
+
9
+ class SingleChannel(BaseChannel):
10
+ def __init__(self, driver=None, path=None):
11
+ path = path or Config.get('logging.channels.single.path')
12
+ make_directory(path)
13
+ self.max_level = Config.get('logging.channels.single.level')
14
+ self.driver = DriverFactory.make(driver or Config.get('logging.channels.single.driver'))(path=path, max_level=self.max_level)
@@ -0,0 +1,19 @@
1
+
2
+ from ..factory import DriverFactory
3
+ from fastapi_startkit.facades import Config
4
+ import os
5
+ import pendulum
6
+ from .BaseChannel import BaseChannel
7
+
8
+ class SlackChannel(BaseChannel):
9
+
10
+ def __init__(self, driver=None, path=None):
11
+ token = Config.get('logging.channels.slack.token')
12
+ channel = Config.get('logging.channels.slack.channel')
13
+ emoji = Config.get('logging.channels.slack.emoji')
14
+ username = Config.get('logging.channels.slack.username')
15
+ self.max_level = Config.get('logging.channels.slack.level')
16
+ self.driver = DriverFactory.make(driver or Config.get('logging.channels.slack.driver'))(emoji=emoji, username=username, token=token, channel=channel)
17
+
18
+ def debug(self, message, *args, **kwargs):
19
+ return self.driver.debug(message, *args, **kwargs)
@@ -0,0 +1,30 @@
1
+ from ..factory import DriverFactory
2
+ from fastapi_startkit.facades import Config
3
+ import os
4
+ import pendulum
5
+ from .MultiBaseChannel import MultiBaseChannel
6
+
7
+ class StackChannel(MultiBaseChannel):
8
+
9
+ def __init__(self, channels=[]):
10
+ channels = channels or Config.get('logging.channels.stack.channels')
11
+ from ..ChannelFactory import ChannelFactory
12
+ self.channels = []
13
+ for channel in channels:
14
+ channel = ChannelFactory.make(channel)()
15
+ self.channels.append(channel)
16
+
17
+ def debug(self, message, *args, **kwargs):
18
+ for channel in self.channels:
19
+ if not channel.driver.should_run('debug', channel.max_level):
20
+ continue
21
+
22
+ channel.driver.debug(message, *args, **kwargs)
23
+
24
+ def notice(self, message, *args, **kwargs):
25
+ for channel in self.channels:
26
+ if not channel.driver.should_run('notice', channel.max_level):
27
+ continue
28
+
29
+ channel.driver.notice(message, *args, **kwargs)
30
+
@@ -0,0 +1,14 @@
1
+ from ..factory import DriverFactory
2
+ from fastapi_startkit.facades import Config
3
+ from fastapi_startkit.utils.filesystem import make_directory
4
+ import os
5
+ import pendulum
6
+ from .BaseChannel import BaseChannel
7
+
8
+ class SyslogChannel(BaseChannel):
9
+
10
+ def __init__(self, driver=None, path=None):
11
+ path = path or Config.get('logging.channels.syslog.path')
12
+ make_directory(path)
13
+ self.max_level = Config.get('logging.channels.syslog.level')
14
+ self.driver = DriverFactory.make(driver or Config.get('logging.channels.syslog.driver'))(path=path, max_level=self.max_level)
@@ -0,0 +1,14 @@
1
+ import os
2
+
3
+ import pendulum
4
+ from fastapi_startkit.facades import Config
5
+
6
+ from ..factory import DriverFactory
7
+ from ..channels.BaseChannel import BaseChannel
8
+
9
+
10
+ class TerminalChannel(BaseChannel):
11
+
12
+ def __init__(self, driver=None, path=None):
13
+ self.max_level = Config.get('logging.channels.terminal.level', 'debug')
14
+ self.driver = DriverFactory.make(driver or Config.get('logging.channels.terminal.driver'))(path=path, max_level=self.max_level)
@@ -0,0 +1,8 @@
1
+ from .SingleChannel import SingleChannel
2
+ from .TerminalChannel import TerminalChannel
3
+ from .DailyChannel import DailyChannel
4
+ from .SlackChannel import SlackChannel
5
+ from .SyslogChannel import SyslogChannel
6
+ from .StackChannel import StackChannel
7
+ from .BaseChannel import BaseChannel
8
+ from .MultiBaseChannel import MultiBaseChannel
@@ -0,0 +1,20 @@
1
+ from fastapi_startkit.environment.environment import env
2
+
3
+ DEFAULT = env('LOG_CHANNEL', 'single')
4
+
5
+ CHANNELS = {
6
+ 'timezone': env('LOG_TIMEZONE', 'UTC'),
7
+ 'single': {
8
+ 'driver': 'single',
9
+ 'level': 'debug',
10
+ 'path': 'storage/logs/single.log'
11
+ },
12
+ 'stack': {
13
+ 'driver': 'stack',
14
+ 'channels': ['single', 'terminal']
15
+ },
16
+ 'terminal': {
17
+ 'driver': 'terminal',
18
+ 'level': 'info'
19
+ }
20
+ }
@@ -0,0 +1,25 @@
1
+ import pendulum
2
+ from fastapi_startkit.facades import Config
3
+
4
+ class BaseDriver:
5
+
6
+ levels = [
7
+ 'emergency',
8
+ 'alert',
9
+ 'critical',
10
+ 'error',
11
+ 'warning',
12
+ 'notice',
13
+ 'info',
14
+ 'debug',
15
+ ]
16
+
17
+ def get_time(self):
18
+ return pendulum.now().in_tz(Config.get('logging.channels.timezone', 'UTC'))
19
+
20
+ def should_run(self, level, max_level):
21
+ if not max_level:
22
+ return True
23
+
24
+ return self.levels.index(level) <= self.levels.index(max_level)
25
+
@@ -0,0 +1,84 @@
1
+ import logging
2
+ import os
3
+ from .BaseDriver import BaseDriver
4
+
5
+ class LogSingleDriver(BaseDriver):
6
+
7
+ def __init__(self, *args, **kwargs):
8
+ self.max_level = kwargs.get('max_level')
9
+ self.path = kwargs.get('path')
10
+ self.log = logging.getLogger('root')
11
+
12
+ handler = logging.FileHandler(self.path, 'a')
13
+ formatter = logging.Formatter('{} - %(levelname)s - %(message)s'.format(self.get_time().to_datetime_string()))
14
+
15
+ handler.setFormatter(formatter)
16
+ self.log.addHandler(handler)
17
+
18
+ def change_format(self, changed_format):
19
+ for hdlr in self.log.handlers[:]: # remove all old handlers
20
+ self.log.removeHandler(hdlr)
21
+
22
+ handler = logging.FileHandler(self.path, 'a')
23
+ formatter = logging.Formatter(changed_format)
24
+
25
+ handler.setFormatter(formatter)
26
+
27
+ self.log.addHandler(handler)
28
+
29
+ def emergency(self, message, *args, **kwargs):
30
+ self.log.setLevel(logging.CRITICAL)
31
+ self.change_format('{} - {} - %(message)s'.format(
32
+ self.get_time().to_datetime_string(),
33
+ 'EMERGENCY'))
34
+ return self.log.critical(message)
35
+
36
+ def alert(self, message, *args, **kwargs):
37
+ self.log.setLevel(logging.CRITICAL)
38
+ self.change_format('{} - {} - %(message)s'.format(
39
+ self.get_time().to_datetime_string(),
40
+ 'ALERT'))
41
+ return self.log.critical(message)
42
+
43
+ def critical(self, message, *args, **kwargs):
44
+ self.log.setLevel(logging.CRITICAL)
45
+ self.change_format('{} - {} - %(message)s'.format(
46
+ self.get_time().to_datetime_string(),
47
+ 'CRITICAL'))
48
+ return self.log.critical(message)
49
+
50
+ def error(self, message, *args, **kwargs):
51
+ self.log.setLevel(logging.ERROR)
52
+ self.change_format('{} - {} - %(message)s'.format(
53
+ self.get_time().to_datetime_string(),
54
+ 'ERROR'))
55
+ return self.log.error(message)
56
+
57
+ def warning(self, message, *args, **kwargs):
58
+ self.log.setLevel(logging.WARNING)
59
+ self.change_format('{} - {} - %(message)s'.format(
60
+ self.get_time().to_datetime_string(),
61
+ 'WARNING'))
62
+ return self.log.warning(message)
63
+
64
+ def notice(self, message, *args, **kwargs):
65
+ self.log.setLevel(logging.INFO)
66
+ self.change_format('{} - {} - %(message)s'.format(
67
+ self.get_time().to_datetime_string(),
68
+ 'NOTICE'))
69
+ return self.log.info(message)
70
+
71
+ def info(self, message, *args, **kwargs):
72
+ self.log.setLevel(logging.INFO)
73
+ self.change_format('{} - {} - %(message)s'.format(
74
+ self.get_time().to_datetime_string(),
75
+ 'INFO'))
76
+ return self.log.info(message)
77
+
78
+ def debug(self, message, *args, **kwargs):
79
+ self.log.setLevel(logging.DEBUG)
80
+ self.change_format('{} - {} - %(message)s'.format(
81
+ self.get_time().to_datetime_string(),
82
+ 'DEBUG'))
83
+ return self.log.debug(message)
84
+