Changeset 7173
- Timestamp:
- 02/28/08 09:48:19 (9 months ago)
- Files:
-
- django/branches/queryset-refactor/django/contrib/admin/views/decorators.py (modified) (3 diffs)
- django/branches/queryset-refactor/django/contrib/auth/decorators.py (modified) (2 diffs)
- django/branches/queryset-refactor/django/core/handlers/base.py (modified) (1 diff)
- django/branches/queryset-refactor/django/db/backends/postgresql/operations.py (modified) (1 diff)
- django/branches/queryset-refactor/django/db/models/fields/related.py (modified) (2 diffs)
- django/branches/queryset-refactor/django/http/__init__.py (modified) (2 diffs)
- django/branches/queryset-refactor/django/template/defaultfilters.py (modified) (2 diffs)
- django/branches/queryset-refactor/django/utils/decorators.py (modified) (2 diffs)
- django/branches/queryset-refactor/django/utils/functional.py (modified) (4 diffs)
- django/branches/queryset-refactor/django/views/decorators/cache.py (modified) (3 diffs)
- django/branches/queryset-refactor/django/views/decorators/http.py (modified) (2 diffs)
- django/branches/queryset-refactor/django/views/decorators/vary.py (modified) (3 diffs)
- django/branches/queryset-refactor/docs/model-api.txt (modified) (1 diff)
- django/branches/queryset-refactor/extras/django_bash_completion (modified) (2 diffs)
- django/branches/queryset-refactor/tests/modeltests/mutually_referential/models.py (modified) (2 diffs)
- django/branches/queryset-refactor/tests/regressiontests/decorators (added)
- django/branches/queryset-refactor/tests/regressiontests/decorators/__init__.py (added)
- django/branches/queryset-refactor/tests/regressiontests/decorators/models.py (added)
- django/branches/queryset-refactor/tests/regressiontests/decorators/tests.py (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/queryset-refactor/django/contrib/admin/views/decorators.py
r7136 r7173 1 import base64 2 import md5 3 import cPickle as pickle 4 try: 5 from functools import wraps 6 except ImportError: 7 from django.utils.functional import wraps # Python 2.3, 2.4 fallback. 8 1 9 from django import http, template 2 10 from django.conf import settings … … 6 14 from django.utils.translation import ugettext_lazy, ugettext as _ 7 15 from django.utils.safestring import mark_safe 8 import base64, md59 import cPickle as pickle10 16 11 17 ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.") … … 105 111 return _display_login_form(request, ERROR_MESSAGE) 106 112 107 return _checklogin113 return wraps(view_func)(_checklogin) django/branches/queryset-refactor/django/contrib/auth/decorators.py
r6690 r7173 1 try: 2 from functools import wraps, update_wrapper 3 except ImportError: 4 from django.utils.functional import wraps, update_wrapper # Python 2.3, 2.4 fallback. 5 1 6 from django.contrib.auth import REDIRECT_FIELD_NAME 2 7 from django.http import HttpResponseRedirect … … 52 57 self.login_url = login_url 53 58 self.redirect_field_name = redirect_field_name 54 self.__name__ = view_func.__name__59 update_wrapper(self, view_func) 55 60 56 61 def __get__(self, obj, cls=None): django/branches/queryset-refactor/django/core/handlers/base.py
r7086 r7173 110 110 return http.HttpResponseForbidden('<h1>Permission denied</h1>') 111 111 except SystemExit: 112 pass # See http://code.djangoproject.com/ticket/1023 112 # Allow sys.exit() to actually exit. See tickets #1023 and #4701 113 raise 113 114 except: # Handle everything else, including SuspiciousOperation, etc. 114 115 # Get the exception info now, in case another exception is thrown later. django/branches/queryset-refactor/django/db/backends/postgresql/operations.py
r7152 r7173 30 30 def field_cast_sql(self, db_type): 31 31 if db_type == 'inet': 32 return ' CAST(%s AS TEXT)'32 return 'HOST(%s)' 33 33 return '%s' 34 34 django/branches/queryset-refactor/django/db/models/fields/related.py
r7171 r7173 24 24 pending_lookups = {} 25 25 26 def add_lookup(rel_cls, field): 27 name = field.rel.to 28 module = rel_cls.__module__ 29 key = (module, name) 30 # Has the model already been loaded? 31 # If so, resolve the string reference right away 32 model = get_model(rel_cls._meta.app_label, field.rel.to, False) 26 def add_lazy_relation(cls, field, relation): 27 """ 28 Adds a lookup on ``cls`` when a related field is defined using a string, 29 i.e.:: 30 31 class MyModel(Model): 32 fk = ForeignKey("AnotherModel") 33 34 This string can be: 35 36 * RECURSIVE_RELATIONSHIP_CONSTANT (i.e. "self") to indicate a recursive 37 relation. 38 39 * The name of a model (i.e "AnotherModel") to indicate another model in 40 the same app. 41 42 * An app-label and model name (i.e. "someapp.AnotherModel") to indicate 43 another model in a different app. 44 45 If the other model hasn't yet been loaded -- almost a given if you're using 46 lazy relationships -- then the relation won't be set up until the 47 class_prepared signal fires at the end of model initialization. 48 """ 49 # Check for recursive relations 50 if relation == RECURSIVE_RELATIONSHIP_CONSTANT: 51 app_label = cls._meta.app_label 52 model_name = cls.__name__ 53 54 else: 55 # Look for an "app.Model" relation 56 try: 57 app_label, model_name = relation.split(".") 58 except ValueError: 59 # If we can't split, assume a model in current app 60 app_label = cls._meta.app_label 61 model_name = relation 62 63 # Try to look up the related model, and if it's already loaded resolve the 64 # string right away. If get_model returns None, it means that the related 65 # model isn't loaded yet, so we need to pend the relation until the class 66 # is prepared. 67 model = get_model(app_label, model_name, False) 33 68 if model: 34 69 field.rel.to = model 35 field.do_related_class(model, rel_cls)70 field.do_related_class(model, cls) 36 71 else: 37 # Mark the related field for later lookup 38 pending_lookups.setdefault(key, []).append((rel_cls, field)) 39 72 key = (app_label, model_name) 73 value = (cls, field) 74 pending_lookups.setdefault(key, []).append(value) 75 40 76 def do_pending_lookups(sender): 41 other_cls = sender 42 key = (other_cls.__module__, other_cls.__name__) 43 for rel_cls, field in pending_lookups.setdefault(key, []): 44 field.rel.to = other_cls 45 field.do_related_class(other_cls, rel_cls) 77 """ 78 Handle any pending relations to the sending model. Sent from class_prepared. 79 """ 80 key = (sender._meta.app_label, sender.__name__) 81 for cls, field in pending_lookups.pop(key, []): 82 field.rel.to = sender 83 field.do_related_class(sender, cls) 46 84 47 85 dispatcher.connect(do_pending_lookups, signal=signals.class_prepared) … … 67 105 other = self.rel.to 68 106 if isinstance(other, basestring): 69 if other == RECURSIVE_RELATIONSHIP_CONSTANT: 70 self.rel.to = cls.__name__ 71 add_lookup(cls, self) 107 add_lazy_relation(cls, self, other) 72 108 else: 73 109 self.do_related_class(other, cls) django/branches/queryset-refactor/django/http/__init__.py
r6954 r7173 172 172 return result 173 173 174 def __deepcopy__(self, memo ={}):174 def __deepcopy__(self, memo): 175 175 import copy 176 176 result = self.__class__('', mutable=True) … … 224 224 def copy(self): 225 225 "Returns a mutable copy of this object." 226 return self.__deepcopy__( )226 return self.__deepcopy__({}) 227 227 228 228 def urlencode(self): django/branches/queryset-refactor/django/template/defaultfilters.py
r7086 r7173 3 3 import re 4 4 import random as random_module 5 try: 6 from functools import wraps 7 except ImportError: 8 from django.utils.functional import wraps # Python 2.3, 2.4 fallback. 5 9 6 10 from django.template import Variable, Library … … 36 40 if hasattr(func, attr): 37 41 setattr(_dec, attr, getattr(func, attr)) 38 return _dec42 return wraps(func)(_dec) 39 43 40 44 ################### django/branches/queryset-refactor/django/utils/decorators.py
r5631 r7173 2 2 3 3 import types 4 try: 5 from functools import wraps 6 except ImportError: 7 from django.utils.functional import wraps # Python 2.3, 2.4 fallback. 4 8 5 9 def decorator_from_middleware(middleware_class): … … 54 58 return result 55 59 return response 56 return _wrapped_view60 return wraps(view_func)(_wrapped_view) 57 61 return _decorator_from_middleware django/branches/queryset-refactor/django/utils/functional.py
r6597 r7173 1 # License for code in this file that was taken from Python 2.5. 2 3 # PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 4 # -------------------------------------------- 5 # 6 # 1. This LICENSE AGREEMENT is between the Python Software Foundation 7 # ("PSF"), and the Individual or Organization ("Licensee") accessing and 8 # otherwise using this software ("Python") in source or binary form and 9 # its associated documentation. 10 # 11 # 2. Subject to the terms and conditions of this License Agreement, PSF 12 # hereby grants Licensee a nonexclusive, royalty-free, world-wide 13 # license to reproduce, analyze, test, perform and/or display publicly, 14 # prepare derivative works, distribute, and otherwise use Python 15 # alone or in any derivative version, provided, however, that PSF's 16 # License Agreement and PSF's notice of copyright, i.e., "Copyright (c) 17 # 2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation; 18 # All Rights Reserved" are retained in Python alone or in any derivative 19 # version prepared by Licensee. 20 # 21 # 3. In the event Licensee prepares a derivative work that is based on 22 # or incorporates Python or any part thereof, and wants to make 23 # the derivative work available to others as provided herein, then 24 # Licensee hereby agrees to include in any such work a brief summary of 25 # the changes made to Python. 26 # 27 # 4. PSF is making Python available to Licensee on an "AS IS" 28 # basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR 29 # IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND 30 # DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS 31 # FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT 32 # INFRINGE ANY THIRD PARTY RIGHTS. 33 # 34 # 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 35 # FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS 36 # A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, 37 # OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 38 # 39 # 6. This License Agreement will automatically terminate upon a material 40 # breach of its terms and conditions. 41 # 42 # 7. Nothing in this License Agreement shall be deemed to create any 43 # relationship of agency, partnership, or joint venture between PSF and 44 # Licensee. This License Agreement does not grant permission to use PSF 45 # trademarks or trade name in a trademark sense to endorse or promote 46 # products or services of Licensee, or any third party. 47 # 48 # 8. By copying, installing or otherwise using Python, Licensee 49 # agrees to be bound by the terms and conditions of this License 50 # Agreement. 51 52 1 53 def curry(_curried_func, *args, **kwargs): 2 54 def _curried(*moreargs, **morekwargs): 3 55 return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs)) 4 56 return _curried 57 58 ### Begin from Python 2.5 functools.py ######################################## 59 60 # Summary of changes made to the Python 2.5 code below: 61 # * swapped ``partial`` for ``curry`` to maintain backwards-compatibility 62 # in Django. 63 # * Wrapped the ``setattr`` call in ``update_wrapper`` with a try-except 64 # block to make it compatible with Python 2.3, which doesn't allow 65 # assigning to ``__name__``. 66 67 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation. 68 # All Rights Reserved. 69 70 ############################################################################### 71 72 # update_wrapper() and wraps() are tools to help write 73 # wrapper functions that can handle naive introspection 74 75 WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__') 76 WRAPPER_UPDATES = ('__dict__',) 77 def update_wrapper(wrapper, 78 wrapped, 79 assigned = WRAPPER_ASSIGNMENTS, 80 updated = WRAPPER_UPDATES): 81 """Update a wrapper function to look like the wrapped function 82 83 wrapper is the function to be updated 84 wrapped is the original function 85 assigned is a tuple naming the attributes assigned directly 86 from the wrapped function to the wrapper function (defaults to 87 functools.WRAPPER_ASSIGNMENTS) 88 updated is a tuple naming the attributes off the wrapper that 89 are updated with the corresponding attribute from the wrapped 90 function (defaults to functools.WRAPPER_UPDATES) 91 """ 92 for attr in assigned: 93 try: 94 setattr(wrapper, attr, getattr(wrapped, attr)) 95 except TypeError: # Python 2.3 doesn't allow assigning to __name__. 96 pass 97 for attr in updated: 98 getattr(wrapper, attr).update(getattr(wrapped, attr)) 99 # Return the wrapper so this can be used as a decorator via curry() 100 return wrapper 101 102 def wraps(wrapped, 103 assigned = WRAPPER_ASSIGNMENTS, 104 updated = WRAPPER_UPDATES): 105 """Decorator factory to apply update_wrapper() to a wrapper function 106 107 Returns a decorator that invokes update_wrapper() with the decorated 108 function as the wrapper argument and the arguments to wraps() as the 109 remaining arguments. Default arguments are as for update_wrapper(). 110 This is a convenience function to simplify applying curry() to 111 update_wrapper(). 112 """ 113 return curry(update_wrapper, wrapped=wrapped, 114 assigned=assigned, updated=updated) 115 116 ### End from Python 2.5 functools.py ########################################## 5 117 6 118 def memoize(func, cache, num_args): … … 19 131 cache[mem_args] = result 20 132 return result 21 return wrap per133 return wraps(func)(wrapper) 22 134 23 135 class Promise(object): … … 111 223 return __proxy__(args, kw) 112 224 113 return __wrapper__225 return wraps(func)(__wrapper__) 114 226 115 227 def allow_lazy(func, *resultclasses): … … 127 239 return func(*args, **kwargs) 128 240 return lazy(func, *resultclasses)(*args, **kwargs) 129 return wrap per241 return wraps(func)(wrapper) django/branches/queryset-refactor/django/views/decorators/cache.py
r4265 r7173 11 11 account on caching -- just like the middleware does. 12 12 """ 13 14 try: 15 from functools import wraps 16 except ImportError: 17 from django.utils.functional import wraps # Python 2.3, 2.4 fallback. 13 18 14 19 from django.utils.decorators import decorator_from_middleware … … 27 32 return response 28 33 29 return _cache_controlled34 return wraps(viewfunc)(_cache_controlled) 30 35 31 36 return _cache_controller … … 40 45 add_never_cache_headers(response) 41 46 return response 42 return _wrapped_view_func47 return wraps(view_func)(_wrapped_view_func) django/branches/queryset-refactor/django/views/decorators/http.py
r4265 r7173 2 2 Decorators for views based on HTTP headers. 3 3 """ 4 5 try: 6 from functools import wraps 7 except ImportError: 8 from django.utils.functional import wraps # Python 2.3, 2.4 fallback. 4 9 5 10 from django.utils.decorators import decorator_from_middleware … … 25 30 return HttpResponseNotAllowed(request_method_list) 26 31 return func(request, *args, **kwargs) 27 return inner32 return wraps(func)(inner) 28 33 return decorator 29 34 django/branches/queryset-refactor/django/views/decorators/vary.py
r4265 r7173 1 try: 2 from functools import wraps 3 except ImportError: 4 from django.utils.functional import wraps # Python 2.3, 2.4 fallback. 5 1 6 from django.utils.cache import patch_vary_headers 2 7 … … 17 22 patch_vary_headers(response, headers) 18 23 return response 19 return inner_func24 return wraps(func)(inner_func) 20 25 return decorator 21 26 … … 33 38 patch_vary_headers(response, ('Cookie',)) 34 39 return response 35 return inner_func40 return wraps(func)(inner_func) django/branches/queryset-refactor/docs/model-api.txt
r7172 r7173 785 785 # ... 786 786 787 Note, however, that you can only use strings to refer to models in the same 788 models.py file -- you cannot use a string to reference a model in a different 789 application, or to reference a model that has been imported from elsewhere. 787 Note, however, that this only refers to models in the same models.py file -- you 788 cannot use a string to reference a model defined in another application or 789 imported from elsewhere. 790 791 **New in Django development version:** to refer to models defined in another 792 application, you must instead explicitially specify the application label. That 793 is, if the ``Manufacturer`` model above is defined in another application called 794 ``production``, you'd need to use:: 795 796 class Car(models.Model): 797 manufacturer = models.ForeignKey('production.Manufacturer') 790 798 791 799 Behind the scenes, Django appends ``"_id"`` to the field name to create its django/branches/queryset-refactor/extras/django_bash_completion
r5245 r7173 62 62 # python manage.py, /some/path/python manage.py (if manage.py exists) 63 63 ( ${COMP_CWORD} -eq 2 && 64 ( $( basename ${COMP_WORDS[0]} ) == python?([1-9]\.[0-9]) ) &&65 ( $( basename ${COMP_WORDS[1]} ) == manage.py) &&64 ( $( basename -- ${COMP_WORDS[0]} ) == python?([1-9]\.[0-9]) ) && 65 ( $( basename -- ${COMP_WORDS[1]} ) == manage.py) && 66 66 ( -r ${COMP_WORDS[1]} ) ) 67 67 || 68 68 ( ${COMP_CWORD} -eq 2 && 69 ( $( basename ${COMP_WORDS[0]} ) == python?([1-9]\.[0-9]) ) &&70 ( $( basename ${COMP_WORDS[1]} ) == django-admin.py) &&69 ( $( basename -- ${COMP_WORDS[0]} ) == python?([1-9]\.[0-9]) ) && 70 ( $( basename -- ${COMP_WORDS[1]} ) == django-admin.py) && 71 71 ( -r ${COMP_WORDS[1]} ) ) ]] ; then 72 72 … … 150 150 python_interpreters=$(whereis python | cut -d " " -f 2-) 151 151 for python in $python_interpreters; do 152 pythons="${pythons} $(basename $python)"152 pythons="${pythons} $(basename -- $python)" 153 153 done 154 154 pythons=$(echo $pythons | tr " " "\n" | sort -u | tr "\n" " ") django/branches/queryset-refactor/tests/modeltests/mutually_referential/models.py
r5876 r7173 2 2 24. Mutually referential many-to-one relationships 3 3 4 To define a many-to-one relationship, use ``ForeignKey()``.4 Strings can be used instead of model literals to set up "lazy" relations. 5 5 """ 6 6 … … 9 9 class Parent(Model): 10 10 name = CharField(max_length=100, core=True) 11 12 # Use a simple string for forward declarations. 11 13 bestchild = ForeignKey("Child", null=True, related_name="favoured_by") 12 14 13 15 class Child(Model): 14 16 name = CharField(max_length=100) 15 parent = ForeignKey(Parent) 17 18 # You can also explicitally specify the related app. 19 parent = ForeignKey("mutually_referential.Parent") 16 20 17 21 __test__ = {'API_TESTS':"""
