Package oauth2client :: Module util
[hide private]
[frames] | no frames]

Source Code for Module oauth2client.util

  1  #!/usr/bin/env python 
  2  # 
  3  # Copyright 2010 Google Inc. 
  4  # 
  5  # Licensed under the Apache License, Version 2.0 (the "License"); 
  6  # you may not use this file except in compliance with the License. 
  7  # You may obtain a copy of the License at 
  8  # 
  9  #     http://www.apache.org/licenses/LICENSE-2.0 
 10  # 
 11  # Unless required by applicable law or agreed to in writing, software 
 12  # distributed under the License is distributed on an "AS IS" BASIS, 
 13  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 14  # See the License for the specific language governing permissions and 
 15  # limitations under the License. 
 16  # 
 17   
 18  """Common utility library.""" 
 19   
 20  __author__ = ['rafek@google.com (Rafe Kaplan)', 
 21                'guido@google.com (Guido van Rossum)', 
 22  ] 
 23  __all__ = [ 
 24    'positional', 
 25    'POSITIONAL_WARNING', 
 26    'POSITIONAL_EXCEPTION', 
 27    'POSITIONAL_IGNORE', 
 28  ] 
 29   
 30  import inspect 
 31  import logging 
 32  import types 
 33  import urllib 
 34  import urlparse 
 35   
 36  try: 
 37    from urlparse import parse_qsl 
 38  except ImportError: 
 39    from cgi import parse_qsl 
 40   
 41  logger = logging.getLogger(__name__) 
 42   
 43  POSITIONAL_WARNING = 'WARNING' 
 44  POSITIONAL_EXCEPTION = 'EXCEPTION' 
 45  POSITIONAL_IGNORE = 'IGNORE' 
 46  POSITIONAL_SET = frozenset([POSITIONAL_WARNING, POSITIONAL_EXCEPTION, 
 47                              POSITIONAL_IGNORE]) 
 48   
 49  positional_parameters_enforcement = POSITIONAL_WARNING 
 50   
51 -def positional(max_positional_args):
52 """A decorator to declare that only the first N arguments my be positional. 53 54 This decorator makes it easy to support Python 3 style key-word only 55 parameters. For example, in Python 3 it is possible to write: 56 57 def fn(pos1, *, kwonly1=None, kwonly1=None): 58 ... 59 60 All named parameters after * must be a keyword: 61 62 fn(10, 'kw1', 'kw2') # Raises exception. 63 fn(10, kwonly1='kw1') # Ok. 64 65 Example: 66 To define a function like above, do: 67 68 @positional(1) 69 def fn(pos1, kwonly1=None, kwonly2=None): 70 ... 71 72 If no default value is provided to a keyword argument, it becomes a required 73 keyword argument: 74 75 @positional(0) 76 def fn(required_kw): 77 ... 78 79 This must be called with the keyword parameter: 80 81 fn() # Raises exception. 82 fn(10) # Raises exception. 83 fn(required_kw=10) # Ok. 84 85 When defining instance or class methods always remember to account for 86 'self' and 'cls': 87 88 class MyClass(object): 89 90 @positional(2) 91 def my_method(self, pos1, kwonly1=None): 92 ... 93 94 @classmethod 95 @positional(2) 96 def my_method(cls, pos1, kwonly1=None): 97 ... 98 99 The positional decorator behavior is controlled by 100 util.positional_parameters_enforcement, which may be set to 101 POSITIONAL_EXCEPTION, POSITIONAL_WARNING or POSITIONAL_IGNORE to raise an 102 exception, log a warning, or do nothing, respectively, if a declaration is 103 violated. 104 105 Args: 106 max_positional_arguments: Maximum number of positional arguments. All 107 parameters after the this index must be keyword only. 108 109 Returns: 110 A decorator that prevents using arguments after max_positional_args from 111 being used as positional parameters. 112 113 Raises: 114 TypeError if a key-word only argument is provided as a positional 115 parameter, but only if util.positional_parameters_enforcement is set to 116 POSITIONAL_EXCEPTION. 117 """ 118 def positional_decorator(wrapped): 119 def positional_wrapper(*args, **kwargs): 120 if len(args) > max_positional_args: 121 plural_s = '' 122 if max_positional_args != 1: 123 plural_s = 's' 124 message = '%s() takes at most %d positional argument%s (%d given)' % ( 125 wrapped.__name__, max_positional_args, plural_s, len(args)) 126 if positional_parameters_enforcement == POSITIONAL_EXCEPTION: 127 raise TypeError(message) 128 elif positional_parameters_enforcement == POSITIONAL_WARNING: 129 logger.warning(message) 130 else: # IGNORE 131 pass 132 return wrapped(*args, **kwargs)
133 return positional_wrapper 134 135 if isinstance(max_positional_args, (int, long)): 136 return positional_decorator 137 else: 138 args, _, _, defaults = inspect.getargspec(max_positional_args) 139 return positional(len(args) - len(defaults))(max_positional_args) 140 141
142 -def scopes_to_string(scopes):
143 """Converts scope value to a string. 144 145 If scopes is a string then it is simply passed through. If scopes is an 146 iterable then a string is returned that is all the individual scopes 147 concatenated with spaces. 148 149 Args: 150 scopes: string or iterable of strings, the scopes. 151 152 Returns: 153 The scopes formatted as a single string. 154 """ 155 if isinstance(scopes, types.StringTypes): 156 return scopes 157 else: 158 return ' '.join(scopes)
159 160
161 -def dict_to_tuple_key(dictionary):
162 """Converts a dictionary to a tuple that can be used as an immutable key. 163 164 The resulting key is always sorted so that logically equivalent dictionaries 165 always produce an identical tuple for a key. 166 167 Args: 168 dictionary: the dictionary to use as the key. 169 170 Returns: 171 A tuple representing the dictionary in it's naturally sorted ordering. 172 """ 173 return tuple(sorted(dictionary.items()))
174 175
176 -def _add_query_parameter(url, name, value):
177 """Adds a query parameter to a url. 178 179 Replaces the current value if it already exists in the URL. 180 181 Args: 182 url: string, url to add the query parameter to. 183 name: string, query parameter name. 184 value: string, query parameter value. 185 186 Returns: 187 Updated query parameter. Does not update the url if value is None. 188 """ 189 if value is None: 190 return url 191 else: 192 parsed = list(urlparse.urlparse(url)) 193 q = dict(parse_qsl(parsed[4])) 194 q[name] = value 195 parsed[4] = urllib.urlencode(q) 196 return urlparse.urlunparse(parsed)
197