Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b02e8a6d5f | ||
|
|
a2b17967cf | ||
|
|
343ebf1714 | ||
|
|
e330791fe3 | ||
|
|
5e1e97ffc4 | ||
|
|
60f8816a10 | ||
|
|
6187c89ba6 | ||
|
|
e441e15907 | ||
|
|
e6c3410639 | ||
|
|
6b6cb5839c | ||
|
|
2a7e9c0c59 | ||
|
|
5b637c0a82 | ||
|
|
5cdd7c1215 |
2
Makefile
2
Makefile
@@ -32,7 +32,7 @@ update:
|
||||
echo "remember that pymysql was tweaked"
|
||||
src:
|
||||
### Use semantic versioning
|
||||
echo 'Version 2.10.1-stable+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION
|
||||
echo 'Version 2.10.3-stable+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION
|
||||
### rm -f all junk files
|
||||
make clean
|
||||
### clean up baisc apps
|
||||
|
||||
2
VERSION
2
VERSION
@@ -1 +1 @@
|
||||
Version 2.10.2-stable+timestamp.2015.03.31.22.25.23
|
||||
Version 2.10.3-stable+timestamp.2015.04.02.16.28.49
|
||||
|
||||
8
applications/admin/static/js/jquery.js
vendored
8
applications/admin/static/js/jquery.js
vendored
File diff suppressed because one or more lines are too long
@@ -18,7 +18,7 @@
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active" id="alltables">
|
||||
<table>
|
||||
<table class="table">
|
||||
{{for db in sorted(databases):}}
|
||||
{{for table in databases[db].tables:}}
|
||||
{{qry='%s.%s.id>0'%(db,table)}}
|
||||
@@ -40,7 +40,7 @@
|
||||
{{=A("%s.%s" % (db,table),_href=URL('select',args=[db],vars=dict(query=qry)))}}
|
||||
</th>
|
||||
<td>
|
||||
{{=A(str(T('New Record')),_href=URL('insert',args=[db,table]),_class="btn")}}
|
||||
{{=A(str(T('New Record')),_href=URL('insert',args=[db,table]),_class="btn btn-default")}}
|
||||
</td>
|
||||
</tr>
|
||||
{{pass}}
|
||||
@@ -61,7 +61,7 @@
|
||||
</pre>
|
||||
{{pass}}
|
||||
{{if table:}}
|
||||
{{=A(str(T('New Record')),_href=URL('insert',args=[request.args[0],table]),_class="btn")}}<br/><br/>
|
||||
{{=A(str(T('New Record')),_href=URL('insert',args=[request.args[0],table]),_class="btn btn-default")}}<br/><br/>
|
||||
<h3>{{=T("Rows in Table")}}</h3><br/>
|
||||
{{else:}}
|
||||
<h3>{{=T("Rows selected")}}</h3><br/>
|
||||
@@ -72,8 +72,8 @@
|
||||
{{=T('"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN')}}</p>
|
||||
<br/><br/>
|
||||
<h4>{{=T("%s selected", nrows)}}</h4>
|
||||
{{if start>0:}}{{=A(T('previous %s rows') % step,_href=URL('select',args=request.args[0],vars=dict(start=start-step)),_class="btn")}}{{pass}}
|
||||
{{if stop<nrows:}}{{=A(T('next %s rows') % step,_href=URL('select',args=request.args[0],vars=dict(start=start+step)),_class="btn")}}{{pass}}
|
||||
{{if start>0:}}{{=A(T('previous %s rows') % step,_href=URL('select',args=request.args[0],vars=dict(start=start-step)),_class="btn btn-default")}}{{pass}}
|
||||
{{if stop<nrows:}}{{=A(T('next %s rows') % step,_href=URL('select',args=request.args[0],vars=dict(start=start+step)),_class="btn btn-default")}}{{pass}}
|
||||
{{if rows:}}
|
||||
<div style="overflow:auto; width:80%;">
|
||||
{{linkto = lambda f, t, r: URL('update', args=[request.args[0], r, f]) if f else "#"}}
|
||||
@@ -82,7 +82,7 @@
|
||||
</div>
|
||||
{{pass}}
|
||||
<br/><br/><h3>{{=T("Import/Export")}}</h3><br/>
|
||||
<a href="{{=URL('csv',args=request.args[0],vars=dict(query=query))}}" class="btn">{{=T("export as csv file")}}</a>
|
||||
<a href="{{=URL('csv',args=request.args[0],vars=dict(query=query))}}" class="btn btn-default">{{=T("export as csv file")}}</a>
|
||||
{{=formcsv or ''}}
|
||||
|
||||
{{elif request.function=='insert':}}
|
||||
|
||||
@@ -114,17 +114,18 @@ def app_cleanup(app, request):
|
||||
for f in os.listdir(path):
|
||||
try:
|
||||
if f[:1] != '.': recursive_unlink(os.path.join(path, f))
|
||||
except IOError:
|
||||
except (OSError, IOError):
|
||||
r = False
|
||||
|
||||
# Remove cache files
|
||||
CacheOnDisk(folder=apath('%s/cache/' % app, request)).clear()
|
||||
path = apath('%s/cache/' % app, request)
|
||||
CacheOnDisk(folder=path).clear()
|
||||
|
||||
if os.path.exists(path):
|
||||
for f in os.listdir(path):
|
||||
try:
|
||||
if f[:1] != '.': recursive_unlink(os.path.join(path, f))
|
||||
except IOError:
|
||||
except (OSError, IOError):
|
||||
r = False
|
||||
return r
|
||||
|
||||
|
||||
74
gluon/contrib/feedparser.py
Executable file → Normal file
74
gluon/contrib/feedparser.py
Executable file → Normal file
@@ -9,7 +9,7 @@ Required: Python 2.4 or later
|
||||
Recommended: iconv_codec <http://cjkpython.i18n.org/>
|
||||
"""
|
||||
|
||||
__version__ = "5.1.2"
|
||||
__version__ = "5.1.3"
|
||||
__license__ = """
|
||||
Copyright (c) 2010-2012 Kurt McKee <contactme@kurtmckee.org>
|
||||
Copyright (c) 2002-2008 Mark Pilgrim
|
||||
@@ -44,7 +44,8 @@ __contributors__ = ["Jason Diamond <http://injektilo.org/>",
|
||||
"Sam Ruby <http://intertwingly.net/>",
|
||||
"Ade Oshineye <http://blog.oshineye.com/>",
|
||||
"Martin Pool <http://sourcefrog.net/>",
|
||||
"Kurt McKee <http://kurtmckee.org/>"]
|
||||
"Kurt McKee <http://kurtmckee.org/>",
|
||||
"Bernd Schlapsi <https://github.com/brot>",]
|
||||
|
||||
# HTTP "User-Agent" header to send to servers when downloading feeds.
|
||||
# If you are embedding feedparser in a larger application, you should
|
||||
@@ -1971,6 +1972,7 @@ class _BaseHTMLProcessor(sgmllib.SGMLParser):
|
||||
def handle_charref(self, ref):
|
||||
# called for each character reference, e.g. for ' ', ref will be '160'
|
||||
# Reconstruct the original character reference.
|
||||
ref = ref.lower()
|
||||
if ref.startswith('x'):
|
||||
value = int(ref[1:], 16)
|
||||
else:
|
||||
@@ -2455,7 +2457,10 @@ class _MicroformatsParser:
|
||||
linktype.startswith('video/') or \
|
||||
(linktype.startswith('application/') and not linktype.endswith('xml')):
|
||||
return 1
|
||||
path = urlparse.urlparse(attrsD['href'])[2]
|
||||
try:
|
||||
path = urlparse.urlparse(attrsD['href'])[2]
|
||||
except ValueError:
|
||||
return 0
|
||||
if path.find('.') == -1:
|
||||
return 0
|
||||
fileext = path.split('.').pop().lower()
|
||||
@@ -2541,7 +2546,8 @@ class _RelativeURIResolver(_BaseHTMLProcessor):
|
||||
('object', 'data'),
|
||||
('object', 'usemap'),
|
||||
('q', 'cite'),
|
||||
('script', 'src')])
|
||||
('script', 'src'),
|
||||
('video', 'poster')])
|
||||
|
||||
def __init__(self, baseuri, encoding, _type):
|
||||
_BaseHTMLProcessor.__init__(self, encoding, _type)
|
||||
@@ -2618,13 +2624,13 @@ class _HTMLSanitizer(_BaseHTMLProcessor):
|
||||
'loop', 'loopcount', 'loopend', 'loopstart', 'low', 'lowsrc', 'max',
|
||||
'maxlength', 'media', 'method', 'min', 'multiple', 'name', 'nohref',
|
||||
'noshade', 'nowrap', 'open', 'optimum', 'pattern', 'ping', 'point-size',
|
||||
'prompt', 'pqg', 'radiogroup', 'readonly', 'rel', 'repeat-max',
|
||||
'repeat-min', 'replace', 'required', 'rev', 'rightspacing', 'rows',
|
||||
'rowspan', 'rules', 'scope', 'selected', 'shape', 'size', 'span', 'src',
|
||||
'start', 'step', 'summary', 'suppress', 'tabindex', 'target', 'template',
|
||||
'title', 'toppadding', 'type', 'unselectable', 'usemap', 'urn', 'valign',
|
||||
'value', 'variable', 'volume', 'vspace', 'vrml', 'width', 'wrap',
|
||||
'xml:lang'])
|
||||
'poster', 'pqg', 'preload', 'prompt', 'radiogroup', 'readonly', 'rel',
|
||||
'repeat-max', 'repeat-min', 'replace', 'required', 'rev', 'rightspacing',
|
||||
'rows', 'rowspan', 'rules', 'scope', 'selected', 'shape', 'size', 'span',
|
||||
'src', 'start', 'step', 'summary', 'suppress', 'tabindex', 'target',
|
||||
'template', 'title', 'toppadding', 'type', 'unselectable', 'usemap',
|
||||
'urn', 'valign', 'value', 'variable', 'volume', 'vspace', 'vrml',
|
||||
'width', 'wrap', 'xml:lang'])
|
||||
|
||||
unacceptable_elements_with_end_tag = set(['script', 'applet', 'style'])
|
||||
|
||||
@@ -2976,9 +2982,9 @@ def _open_resource(url_file_stream_or_string, etag, modified, agent, referrer, h
|
||||
url_file_stream_or_string = 'http:' + url_file_stream_or_string[5:]
|
||||
if not agent:
|
||||
agent = USER_AGENT
|
||||
# test for inline user:password for basic auth
|
||||
# Test for inline user:password credentials for HTTP basic auth
|
||||
auth = None
|
||||
if base64:
|
||||
if base64 and not url_file_stream_or_string.startswith('ftp:'):
|
||||
urltype, rest = urllib.splittype(url_file_stream_or_string)
|
||||
realhost, rest = urllib.splithost(rest)
|
||||
if realhost:
|
||||
@@ -3471,15 +3477,7 @@ _rfc822_match = re.compile(
|
||||
"(?:%s, )?%s(?: %s)?" % (_rfc822_dayname, _rfc822_date, _rfc822_time)
|
||||
).match
|
||||
|
||||
def _parse_date_rfc822(dt):
|
||||
"""Parse RFC 822 dates and times, with one minor
|
||||
difference: years may be 4DIGIT or 2DIGIT.
|
||||
http://tools.ietf.org/html/rfc822#section-5"""
|
||||
try:
|
||||
m = _rfc822_match(dt.lower()).groupdict(0)
|
||||
except AttributeError:
|
||||
return None
|
||||
|
||||
def _parse_date_group_rfc822(m):
|
||||
# Calculate a date and timestamp
|
||||
for k in ('year', 'day', 'hour', 'minute', 'second'):
|
||||
m[k] = int(m[k])
|
||||
@@ -3487,7 +3485,7 @@ def _parse_date_rfc822(dt):
|
||||
# If the year is 2 digits, assume everything in the 90's is the 1990's
|
||||
if m['year'] < 100:
|
||||
m['year'] += (1900, 2000)[m['year'] < 90]
|
||||
stamp = datetime.datetime(*[m[i] for i in
|
||||
stamp = datetime.datetime(*[m[i] for i in
|
||||
('year', 'month', 'day', 'hour', 'minute', 'second')])
|
||||
|
||||
# Use the timezone information to calculate the difference between
|
||||
@@ -3512,8 +3510,36 @@ def _parse_date_rfc822(dt):
|
||||
|
||||
# Return the date and timestamp in UTC
|
||||
return (stamp - delta).utctimetuple()
|
||||
|
||||
def _parse_date_rfc822(dt):
|
||||
"""Parse RFC 822 dates and times, with one minor
|
||||
difference: years may be 4DIGIT or 2DIGIT.
|
||||
http://tools.ietf.org/html/rfc822#section-5"""
|
||||
try:
|
||||
m = _rfc822_match(dt.lower()).groupdict(0)
|
||||
except AttributeError:
|
||||
return None
|
||||
|
||||
return _parse_date_group_rfc822(m)
|
||||
registerDateHandler(_parse_date_rfc822)
|
||||
|
||||
def _parse_date_rfc822_grubby(dt):
|
||||
"""Parse date format similar to RFC 822, but
|
||||
the comma after the dayname is optional and
|
||||
month/day are inverted"""
|
||||
_rfc822_date_grubby = "%s %s %s" % (_rfc822_month, _rfc822_day, _rfc822_year)
|
||||
_rfc822_match_grubby = re.compile(
|
||||
"(?:%s[,]? )?%s(?: %s)?" % (_rfc822_dayname, _rfc822_date_grubby, _rfc822_time)
|
||||
).match
|
||||
|
||||
try:
|
||||
m = _rfc822_match_grubby(dt.lower()).groupdict(0)
|
||||
except AttributeError:
|
||||
return None
|
||||
|
||||
return _parse_date_group_rfc822(m)
|
||||
registerDateHandler(_parse_date_rfc822_grubby)
|
||||
|
||||
def _parse_date_asctime(dt):
|
||||
"""Parse asctime-style dates"""
|
||||
dayname, month, day, remainder = dt.split(None, 3)
|
||||
@@ -3699,7 +3725,7 @@ def convert_to_utf8(http_headers, data):
|
||||
u'application/xml-external-parsed-entity')
|
||||
text_content_types = (u'text/xml', u'text/xml-external-parsed-entity')
|
||||
if (http_content_type in application_content_types) or \
|
||||
(http_content_type.startswith(u'application/') and
|
||||
(http_content_type.startswith(u'application/') and
|
||||
http_content_type.endswith(u'+xml')):
|
||||
acceptable_content_type = 1
|
||||
rfc3023_encoding = http_encoding or xml_encoding or u'utf-8'
|
||||
|
||||
@@ -1,254 +0,0 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
from imaplib import ParseFlags
|
||||
|
||||
# mockimaplib: A very simple mock server module for imap client APIs
|
||||
# Copyright (C) 2014 Alan Etkin <spametki@gmail.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or(at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this program. If not, see
|
||||
# <http://www.gnu.org/licenses/lgpl.html>
|
||||
|
||||
"""
|
||||
mockimaplib allows you to test applications connecting to a dummy imap
|
||||
service. For more details on the api subset implemented,
|
||||
refer to the imaplib docs.
|
||||
|
||||
The client should configure a dictionary to map imap string queries to sets
|
||||
of entries stored in a message dummy storage dictionary. The module includes
|
||||
a small set of default message records (SPAM and MESSAGES), two mailboxes
|
||||
(Draft and INBOX) and a list of query/resultset entries (RESULTS).
|
||||
|
||||
Usage:
|
||||
|
||||
>>> import mockimaplib
|
||||
>>> connection = mockimaplib.IMAP4_SSL(<host>)
|
||||
>>> connection.login(<user>, <password>)
|
||||
None
|
||||
>>> connection.select("INBOX")
|
||||
("OK", ... <mailbox length>)
|
||||
# fetch commands specifying single uid or message id
|
||||
# will try to get messages recorded in SPAM
|
||||
>>> connection.uid(...)
|
||||
<search query or fetch result>
|
||||
# returns a string list of matching message ids
|
||||
>>> connection.search(<query>)
|
||||
("OK", ... "1 2 ... n")
|
||||
"""
|
||||
|
||||
MESSAGES = (
|
||||
'MIME-Version: 1.0\r\nReceived: by 10.140.91.199 with HTTP; Mon, 27 Jan 2014 13:52:30 -0800 (PST)\r\nDate: Mon, 27 Jan 2014 19:52:30 -0200\r\nDelivered-To: nurse@example.com\r\nMessage-ID: <10101010101010010000010101010001010101001010010000001@mail.example.com>\r\nSubject: spam1\r\nFrom: Mr. Gumby <gumby@example.com>\r\nTo: The nurse <nurse@example.com>\r\nContent-Type: text/plain; charset=ISO-8859-1\r\n\r\nNurse!\r\n\r\n\r\n',
|
||||
'MIME-Version: 1.0\r\nReceived: by 10.140.91.199 with HTTP; Mon, 27 Jan 2014 13:52:47 -0800 (PST)\r\nDate: Mon, 27 Jan 2014 19:52:47 -0200\r\nDelivered-To: nurse@example.com\r\nMessage-ID: <101010101010100100000101010100010101010010100100000010@mail.example.com>\r\nSubject: spam2\r\nFrom: Mr. Gumby <gumby@example.com>\r\nTo: The nurse <nurse@example.com>\r\nContent-Type: text/plain; charset=ISO-8859-1\r\n\r\nNurse, nurse!',
|
||||
'MIME-Version: 1.0\r\nReceived: by 10.140.91.199 with HTTP; Mon, 27 Jan 2014 13:54:54 -0800 (PST)\r\nDate: Mon, 27 Jan 2014 19:54:54 -0200\r\nDelivered-To: nurse@example.com\r\nMessage-ID: <1010101010101001000001010101000101010100101001000000101@mail.example.com>\r\nSubject: spamalot1\r\nFrom: Mr. Gumby <gumby@example.com>\r\nTo: The nurse <nurse@example.com>\r\nContent-Type: text/plain; charset=ISO-8859-1\r\n\r\nNurse!\r\n\r\n\r\n',
|
||||
'MIME-Version: 1.0\r\n\r\nReceived: by 10.140.91.199 with HTTP; Mon, 27 Jan 2014 13:54:54 -0800 (PST)\r\nDate: Mon, 27 Jan 2014 19:54:54 -0200\r\nDelivered-To: nurse@example.com\r\nMessage-ID: <101010101010100100000101010100010101010010100100000010101@mail.example.com>\r\nSubject: spamalot2\r\nFrom: Mr. Gumby <gumby@example.com>\r\nTo: The nurse <nurse@example.com>\r\nContent-Type: text/plain; charset=ISO-8859-1\r\n\r\nNurse! ... Nurse! ... Nurse!\r\n\r\n\r\n')
|
||||
|
||||
SPAM = {
|
||||
"INBOX": [
|
||||
{"uid": "483209",
|
||||
"headers": MESSAGES[0],
|
||||
"complete": MESSAGES[0],
|
||||
"flags": ""},
|
||||
{"uid": "483211",
|
||||
"headers": MESSAGES[1],
|
||||
"complete": MESSAGES[1],
|
||||
"flags": ""},
|
||||
{"uid": "483225",
|
||||
"headers": MESSAGES[2],
|
||||
"complete": MESSAGES[2],
|
||||
"flags": ""}],
|
||||
"Draft":[
|
||||
{"uid": "483432",
|
||||
"headers": MESSAGES[3],
|
||||
"complete": MESSAGES[3],
|
||||
"flags": ""},]
|
||||
}
|
||||
|
||||
RESULTS = {
|
||||
# <query string>: [<str uid> | <long id>, ...]
|
||||
"INBOX": {
|
||||
"(ALL)": (1, 2, 3),
|
||||
"(1:3)": (1, 2, 3)},
|
||||
"Draft": {
|
||||
"(1:1)": (1,)},
|
||||
}
|
||||
|
||||
class Connection(object):
|
||||
"""Dummy connection object for the imap client.
|
||||
By default, uses the module SPAM and RESULT
|
||||
sets (use Connection.setup for custom values)"""
|
||||
def login(self, user, password):
|
||||
pass
|
||||
|
||||
def __init__(self):
|
||||
self._readonly = False
|
||||
self._mailbox = None
|
||||
self.setup()
|
||||
|
||||
def list(self):
|
||||
return ('OK', ['(\\HasNoChildren) "/" "%s"' % key for key in self.spam])
|
||||
|
||||
def select(self, tablename, readonly=False):
|
||||
self._readonly = readonly
|
||||
"""args: mailbox, boolean
|
||||
result[1][0] -> int last message id / mailbox lenght
|
||||
result[0] = 'OK'
|
||||
"""
|
||||
self._mailbox = tablename
|
||||
return ('OK', (len(SPAM[self._mailbox]), None))
|
||||
|
||||
def uid(self, command, uid, arg):
|
||||
""" args:
|
||||
command: "search" | "fetch"
|
||||
uid: None | uid
|
||||
parts: "(ALL)" | "(RFC822 FLAGS)" | "(RFC822.HEADER FLAGS)"
|
||||
|
||||
"search", None, "(ALL)" -> ("OK", ("uid_1 uid_2 ... uid_<mailbox length>", None))
|
||||
"search", None, "<query>" -> ("OK", ("uid_1 uid_2 ... uid_n", None))
|
||||
"fetch", uid, parts -> ("OK", (("<id> ...", "<raw message as specified in parts>"), "<flags>")
|
||||
[0] [1][0][0] [1][0][1] [1][1]
|
||||
"""
|
||||
if command == "search":
|
||||
return self._search(arg)
|
||||
elif command == "fetch":
|
||||
return self._fetch(uid, arg)
|
||||
|
||||
def _search(self, query):
|
||||
return ("OK", (" ".join([str(item["uid"]) for item in self._get_messages(query)]), None))
|
||||
|
||||
def _fetch(self, value, arg):
|
||||
try:
|
||||
message = self.spam[self._mailbox][value - 1]
|
||||
message_id = value
|
||||
except TypeError:
|
||||
for x, item in enumerate(self.spam[self._mailbox]):
|
||||
if item["uid"] == value:
|
||||
message = item
|
||||
message_id = x + 1
|
||||
break
|
||||
|
||||
parts = "headers"
|
||||
if arg in ("(ALL)", "(RFC822 FLAGS)"):
|
||||
parts = "complete"
|
||||
|
||||
return ("OK", (("%s " % message_id, message[parts]), message["flags"]))
|
||||
|
||||
def _get_messages(self, query):
|
||||
if query.strip().isdigit():
|
||||
return [self.spam[self._mailbox][int(query.strip()) - 1],]
|
||||
elif query[1:-1].strip().isdigit():
|
||||
return [self.spam[self._mailbox][int(query[1:-1].strip()) -1],]
|
||||
elif query[1:-1].replace("UID", "").strip().isdigit():
|
||||
for item in self.spam[self._mailbox]:
|
||||
if item["uid"] == query[1:-1].replace("UID", "").strip():
|
||||
return [item,]
|
||||
messages = []
|
||||
try:
|
||||
for m in self.results[self._mailbox][query]:
|
||||
try:
|
||||
self.spam[self._mailbox][m - 1]["id"] = m
|
||||
messages.append(self.spam[self._mailbox][m - 1])
|
||||
except TypeError:
|
||||
for x, item in enumerate(self.spam[self._mailbox]):
|
||||
if item["uid"] == m:
|
||||
item["id"] = x + 1
|
||||
messages.append(item)
|
||||
break
|
||||
except IndexError:
|
||||
# message removed
|
||||
pass
|
||||
return messages
|
||||
except KeyError:
|
||||
raise ValueError("The client issued an unexpected query: %s" % query)
|
||||
|
||||
def setup(self, spam={}, results={}):
|
||||
"""adds custom message and query databases or sets
|
||||
the values to the module defaults.
|
||||
"""
|
||||
|
||||
self.spam = spam
|
||||
self.results = results
|
||||
if not spam:
|
||||
for key in SPAM:
|
||||
self.spam[key] = []
|
||||
for d in SPAM[key]:
|
||||
self.spam[key].append(d.copy())
|
||||
if not results:
|
||||
for key in RESULTS:
|
||||
self.results[key] = RESULTS[key].copy()
|
||||
|
||||
|
||||
def search(self, first, query):
|
||||
""" args:
|
||||
first: None
|
||||
query: string with mailbox query (flags, date, uid, id, ...)
|
||||
example: '2:15723 BEFORE 27-Jan-2014 FROM "gumby"'
|
||||
result[1][0] -> "id_1 id_2 ... id_n"
|
||||
"""
|
||||
messages = self._get_messages(query)
|
||||
ids = " ".join([str(item["id"]) for item in messages])
|
||||
return ("OK", (ids, None))
|
||||
|
||||
def append(self, mailbox, flags, struct_time, message):
|
||||
"""
|
||||
result, data = self.connection.append(mailbox, flags, struct_time, message)
|
||||
if result == "OK":
|
||||
uid = int(re.findall("\d+", str(data))[-1])
|
||||
"""
|
||||
last = self.spam[mailbox][-1]
|
||||
try:
|
||||
uid = int(last["uid"]) +1
|
||||
except ValueError:
|
||||
alluids = []
|
||||
for _mailbox in self.spam.keys():
|
||||
for item in self.spam[_mailbox]:
|
||||
try:
|
||||
alluids.append(int(item["uid"]))
|
||||
except:
|
||||
pass
|
||||
if len(alluids) > 0:
|
||||
uid = max(alluids) + 1
|
||||
else:
|
||||
uid = 1
|
||||
flags = "FLAGS " + flags
|
||||
item = {"uid": str(uid), "headers": message, "complete": message, "flags": flags}
|
||||
self.spam[mailbox].append(item)
|
||||
return ("OK", "spam spam %s spam" % uid)
|
||||
|
||||
|
||||
def store(self, *args):
|
||||
"""
|
||||
implements some flag commands
|
||||
args: ("<id>", "<+|->FLAGS", "(\\Flag1 \\Flag2 ... \\Flagn)")
|
||||
"""
|
||||
message = self.spam[self._mailbox][int(args[0] - 1)]
|
||||
old_flags = ParseFlags(message["flags"])
|
||||
flags = ParseFlags("FLAGS" + args[2])
|
||||
if args[1].strip().startswith("+"):
|
||||
message["flags"] = "FLAGS (%s)" % " ".join(set(flags + old_flags))
|
||||
elif args[1].strip().startswith("-"):
|
||||
message["flags"] = "FLAGS (%s)" % " ".join([flag for flag in old_flags if not flag in flags])
|
||||
|
||||
def expunge(self):
|
||||
"""implements removal of deleted flag messages"""
|
||||
for x, item in enumerate(self.spam[self._mailbox]):
|
||||
if "\\Deleted" in item["flags"]:
|
||||
self.spam[self._mailbox].pop(x)
|
||||
|
||||
|
||||
class IMAP4(object):
|
||||
""">>> connection = IMAP4() # creates the dummy imap4 client object"""
|
||||
def __new__(self, *args, **kwargs):
|
||||
# args: (server, port)
|
||||
return Connection()
|
||||
|
||||
IMAP4_SSL = IMAP4
|
||||
@@ -41,12 +41,15 @@ class CustomImportException(ImportError):
|
||||
|
||||
def custom_importer(name, globals=None, locals=None, fromlist=None, level=-1):
|
||||
"""
|
||||
web2py's custom importer. It behaves like the standard Python importer but
|
||||
web2py's custom importer. It behaves like the standard Python importer but
|
||||
it tries to transform import statements as something like
|
||||
"import applications.app_name.modules.x".
|
||||
If the import fails, it falls back on naive_importer
|
||||
"""
|
||||
|
||||
if isinstance(name, unicode):
|
||||
name = name.encode('utf8')
|
||||
|
||||
globals = globals or {}
|
||||
locals = locals or {}
|
||||
fromlist = fromlist or []
|
||||
@@ -77,7 +80,7 @@ def custom_importer(name, globals=None, locals=None, fromlist=None, level=-1):
|
||||
if not fromlist:
|
||||
# import like "import x" or "import x.y"
|
||||
result = None
|
||||
for itemname in name.split("."):
|
||||
for itemname in name.split("."):
|
||||
new_mod = base_importer(
|
||||
modules_prefix, globals, locals, [itemname], level)
|
||||
try:
|
||||
|
||||
@@ -23,6 +23,7 @@ base_modules = ['aifc', 'anydbm', 'array', 'asynchat', 'asyncore', 'atexit',
|
||||
'collections', 'colorsys', 'compileall', 'compiler',
|
||||
'compiler.ast', 'compiler.visitor', 'ConfigParser',
|
||||
'contextlib', 'Cookie', 'cookielib', 'copy', 'copy_reg',
|
||||
'collections',
|
||||
'cPickle', 'cProfile', 'cStringIO', 'csv', 'ctypes',
|
||||
'datetime', 'decimal', 'difflib', 'dircache', 'dis',
|
||||
'doctest', 'DocXMLRPCServer', 'dumbdbm', 'dummy_thread',
|
||||
@@ -67,13 +68,6 @@ base_modules = ['aifc', 'anydbm', 'array', 'asynchat', 'asyncore', 'atexit',
|
||||
'MimeWriter', 'mimify', 'multifile', 'sets']
|
||||
|
||||
contributed_modules = []
|
||||
for root, dirs, files in os.walk('gluon'):
|
||||
for candidate in ['.'.join(
|
||||
os.path.join(root, os.path.splitext(name)[0]).split(os.sep))
|
||||
for name in files if name.endswith('.py')
|
||||
and root.split(os.sep) != ['gluon', 'tests']
|
||||
]:
|
||||
contributed_modules.append(candidate)
|
||||
|
||||
# Python base version
|
||||
python_version = sys.version[:3]
|
||||
|
||||
@@ -2148,7 +2148,7 @@ class SQLFORM(FORM):
|
||||
else:
|
||||
fields = []
|
||||
columns = []
|
||||
filter1 = lambda f: isinstance(f, Field)
|
||||
filter1 = lambda f: isinstance(f, Field) and f.type != 'blob'
|
||||
filter2 = lambda f: isinstance(f, Field) and f.readable
|
||||
for table in tables:
|
||||
fields += filter(filter1, table)
|
||||
|
||||
@@ -42,10 +42,13 @@ from gluon import *
|
||||
from gluon.contrib.autolinks import expand_one
|
||||
from gluon.contrib.markmin.markmin2html import \
|
||||
replace_at_urls, replace_autolinks, replace_components
|
||||
from pydal.objects import Table, Row, Set, Query
|
||||
from pydal.objects import Row, Set, Query
|
||||
|
||||
import gluon.serializers as serializers
|
||||
|
||||
Table = DAL.Table
|
||||
Field = DAL.Field
|
||||
|
||||
try:
|
||||
# try stdlib (Python 2.6)
|
||||
import json as json_parser
|
||||
|
||||
Reference in New Issue
Block a user