/usr/lib/python3/dist-packages/plainbox/impl/__init__.py is in python3-plainbox 0.25-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | # This file is part of Checkbox.
#
# Copyright 2012 Canonical Ltd.
# Written by:
# Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
#
# Checkbox is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3,
# as published by the Free Software Foundation.
#
# Checkbox is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.
"""
:mod:`plainbox.impl` -- implementation package
==============================================
.. warning::
THIS MODULE DOES NOT HAVE STABLE PUBLIC API
"""
from functools import wraps
from inspect import getabsfile
from warnings import warn
import os.path
import sys
import textwrap
import plainbox
from plainbox.impl._textwrap import _textwrap_indent
def _get_doc_margin(doc):
"""
Find minimum indentation of any non-blank lines after first line.
"""
lines = doc.expandtabs().split('\n')
margin = sys.maxsize
for line in lines[1:]:
content = len(line.lstrip())
if content:
indent = len(line) - content
margin = min(margin, indent)
return 0 if margin == sys.maxsize else margin
def public(import_path, introduced=None, deprecated=None):
"""
Public API decorator generator.
This decorator serves multiple uses:
* It clearly documents all public APIs. This is visible to
both developers reading the source code directly and to people
reading code documentation (by adjusting __doc__)
* It provides a stable import location while allowing to move the
implementation around as the code evolves. This unbinds the name and
documentation of the symbol from the code.
* It documents when each function was introduced. This is also visible
in the generated documentation.
* It documents when each function will be decommissioned. This is
visible in the generated documentation and at runtime. Each initial
call to a deprecated function will cause a PendingDeprecationWarnings
to be logged.
The actual implementation of the function must be in in a module specified
by import_path. It can be a module name or a module name and a function
name, when separated by a colon.
"""
# Create a forwarding decorator for the shim function The shim argument is
# the actual empty function from the public module that serves as
# documentation carrier.
def decorator(shim):
# Allow to override function name by specifying it in the import path
# after a colon. If missing it defaults to the name of the shim
try:
module_name, func_name = import_path.split(":", 1)
except ValueError:
module_name, func_name = import_path, shim.__name__
# Import the module with the implementation and extract the function
module = __import__(module_name, fromlist=[''])
try:
impl = getattr(module, func_name)
except AttributeError:
raise NotImplementedError(
"%s.%s does not exist" % (module_name, func_name))
@wraps(shim)
def call_impl(*args, **kwargs):
return impl(*args, **kwargs)
# Document the public nature of the function
call_impl.__doc__ += "\n".join([
"",
" This function is a part of the public API",
" The private implementation is in {}:{}".format(
import_path, shim.__name__)
])
if introduced is None:
call_impl.__doc__ += "\n".join([
"",
" This function was introduced in the initial version of"
" plainbox",
])
else:
call_impl.__doc__ += "\n".join([
"",
" This function was introduced in version: {}".format(
introduced)
])
# Document deprecation status, if any
if deprecated is not None:
call_impl.__doc__ += "\n".join([
" warn:",
" This function is deprecated",
" It will be removed in version: {}".format(deprecated),
])
# Add implementation docs, if any
if impl.__doc__ is not None:
call_impl.__doc__ += "\n".join([
" Additional documentation from the private"
" implementation:"])
call_impl.__doc__ += impl.__doc__
return call_impl
return decorator
def deprecated(version, explanation=None):
"""
Decorator for marking functions as deprecated
:param version:
Version in which a function is deprecated
:param explanation:
Explanation of the deprecation. Ideally this will include hints on how
to get a modern replacement.
Deprecated functions are candidates for removal. Existing code should be
adapted not to make any calls to the deprecated functions. New code should
not use such functions.
..note::
Due to the way python warning module works, to see deprecated function
notices re-run your application with PYTHONWARNINGS=once
"""
if not isinstance(version, str):
# Due to a common mistake, 'version' is probably the decorated function
# and @deprecated was called without ()
raise SyntaxError("@deprecated() must be called with a parameter")
def decorator(func):
"""
The @deprecated decorator with deprecation information
"""
msg = "{0} is deprecated since version {1}".format(
func.__name__, version)
if func.__doc__ is None:
func.__doc__ = ''
indent = 4 * ' '
else:
indent = _get_doc_margin(func.__doc__) * ' '
func.__doc__ += indent + '\n'
func.__doc__ += indent + '.. deprecated:: {}'.format(version)
if explanation is not None:
func.__doc__ += _textwrap_indent(
textwrap.dedent(explanation), prefix=indent * 2)
@wraps(func)
def wrapper(*args, **kwargs):
warn(DeprecationWarning(msg), stacklevel=2)
return func(*args, **kwargs)
return wrapper
return decorator
def get_plainbox_dir():
"""
Return the root directory of the plainbox package.
"""
return os.path.dirname(getabsfile(plainbox))
|