devstatusdecos 0.0.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.
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env python
2
+
3
+ """
4
+ devstatusdecos
5
+
6
+ Decorators, warnings, and exceptions related to documentation
7
+ of the development statuses of classes, functions, and other objects.
8
+ """
9
+
10
+ __all__ = ["deprecated",
11
+ "superseded",
12
+ "insecure",
13
+ "pending_deprecation",
14
+ "experimental",
15
+ "todo",
16
+ "TODO",
17
+ "fixme",
18
+ "FIXME",
19
+ "InsecureError",
20
+ "FatallyInsecureError",
21
+ "ExperimentalWarning",
22
+ "TodoWarning",
23
+ "TodoError"
24
+ ]
25
+
26
+ __version__ = "v0.0.0.0"
27
+
28
+ from .devstatusdecos import *
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env python
2
+
3
+ """
4
+ _type_imports
5
+
6
+ Various imports related to type annotations.
7
+ Not expected to be imported on it's own.
8
+ """
9
+ # pylint:disable=unused-import
10
+
11
+
12
+ from sys import version_info
13
+
14
+
15
+ try:
16
+ from typing import LiteralString # noqa:F401
17
+ except ImportError:
18
+ from typing_extensions import LiteralString # noqa:F401
19
+
20
+
21
+ try:
22
+ from typing import Type # noqa:F401
23
+ except ImportError:
24
+ from typing_extensions import Type # noqa:F401
25
+
26
+
27
+ try:
28
+ from typing import Generic # noqa:F401
29
+ except ImportError:
30
+ from typing_extensions import Generic # noqa:F401
31
+
32
+
33
+ try:
34
+ from typing import TypeVar # noqa:F401
35
+ except ImportError:
36
+ from typing_extensions import TypeVar # noqa:F401
37
+
38
+
39
+ try:
40
+ from typing import overload
41
+ except ImportError:
42
+ from typing_extensions import overload # noqa:F401
43
+
44
+
45
+ try:
46
+ from typing import Callable
47
+ except ImportError:
48
+ from typing_extensions import Callable # noqa:F401
49
+
50
+
51
+ try:
52
+ from typing import Any # noqa:F401
53
+ except ImportError:
54
+ from typing_extensions import Any # noqa:F401
55
+
56
+
57
+ try:
58
+ from typing import ParamSpec # noqa:F401
59
+ except ImportError:
60
+ from typing_extensions import ParamSpec # noqa:F401
61
+
62
+
63
+ try:
64
+ from typing import Never # noqa:F401
65
+ except ImportError:
66
+ from typing_extensions import Never # noqa:F401
67
+
68
+
69
+ try:
70
+ from typing import cast # noqa:F401
71
+ except ImportError:
72
+ from typing_extensions import cast # noqa:F401
73
+
74
+
75
+ try:
76
+ from typing import TypeAlias # noqa:F401
77
+ except ImportError:
78
+ from typing_extensions import TypeAlias # noqa:F401
79
+
80
+
81
+ try:
82
+ from typing import Tuple # noqa:F401
83
+ except ImportError:
84
+ from typing_extensions import Tuple # noqa:F401
85
+
86
+
87
+ try:
88
+ from typing import NoReturn # noqa:F401
89
+ except ImportError:
90
+ from typing_extensions import NoReturn # noqa:F401
91
+
92
+
93
+ VersionInfoTuple:TypeAlias = (Tuple[int, int, int, LiteralString, int] |
94
+ Tuple[int, int, int, LiteralString] |
95
+ Tuple[int, int, int] |
96
+ Tuple[int, int] |
97
+ Tuple[int] |
98
+ Tuple[()] |
99
+ None
100
+ )
101
+
102
+
103
+ T = TypeVar("T")
104
+
105
+
106
+ PS = ParamSpec("PS")
107
+
108
+
109
+ if version_info >= (3, 13):
110
+ RT = TypeVar("RT", default=None) # type:ignore
111
+ else:
112
+ RT = TypeVar("RT")
113
+
114
+
115
+ if version_info >= (3, 13):
116
+ VersionInfoTupleT = TypeVar("VersionInfoTupleT",
117
+ bound = VersionInfoTuple,
118
+ default = None # type:ignore
119
+ )
120
+ else:
121
+ VersionInfoTupleT = TypeVar("VersionInfoTupleT",
122
+ bound = VersionInfoTuple
123
+ )
124
+
125
+
126
+ del version_info
@@ -0,0 +1,249 @@
1
+ #!/usr/bin/env python
2
+
3
+ """
4
+ devstatusdecos
5
+
6
+ Decorators, warnings, and exceptions related to documentation
7
+ of the development statuses of classes, functions, and other objects.
8
+ """
9
+
10
+ __all__ = ["deprecated",
11
+ "superseded",
12
+ "insecure",
13
+ "pending_deprecation",
14
+ "experimental",
15
+ "todo",
16
+ "TODO",
17
+ "fixme",
18
+ "FIXME",
19
+ "InsecureError",
20
+ "FatallyInsecureError",
21
+ "ExperimentalWarning",
22
+ "TodoWarning",
23
+ "TodoError"
24
+ ]
25
+
26
+ from warnings import simplefilter
27
+ from functools import wraps
28
+ from sys import version_info
29
+
30
+ from ._type_imports import * # pylint:disable=wildcard-import,unused-wildcard-import
31
+
32
+ try:
33
+ from typing_extensions import deprecated
34
+ except ImportError as e:
35
+ if version_info < (3, 13, 3):
36
+ raise e # there is a bug in __new__ for previous versions
37
+ else:
38
+ # pylint:disable-next=ungrouped-imports
39
+ from warnings import deprecated # pyright:ignore[reportAttributeAccessIssue]
40
+ deprecated = cast(Type, deprecated)
41
+ superseded = deprecated
42
+
43
+
44
+ class InsecureError(RuntimeError):
45
+ """
46
+ An exception raised when a `insecure` Callable is executed.
47
+
48
+ This is a subclass of `RuntimeError`
49
+ and is used to indicate that a function or class is in some way insecure
50
+ and should not be allowed to execute further.
51
+ This exception is used mainly by the `insecure` decorator.
52
+ """
53
+
54
+
55
+ class FatallyInsecureError(InsecureError, SystemExit):
56
+ """
57
+ An extention of `InsecureError`, raised in conditions where a function or class
58
+ should raise an error that attempts to force termination of execution via an exception.
59
+ """
60
+ def __init__(self, *args: object, code:int = 1) -> None:
61
+ super(InsecureError, self).__init__(*args)
62
+ self.code = code
63
+
64
+
65
+ class ExperimentalWarning(Warning):
66
+ """A warning used to indicate that a function or class
67
+ is experimental and may change at any time."""
68
+
69
+
70
+ simplefilter('default', ExperimentalWarning)
71
+
72
+
73
+ class TodoWarning(ExperimentalWarning):
74
+ """A warning used to indicate that a function or class
75
+ contains something todo and likely is missing a key part of
76
+ its functionality and may change at any time or even be removed.
77
+ This will also always be raised as a error when a `todo`
78
+ `Callable` is called."""
79
+
80
+
81
+ simplefilter('always', TodoWarning)
82
+
83
+
84
+ class TodoError(NotImplementedError):
85
+ """
86
+ An exception raised when a `todo` Callable is executed.
87
+
88
+ This is a subclass of `NotImplementedError` and is used to indicate that
89
+ a function or class contains a todo and is likely missing a key part of
90
+ its functionality. This exception is used mainly by the `todo` decorator.
91
+ """
92
+
93
+
94
+ class insecure(): # pylint:disable=invalid-name
95
+ """A decorator that marks a class,
96
+ function or method as insecure, indicating that it
97
+ should not be allowed to execute further.
98
+ Unlike other dev stats decorators,
99
+ this replaces the a decorated callable or type entirely with
100
+ a callable that raises an error,
101
+ which may confuse some type checkers.
102
+
103
+ While not intended for use on things besides types or callables,
104
+ the exception will be raised immediately in cases there the decorated
105
+ object is not callable.
106
+ """
107
+
108
+ def __init__(self,
109
+ message:str,
110
+ fatal:bool,
111
+ code:int = 1,
112
+ ):
113
+ self.exc = FatallyInsecureError(message, code = code)
114
+ if not fatal:
115
+ self.exc = InsecureError(message)
116
+ self.code = code
117
+
118
+ def __call__(self, arg:Any) -> Callable[..., NoReturn]: # noqa:F811, E301
119
+ if not callable(arg):
120
+ # its already possibly to late, but lets stop anyway
121
+ raise self.exc
122
+
123
+ def __wrapper(*_, **__):
124
+ raise self.exc
125
+
126
+ return __wrapper
127
+
128
+
129
+ class pending_deprecation(deprecated, Generic[VersionInfoTupleT]): # pylint:disable=invalid-name
130
+ """A decorator that indicates that the decorated class, function,
131
+ or method is pending deprecation.
132
+
133
+ Note that this inherits the native `deprecated` decorator,
134
+ so some introspective tools might falsely flag this as
135
+ a deprecated function instead."""
136
+
137
+ def __init__(self,
138
+ message:LiteralString,
139
+ /,
140
+ *,
141
+ pending_category:Type[DeprecationWarning | PendingDeprecationWarning
142
+ ]|None = PendingDeprecationWarning,
143
+ deprecated_category:Any = ..., # pylint:disable=unused-argument
144
+ stacklevel:int = 1,
145
+ deprecate_py_ver:Any = ... # pylint:disable=unused-argument
146
+ ):
147
+ super().__init__(message, category=pending_category, stacklevel=stacklevel)
148
+
149
+ def __new__(cls,
150
+ message:LiteralString,
151
+ /,
152
+ *,
153
+ pending_category:Type[DeprecationWarning | PendingDeprecationWarning
154
+ ]|None = PendingDeprecationWarning,
155
+ deprecated_category:Type[DeprecationWarning
156
+ ]|None = DeprecationWarning,
157
+ stacklevel:int = 1,
158
+ deprecate_py_ver:VersionInfoTupleT = None
159
+ ):
160
+ if deprecate_py_ver is not None and version_info >= deprecate_py_ver:
161
+ return deprecated(message, category=deprecated_category, stacklevel=stacklevel)
162
+ return super().__new__(cls)
163
+
164
+
165
+ class experimental(deprecated): # pylint:disable=invalid-name
166
+ """A decorator that marks a class,
167
+ function or method as experimental and should be used with caution.
168
+ Note that this inherits the native `deprecated` decorator,
169
+ so some introspective tools might falsely flag this as
170
+ a deprecated function instead."""
171
+
172
+ def __init__(self,
173
+ message:LiteralString,
174
+ /,
175
+ *,
176
+ category:Type[Warning]|None = ExperimentalWarning,
177
+ stacklevel:int = 1):
178
+ super().__init__(message, category=category, stacklevel=stacklevel)
179
+
180
+
181
+ class todo(experimental): # pylint:disable=invalid-name
182
+ """
183
+ A decorator that marks a class, function, or method as todo and is
184
+ presumed to be missing a key part of it's functionality.
185
+ It may change at any time or even removed.
186
+
187
+ This will always raise a `TodoError` when a `todo`
188
+ Callable is called (or Type is initalized),
189
+ unless `error_condition`
190
+ is truthy or a callable that will return `True`.
191
+ `error_condition` will always be checked when the wrapped
192
+ function is called.
193
+
194
+ The constructor matches the same parameters as `deprecated`,
195
+ in exception for the fact that the default warning type is a
196
+ `TodoWarning` and that 'TODO:' is always appended to the message.
197
+ """
198
+
199
+ # Sadly there is not way to easily make type checkers
200
+ # recognise this besides making a plugin for this,
201
+ # so we have to piggyback off of the deprecation
202
+ # detection in all the type checkers for now.
203
+
204
+ TODO_PREFIX:LiteralString = "TODO: "
205
+
206
+ def __init__(self,
207
+ message:LiteralString,
208
+ error_condition:Callable[[Any], bool] | None = None,
209
+ /,
210
+ *,
211
+ category:Type[Warning] | None = TodoWarning,
212
+ stacklevel:int = 1
213
+ ):
214
+ if not message.startswith(self.TODO_PREFIX):
215
+ message = self.TODO_PREFIX + message
216
+ super().__init__(message,
217
+ category=category,
218
+ stacklevel=stacklevel
219
+ )
220
+ self.error_condition = error_condition
221
+
222
+ @overload
223
+ def __call__(self, # noqa:F811, E302
224
+ arg:Callable[PS, RT],
225
+ /,
226
+ ) -> Callable[PS, RT|Never]:
227
+ ...
228
+
229
+ @overload # noqa:E301
230
+ def __call__(self, arg:T, /) -> T: # noqa:F811, E302
231
+ ...
232
+
233
+ def __call__(self, arg:Any, /) -> Any: # noqa:F811, E301
234
+ arg = super().__call__(arg)
235
+ d = f"{self.message}\n{getattr(arg, '__doc__', '')}".strip()
236
+ setattr(arg, "__doc__", d)
237
+ if callable(arg):
238
+ @wraps(arg, assigned=("__module__", "__name__", "__qualname__", "__doc__"))
239
+ def __wrapper(*args, **kwargs):
240
+ if self.error_condition is not None and self.error_condition(arg):
241
+ raise TodoError(self.message)
242
+ return arg(*args, **kwargs)
243
+ return __wrapper
244
+ return arg
245
+
246
+
247
+ TODO = todo
248
+ fixme = todo # pylint:disable=invalid-name
249
+ FIXME = todo
File without changes
@@ -0,0 +1,115 @@
1
+ Metadata-Version: 2.4
2
+ Name: devstatusdecos
3
+ Version: 0.0.0.0
4
+ Summary: Decorators, warnings, and exceptions for explicitly marking the development status of Python objects
5
+ Author-email: Markus Hammer <107761433+MarkusHammer@users.noreply.github.com>
6
+ License: Copyright © 2026 Markus Hammer
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
11
+
12
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13
+
14
+ Project-URL: Homepage, https://github.com/MarkusHammer/devstatusdecos
15
+ Project-URL: Documentation, https://MarkusHammer.gthub.io/devstatusdecos
16
+ Project-URL: Github, https://github.com/MarkusHammer/devstatusdecos
17
+ Project-URL: Issues, https://github.com/MarkusHammer/devstatusdecos/issues
18
+ Project-URL: Pull Requests, https://github.com/MarkusHammer/devstatusdecos/pulls
19
+ Project-URL: Git, https://github.com/MarkusHammer/devstatusdecos.git
20
+ Keywords: api,decorators,deprecation,design,development,experimental,fixme,management,pending,qa,quality,runtime,simple,single,small,stability,todo,tools,utils,validation,warnings
21
+ Classifier: Intended Audience :: Developers
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Programming Language :: Python :: 3.13
26
+ Classifier: Programming Language :: Python :: 3
27
+ Classifier: Programming Language :: Python
28
+ Classifier: Topic :: Software Development :: Libraries
29
+ Classifier: Topic :: Software Development :: Quality Assurance
30
+ Classifier: Topic :: Software Development :: Testing
31
+ Classifier: Topic :: Utilities
32
+ Classifier: Typing :: Typed
33
+ Classifier: Natural Language :: English
34
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
35
+ Requires-Python: >=3.10
36
+ Description-Content-Type: text/markdown
37
+ License-File: LICENCE
38
+ Requires-Dist: typing_extensions; python_version < "3.13.3"
39
+ Provides-Extra: dev
40
+ Requires-Dist: setuptools>=64.0.0; extra == "dev"
41
+ Requires-Dist: pipreqs; extra == "dev"
42
+ Requires-Dist: validate-pyproject[all]; extra == "dev"
43
+ Requires-Dist: build; extra == "dev"
44
+ Requires-Dist: twine; extra == "dev"
45
+ Requires-Dist: coverage; extra == "dev"
46
+ Requires-Dist: pdoc3; extra == "dev"
47
+ Requires-Dist: pyright; extra == "dev"
48
+ Requires-Dist: pylint; extra == "dev"
49
+ Requires-Dist: flake8; extra == "dev"
50
+ Dynamic: license-file
51
+
52
+ # `devstatusdecos`
53
+
54
+ > Decorators, warnings, and exceptions for explicitly marking the development status of Python objects.
55
+
56
+ [![CodeQL](https://github.com/MarkusHammer/devstatusdecos/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/MarkusHammer/devstatusdecos/actions/workflows/github-code-scanning/codeql) [![Ko-Fi](https://img.shields.io/badge/Ko--fi-F16061?style=for-the-badge&logo=ko-fi&logoColor=white)](https://ko-fi.com/markushammer)
57
+
58
+ This module provides structured, runtime-enforced annotations for things like deprecation, experimental APIs, insecure code paths, and unfinished implementations.
59
+
60
+ [Documentation](https://MarkusHammer.github.io/devstatusdecos)
61
+
62
+ ## Features
63
+
64
+ - Imports (and requires access to) the `deprecated` decorator from either `typing_extensions` or `warnings`. `typing_extensions` is requires for python < 3.13.3.
65
+ - `pending_deprecation`, which raises the builtin `PendingDeprecationWarning` with optional the option of automatic escalation to `deprecated` status based on python version.
66
+ - `experimental`, analogous to `deprecated`, raises a `ExperimentalWarning` warning when called.
67
+ - `todo`, analogous to `deprecated`, raises a `ExperimentalWarning` warning when called, optionally raising a `TodoError` in a wrapped callable.
68
+ - `insecure`, which always raises a `InsecureError` or `FatallyInsecureError`, optionally exiting.
69
+
70
+ ## Installation
71
+
72
+ `pip install devstatusdecos`
73
+
74
+ ## Example
75
+
76
+ ``` python
77
+ from devstatusdecos import experimental, todo, insecure
78
+
79
+ @experimental("API may change")
80
+ def new_feature():
81
+ ...
82
+
83
+ @todo("Implement edge case handling")
84
+ class Incomplete():
85
+ def __init__(self):
86
+ ...
87
+
88
+ @insecure("Uses unsafe cryptography", fatal=True)
89
+ def bad_idea():
90
+ ...
91
+ ```
92
+
93
+ # Security Policy
94
+
95
+ While the python source code will be actively maintained, any binary files (if at all provided) are in no way supported.
96
+ These are provided as a courtesy and are not intended to be the main usage of this software.
97
+ Please keep this in mind when choosing how you wish to use this software.
98
+
99
+ ## Supported Versions
100
+
101
+ | Version | Supported |
102
+ | ----------- | --------- |
103
+ | 0.0.0.0 < | ❌ |
104
+
105
+ ## Reporting a Vulnerability
106
+
107
+ Please report any issues to the email 107761433+MarkusHammer{THEN THE @ SYMBOL HERE}users.noreply.github.com
108
+
109
+ Copyright © 2026 Markus Hammer
110
+
111
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
112
+
113
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
114
+
115
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,10 @@
1
+ devstatusdecos/__init__.py,sha256=VSXGqq4Ocs8cpS8hfJH3NZSQI2cC2NJipBd75TfCNf8,620
2
+ devstatusdecos/_type_imports.py,sha256=FU9MDRZvut4QJ2jPCZg4vIaYSSX8dFkaqEJKOLJy-vA,2771
3
+ devstatusdecos/devstatusdecos.py,sha256=SOJu-FrYvJo_i7O3WW0aouso2q5seNWX1ITVkJlmyzc,8667
4
+ devstatusdecos/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ devstatusdecos-0.0.0.0.dist-info/licenses/LICENCE,sha256=Mr_EX1s02EQAObw8hZ0USOnPx37-NzxGMpHmIezld8Y,1064
6
+ devstatusdecos-0.0.0.0.dist-info/METADATA,sha256=W02ftgljBnFYiE_ZWxMFvzMP-Td2tAZX0N7oiLnSInc,6800
7
+ devstatusdecos-0.0.0.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
8
+ devstatusdecos-0.0.0.0.dist-info/top_level.txt,sha256=iIHJAOL6jqt2GGL_YeX2WLxXkNAC4wbY1LRzUiWR_B4,15
9
+ devstatusdecos-0.0.0.0.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
10
+ devstatusdecos-0.0.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,7 @@
1
+ Copyright © 2026 Markus Hammer
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1 @@
1
+ devstatusdecos
@@ -0,0 +1 @@
1
+