uwsgiconf 2.0.0__py3-none-any.whl

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 (113) hide show
  1. uwsgiconf/__init__.py +1 -0
  2. uwsgiconf/base.py +298 -0
  3. uwsgiconf/cli.py +105 -0
  4. uwsgiconf/config.py +844 -0
  5. uwsgiconf/contrib/django/__init__.py +5 -0
  6. uwsgiconf/contrib/django/uwsgify/__init__.py +1 -0
  7. uwsgiconf/contrib/django/uwsgify/admin/__init__.py +12 -0
  8. uwsgiconf/contrib/django/uwsgify/admin/base.py +54 -0
  9. uwsgiconf/contrib/django/uwsgify/admin/models.py +38 -0
  10. uwsgiconf/contrib/django/uwsgify/admin/realms.py +236 -0
  11. uwsgiconf/contrib/django/uwsgify/admin/task.py +35 -0
  12. uwsgiconf/contrib/django/uwsgify/apps.py +25 -0
  13. uwsgiconf/contrib/django/uwsgify/cache.py +63 -0
  14. uwsgiconf/contrib/django/uwsgify/locale/ru/LC_MESSAGES/django.mo +0 -0
  15. uwsgiconf/contrib/django/uwsgify/locale/ru/LC_MESSAGES/django.po +259 -0
  16. uwsgiconf/contrib/django/uwsgify/management/__init__.py +1 -0
  17. uwsgiconf/contrib/django/uwsgify/management/commands/__init__.py +1 -0
  18. uwsgiconf/contrib/django/uwsgify/management/commands/_base.py +34 -0
  19. uwsgiconf/contrib/django/uwsgify/management/commands/uwsgi_log.py +22 -0
  20. uwsgiconf/contrib/django/uwsgify/management/commands/uwsgi_reload.py +30 -0
  21. uwsgiconf/contrib/django/uwsgify/management/commands/uwsgi_run.py +41 -0
  22. uwsgiconf/contrib/django/uwsgify/management/commands/uwsgi_stats.py +9 -0
  23. uwsgiconf/contrib/django/uwsgify/management/commands/uwsgi_stop.py +18 -0
  24. uwsgiconf/contrib/django/uwsgify/management/commands/uwsgi_sysinit.py +51 -0
  25. uwsgiconf/contrib/django/uwsgify/migrations/0001_initial.py +34 -0
  26. uwsgiconf/contrib/django/uwsgify/migrations/__init__.py +0 -0
  27. uwsgiconf/contrib/django/uwsgify/models.py +12 -0
  28. uwsgiconf/contrib/django/uwsgify/settings.py +18 -0
  29. uwsgiconf/contrib/django/uwsgify/static/uwsgify/403.html +28 -0
  30. uwsgiconf/contrib/django/uwsgify/static/uwsgify/404.html +29 -0
  31. uwsgiconf/contrib/django/uwsgify/static/uwsgify/500.html +29 -0
  32. uwsgiconf/contrib/django/uwsgify/static/uwsgify/503.html +30 -0
  33. uwsgiconf/contrib/django/uwsgify/taskutils/__init__.py +0 -0
  34. uwsgiconf/contrib/django/uwsgify/taskutils/backends.py +126 -0
  35. uwsgiconf/contrib/django/uwsgify/taskutils/context.py +22 -0
  36. uwsgiconf/contrib/django/uwsgify/taskutils/decorators.py +72 -0
  37. uwsgiconf/contrib/django/uwsgify/taskutils/models.py +111 -0
  38. uwsgiconf/contrib/django/uwsgify/templates/admin/uwsgify/onepage.html +46 -0
  39. uwsgiconf/contrib/django/uwsgify/toolbox.py +306 -0
  40. uwsgiconf/contrib/django/uwsgify/utils.py +3 -0
  41. uwsgiconf/contrib/django/uwsgify/uwsgiinit.py +48 -0
  42. uwsgiconf/emulator/__init__.py +0 -0
  43. uwsgiconf/emulator/caching.py +53 -0
  44. uwsgiconf/emulator/mules.py +10 -0
  45. uwsgiconf/emulator/rpc.py +16 -0
  46. uwsgiconf/emulator/scheduling.py +13 -0
  47. uwsgiconf/emulator/signals.py +30 -0
  48. uwsgiconf/exceptions.py +11 -0
  49. uwsgiconf/formatters.py +142 -0
  50. uwsgiconf/maintenance.py +12 -0
  51. uwsgiconf/options/__init__.py +38 -0
  52. uwsgiconf/options/alarm_types.py +90 -0
  53. uwsgiconf/options/alarms.py +152 -0
  54. uwsgiconf/options/applications.py +94 -0
  55. uwsgiconf/options/caching.py +219 -0
  56. uwsgiconf/options/empire.py +211 -0
  57. uwsgiconf/options/locks.py +73 -0
  58. uwsgiconf/options/logging.py +560 -0
  59. uwsgiconf/options/logging_encoders.py +106 -0
  60. uwsgiconf/options/logging_loggers.py +233 -0
  61. uwsgiconf/options/main_process.py +464 -0
  62. uwsgiconf/options/main_process_actions.py +224 -0
  63. uwsgiconf/options/master_process.py +362 -0
  64. uwsgiconf/options/monitoring.py +258 -0
  65. uwsgiconf/options/monitoring_collectors.py +138 -0
  66. uwsgiconf/options/monitoring_metric_types.py +123 -0
  67. uwsgiconf/options/monitoring_pushers.py +225 -0
  68. uwsgiconf/options/networking.py +383 -0
  69. uwsgiconf/options/networking_sockets.py +350 -0
  70. uwsgiconf/options/python.py +237 -0
  71. uwsgiconf/options/queue.py +39 -0
  72. uwsgiconf/options/routing.py +419 -0
  73. uwsgiconf/options/routing_actions.py +669 -0
  74. uwsgiconf/options/routing_modifiers.py +431 -0
  75. uwsgiconf/options/routing_routers.py +1061 -0
  76. uwsgiconf/options/routing_subjects.py +167 -0
  77. uwsgiconf/options/routing_vars.py +145 -0
  78. uwsgiconf/options/spooler.py +111 -0
  79. uwsgiconf/options/statics.py +196 -0
  80. uwsgiconf/options/subscriptions.py +216 -0
  81. uwsgiconf/options/subscriptions_algos.py +39 -0
  82. uwsgiconf/options/workers.py +463 -0
  83. uwsgiconf/options/workers_cheapening.py +250 -0
  84. uwsgiconf/presets/__init__.py +0 -0
  85. uwsgiconf/presets/empire.py +86 -0
  86. uwsgiconf/presets/nice.py +401 -0
  87. uwsgiconf/runtime/__init__.py +0 -0
  88. uwsgiconf/runtime/alarms.py +3 -0
  89. uwsgiconf/runtime/asynced.py +13 -0
  90. uwsgiconf/runtime/caching.py +173 -0
  91. uwsgiconf/runtime/control.py +65 -0
  92. uwsgiconf/runtime/locking.py +87 -0
  93. uwsgiconf/runtime/logging.py +20 -0
  94. uwsgiconf/runtime/monitoring.py +107 -0
  95. uwsgiconf/runtime/mules.py +243 -0
  96. uwsgiconf/runtime/platform.py +159 -0
  97. uwsgiconf/runtime/request.py +51 -0
  98. uwsgiconf/runtime/rpc.py +73 -0
  99. uwsgiconf/runtime/scheduling.py +261 -0
  100. uwsgiconf/runtime/signals.py +201 -0
  101. uwsgiconf/runtime/spooler.py +426 -0
  102. uwsgiconf/runtime/websockets.py +32 -0
  103. uwsgiconf/settings.py +29 -0
  104. uwsgiconf/sysinit.py +149 -0
  105. uwsgiconf/typehints.py +8 -0
  106. uwsgiconf/utils.py +544 -0
  107. uwsgiconf/uwsgi.py +26 -0
  108. uwsgiconf/uwsgi_stub.py +1272 -0
  109. uwsgiconf-2.0.0.dist-info/METADATA +159 -0
  110. uwsgiconf-2.0.0.dist-info/RECORD +113 -0
  111. uwsgiconf-2.0.0.dist-info/WHEEL +4 -0
  112. uwsgiconf-2.0.0.dist-info/entry_points.txt +2 -0
  113. uwsgiconf-2.0.0.dist-info/licenses/LICENSE +28 -0
uwsgiconf/__init__.py ADDED
@@ -0,0 +1 @@
1
+ VERSION = '2.0.0'
uwsgiconf/base.py ADDED
@@ -0,0 +1,298 @@
1
+ from collections.abc import Callable
2
+ from typing import TYPE_CHECKING, Any, Union
3
+
4
+ from .utils import listify
5
+
6
+ if TYPE_CHECKING:
7
+ from .config import Section
8
+
9
+
10
+ class Options:
11
+ """Options descriptor. Allows option."""
12
+
13
+ def __init__(self, opt_type: type['OptionsGroup']):
14
+ """
15
+ :param opt_type:
16
+
17
+ """
18
+ self.opt_type = opt_type
19
+
20
+ def __get__(self, section: 'Section', section_cls: type['Section']) -> Union['OptionsGroup', type['OptionsGroup']]:
21
+ """
22
+
23
+ :param section:
24
+ :param section_cls:
25
+
26
+ """
27
+ key = self.opt_type.__name__
28
+
29
+ try:
30
+ options_obj = section._options_objects.get(key)
31
+
32
+ except AttributeError:
33
+ # Allow easy access to option group static params:
34
+ # Section.networking.socket_types.DEFAULT
35
+ return self.opt_type
36
+
37
+ if not options_obj:
38
+ options_obj = self.opt_type(_section=section)
39
+
40
+ section._options_objects[key] = options_obj
41
+
42
+ return options_obj
43
+
44
+
45
+ class OptionKey:
46
+
47
+ __slots__ = ['key']
48
+
49
+ def __init__(self, key: str):
50
+ self.key = key
51
+
52
+ def swap(self, new_key: Any):
53
+
54
+ if new_key:
55
+ self.key = f'{new_key}'
56
+
57
+ def __str__(self):
58
+ return self.key
59
+
60
+ def __eq__(self, obj):
61
+ return self.key == obj
62
+
63
+ def __hash__(self):
64
+ return hash(self.key)
65
+
66
+
67
+ class OptionsGroup:
68
+ """Introduces group of options.
69
+
70
+ Basic group parameters may be passed to initializer
71
+ or `set_basic_params` method.
72
+
73
+ Usually methods setting parameters are named `set_***_params`.
74
+
75
+ Methods ending with `_params` return section object and may be chained.
76
+
77
+ """
78
+ _section: 'Section' = None
79
+ """Section this option group belongs to."""
80
+
81
+ plugin: bool | str = False
82
+ """Indication this option group belongs to a plugin."""
83
+
84
+ name: str = ''
85
+ """Name to represent the group."""
86
+
87
+ def __init__(self, *args, **kwargs):
88
+ if self._section is None:
89
+ self._section = kwargs.pop('_section', None)
90
+
91
+ self.set_basic_params(*args, **kwargs)
92
+
93
+ def _get_name(self, *args, **kwargs) -> str:
94
+ return self.name
95
+
96
+ def __str__(self):
97
+ return self._get_name()
98
+
99
+ def __call__(self, *args, **kwargs) -> 'Section':
100
+ """The call is translated into ``set_basic_params``` call.
101
+
102
+ This approach is much more convenient yet IDE most probably won't
103
+ give you a hint on what arguments are accepted.
104
+
105
+ :param args:
106
+ :param kwargs:
107
+
108
+ """
109
+ return self.set_basic_params(*args, **kwargs)
110
+
111
+ def __eq__(self, obj):
112
+ return f'{self}' == obj
113
+
114
+ def __hash__(self):
115
+ return hash(f'{self}')
116
+
117
+ def set_basic_params(self, *args, **kwargs) -> 'Section':
118
+ return self._section
119
+
120
+ def _set(
121
+ self,
122
+ key: str,
123
+ value: Any,
124
+ *,
125
+ condition: bool | str | None = True,
126
+ cast: Callable | None = None,
127
+ multi: bool = False,
128
+ plugin: str | None = None,
129
+ priority: int | None = None
130
+ ):
131
+ """
132
+
133
+ :param key: Option name
134
+
135
+ :param value: Option value. Can be a lis if ``multi``.
136
+
137
+ :param condition: Condition to test whether this option should be added to section.
138
+ * True - test value is not None.
139
+
140
+ :param cast: Value type caster.
141
+ * bool - treat value as a flag
142
+
143
+ :param multi: Indicate that many options can use the same name.
144
+
145
+ :param plugin: Plugin this option exposed by. Activated automatically.
146
+
147
+ :param priority: Option priority indicator. Options with lower numbers will come first.
148
+
149
+ """
150
+ key = OptionKey(key)
151
+
152
+ def set_plugin(plugin):
153
+ self._section.set_plugins_params(plugins=plugin)
154
+
155
+ def handle_priority(value, *, use_list=False):
156
+
157
+ if priority is not None:
158
+ # Restructure options.
159
+ opts_copy = opts.copy()
160
+ opts.clear()
161
+
162
+ existing_value = opts_copy.pop(key, [])
163
+
164
+ if use_list:
165
+ existing_value.extend(value)
166
+ value = existing_value
167
+
168
+ for pos, (item_key, item_val) in enumerate(opts_copy.items()):
169
+
170
+ if priority == pos:
171
+ opts[key] = value
172
+
173
+ opts[item_key] = item_val
174
+
175
+ return True
176
+
177
+ def handle_plugin_required(val):
178
+
179
+ if isinstance(val, ParametrizedValue):
180
+ key.swap(val.opt_key or key) # todo
181
+
182
+ if val.plugin:
183
+ # Automatic plugin activation.
184
+ set_plugin(val.plugin)
185
+
186
+ if val._opts:
187
+ opts.update(val._opts)
188
+
189
+ if condition is True:
190
+ condition = value is not None
191
+
192
+ if condition is None or condition:
193
+
194
+ opts = self._section._opts
195
+
196
+ if cast is bool:
197
+ if value:
198
+ value = 'true'
199
+
200
+ else:
201
+ try:
202
+ del opts[key]
203
+ except KeyError:
204
+ pass
205
+
206
+ return
207
+
208
+ if self.plugin is True:
209
+ # Automatic plugin activation when option from it is used.
210
+ set_plugin(self)
211
+
212
+ if plugin:
213
+ set_plugin(plugin)
214
+
215
+ if isinstance(value, tuple): # Tuple - expect ParametrizedValue.
216
+ list(map(handle_plugin_required, value))
217
+ value = ' '.join(map(str, value))
218
+
219
+ if multi:
220
+ values = []
221
+
222
+ # First activate plugin if required.
223
+ for value_ in listify(value):
224
+ handle_plugin_required(value_)
225
+ values.append(value_)
226
+
227
+ # Second: list in new option.
228
+ if not handle_priority(values, use_list=True):
229
+ opts.setdefault(key, []).extend(values)
230
+
231
+ else:
232
+ handle_plugin_required(value)
233
+
234
+ if not handle_priority(value):
235
+ opts[key] = value
236
+
237
+ def _make_section_like(self):
238
+ self._section = type('SectionLike', (object,), {'_opts': {}})
239
+
240
+ def _contribute_to_opts(self, target):
241
+ target_section = target._section
242
+ target_section._opts.update(self._section._opts)
243
+
244
+
245
+ class ParametrizedValue(OptionsGroup):
246
+ """Represents parametrized option value."""
247
+
248
+ alias: str = ''
249
+ """Alias to address this value."""
250
+
251
+ args_joiner: str = ' '
252
+ """Symbol to join arguments with."""
253
+
254
+ name_separator: str = ':'
255
+ """Separator to add after name portion."""
256
+
257
+ name_separator_strip: bool = False
258
+ """Strip leading and trailing name separator from the result."""
259
+
260
+ opt_key: str | None = None
261
+ """Allows swapping default option key with custom value."""
262
+
263
+ def __init__(self, *args):
264
+ self.args = list(args)
265
+ self._opts = {}
266
+ super().__init__(_section=self)
267
+
268
+ def __str__(self):
269
+ args = [f'{arg}' for arg in self.args if arg is not None]
270
+
271
+ result = ''
272
+
273
+ if self.opt_key is None:
274
+ result += self._get_name() + self.name_separator
275
+
276
+ result += self.args_joiner.join(args)
277
+
278
+ if self.alias:
279
+ result = f'{self.alias} {result}'
280
+
281
+ result = result.strip()
282
+
283
+ if self.name_separator_strip:
284
+ result = result.strip(self.name_separator)
285
+
286
+ return result
287
+
288
+
289
+ class TemplatedValue(ParametrizedValue):
290
+
291
+ tpl: str = '%s'
292
+
293
+ def __init__(self, name: str):
294
+ self._name = name
295
+ super().__init__()
296
+
297
+ def __str__(self):
298
+ return self.tpl % self._name
uwsgiconf/cli.py ADDED
@@ -0,0 +1,105 @@
1
+ import sys
2
+ from contextlib import contextmanager
3
+
4
+ import click
5
+
6
+ from uwsgiconf import VERSION
7
+ from uwsgiconf.exceptions import ConfigurationError
8
+ from uwsgiconf.sysinit import TYPE_SYSTEMD, TYPES, get_config
9
+ from uwsgiconf.utils import ConfModule, UwsgiRunner
10
+
11
+
12
+ @contextmanager
13
+ def errorprint():
14
+ """Print out descriptions from ConfigurationError."""
15
+ try:
16
+ yield
17
+
18
+ except ConfigurationError as e:
19
+ click.secho(f'{e}', err=True, fg='red')
20
+ sys.exit(1)
21
+
22
+
23
+ @click.group()
24
+ @click.version_option(version='.'.join(map(str, VERSION)))
25
+ def base():
26
+ """uwsgiconf command line utility.
27
+
28
+ Tools to facilitate uWSGI configuration.
29
+
30
+ """
31
+
32
+ arg_conf = click.argument(
33
+ 'conf', type=click.Path(exists=True, dir_okay=False), default=ConfModule.default_name)
34
+
35
+
36
+ @base.command()
37
+ @arg_conf
38
+ @click.option('--only', help='Configuration alias from module to run uWSGI with.')
39
+ def run(conf, only):
40
+ """Runs uWSGI passing to it using the default or another `uwsgiconf` configuration module.
41
+
42
+ """
43
+ with errorprint():
44
+ config = ConfModule(conf)
45
+ spawned = config.spawn_uwsgi(only=only)
46
+
47
+ for alias, pid in spawned:
48
+ click.secho(f"Spawned uWSGI for configuration aliased '{alias}'. PID {pid}", fg='green')
49
+
50
+
51
+ @base.command()
52
+ @arg_conf
53
+ def compile(conf):
54
+ """Compiles classic uWSGI configuration file using the default
55
+ or given `uwsgiconf` configuration module.
56
+
57
+ """
58
+ with errorprint():
59
+ config = ConfModule(conf)
60
+ for conf in config.configurations:
61
+ conf.format(do_print=True)
62
+
63
+
64
+ @base.command()
65
+ @click.argument('systype', type=click.Choice(TYPES), default=TYPE_SYSTEMD)
66
+ @arg_conf
67
+ @click.option('--project', help='Project name to use as service name.')
68
+ def sysinit(systype, conf, project):
69
+ """Outputs configuration for system initialization subsystem."""
70
+
71
+ click.secho(get_config(
72
+ systype,
73
+ conf=ConfModule(conf).configurations[0],
74
+ conf_path=conf,
75
+ project_name=project,
76
+ ))
77
+
78
+
79
+ @base.command()
80
+ def probe_plugins():
81
+ """Runs uWSGI to determine what plugins are available and prints them out.
82
+
83
+ Generic plugins come first then after blank line follow request plugins.
84
+
85
+ """
86
+ plugins = UwsgiRunner().get_plugins()
87
+
88
+ for plugin in sorted(plugins.generic):
89
+ click.secho(plugin)
90
+
91
+ click.secho('')
92
+
93
+ for plugin in sorted(plugins.request):
94
+ click.secho(plugin)
95
+
96
+
97
+ def main():
98
+ """
99
+ CLI entry point
100
+ """
101
+ base(obj={})
102
+
103
+
104
+ if __name__ == '__main__':
105
+ main()