source: publico/il.spdo/trunk/Paste-1.7.5.1-py2.6.egg/paste/url.py @ 5327

Última Alteração nesse arquivo desde 5327 foi 5327, incluída por fabianosantos, 8 anos atrás

Import inicial.

File size: 14.3 KB
Linha 
1# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
2# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
3
4"""
5This module implements a class for handling URLs.
6"""
7import urllib
8import cgi
9from paste import request
10# Imported lazily from FormEncode:
11variabledecode = None
12
13__all__ = ["URL", "Image"]
14
15def html_quote(v):
16    if v is None:
17        return ''
18    return cgi.escape(str(v), 1)
19
20def url_quote(v):
21    if v is None:
22        return ''
23    return urllib.quote(str(v))
24
25url_unquote = urllib.unquote
26
27def js_repr(v):
28    if v is None:
29        return 'null'
30    elif v is False:
31        return 'false'
32    elif v is True:
33        return 'true'
34    elif isinstance(v, list):
35        return '[%s]' % ', '.join(map(js_repr, v))
36    elif isinstance(v, dict):
37        return '{%s}' % ', '.join(
38            ['%s: %s' % (js_repr(key), js_repr(value))
39             for key, value in v])
40    elif isinstance(v, str):
41        return repr(v)
42    elif isinstance(v, unicode):
43        # @@: how do you do Unicode literals in Javascript?
44        return repr(v.encode('UTF-8'))
45    elif isinstance(v, (float, int)):
46        return repr(v)
47    elif isinstance(v, long):
48        return repr(v).lstrip('L')
49    elif hasattr(v, '__js_repr__'):
50        return v.__js_repr__()
51    else:
52        raise ValueError(
53            "I don't know how to turn %r into a Javascript representation"
54            % v)
55
56class URLResource(object):
57
58    """
59    This is an abstract superclass for different kinds of URLs
60    """
61
62    default_params = {}
63
64    def __init__(self, url, vars=None, attrs=None,
65                 params=None):
66        self.url = url or '/'
67        self.vars = vars or []
68        self.attrs = attrs or {}
69        self.params = self.default_params.copy()
70        self.original_params = params or {}
71        if params:
72            self.params.update(params)
73
74    #@classmethod
75    def from_environ(cls, environ, with_query_string=True,
76                     with_path_info=True, script_name=None,
77                     path_info=None, querystring=None):
78        url = request.construct_url(
79            environ, with_query_string=False,
80            with_path_info=with_path_info, script_name=script_name,
81            path_info=path_info)
82        if with_query_string:
83            if querystring is None:
84                vars = request.parse_querystring(environ)
85            else:
86                vars = cgi.parse_qsl(
87                    querystring,
88                    keep_blank_values=True,
89                    strict_parsing=False)
90        else:
91            vars = None
92        v = cls(url, vars=vars)
93        return v
94
95    from_environ = classmethod(from_environ)
96
97    def __call__(self, *args, **kw):
98        res = self._add_positional(args)
99        res = res._add_vars(kw)
100        return res
101
102    def __getitem__(self, item):
103        if '=' in item:
104            name, value = item.split('=', 1)
105            return self._add_vars({url_unquote(name): url_unquote(value)})
106        return self._add_positional((item,))
107
108    def attr(self, **kw):
109        for key in kw.keys():
110            if key.endswith('_'):
111                kw[key[:-1]] = kw[key]
112                del kw[key]
113        new_attrs = self.attrs.copy()
114        new_attrs.update(kw)
115        return self.__class__(self.url, vars=self.vars,
116                              attrs=new_attrs,
117                              params=self.original_params)
118
119    def param(self, **kw):
120        new_params = self.original_params.copy()
121        new_params.update(kw)
122        return self.__class__(self.url, vars=self.vars,
123                              attrs=self.attrs,
124                              params=new_params)
125
126    def coerce_vars(self, vars):
127        global variabledecode
128        need_variable_encode = False
129        for key, value in vars.items():
130            if isinstance(value, dict):
131                need_variable_encode = True
132            if key.endswith('_'):
133                vars[key[:-1]] = vars[key]
134                del vars[key]
135        if need_variable_encode:
136            if variabledecode is None:
137                from formencode import variabledecode
138            vars = variabledecode.variable_encode(vars)
139        return vars
140
141   
142    def var(self, **kw):
143        kw = self.coerce_vars(kw)
144        new_vars = self.vars + kw.items()
145        return self.__class__(self.url, vars=new_vars,
146                              attrs=self.attrs,
147                              params=self.original_params)
148
149    def setvar(self, **kw):
150        """
151        Like ``.var(...)``, except overwrites keys, where .var simply
152        extends the keys.  Setting a variable to None here will
153        effectively delete it.
154        """
155        kw = self.coerce_vars(kw)
156        new_vars = []
157        for name, values in self.vars:
158            if name in kw:
159                continue
160            new_vars.append((name, values))
161        new_vars.extend(kw.items())
162        return self.__class__(self.url, vars=new_vars,
163                              attrs=self.attrs,
164                              params=self.original_params)
165
166    def setvars(self, **kw):
167        """
168        Creates a copy of this URL, but with all the variables set/reset
169        (like .setvar(), except clears past variables at the same time)
170        """
171        return self.__class__(self.url, vars=kw.items(),
172                              attrs=self.attrs,
173                              params=self.original_params)
174
175    def addpath(self, *paths):
176        u = self
177        for path in paths:
178            path = str(path).lstrip('/')
179            new_url = u.url
180            if not new_url.endswith('/'):
181                new_url += '/'
182            u = u.__class__(new_url+path, vars=u.vars,
183                            attrs=u.attrs,
184                            params=u.original_params)
185        return u
186           
187    __div__ = addpath
188
189    def become(self, OtherClass):
190        return OtherClass(self.url, vars=self.vars,
191                          attrs=self.attrs,
192                          params=self.original_params)
193   
194    def href__get(self):
195        s = self.url
196        if self.vars:
197            s += '?'
198            vars = []
199            for name, val in self.vars:
200                if isinstance(val, (list, tuple)):
201                    val = [v for v in val if v is not None]
202                elif val is None:
203                    continue
204                vars.append((name, val))
205            s += urllib.urlencode(vars, True)
206        return s
207
208    href = property(href__get)
209
210    def __repr__(self):
211        base = '<%s %s' % (self.__class__.__name__,
212                           self.href or "''")
213        if self.attrs:
214            base += ' attrs(%s)' % (
215                ' '.join(['%s="%s"' % (html_quote(n), html_quote(v))
216                          for n, v in self.attrs.items()]))
217        if self.original_params:
218            base += ' params(%s)' % (
219                ', '.join(['%s=%r' % (n, v)
220                           for n, v in self.attrs.items()]))
221        return base + '>'
222   
223    def html__get(self):
224        if not self.params.get('tag'):
225            raise ValueError(
226                "You cannot get the HTML of %r until you set the "
227                "'tag' param'" % self)
228        content = self._get_content()
229        tag = '<%s' % self.params.get('tag')
230        attrs = ' '.join([
231            '%s="%s"' % (html_quote(n), html_quote(v))
232            for n, v in self._html_attrs()])
233        if attrs:
234            tag += ' ' + attrs
235        tag += self._html_extra()
236        if content is None:
237            return tag + ' />'
238        else:
239            return '%s>%s</%s>' % (tag, content, self.params.get('tag'))
240
241    html = property(html__get)
242
243    def _html_attrs(self):
244        return self.attrs.items()
245
246    def _html_extra(self):
247        return ''
248
249    def _get_content(self):
250        """
251        Return the content for a tag (for self.html); return None
252        for an empty tag (like ``<img />``)
253        """
254        raise NotImplementedError
255   
256    def _add_vars(self, vars):
257        raise NotImplementedError
258
259    def _add_positional(self, args):
260        raise NotImplementedError
261
262class URL(URLResource):
263
264    r"""
265    >>> u = URL('http://localhost')
266    >>> u
267    <URL http://localhost>
268    >>> u = u['view']
269    >>> str(u)
270    'http://localhost/view'
271    >>> u['//foo'].param(content='view').html
272    '<a href="http://localhost/view/foo">view</a>'
273    >>> u.param(confirm='Really?', content='goto').html
274    '<a href="http://localhost/view" onclick="return confirm(\'Really?\')">goto</a>'
275    >>> u(title='See "it"', content='goto').html
276    '<a href="http://localhost/view?title=See+%22it%22">goto</a>'
277    >>> u('another', var='fuggetaboutit', content='goto').html
278    '<a href="http://localhost/view/another?var=fuggetaboutit">goto</a>'
279    >>> u.attr(content='goto').html
280    Traceback (most recent call last):
281        ....
282    ValueError: You must give a content param to <URL http://localhost/view attrs(content="goto")> generate anchor tags
283    >>> str(u['foo=bar%20stuff'])
284    'http://localhost/view?foo=bar+stuff'
285    """
286
287    default_params = {'tag': 'a'}
288
289    def __str__(self):
290        return self.href
291
292    def _get_content(self):
293        if not self.params.get('content'):
294            raise ValueError(
295                "You must give a content param to %r generate anchor tags"
296                % self)
297        return self.params['content']
298
299    def _add_vars(self, vars):
300        url = self
301        for name in ('confirm', 'content'):
302            if name in vars:
303                url = url.param(**{name: vars.pop(name)})
304        if 'target' in vars:
305            url = url.attr(target=vars.pop('target'))
306        return url.var(**vars)
307
308    def _add_positional(self, args):
309        return self.addpath(*args)
310
311    def _html_attrs(self):
312        attrs = self.attrs.items()
313        attrs.insert(0, ('href', self.href))
314        if self.params.get('confirm'):
315            attrs.append(('onclick', 'return confirm(%s)'
316                          % js_repr(self.params['confirm'])))
317        return attrs
318
319    def onclick_goto__get(self):
320        return 'location.href=%s; return false' % js_repr(self.href)
321
322    onclick_goto = property(onclick_goto__get)
323
324    def button__get(self):
325        return self.become(Button)
326
327    button = property(button__get)
328
329    def js_popup__get(self):
330        return self.become(JSPopup)
331
332    js_popup = property(js_popup__get)
333           
334class Image(URLResource):
335
336    r"""
337    >>> i = Image('/images')
338    >>> i = i / '/foo.png'
339    >>> i.html
340    '<img src="/images/foo.png" />'
341    >>> str(i['alt=foo'])
342    '<img src="/images/foo.png" alt="foo" />'
343    >>> i.href
344    '/images/foo.png'
345    """
346   
347    default_params = {'tag': 'img'}
348
349    def __str__(self):
350        return self.html
351
352    def _get_content(self):
353        return None
354
355    def _add_vars(self, vars):
356        return self.attr(**vars)
357
358    def _add_positional(self, args):
359        return self.addpath(*args)
360
361    def _html_attrs(self):
362        attrs = self.attrs.items()
363        attrs.insert(0, ('src', self.href))
364        return attrs
365
366class Button(URLResource):
367
368    r"""
369    >>> u = URL('/')
370    >>> u = u / 'delete'
371    >>> b = u.button['confirm=Sure?'](id=5, content='del')
372    >>> str(b)
373    '<button onclick="if (confirm(\'Sure?\')) {location.href=\'/delete?id=5\'}; return false">del</button>'
374    """
375
376    default_params = {'tag': 'button'}
377
378    def __str__(self):
379        return self.html
380
381    def _get_content(self):
382        if self.params.get('content'):
383            return self.params['content']
384        if self.attrs.get('value'):
385            return self.attrs['content']
386        # @@: Error?
387        return None
388
389    def _add_vars(self, vars):
390        button = self
391        if 'confirm' in vars:
392            button = button.param(confirm=vars.pop('confirm'))
393        if 'content' in vars:
394            button = button.param(content=vars.pop('content'))
395        return button.var(**vars)
396
397    def _add_positional(self, args):
398        return self.addpath(*args)
399
400    def _html_attrs(self):
401        attrs = self.attrs.items()
402        onclick = 'location.href=%s' % js_repr(self.href)
403        if self.params.get('confirm'):
404            onclick = 'if (confirm(%s)) {%s}' % (
405                js_repr(self.params['confirm']), onclick)
406        onclick += '; return false'
407        attrs.insert(0, ('onclick', onclick))
408        return attrs
409
410class JSPopup(URLResource):
411
412    r"""
413    >>> u = URL('/')
414    >>> u = u / 'view'
415    >>> j = u.js_popup(content='view')
416    >>> j.html
417    '<a href="/view" onclick="window.open(\'/view\', \'_blank\'); return false" target="_blank">view</a>'
418    """
419
420    default_params = {'tag': 'a', 'target': '_blank'}
421
422    def _add_vars(self, vars):
423        button = self
424        for var in ('width', 'height', 'stripped', 'content'):
425            if var in vars:
426                button = button.param(**{var: vars.pop(var)})
427        return button.var(**vars)
428
429    def _window_args(self):
430        p = self.params
431        features = []
432        if p.get('stripped'):
433            p['location'] = p['status'] = p['toolbar'] = '0'
434        for param in 'channelmode directories fullscreen location menubar resizable scrollbars status titlebar'.split():
435            if param not in p:
436                continue
437            v = p[param]
438            if v not in ('yes', 'no', '1', '0'):
439                if v:
440                    v = '1'
441                else:
442                    v = '0'
443            features.append('%s=%s' % (param, v))
444        for param in 'height left top width':
445            if not p.get(param):
446                continue
447            features.append('%s=%s' % (param, p[param]))
448        args = [self.href, p['target']]
449        if features:
450            args.append(','.join(features))
451        return ', '.join(map(js_repr, args))
452
453    def _html_attrs(self):
454        attrs = self.attrs.items()
455        onclick = ('window.open(%s); return false'
456                   % self._window_args())
457        attrs.insert(0, ('target', self.params['target']))
458        attrs.insert(0, ('onclick', onclick))
459        attrs.insert(0, ('href', self.href))
460        return attrs
461
462    def _get_content(self):
463        if not self.params.get('content'):
464            raise ValueError(
465                "You must give a content param to %r generate anchor tags"
466                % self)
467        return self.params['content']
468
469    def _add_positional(self, args):
470        return self.addpath(*args)
471
472if __name__ == '__main__':
473    import doctest
474    doctest.testmod()
475   
Note: Veja TracBrowser para ajuda no uso do navegador do trac.
 

The contents and data of this website are published under license:
Creative Commons 4.0 Brasil - Atribuir Fonte - Compartilhar Igual.