Use versionadded and versionchanged in doc

Document in which version new types and functions were added using
".. versionadded:: x.y". Document changes using
".. versionchanged:: x.y."

For new modules, add the versionadded tag in the module top
docstring, not on each type/function.

Add fileutils to documentation. The doc part was forgotten during the
graduation.

Add docstrings to convert versions of versionutils.

I used "git blame" + "git tag --contains=SHA1" to find these version,
and then I checked manually each version.

Change-Id: Ia2f00aa29eb36410a49fc1d350896a569a7737a1
This commit is contained in:
Victor Stinner 2015-10-15 14:57:35 +02:00
parent 6aa24675e8
commit 7f57de5bb2
14 changed files with 172 additions and 10 deletions

View File

@ -0,0 +1,7 @@
=============
fileutils
=============
.. automodule:: oslo_utils.fileutils
:members:

View File

@ -21,6 +21,7 @@ API Documentation
api/encodeutils
api/eventletutils
api/excutils
api/fileutils
api/fixture
api/importutils
api/netutils

View File

@ -104,6 +104,8 @@ def exception_to_unicode(exc):
If the exception message is a bytes strings, try to decode it from UTF-8
(superset of ASCII), from the locale encoding, or fallback to decoding it
from ISO-8859-1 (which never fails).
.. versionadded:: 1.6
"""
msg = None
if six.PY2:

View File

@ -14,6 +14,12 @@
# License for the specific language governing permissions and limitations
# under the License.
"""
Eventlet utils helper module.
.. versionadded:: 1.3
"""
import threading
import warnings
@ -35,6 +41,13 @@ _ALL_PATCH = frozenset(['__builtin__', 'MySQLdb', 'os',
def fetch_current_thread_functor():
"""Get the current thread.
If eventlet is used to monkey-patch the threading module, return the
current eventlet greenthread. Otherwise, return the current Python thread.
.. versionadded:: 1.5
"""
# Until https://github.com/eventlet/eventlet/issues/172 is resolved
# or addressed we have to use complicated workaround to get a object
# that will not be recycled; the usage of threading.current_thread()

View File

@ -45,6 +45,8 @@ class CausedByException(Exception):
should itself be an exception instance, this is useful for
creating a chain of exceptions for versions of python where
this is not yet implemented/supported natively.
.. versionadded:: 2.4
"""
def __init__(self, message, cause=None):
super(CausedByException, self).__init__(message)
@ -126,6 +128,8 @@ def raise_with_cause(exc_cls, message, *args, **kwargs):
exceptions constructor.
:param kwargs: any additional keyword arguments to pass to the
exceptions constructor.
.. versionadded:: 1.6
"""
if 'cause' not in kwargs:
exc_type, exc, exc_tb = sys.exc_info()
@ -174,6 +178,9 @@ class save_and_reraise_exception(object):
[if statements to determine whether to raise a new exception]
# Not raising a new exception, so reraise
ctxt.reraise = True
.. versionchanged:: 1.4
Added *logger* optional parameter.
"""
def __init__(self, reraise=True, logger=None):
self.reraise = reraise

View File

@ -13,6 +13,12 @@
# License for the specific language governing permissions and limitations
# under the License.
"""
File utilities.
.. versionadded:: 1.8
"""
import contextlib
import errno
import logging
@ -87,6 +93,8 @@ def write_to_tempfile(content, path=None, suffix='', prefix='tmp'):
For example: it can be used in database tests for creating
configuration files.
.. versionadded:: 1.9
"""
if path:
ensure_tree(path)

View File

@ -14,6 +14,12 @@
# License for the specific language governing permissions and limitations
# under the License.
"""
Test fixtures.
.. versionadded:: 1.3
"""
import fixtures
from oslo_utils import timeutils

View File

@ -22,7 +22,10 @@ import traceback
def import_class(import_str):
"""Returns a class from a string including module and class."""
"""Returns a class from a string including module and class.
.. versionadded:: 0.3
"""
mod_str, _sep, class_str = import_str.rpartition('.')
__import__(mod_str)
try:
@ -34,7 +37,10 @@ def import_class(import_str):
def import_object(import_str, *args, **kwargs):
"""Import a class and return an instance of it."""
"""Import a class and return an instance of it.
.. versionadded:: 0.3
"""
return import_class(import_str)(*args, **kwargs)
@ -44,6 +50,12 @@ def import_object_ns(name_space, import_str, *args, **kwargs):
Imports a class and return an instance of it, first by trying
to find the class in a default namespace, then failing back to
a full path if not found in the default namespace.
.. versionadded:: 0.3
.. versionchanged:: 2.6
Don't capture :exc:`ImportError` when instanciating the object, only
when importing the object class.
"""
import_value = "%s.%s" % (name_space, import_str)
try:
@ -54,12 +66,19 @@ def import_object_ns(name_space, import_str, *args, **kwargs):
def import_module(import_str):
"""Import a module."""
"""Import a module.
.. versionadded:: 0.3
"""
__import__(import_str)
return sys.modules[import_str]
def import_versioned_module(version, submodule=None):
"""Import a versioned module.
.. versionadded:: 0.3
"""
module = 'oslo.v%s' % version
if submodule:
module = '.'.join((module, submodule))

View File

@ -87,6 +87,8 @@ def is_valid_ipv4(address):
:param address: Value to verify
:type address: string
:returns: bool
.. versionadded:: 1.1
"""
try:
return netaddr.valid_ipv4(address)
@ -100,6 +102,8 @@ def is_valid_ipv6(address):
:param address: Value to verify
:type address: string
:returns: bool
.. versionadded:: 1.1
"""
try:
return netaddr.valid_ipv6(address)
@ -117,6 +121,8 @@ def get_ipv6_addr_by_EUI64(prefix, mac):
:param mac: IEEE 802 48-bit MAC address.
:returns: IPv6 address on success.
:raises ValueError, TypeError: For any invalid input.
.. versionadded:: 1.4
"""
# Check if the prefix is an IPv4 address
if netaddr.valid_ipv4(prefix):
@ -143,6 +149,7 @@ def is_ipv6_enabled():
:returns: True if the platform has IPv6 support, False otherwise.
.. versionadded:: 1.4
"""
global _IS_IPV6_ENABLED
@ -164,12 +171,17 @@ def is_valid_ip(address):
:param address: Value to verify
:type address: string
:returns: bool
.. versionadded:: 1.1
"""
return is_valid_ipv4(address) or is_valid_ipv6(address)
def is_valid_port(port):
"""Verify that port represents a valid port number."""
"""Verify that port represents a valid port number.
.. versionadded:: 1.1.1
"""
try:
val = int(port)
except (ValueError, TypeError):
@ -185,6 +197,11 @@ def get_my_ipv4():
were to be sent out to some well known address on the Internet. In this
case, IP from RFC5737 is used, but the specific address does not
matter much. No traffic is actually sent.
.. versionadded:: 1.1
.. versionchanged:: 1.2.1
Return ``'127.0.0.1'`` if there is no default interface.
"""
try:
csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

View File

@ -14,6 +14,12 @@
# License for the specific language governing permissions and limitations
# under the License.
"""
Reflection module.
.. versionadded:: 1.1
"""
import inspect
import types
@ -31,7 +37,10 @@ _BUILTIN_MODULES = ('builtins', '__builtin__', '__builtins__', 'exceptions')
def get_members(obj, exclude_hidden=True):
"""Yields the members of an object, filtering by hidden/not hidden."""
"""Yields the members of an object, filtering by hidden/not hidden.
.. versionadded:: 2.3
"""
for (name, value) in inspect.getmembers(obj):
if name.startswith("_") and exclude_hidden:
continue

View File

@ -213,7 +213,7 @@ def to_slug(value, incoming=None, errors="strict"):
def mask_password(message, secret="***"):
"""Replace password with 'secret' in message.
"""Replace password with *secret* in message.
:param message: The string which includes security information.
:param secret: value with which to replace passwords.
@ -231,6 +231,24 @@ def mask_password(message, secret="***"):
"'original_password' : '***'"
>>> mask_password("u'original_password' : u'aaaaa'")
"u'original_password' : u'***'"
.. versionadded:: 0.2
.. versionchanged:: 1.1
Replace also ``'auth_token'``, ``'new_pass'`` and ``'auth_password'``
keys.
.. versionchanged:: 1.1.1
Replace also ``'secret_uuid'`` key.
.. versionchanged:: 1.5
Replace also ``'sys_pswd'`` key.
.. versionchanged:: 2.6
Replace also ``'token'`` key.
.. versionchanged:: 2.7
Replace also ``'secret'`` key.
"""
try:
@ -262,6 +280,8 @@ def is_int_like(val):
:param val: Value to verify
:type val: string
:returns: bool
.. versionadded:: 1.1
"""
try:
return six.text_type(int(val)) == six.text_type(val)

View File

@ -105,7 +105,12 @@ def normalize_time(timestamp):
def is_older_than(before, seconds):
"""Return True if before is older than seconds."""
"""Return True if before is older than seconds.
.. versionchanged:: 1.7
Accept datetime string with timezone information.
Fix comparison with timezone aware datetime.
"""
if isinstance(before, six.string_types):
before = parse_isotime(before)
@ -115,7 +120,12 @@ def is_older_than(before, seconds):
def is_newer_than(after, seconds):
"""Return True if after is newer than seconds."""
"""Return True if after is newer than seconds.
.. versionchanged:: 1.7
Accept datetime string with timezone information.
Fix comparison with timezone aware datetime.
"""
if isinstance(after, six.string_types):
after = parse_isotime(after)
@ -129,6 +139,8 @@ def utcnow_ts(microsecond=False):
See :py:class:`oslo_utils.fixture.TimeFixture`.
.. versionchanged:: 1.3
Added optional *microsecond* parameter.
"""
if utcnow.override_time is None:
# NOTE(kgriffs): This is several times faster
@ -152,6 +164,8 @@ def utcnow(with_timezone=False):
See :py:class:`oslo_utils.fixture.TimeFixture`.
.. versionchanged:: 1.6
Added *with_timezone* parameter.
"""
if utcnow.override_time:
try:
@ -171,6 +185,9 @@ def utcnow(with_timezone=False):
def iso8601_from_timestamp(timestamp, microsecond=False):
"""Returns an iso8601 formatted date from timestamp.
.. versionchanged:: 1.3
Added optional *microsecond* parameter.
.. deprecated:: 1.5.0
Use :func:`datetime.datetime.utcfromtimestamp` and
:func:`datetime.datetime.isoformat` instead.
@ -227,7 +244,11 @@ def clear_time_override():
def marshall_now(now=None):
"""Make an rpc-safe datetime with microseconds."""
"""Make an rpc-safe datetime with microseconds.
.. versionchanged:: 1.6
Timezone information is now serialized instead of being stripped.
"""
if not now:
now = utcnow()
d = dict(day=now.day, month=now.month, year=now.year, hour=now.hour,
@ -239,7 +260,14 @@ def marshall_now(now=None):
def unmarshall_time(tyme):
"""Unmarshall a datetime dict."""
"""Unmarshall a datetime dict.
.. versionchanged:: 1.5
Drop leap second.
.. versionchanged:: 1.6
Added support for timezone information.
"""
# NOTE(ihrachys): datetime does not support leap seconds,
# so the best thing we can do for now is dropping them
@ -298,6 +326,8 @@ class Split(object):
"""A *immutable* stopwatch split.
See: http://en.wikipedia.org/wiki/Stopwatch for what this is/represents.
.. versionadded:: 1.4
"""
__slots__ = ['_elapsed', '_length']
@ -337,6 +367,8 @@ class StopWatch(object):
depending on operating system and python version).
.. _monotonic: https://pypi.python.org/pypi/monotonic/
.. versionadded:: 1.4
"""
_STARTED = 'STARTED'
_STOPPED = 'STOPPED'

View File

@ -15,6 +15,8 @@
"""
UUID related utilities and helper functions.
.. versionadded:: 1.1
"""
import uuid
@ -42,6 +44,9 @@ def is_uuid_like(val):
:param val: Value to verify
:type val: string
:returns: bool
.. versionchanged:: 1.1.1
Support non-lowercase UUIDs.
"""
try:
return str(uuid.UUID(val)).replace('-', '') == _format_uuid_string(val)

View File

@ -15,6 +15,8 @@
"""
Helpers for comparing version strings.
.. versionadded:: 1.6
"""
import logging
@ -51,6 +53,12 @@ def is_compatible(requested_version, current_version, same_major=True):
def convert_version_to_int(version):
"""Convert a version to an integer.
*version* must be a string with dots or a tuple of integers.
.. versionadded:: 2.0
"""
try:
if isinstance(version, six.string_types):
version = convert_version_to_tuple(version)
@ -62,6 +70,10 @@ def convert_version_to_int(version):
def convert_version_to_str(version_int):
"""Convert a version integer to a string with dots.
.. versionadded:: 2.0
"""
version_numbers = []
factor = 1000
while version_int != 0:
@ -73,4 +85,8 @@ def convert_version_to_str(version_int):
def convert_version_to_tuple(version_str):
"""Convert a version string with dots to a tuple.
.. versionadded:: 2.0
"""
return tuple(int(part) for part in version_str.split('.'))