~ubuntu-branches/debian/sid/sqlalchemy/sid

« back to all changes in this revision

Viewing changes to lib/sqlalchemy/util/langhelpers.py

  • Committer: Bazaar Package Importer
  • Author(s): Piotr Ożarowski
  • Date: 2011-10-18 00:02:50 UTC
  • mfrom: (1.4.16 upstream)
  • Revision ID: james.westby@ubuntu.com-20111018000250-prowqcleosluapxg
Tags: 0.7.3-2
remove build-indep from build target's dependencies (closes: 645697)

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
import sys
16
16
import types
17
17
import warnings
18
 
from compat import update_wrapper, set_types, threading
 
18
from compat import update_wrapper, set_types, threading, callable, inspect_getfullargspec, py3k
19
19
from sqlalchemy import exc
20
20
 
21
21
def _unique_symbols(used, *bases):
38
38
    def decorate(fn):
39
39
        if not inspect.isfunction(fn):
40
40
            raise Exception("not a decoratable function")
41
 
        spec = inspect.getargspec(fn)
 
41
        spec = inspect_getfullargspec(fn)
42
42
        names = tuple(spec[0]) + spec[1:3] + (fn.func_name,)
43
43
        targ_name, fn_name = _unique_symbols(names, 'target', 'fn')
44
44
 
149
149
       'apply_pos': '(self, a, b, c, **d)'}
150
150
 
151
151
    """
152
 
    spec = callable(fn) and inspect.getargspec(fn) or fn
 
152
    if callable(fn):
 
153
        spec = inspect_getfullargspec(fn)
 
154
    else:
 
155
        # we accept an existing argspec...
 
156
        spec = fn
153
157
    args = inspect.formatargspec(*spec)
154
158
    if spec[0]:
155
159
        self_arg = spec[0][0]
157
161
        self_arg = '%s[0]' % spec[1]
158
162
    else:
159
163
        self_arg = None
160
 
    apply_pos = inspect.formatargspec(spec[0], spec[1], spec[2])
161
 
    defaulted_vals = spec[3] is not None and spec[0][0-len(spec[3]):] or ()
162
 
    apply_kw = inspect.formatargspec(spec[0], spec[1], spec[2], defaulted_vals,
 
164
 
 
165
    if py3k:
 
166
        apply_pos = inspect.formatargspec(spec[0], spec[1], spec[2], None, spec[4])
 
167
        num_defaults = 0
 
168
        if spec[3]:
 
169
            num_defaults += len(spec[3])
 
170
        if spec[4]:
 
171
            num_defaults += len(spec[4])
 
172
        name_args = spec[0] + spec[4]
 
173
    else:
 
174
        apply_pos = inspect.formatargspec(spec[0], spec[1], spec[2])
 
175
        num_defaults = 0
 
176
        if spec[3]:
 
177
            num_defaults += len(spec[3])
 
178
        name_args = spec[0]
 
179
 
 
180
    if num_defaults:
 
181
        defaulted_vals = name_args[0-num_defaults:]
 
182
    else:
 
183
        defaulted_vals = ()
 
184
 
 
185
    apply_kw = inspect.formatargspec(name_args, spec[1], spec[2], defaulted_vals,
163
186
                                     formatvalue=lambda x: '=' + x)
164
187
    if grouped:
165
188
        return dict(args=args, self_arg=self_arg,
237
260
            for arg in args[1:-default_len]:
238
261
                yield repr(getattr(obj, arg, None))
239
262
            for (arg, defval) in zip(args[-default_len:], defaults):
240
 
                val = getattr(obj, arg, None)
241
 
                if val != defval:
242
 
                    yield '%s=%r' % (arg, val)
 
263
                try:
 
264
                    val = getattr(obj, arg, None)
 
265
                    if val != defval:
 
266
                        yield '%s=%r' % (arg, val)
 
267
                except:
 
268
                    pass
243
269
    return "%s(%s)" % (obj.__class__.__name__, ", ".join(genargs()))
244
270
 
245
271
class portable_instancemethod(object):
493
519
class group_expirable_memoized_property(object):
494
520
    """A family of @memoized_properties that can be expired in tandem."""
495
521
 
496
 
    def __init__(self):
 
522
    def __init__(self, attributes=()):
497
523
        self.attributes = []
 
524
        if attributes:
 
525
            self.attributes.extend(attributes)
498
526
 
499
527
    def expire_instance(self, instance):
500
528
        """Expire all memoized properties for *instance*."""
506
534
        self.attributes.append(fn.__name__)
507
535
        return memoized_property(fn)
508
536
 
 
537
    def method(self, fn):
 
538
        self.attributes.append(fn.__name__)
 
539
        return memoized_instancemethod(fn)
 
540
 
509
541
class importlater(object):
510
542
    """Deferred import object.
511
543
 
518
550
        from mypackage.somemodule import somesubmod
519
551
 
520
552
    except evaluted upon attribute access to "somesubmod".
 
553
    
 
554
    importlater() currently requires that resolve_all() be
 
555
    called, typically at the bottom of a package's __init__.py.
 
556
    This is so that __import__ still called only at 
 
557
    module import time, and not potentially within
 
558
    a non-main thread later on.
521
559
 
522
560
    """
 
561
 
 
562
    _unresolved = set()
 
563
 
523
564
    def __init__(self, path, addtl=None):
524
565
        self._il_path = path
525
566
        self._il_addtl = addtl
 
567
        importlater._unresolved.add(self)
 
568
 
 
569
    @classmethod
 
570
    def resolve_all(cls):
 
571
        for m in list(importlater._unresolved):
 
572
            m._resolve()
 
573
 
 
574
    @property
 
575
    def _full_path(self):
 
576
        if self._il_addtl:
 
577
            return self._il_path + "." + self._il_addtl
 
578
        else:
 
579
            return self._il_path
526
580
 
527
581
    @memoized_property
528
582
    def module(self):
 
583
        if self in importlater._unresolved:
 
584
            raise ImportError(
 
585
                    "importlater.resolve_all() hasn't been called")
 
586
 
 
587
        m = self._initial_import
529
588
        if self._il_addtl:
530
 
            m = __import__(self._il_path, globals(), locals(),
531
 
                                [self._il_addtl])
532
 
            try:
533
 
                return getattr(m, self._il_addtl)
534
 
            except AttributeError:
535
 
                raise ImportError(
536
 
                        "Module %s has no attribute '%s'" %
537
 
                        (self._il_path, self._il_addtl)
538
 
                    )
 
589
            m = getattr(m, self._il_addtl)
539
590
        else:
540
 
            m = __import__(self._il_path)
541
591
            for token in self._il_path.split(".")[1:]:
542
592
                m = getattr(m, token)
543
 
            return m
 
593
        return m
 
594
 
 
595
    def _resolve(self):
 
596
        importlater._unresolved.discard(self)
 
597
        if self._il_addtl:
 
598
            self._initial_import = __import__(
 
599
                                self._il_path, globals(), locals(), 
 
600
                                [self._il_addtl])
 
601
        else:
 
602
            self._initial_import = __import__(self._il_path)
544
603
 
545
604
    def __getattr__(self, key):
 
605
        if key == 'module':
 
606
            raise ImportError("Could not resolve module %s" 
 
607
                                % self._full_path)
546
608
        try:
547
609
            attr = getattr(self.module, key)
548
610
        except AttributeError:
549
611
            raise AttributeError(
550
612
                        "Module %s has no attribute '%s'" %
551
 
                        (self._il_path, key)
 
613
                        (self._full_path, key)
552
614
                    )
553
615
        self.__dict__[key] = attr
554
616
        return attr
610
672
    return cls(**kw)
611
673
 
612
674
 
 
675
def counter():
 
676
    """Return a threadsafe counter function."""
 
677
 
 
678
    lock = threading.Lock()
 
679
    counter = itertools.count(1L)
 
680
 
 
681
    # avoid the 2to3 "next" transformation...
 
682
    def _next():
 
683
        lock.acquire()
 
684
        try:
 
685
            return counter.next()
 
686
        finally:
 
687
            lock.release()
 
688
 
 
689
    return _next
 
690
 
613
691
def duck_type_collection(specimen, default=None):
614
692
    """Given an instance or class, guess if it is or is acting as one of
615
693
    the basic collection types: list, set and dict.  If the __emulates__