mirror of
https://github.com/viq/NewsBlur.git
synced 2025-08-05 16:49:45 +00:00
138 lines
4.1 KiB
Python
138 lines
4.1 KiB
Python
#!/usr/bin/env python
|
|
#
|
|
# Copyright 2010 Google Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
#
|
|
|
|
"""Common utility library."""
|
|
|
|
__author__ = [
|
|
"rafek@google.com (Rafe Kaplan)",
|
|
"guido@google.com (Guido van Rossum)",
|
|
]
|
|
__all__ = [
|
|
"positional",
|
|
]
|
|
|
|
import inspect
|
|
import logging
|
|
|
|
import gflags
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
FLAGS = gflags.FLAGS
|
|
|
|
gflags.DEFINE_enum(
|
|
"positional_parameters_enforcement",
|
|
"WARNING",
|
|
["EXCEPTION", "WARNING", "IGNORE"],
|
|
"The action when an oauth2client.util.positional declaration is violated.",
|
|
)
|
|
|
|
|
|
def positional(max_positional_args):
|
|
"""A decorator to declare that only the first N arguments my be positional.
|
|
|
|
This decorator makes it easy to support Python 3 style key-word only
|
|
parameters. For example, in Python 3 it is possible to write:
|
|
|
|
def fn(pos1, *, kwonly1=None, kwonly1=None):
|
|
...
|
|
|
|
All named parameters after * must be a keyword:
|
|
|
|
fn(10, 'kw1', 'kw2') # Raises exception.
|
|
fn(10, kwonly1='kw1') # Ok.
|
|
|
|
Example:
|
|
To define a function like above, do:
|
|
|
|
@positional(1)
|
|
def fn(pos1, kwonly1=None, kwonly2=None):
|
|
...
|
|
|
|
If no default value is provided to a keyword argument, it becomes a required
|
|
keyword argument:
|
|
|
|
@positional(0)
|
|
def fn(required_kw):
|
|
...
|
|
|
|
This must be called with the keyword parameter:
|
|
|
|
fn() # Raises exception.
|
|
fn(10) # Raises exception.
|
|
fn(required_kw=10) # Ok.
|
|
|
|
When defining instance or class methods always remember to account for
|
|
'self' and 'cls':
|
|
|
|
class MyClass(object):
|
|
|
|
@positional(2)
|
|
def my_method(self, pos1, kwonly1=None):
|
|
...
|
|
|
|
@classmethod
|
|
@positional(2)
|
|
def my_method(cls, pos1, kwonly1=None):
|
|
...
|
|
|
|
The positional decorator behavior is controlled by the
|
|
--positional_parameters_enforcement flag. The flag may be set to 'EXCEPTION',
|
|
'WARNING' or 'IGNORE' to raise an exception, log a warning, or do nothing,
|
|
respectively, if a declaration is violated.
|
|
|
|
Args:
|
|
max_positional_arguments: Maximum number of positional arguments. All
|
|
parameters after the this index must be keyword only.
|
|
|
|
Returns:
|
|
A decorator that prevents using arguments after max_positional_args from
|
|
being used as positional parameters.
|
|
|
|
Raises:
|
|
TypeError if a key-word only argument is provided as a positional parameter,
|
|
but only if the --positional_parameters_enforcement flag is set to
|
|
'EXCEPTION'.
|
|
"""
|
|
|
|
def positional_decorator(wrapped):
|
|
def positional_wrapper(*args, **kwargs):
|
|
if len(args) > max_positional_args:
|
|
plural_s = ""
|
|
if max_positional_args != 1:
|
|
plural_s = "s"
|
|
message = "%s() takes at most %d positional argument%s (%d given)" % (
|
|
wrapped.__name__,
|
|
max_positional_args,
|
|
plural_s,
|
|
len(args),
|
|
)
|
|
if FLAGS.positional_parameters_enforcement == "EXCEPTION":
|
|
raise TypeError(message)
|
|
elif FLAGS.positional_parameters_enforcement == "WARNING":
|
|
logger.warning(message)
|
|
else: # IGNORE
|
|
pass
|
|
return wrapped(*args, **kwargs)
|
|
|
|
return positional_wrapper
|
|
|
|
if isinstance(max_positional_args, int):
|
|
return positional_decorator
|
|
else:
|
|
args, _, _, defaults = inspect.getargspec(max_positional_args)
|
|
return positional(len(args) - len(defaults))(max_positional_args)
|