Fix and enable Gating on H404

Enable gating on the Hacking H404 check - docstring
should start with a summary.

Change-Id: I80612a15bd11f689e9e9f4dc2ff812138630ddbd
This commit is contained in:
Dirk Mueller
2013-08-04 23:10:16 +02:00
committed by Morgan Fainberg
parent 0e11cf03cf
commit dc5c33a9e5
13 changed files with 81 additions and 145 deletions

View File

@@ -34,9 +34,8 @@ except NameError:
def getid(obj):
"""
Abstracts the common pattern of allowing both an object or an object's ID
(UUID) as a parameter when dealing with relationships.
"""Abstracts the common pattern of allowing both an object or an object's
ID (UUID) as a parameter when dealing with relationships.
"""
# Try to return the object's UUID first, if we have a UUID.
@@ -75,9 +74,8 @@ def filter_kwargs(f):
class Manager(object):
"""
Managers interact with a particular type of API (servers, flavors, images,
etc.) and provide CRUD operations for them.
"""Managers interact with a particular type of API (servers, flavors,
images, etc.) and provide CRUD operations for them.
"""
resource_class = None
@@ -138,8 +136,7 @@ class Manager(object):
class ManagerWithFind(Manager):
"""
Like a `Manager`, but with additional `find()`/`findall()` methods.
"""Like a `Manager`, but with additional `find()`/`findall()` methods.
"""
__metaclass__ = abc.ABCMeta
@@ -149,8 +146,7 @@ class ManagerWithFind(Manager):
pass
def find(self, **kwargs):
"""
Find a single item with attributes matching ``**kwargs``.
"""Find a single item with attributes matching ``**kwargs``.
This isn't very efficient: it loads the entire list then filters on
the Python side.
@@ -167,8 +163,7 @@ class ManagerWithFind(Manager):
return rl[0]
def findall(self, **kwargs):
"""
Find all items with attributes matching ``**kwargs``.
"""Find all items with attributes matching ``**kwargs``.
This isn't very efficient: it loads the entire list then filters on
the Python side.
@@ -287,9 +282,7 @@ class CrudManager(Manager):
@filter_kwargs
def find(self, **kwargs):
"""
Find a single item with attributes matching ``**kwargs``.
"""
"""Find a single item with attributes matching ``**kwargs``."""
url = self.build_url(dict_args_in_out=kwargs)
rl = self._list(
@@ -310,8 +303,7 @@ class CrudManager(Manager):
class Resource(object):
"""
A resource represents a particular instance of an object (tenant, user,
"""A resource represents a particular instance of an object (tenant, user,
etc). This is pretty much just a bag for attributes.
:param manager: Manager object

View File

@@ -28,10 +28,9 @@ import six
class Ec2Signer(object):
"""
Utility class which adds allows a request to be signed with an AWS style
"""Utility class which adds allows a request to be signed with an AWS style
signature, which can then be used for authentication via the keystone ec2
authentication extension
authentication extension.
"""
def __init__(self, secret_key):
@@ -41,9 +40,9 @@ class Ec2Signer(object):
self.hmac_256 = hmac.new(self.secret_key, digestmod=hashlib.sha256)
def _v4_creds(self, credentials):
"""
Detect if the credentials are for a v4 signed request, since AWS
"""Detect if the credentials are for a v4 signed request, since AWS
removed the SignatureVersion field from the v4 request spec...
This expects a dict of the request headers to be passed in the
credentials dict, since the recommended way to pass v4 creds is
via the 'Authorization' header
@@ -127,9 +126,8 @@ class Ec2Signer(object):
@staticmethod
def _canonical_qs(params):
"""
Construct a sorted, correctly encoded query string as required for
_calc_signature_2 and _calc_signature_4
"""Construct a sorted, correctly encoded query string as required for
_calc_signature_2 and _calc_signature_4.
"""
keys = params.keys()
keys.sort()
@@ -164,8 +162,7 @@ class Ec2Signer(object):
hashlib.sha256).digest()
def signature_key(datestamp, region_name, service_name):
"""
Signature key derivation, see
"""Signature key derivation, see
http://docs.aws.amazon.com/general/latest/gr/
signature-v4-examples.html#signature-v4-examples-python
"""
@@ -177,8 +174,9 @@ class Ec2Signer(object):
return k_signing
def auth_param(param_name):
"""
Get specified auth parameter, provided via one of:
"""Get specified auth parameter.
Provided via one of:
- the Authorization header
- the X-Amz-* query parameters
"""
@@ -191,8 +189,8 @@ class Ec2Signer(object):
return param_str
def date_param():
"""
Get the X-Amz-Date' value, which can be either a header or paramter
"""Get the X-Amz-Date' value, which can be either a header
or parameter.
Note AWS supports parsing the Date header also, but this is not
currently supported here as it will require some format mangling

View File

@@ -42,9 +42,8 @@ class NoUniqueMatch(Exception):
class ClientException(Exception):
"""
The base exception class for all exceptions this library raises.
"""
"""The base exception class for all exceptions this library raises."""
def __init__(self, code, message=None, details=None):
self.code = code
self.message = message or self.__class__.message
@@ -55,24 +54,21 @@ class ClientException(Exception):
class BadRequest(ClientException):
"""
HTTP 400 - Bad request: you sent some malformed data.
"""
"""HTTP 400 - Bad request: you sent some malformed data."""
http_status = 400
message = "Bad request"
class Unauthorized(ClientException):
"""
HTTP 401 - Unauthorized: bad credentials.
"""
"""HTTP 401 - Unauthorized: bad credentials."""
http_status = 401
message = "Unauthorized"
class Forbidden(ClientException):
"""
HTTP 403 - Forbidden: your credentials don't give you access to this
"""HTTP 403 - Forbidden: your credentials do not allow access to this
resource.
"""
http_status = 403
@@ -80,32 +76,26 @@ class Forbidden(ClientException):
class NotFound(ClientException):
"""
HTTP 404 - Not found
"""
"""HTTP 404 - Not found."""
http_status = 404
message = "Not found"
class MethodNotAllowed(ClientException):
"""
HTTP 405 - Method not allowed
"""
"""HTTP 405 - Method not allowed."""
http_status = 405
message = "Method not allowed"
class Conflict(ClientException):
"""
HTTP 409 - Conflict
"""
"""HTTP 409 - Conflict."""
http_status = 409
message = "Conflict"
class OverLimit(ClientException):
"""
HTTP 413 - Over limit: you're over the API limits for this time period.
"""HTTP 413 - Over limit: you're over the API limits for this time
period.
"""
http_status = 413
message = "Over limit"
@@ -113,17 +103,15 @@ class OverLimit(ClientException):
# NotImplemented is a python keyword.
class HTTPNotImplemented(ClientException):
"""
HTTP 501 - Not Implemented: the server does not support this operation.
"""HTTP 501 - Not Implemented: the server does not support this
operation.
"""
http_status = 501
message = "Not Implemented"
class ServiceUnavailable(ClientException):
"""
HTTP 503 - Service Unavailable: The server is currently unavailable.
"""
"""HTTP 503 - Service Unavailable: The server is currently unavailable."""
http_status = 503
message = "Service Unavailable"
@@ -146,9 +134,8 @@ _code_map = dict((c.http_status, c) for c in [BadRequest,
def from_response(response, body=None):
"""
Return an instance of an ClientException or subclass
based on an requests response.
"""Return an instance of a ClientException or subclass
based on a requests response.
Usage::

View File

@@ -442,8 +442,8 @@ class OpenStackIdentityShell(object):
return shell_v2_0.CLIENT_CLASS
def do_bash_completion(self, args):
"""
Prints all of the commands and options to stdout.
"""Prints all of the commands and options to stdout.
The keystone.bash_completion script doesn't have to hard code them.
"""
commands = set()
@@ -460,9 +460,7 @@ class OpenStackIdentityShell(object):
@utils.arg('command', metavar='<subcommand>', nargs='?',
help='Display help for <subcommand>')
def do_help(self, args):
"""
Display help about this program or one of its subcommands.
"""
"""Display help about this program or one of its subcommands."""
if getattr(args, 'command', None):
if args.command in self.subcommands:
self.subcommands[args.command].print_help()

View File

@@ -113,10 +113,10 @@ def unauthenticated(f):
def isunauthenticated(f):
"""
Checks to see if the function is marked as not requiring authentication
with the @unauthenticated decorator. Returns True if decorator is
set to True, False otherwise.
"""Checks to see if the function is marked as not requiring authentication
with the @unauthenticated decorator.
Returns True if decorator is set to True, False otherwise.
"""
return getattr(f, 'unauthenticated', False)
@@ -135,9 +135,8 @@ def hash_signed_token(signed_text):
def prompt_for_password():
"""
Prompt user for password if not provided so the password
doesn't show up in the bash history.
"""Prompt user for password if not provided so the password
doesn't show up in the bash history.
"""
if not (hasattr(sys.stdin, 'isatty') and sys.stdin.isatty()):
# nothing to do

View File

@@ -28,8 +28,8 @@ class CredentialsManager(base.ManagerWithFind):
resource_class = EC2
def create(self, user_id, tenant_id):
"""
Create a new access/secret pair for the user/tenant pair
"""Create a new access/secret pair for the user/tenant pair.
:rtype: object of type :class:`EC2`
"""
@@ -39,24 +39,22 @@ class CredentialsManager(base.ManagerWithFind):
params, "credential")
def list(self, user_id):
"""
Get a list of access/secret pairs for a user_id
"""Get a list of access/secret pairs for a user_id.
:rtype: list of :class:`EC2`
"""
return self._list("/users/%s/credentials/OS-EC2" % user_id,
"credentials")
def get(self, user_id, access):
"""
Get the access/secret pair for a given access key
"""Get the access/secret pair for a given access key.
:rtype: object of type :class:`EC2`
"""
return self._get("/users/%s/credentials/OS-EC2/%s" %
(user_id, base.getid(access)), "credential")
def delete(self, user_id, access):
"""
Delete an access/secret pair for a user
"""
"""Delete an access/secret pair for a user."""
return self._delete("/users/%s/credentials/OS-EC2/%s" %
(user_id, base.getid(access)))

View File

@@ -34,22 +34,16 @@ class RoleManager(base.ManagerWithFind):
return self._get("/OS-KSADM/roles/%s" % base.getid(role), "role")
def create(self, name):
"""
Create a role.
"""
"""Create a role."""
params = {"role": {"name": name}}
return self._create('/OS-KSADM/roles', params, "role")
def delete(self, role):
"""
Delete a role.
"""
"""Delete a role."""
return self._delete("/OS-KSADM/roles/%s" % base.getid(role))
def list(self):
"""
List all available roles.
"""
"""List all available roles."""
return self._list("/OS-KSADM/roles", "roles")
def roles_for_user(self, user, tenant=None):

View File

@@ -75,10 +75,7 @@ class TenantManager(base.ManagerWithFind):
return self._get("/tenants/%s" % tenant_id, "tenant")
def create(self, tenant_name, description=None, enabled=True, **kwargs):
"""
Create a new tenant.
"""
"""Create a new tenant."""
params = {"tenant": {"name": tenant_name,
"description": description,
"enabled": enabled}}
@@ -91,8 +88,7 @@ class TenantManager(base.ManagerWithFind):
return self._create('/tenants', params, "tenant")
def list(self, limit=None, marker=None):
"""
Get a list of tenants.
"""Get a list of tenants.
:param integer limit: maximum number to return. (optional)
:param string marker: use when specifying a limit and making
@@ -125,9 +121,7 @@ class TenantManager(base.ManagerWithFind):
def update(self, tenant_id, tenant_name=None, description=None,
enabled=None, **kwargs):
"""
Update a tenant with a new name and description.
"""
"""Update a tenant with a new name and description."""
body = {"tenant": {'id': tenant_id}}
if tenant_name is not None:
body['tenant']['name'] = tenant_name
@@ -145,9 +139,7 @@ class TenantManager(base.ManagerWithFind):
return self._create("/tenants/%s" % tenant_id, body, "tenant")
def delete(self, tenant):
"""
Delete a tenant.
"""
"""Delete a tenant."""
return self._delete("/tenants/%s" % (base.getid(tenant)))
def list_users(self, tenant):

View File

@@ -39,8 +39,7 @@ class UserManager(base.ManagerWithFind):
return self._get("/users/%s" % base.getid(user), "user")
def update(self, user, **kwargs):
"""
Update user data.
"""Update user data.
Supported arguments include ``name``, ``email``, and ``enabled``.
"""
@@ -52,9 +51,7 @@ class UserManager(base.ManagerWithFind):
return self._update(url, params, "user")
def update_enabled(self, user, enabled):
"""
Update enabled-ness
"""
"""Update enabled-ness."""
params = {"user": {"id": base.getid(user),
"enabled": enabled}}
@@ -62,9 +59,7 @@ class UserManager(base.ManagerWithFind):
"user")
def update_password(self, user, password):
"""
Update password
"""
"""Update password."""
params = {"user": {"id": base.getid(user),
"password": password}}
@@ -72,9 +67,7 @@ class UserManager(base.ManagerWithFind):
params, "user")
def update_own_password(self, origpasswd, passwd):
"""
Update password
"""
"""Update password."""
params = {"user": {"password": passwd,
"original_password": origpasswd}}
@@ -84,9 +77,7 @@ class UserManager(base.ManagerWithFind):
management=False)
def update_tenant(self, user, tenant):
"""
Update default tenant.
"""
"""Update default tenant."""
params = {"user": {"id": base.getid(user),
"tenantId": base.getid(tenant)}}
@@ -96,9 +87,7 @@ class UserManager(base.ManagerWithFind):
params, "user")
def create(self, name, password, email, tenant_id=None, enabled=True):
"""
Create a user.
"""
"""Create a user."""
# FIXME(ja): email should be optional, keystone currently requires it
params = {"user": {"name": name,
"password": password,
@@ -108,14 +97,11 @@ class UserManager(base.ManagerWithFind):
return self._create('/users', params, "user")
def delete(self, user):
"""
Delete a user.
"""
"""Delete a user."""
return self._delete("/users/%s" % base.getid(user))
def list(self, tenant_id=None, limit=None, marker=None):
"""
Get a list of users (optionally limited to a tenant)
"""Get a list of users (optionally limited to a tenant).
:rtype: list of :class:`User`
"""

View File

@@ -23,9 +23,7 @@ def assert_has_keys(dict, required=[], optional=[]):
class FakeClient(object):
def assert_called(self, method, url, body=None, pos=-1):
"""
Assert than an API method was just called.
"""
"""Assert than an API method was just called."""
expected = (method, url)
called = self.callstack[pos][0:2]
@@ -38,9 +36,7 @@ class FakeClient(object):
assert self.callstack[pos][2] == body
def assert_called_anytime(self, method, url, body=None):
"""
Assert than an API method was called anytime in the test.
"""
"""Assert than an API method was called anytime in the test."""
expected = (method, url)
assert self.callstack, ("Expected %s %s but no calls were made." %

View File

@@ -105,8 +105,9 @@ class Ec2SignerTest(testtools.TestCase):
self.assertEqual(signature, expected)
def test_generate_v4(self):
"""
Test v4 generator with data from AWS docs example, see:
"""Test v4 generator with data from AWS docs example.
see:
http://docs.aws.amazon.com/general/latest/gr/
sigv4-create-canonical-request.html
and
@@ -145,9 +146,7 @@ class Ec2SignerTest(testtools.TestCase):
self.assertEqual(signature, expected)
def test_generate_v4_port(self):
"""
Test v4 generator with host:port format
"""
"""Test v4 generator with host:port format."""
# Create a new signer object with the AWS example key
secret = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
signer = Ec2Signer(secret)
@@ -181,10 +180,9 @@ class Ec2SignerTest(testtools.TestCase):
self.assertEqual(signature, expected)
def test_generate_v4_port_strip(self):
"""
Test v4 generator with host:port format, but for an old
"""Test v4 generator with host:port format, but for an old
(<2.9.3) version of boto, where the port should be stripped
to match boto behavior
to match boto behavior.
"""
# Create a new signer object with the AWS example key
secret = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
@@ -220,9 +218,8 @@ class Ec2SignerTest(testtools.TestCase):
self.assertEqual(expected, signature)
def test_generate_v4_port_nostrip(self):
"""
Test v4 generator with host:port format, but for an new
(>=2.9.3) version of boto, where the port should not be stripped
"""Test v4 generator with host:port format, but for an new
(>=2.9.3) version of boto, where the port should not be stripped.
"""
# Create a new signer object with the AWS example key
secret = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'

View File

@@ -54,8 +54,7 @@ class KeyringTest(utils.TestCase):
keyring.set_keyring(MemoryKeyring())
def test_no_keyring_key(self):
"""
Ensure that we get no value back if we don't have use_keyring
"""Ensure that we get no value back if we don't have use_keyring
set in the client.
"""
cl = httpclient.HTTPClient(username=USERNAME, password=PASSWORD,

View File

@@ -34,6 +34,6 @@ downloadcache = ~/cache/pip
# H302: import only modules
# H304: no relative imports
# H404: multi line docstring should start with a summary
ignore = F811,F821,F841,H102,H302,H304,H404
ignore = F811,F821,F841,H102,H302,H304
show-source = True
exclude = .venv,.tox,dist,doc,*egg,build