Merge branch 'edge'

This commit is contained in:
Rushabh Mehta 2013-01-15 14:55:13 +05:30
commit acdac87384
10 changed files with 120 additions and 86 deletions

View file

@ -226,7 +226,7 @@ def validate_permissions(permissions, for_remove=False):
issubmittable = webnotes.conn.get_value("DocType", doctype, "is_submittable")
def get_txt(d):
return "For %s (level %s) in %s:" % (d.role, d.permlevel, d.parent)
return "For %s (level %s) in %s row %s:" % (d.role, d.permlevel, d.parent, d.idx)
def check_atleast_one_set(d):
if not d.read and not d.write and not d.submit and not d.cancel and not d.create:
@ -245,7 +245,7 @@ def validate_permissions(permissions, for_remove=False):
raise_exception=True)
def check_level_zero_is_set(d):
if d.permlevel > 0 and d.role != 'All':
if cint(d.permlevel) > 0 and d.role != 'All':
if not permissions.get({"role": d.role, "permlevel": 0}):
webnotes.msgprint(get_txt(d) + " Higher level permissions are meaningless if level 0 permission is not set.",
raise_exception=True)

View file

View file

@ -0,0 +1,8 @@
# For license information, please see license.txt
from __future__ import unicode_literals
import webnotes
class DocType:
def __init__(self, d, dl):
self.doc, self.doclist = d, dl

View file

@ -0,0 +1,59 @@
[
{
"owner": "Administrator",
"docstatus": 0,
"creation": "2013-01-15 12:42:11",
"modified_by": "Administrator",
"modified": "2013-01-15 12:49:23"
},
{
"autoname": "SCHLOG.#####",
"description": "Log of Scheduler Errors",
"doctype": "DocType",
"module": "Core",
"document_type": "System",
"name": "__common__"
},
{
"name": "__common__",
"parent": "Scheduler Log",
"doctype": "DocField",
"parenttype": "DocType",
"permlevel": 0,
"parentfield": "fields"
},
{
"parent": "Scheduler Log",
"read": 1,
"cancel": 1,
"name": "__common__",
"create": 1,
"doctype": "DocPerm",
"submit": 0,
"write": 1,
"parenttype": "DocType",
"role": "System Manager",
"report": 1,
"permlevel": 0,
"parentfield": "permissions"
},
{
"name": "Scheduler Log",
"doctype": "DocType"
},
{
"doctype": "DocField",
"label": "Method",
"fieldname": "method",
"fieldtype": "Data"
},
{
"doctype": "DocField",
"label": "Error",
"fieldname": "error",
"fieldtype": "Text"
},
{
"doctype": "DocPerm"
}
]

View file

@ -59,7 +59,7 @@ $.extend(wn.model, {
if(def_vals[df["default"]])
return def_vals[df["default"]];
else if(df.fieldtype=="Time" && !df["default"] && df.reqd)
else if(df.fieldtype=="Time" && (!df["default"]))
return dateutil.get_cur_time()
else if(df["default"])
return df["default"];

View file

@ -75,7 +75,7 @@ wn.views.CommunicationList = Class.extend({
make_line: function(doc) {
var me = this;
var comm = $(repl('<tr><td>\
<a href="#Form/Communication/%(name)s" style="font-size: 90%; float: right;">'
<a href="#Form/Communication/%(name)s" class="show-details" style="font-size: 90%; float: right;">'
+wn._('Show Details')+'</a>\
<p class="comm-header" title="'+wn._('Click to Expand / Collapse')+'">\
<b>%(_sender)s on %(when)s</b></p>\
@ -83,6 +83,10 @@ wn.views.CommunicationList = Class.extend({
padding: 10px; overflow-x: auto; display: none;"></div>\
</td></tr>', doc))
.appendTo(this.body);
if(!doc.name) {
comm.find(".show-details").toggle(false);
}
comm.find(".comm-header")
.css({"cursor":"pointer"})

View file

@ -48,6 +48,8 @@ class ModelWrapper:
self.load_from_db(dt, dn)
elif isinstance(dt, list):
self.set_doclist(dt)
elif isinstance(dt, dict):
self.set_doclist([dt])
def load_from_db(self, dt=None, dn=None, prefix='tab'):
"""

View file

@ -59,19 +59,7 @@ def get_fullname(profile):
return profile
# TODO: deprecate it
def decode_email_header(s):
import email.header
# replace double quotes with blank
# double quotes in header prohibit decoding of header
decoded_header_tuple = email.header.decode_header(s.replace('"', ''))
decoded_list = map(lambda h: unicode(h[0], encoding=h[1] or 'utf-8'), decoded_header_tuple)
return " ".join(decoded_list)
def get_email_id(user):
def get_formatted_email(user):
"""get email id of user formatted as: John Doe <johndoe@example.com>"""
if user == "Administrator":
return user
@ -81,14 +69,15 @@ def get_email_id(user):
def extract_email_id(email):
"""fetch only the email part of the email id"""
import re
sender_email = re.findall("<([^>]*)>", email)
return sender_email and sender_email[0] or ""
from email.utils import parseaddr
if ',' in email and email.count("@")==1:
email = email.split(",")[-1]
fullname, email_id = parseaddr(email)
return email_id
def validate_email_add(email_str):
"""Validates the email string"""
from email.utils import parseaddr
real_name, email = parseaddr(email_str)
email = extract_email_id(email_str)
import re
return re.match("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", email.lower())

View file

@ -21,9 +21,7 @@
#
from __future__ import unicode_literals
"""
This module contains classes for managing incoming emails
"""
from webnotes.utils import extract_email_id
class IncomingMail:
"""
@ -41,18 +39,21 @@ class IncomingMail:
self.html_content = ''
self.attachments = []
self.parse()
self.set_content_and_type()
self.from_email = extract_email_id(self.mail["From"])
def parse(self):
"""
Extracts text, html and attachments from the mail
"""
for part in self.mail.walk():
self.process_part(part)
def set_content_and_type(self):
self.content, self.content_type = '[Blank Email]', 'text/plain'
if self.text_content:
self.content, self.content_type = self.text_content, 'text/plain'
else:
self.content, self.content_type = self.html_content, 'text/html'
def process_part(self, part):
"""
Process a single part of an email
"""
content_type = part.get_content_type()
charset = part.get_content_charset()
if not charset: charset = self.get_charset(part)
@ -67,15 +68,9 @@ class IncomingMail:
self.get_attachment(part, charset)
def get_text_content(self):
"""
Returns the text parts of the email. If None, then HTML parts
"""
return self.text_content or self.html_content
def get_charset(self, part):
"""
Guesses character set
"""
charset = part.get_content_charset()
if not charset:
import chardet
@ -84,57 +79,48 @@ class IncomingMail:
return charset
def get_payload(self, part, charset):
"""
get utf-8 encoded part content
"""
try:
return unicode(part.get_payload(decode=True),str(charset),"ignore")
except LookupError, e:
return part.get_payload()
def get_attachment(self, part, charset):
"""
Extracts an attachment
"""
self.attachments.append({
'content-type': part.get_content_type(),
'filename': part.get_filename(),
'content': part.get_payload(decode=True),
})
def save_attachments_in_doc(self, doc):
from webnotes.utils.file_manager import save_file, add_file_list
for attachment in self.attachments:
fid = save_file(attachment['filename'], attachment['content'])
status = add_file_list(doc.doctype, doc.name, fid, fid)
def get_thread_id(self):
"""
Extracts thread id of the message between first []
from the subject
"""
import re
subject = self.mail.get('Subject', '')
return re.findall('(?<=\[)[\w/-]+', subject)
l= re.findall('(?<=\[)[\w/-]+', subject)
return l and l[0] or None
class POP3Mailbox:
"""
A simple pop3 mailbox, abstracts connection and mail extraction
To use, subclass it and override method process_message(from, subject, text, thread_id)
"""
def __init__(self):
self.setup()
self.get_messages()
def __init__(self, settings_doc):
"""
settings_doc must contain
use_ssl, host, username, password
(by name or object)
"""
if isinstance(settings_doc, basestring):
from webnotes.model.doc import Document
self.settings = Document(settings_doc, settings_doc)
else:
self.settings = settings_doc
def setup(self):
# overrride
self.settings = webnotes._dict()
def check_mails(self):
# overrride
return True
def process_message(self, mail):
# overrride
pass
def connect(self):
"""
Connects to the mailbox
"""
import poplib
if self.settings.use_ssl:
@ -145,10 +131,6 @@ class POP3Mailbox:
self.pop.pass_(self.settings.password)
def get_messages(self):
"""
Loads messages from the mailbox and calls
process_message for each message
"""
import webnotes
if not self.check_mails():
@ -190,15 +172,3 @@ class POP3Mailbox:
self.pop.quit()
webnotes.conn.begin()
def check_mails(self):
"""
To be overridden
If mailbox is to be scanned, returns true
"""
return True
def process_message(self, mail):
"""
To be overriden
"""
pass

View file

@ -101,8 +101,10 @@ def log(method):
import webnotes.utils
webnotes.conn.begin()
webnotes.conn.sql("""insert into __SchedulerLog (`timestamp`, method, error)
values (%s, %s, %s)""", (webnotes.utils.now_datetime(), method, traceback))
d = webnotes.doc("Scheduler Log")
d.method = method
d.error = traceback
d.save()
webnotes.conn.commit()
return traceback