diff --git a/FeedTheMonkey.app/Contents/Frameworks/FeedTheMonkey b/FeedTheMonkey.app/Contents/Frameworks/FeedTheMonkey new file mode 100755 index 0000000..745e0c9 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/FeedTheMonkey @@ -0,0 +1,537 @@ +#!/usr/bin/env python2 + +import sys, os, json, tempfile, urllib2, urllib, json +from PyQt4 import QtGui, QtCore, QtWebKit, QtNetwork +from threading import Thread +from sys import platform as _platform + +settings = QtCore.QSettings("jabs.nu", "feedthemonkey") + +class MainWindow(QtGui.QMainWindow): + def __init__(self): + QtGui.QMainWindow.__init__(self) + self.setWindowIcon(QtGui.QIcon("feedmonkey")) + self.addAction(QtGui.QAction("Full Screen", self, checkable=True, toggled=lambda v: self.showFullScreen() if v else self.showNormal(), shortcut="F11")) + self.history = self.get("history", []) + self.restoreGeometry(QtCore.QByteArray.fromRawData(settings.value("geometry").toByteArray())) + self.restoreState(QtCore.QByteArray.fromRawData(settings.value("state").toByteArray())) + + self.initUI() + + session_id = self.get("session_id") + server_url = self.get("server_url") + + if not (session_id and server_url): + self.authenticate() + else: + self.initApp() + + + def initUI(self): + self.list = List(self) + self.content = Content(self) + + self.splitter = QtGui.QSplitter(QtCore.Qt.Vertical, self) + self.splitter.setHandleWidth(1) + self.splitter.addWidget(self.list) + self.splitter.addWidget(self.content) + self.splitter.restoreState(settings.value("splitterSizes").toByteArray()); + self.splitter.splitterMoved.connect(self.splitterMoved) + + self.setCentralWidget(self.splitter) + + def mkAction(name, connect, shortcut=None): + action = QtGui.QAction(name, self) + action.triggered.connect(connect) + if shortcut: + action.setShortcut(shortcut) + return action + + mb = self.menuBar() + + fileMenu = mb.addMenu("&File") + fileMenu.addAction(mkAction("&Close", self.close, "Ctrl+W")) + fileMenu.addAction(mkAction("&Log Out", self.logOut)) + fileMenu.addSeparator() + fileMenu.addAction(mkAction("&Exit", self.close, "Ctrl+Q")) + + actionMenu = mb.addMenu("&Action") + actionMenu.addAction(mkAction("&Reload", self.content.reload, "R")) + actionMenu.addAction(mkAction("Set &Unread", self.content.setUnread, "U")) + actionMenu.addAction(mkAction("&Next", self.content.showNext, "J")) + actionMenu.addAction(mkAction("&Previous", self.content.showPrevious, "K")) + actionMenu.addAction(mkAction("&Open in Browser", self.content.openCurrent, "N")) + + viewMenu = mb.addMenu("&View") + viewMenu.addAction(mkAction("Zoom &In", lambda: self.content.wb.setZoomFactor(self.content.wb.zoomFactor() + 0.2), "Ctrl++")) + viewMenu.addAction(mkAction("Zoom &Out", lambda: self.content.wb.setZoomFactor(self.content.wb.zoomFactor() - 0.2), "Ctrl+-")) + viewMenu.addAction(mkAction("&Reset", lambda: self.content.wb.setZoomFactor(1), "Ctrl+0")) + + windowMenu = mb.addMenu("&Window") + windowMenu.addAction(mkAction("Default", self.resetSplitter, "Ctrl+D")) + + helpMenu = mb.addMenu("&Help") + helpMenu.addAction(mkAction("&About", lambda: QtGui.QDesktopServices.openUrl(QtCore.QUrl("http://jabs.nu/feedthemonkey", QtCore.QUrl.TolerantMode)) )) + + def initApp(self): + session_id = self.get("session_id") + server_url = self.get("server_url") + self.tinyTinyRSS = TinyTinyRSS(self, server_url, session_id) + + self.content.evaluateJavaScript("setArticle('loading')") + self.content.reload() + self.show() + + def closeEvent(self, ev): + settings.setValue("geometry", self.saveGeometry()) + settings.setValue("state", self.saveState()) + return QtGui.QMainWindow.closeEvent(self, ev) + + def put(self, key, value): + "Persist an object somewhere under a given key" + settings.setValue(key, json.dumps(value)) + settings.sync() + + def get(self, key, default=None): + "Get the object stored under 'key' in persistent storage, or the default value" + v = settings.value(key) + return json.loads(unicode(v.toString())) if v.isValid() else default + + def setWindowTitle(self, t): + super(QtGui.QMainWindow, self).setWindowTitle("Feed the Monkey" + t) + + def splitterMoved(self, pos, index): + settings.setValue("splitterSizes", self.splitter.saveState()); + + def resetSplitter(self): + sizes = self.splitter.sizes() + top = sizes[0] + bottom = sizes[1] + sizes[0] = 200 + sizes[1] = bottom + top - 200 + self.splitter.setSizes(sizes) + + def authenticate(self): + + dialog = Login() + + def callback(): + + server_url = str(dialog.textServerUrl.text()) + user = str(dialog.textName.text()) + password = str(dialog.textPass.text()) + + session_id = TinyTinyRSS.login(server_url, user, password) + if session_id: + self.put("session_id", session_id) + self.put("server_url", server_url) + self.initApp() + else: + self.authenticate() + + dialog.accepted.connect(callback) + + dialog.exec_() + + def logOut(self): + self.hide() + self.content.evaluateJavaScript("setArticle('logout')") + self.tinyTinyRSS.logOut() + self.tinyTinyRSS = None + self.put("session_id", None) + self.put("server_url", None) + self.authenticate() + +class List(QtGui.QTableWidget): + def __init__(self, container): + QtGui.QTableWidget.__init__(self) + self.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) + self.app = container + self.itemSelectionChanged.connect(self.rowSelected) + self.setShowGrid(False) + + def initHeader(self): + self.clear() + self.setColumnCount(3) + self.setHorizontalHeaderLabels(("Feed", "Title", "Date")) + self.horizontalHeader().setResizeMode(0, QtGui.QHeaderView.ResizeToContents) + self.horizontalHeader().setResizeMode(1, QtGui.QHeaderView.Stretch) + self.horizontalHeader().setResizeMode(2, QtGui.QHeaderView.ResizeToContents) + self.verticalHeader().hide() + + def setItems(self, articles): + self.initHeader() + self.setRowCount(len(articles)) + row = 0 + for article in articles: + if "feed_title" in article: + feed_title = QtGui.QTableWidgetItem(article["feed_title"]) + feed_title.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + self.setItem(row, 0, feed_title) + if "title" in article: + title = QtGui.QTableWidgetItem(article["title"]) + title.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + self.setItem(row, 1, title) + if "updated" in article: + date = QtCore.QDateTime.fromTime_t(article["updated"]).toString(QtCore.Qt.SystemLocaleShortDate) + d = QtGui.QTableWidgetItem(date) + d.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + self.setItem(row, 2, d) + if "author" in article: + author = QtGui.QTableWidgetItem(article["author"]) + author.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + self.setItem(row, 3, author) + self.resizeRowToContents(row) + row += 1 + self.selectRow(0) + + def rowSelected(self): + indexes = self.selectedIndexes() + if len(indexes) > 0: + row = indexes[0].row() + self.app.content.showIndex(row) + + def updateRead(self): + for row, article in enumerate(self.app.content.unread_articles): + for x in xrange(0,3): + item = self.item(row, x) + font = item.font() + font.setBold(article["unread"]) + item.setFont(font) + + +class Content(QtGui.QWidget): + def __init__(self, container): + QtGui.QWidget.__init__(self) + + self.app = container + self.index = 0 + + self.wb = QtWebKit.QWebView(titleChanged=lambda t: container.setWindowTitle(t)) + self.wb.page().setLinkDelegationPolicy(QtWebKit.QWebPage.DelegateAllLinks) + self.wb.linkClicked.connect(lambda url: self.openLink(url)) + + self.setLayout(QtGui.QVBoxLayout(spacing=0)) + self.layout().setContentsMargins(0, 0, 0, 0) + self.layout().addWidget(self.wb) + + self.do_show_next = QtGui.QShortcut(QtCore.Qt.Key_Right, self, activated=self.showNext) + self.do_show_previous = QtGui.QShortcut(QtCore.Qt.Key_Left, self, activated=self.showPrevious) + self.do_open = QtGui.QShortcut("Return", self, activated=self.openCurrent) + + self.wb.settings().setAttribute(QtWebKit.QWebSettings.PluginsEnabled, True) + self.wb.settings().setIconDatabasePath(tempfile.mkdtemp()) + self.wb.setHtml(self.templateString()) + + self.unread_articles = [] + + def openLink(self, url): + QtGui.QDesktopServices.openUrl(url) + + def reload(self): + w = WorkerThread(self.app, self._reload) + self.connect(w, QtCore.SIGNAL("reload_done()"), self.reload_done) + w.start() + + def setUnread(self): + article = self.unread_articles[self.index] + article["unread"] = True + article["set_unread"] = True + self.app.list.updateRead() + + def _reload(self): + self.unread_articles = self.app.tinyTinyRSS.getUnreadFeeds() + self.index = -1 + + def reload_done(self): + self.setUnreadCount() + if len(self.unread_articles) > 0: + self.showNext() + self.app.list.setItems(self.unread_articles) + + def showIndex(self, index): + previous = self.unread_articles[self.index] + if not "set_unread" in previous or not previous["set_unread"]: + self.app.tinyTinyRSS.setArticleRead(previous["id"]) + previous["unread"] = False + self.app.list.updateRead() + else: + previous["set_unread"] = False + self.index = index + current = self.unread_articles[self.index] + self.setArticle(current) + self.setUnreadCount() + + def showNext(self): + if self.index >= 0 and self.index < len(self.unread_articles): + previous = self.unread_articles[self.index] + if not "set_unread" in previous or not previous["set_unread"]: + self.app.tinyTinyRSS.setArticleRead(previous["id"]) + previous["unread"] = False + self.app.list.updateRead() + else: + previous["set_unread"] = False + + if len(self.unread_articles) > self.index + 1: + self.index += 1 + current = self.unread_articles[self.index] + self.setArticle(current) + else: + if self.index < len(self.unread_articles): + self.index += 1 + + self.setUnreadCount() + self.app.list.selectRow(self.index) + + def showPrevious(self): + if self.index > 0: + self.index -= 1 + previous = self.unread_articles[self.index] + self.setArticle(previous) + self.setUnreadCount() + self.app.list.selectRow(self.index) + + def openCurrent(self): + current = self.unread_articles[self.index] + url = QtCore.QUrl(current["link"]) + self.openLink(url) + + def setArticle(self, article): + func = u"setArticle({});".format(json.dumps(article)) + self.evaluateJavaScript(func) + + def evaluateJavaScript(self, func): + return self.wb.page().mainFrame().evaluateJavaScript(func) + + def setUnreadCount(self): + length = len(self.unread_articles) + i = 0 + if self.index > 0: + i = self.index + unread = length - i + + self.app.setWindowTitle(" (" + str(unread) + "/" + str(length) + ")") + if unread < 1: + self.evaluateJavaScript("setArticle('empty')") + + def templateString(self): + html=""" + + + + + ttrssl + + + + +
+

+

+

+
+
+ + """ + return html # string.replace(html, " + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + Python + CFBundleGetInfoString + Python Runtime and Library + CFBundleIdentifier + org.python.python + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Python + CFBundlePackageType + FMWK + CFBundleShortVersionString + 2.7.5, (c) 2004-2013 Python Software Foundation. + CFBundleLongVersionString + 2.7.5, (c) 2004-2013 Python Software Foundation. + CFBundleSignature + ???? + CFBundleVersion + 2.7.5 + + diff --git a/FeedTheMonkey.app/Contents/Frameworks/Python.framework/Versions/2.7/include/python2.7/pyconfig.h b/FeedTheMonkey.app/Contents/Frameworks/Python.framework/Versions/2.7/include/python2.7/pyconfig.h new file mode 100644 index 0000000..07e2197 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/Python.framework/Versions/2.7/include/python2.7/pyconfig.h @@ -0,0 +1,1267 @@ +/* pyconfig.h. Generated from pyconfig.h.in by configure. */ +/* pyconfig.h.in. Generated from configure.ac by autoheader. */ + + +#ifndef Py_PYCONFIG_H +#define Py_PYCONFIG_H + + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define for AIX if your compiler is a genuine IBM xlC/xlC_r and you want + support for AIX C++ shared extension modules. */ +/* #undef AIX_GENUINE_CPLUSPLUS */ + +/* Define this if you have AtheOS threads. */ +/* #undef ATHEOS_THREADS */ + +/* Define this if you have BeOS threads. */ +/* #undef BEOS_THREADS */ + +/* Define if you have the Mach cthreads package */ +/* #undef C_THREADS */ + +/* Define if C doubles are 64-bit IEEE 754 binary format, stored in ARM + mixed-endian order (byte order 45670123) */ +/* #undef DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754 */ + +/* Define if C doubles are 64-bit IEEE 754 binary format, stored with the most + significant byte first */ +/* #undef DOUBLE_IS_BIG_ENDIAN_IEEE754 */ + +/* Define if C doubles are 64-bit IEEE 754 binary format, stored with the + least significant byte first */ +#define DOUBLE_IS_LITTLE_ENDIAN_IEEE754 1 + +/* Define if --enable-ipv6 is specified */ +#define ENABLE_IPV6 1 + +/* Define if flock needs to be linked with bsd library. */ +/* #undef FLOCK_NEEDS_LIBBSD */ + +/* Define if getpgrp() must be called as getpgrp(0). */ +/* #undef GETPGRP_HAVE_ARG */ + +/* Define if gettimeofday() does not have second (timezone) argument This is + the case on Motorola V4 (R40V4.2) */ +/* #undef GETTIMEOFDAY_NO_TZ */ + +/* Define to 1 if you have the `acosh' function. */ +#define HAVE_ACOSH 1 + +/* struct addrinfo (netdb.h) */ +#define HAVE_ADDRINFO 1 + +/* Define to 1 if you have the `alarm' function. */ +#define HAVE_ALARM 1 + +/* Define this if your time.h defines altzone. */ +/* #undef HAVE_ALTZONE */ + +/* Define to 1 if you have the `asinh' function. */ +#define HAVE_ASINH 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ASM_TYPES_H */ + +/* Define to 1 if you have the `atanh' function. */ +#define HAVE_ATANH 1 + +/* Define if GCC supports __attribute__((format(PyArg_ParseTuple, 2, 3))) */ +/* #undef HAVE_ATTRIBUTE_FORMAT_PARSETUPLE */ + +/* Define to 1 if you have the `bind_textdomain_codeset' function. */ +/* #undef HAVE_BIND_TEXTDOMAIN_CODESET */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_BLUETOOTH_BLUETOOTH_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_BLUETOOTH_H */ + +/* Define if nice() returns success/failure instead of the new priority. */ +/* #undef HAVE_BROKEN_NICE */ + +/* Define if the system reports an invalid PIPE_BUF value. */ +/* #undef HAVE_BROKEN_PIPE_BUF */ + +/* Define if poll() sets errno on invalid file descriptors. */ +/* #undef HAVE_BROKEN_POLL */ + +/* Define if the Posix semaphores do not work on your system */ +/* #undef HAVE_BROKEN_POSIX_SEMAPHORES */ + +/* Define if pthread_sigmask() does not work on your system. */ +/* #undef HAVE_BROKEN_PTHREAD_SIGMASK */ + +/* define to 1 if your sem_getvalue is broken. */ +#define HAVE_BROKEN_SEM_GETVALUE 1 + +/* Define if `unsetenv` does not return an int. */ +/* #undef HAVE_BROKEN_UNSETENV */ + +/* Define this if you have the type _Bool. */ +#define HAVE_C99_BOOL 1 + +/* Define to 1 if you have the 'chflags' function. */ +#define HAVE_CHFLAGS 1 + +/* Define to 1 if you have the `chown' function. */ +#define HAVE_CHOWN 1 + +/* Define if you have the 'chroot' function. */ +#define HAVE_CHROOT 1 + +/* Define to 1 if you have the `clock' function. */ +#define HAVE_CLOCK 1 + +/* Define to 1 if you have the `confstr' function. */ +#define HAVE_CONFSTR 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CONIO_H */ + +/* Define to 1 if you have the `copysign' function. */ +#define HAVE_COPYSIGN 1 + +/* Define to 1 if you have the `ctermid' function. */ +#define HAVE_CTERMID 1 + +/* Define if you have the 'ctermid_r' function. */ +#define HAVE_CTERMID_R 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CURSES_H 1 + +/* Define if you have the 'is_term_resized' function. */ +#define HAVE_CURSES_IS_TERM_RESIZED 1 + +/* Define if you have the 'resizeterm' function. */ +#define HAVE_CURSES_RESIZETERM 1 + +/* Define if you have the 'resize_term' function. */ +#define HAVE_CURSES_RESIZE_TERM 1 + +/* Define to 1 if you have the declaration of `isfinite', and to 0 if you + don't. */ +#define HAVE_DECL_ISFINITE 1 + +/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't. + */ +#define HAVE_DECL_ISINF 1 + +/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't. + */ +#define HAVE_DECL_ISNAN 1 + +/* Define to 1 if you have the declaration of `tzname', and to 0 if you don't. + */ +/* #undef HAVE_DECL_TZNAME */ + +/* Define to 1 if you have the device macros. */ +#define HAVE_DEVICE_MACROS 1 + +/* Define to 1 if you have the /dev/ptc device file. */ +/* #undef HAVE_DEV_PTC */ + +/* Define to 1 if you have the /dev/ptmx device file. */ +#define HAVE_DEV_PTMX 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DIRECT_H */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#define HAVE_DIRENT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `dlopen' function. */ +#define HAVE_DLOPEN 1 + +/* Define to 1 if you have the `dup2' function. */ +#define HAVE_DUP2 1 + +/* Defined when any dynamic module loading is enabled. */ +#define HAVE_DYNAMIC_LOADING 1 + +/* Define if you have the 'epoll' functions. */ +/* #undef HAVE_EPOLL */ + +/* Define to 1 if you have the `erf' function. */ +#define HAVE_ERF 1 + +/* Define to 1 if you have the `erfc' function. */ +#define HAVE_ERFC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the `execv' function. */ +#define HAVE_EXECV 1 + +/* Define to 1 if you have the `expm1' function. */ +#define HAVE_EXPM1 1 + +/* Define if you have the 'fchdir' function. */ +#define HAVE_FCHDIR 1 + +/* Define to 1 if you have the `fchmod' function. */ +#define HAVE_FCHMOD 1 + +/* Define to 1 if you have the `fchown' function. */ +#define HAVE_FCHOWN 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the 'fdatasync' function. */ +/* #undef HAVE_FDATASYNC */ + +/* Define to 1 if you have the `finite' function. */ +#define HAVE_FINITE 1 + +/* Define to 1 if you have the `flock' function. */ +#define HAVE_FLOCK 1 + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Define to 1 if you have the `forkpty' function. */ +#define HAVE_FORKPTY 1 + +/* Define to 1 if you have the `fpathconf' function. */ +#define HAVE_FPATHCONF 1 + +/* Define to 1 if you have the `fseek64' function. */ +/* #undef HAVE_FSEEK64 */ + +/* Define to 1 if you have the `fseeko' function. */ +#define HAVE_FSEEKO 1 + +/* Define to 1 if you have the `fstatvfs' function. */ +#define HAVE_FSTATVFS 1 + +/* Define if you have the 'fsync' function. */ +#define HAVE_FSYNC 1 + +/* Define to 1 if you have the `ftell64' function. */ +/* #undef HAVE_FTELL64 */ + +/* Define to 1 if you have the `ftello' function. */ +#define HAVE_FTELLO 1 + +/* Define to 1 if you have the `ftime' function. */ +#define HAVE_FTIME 1 + +/* Define to 1 if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the `gai_strerror' function. */ +#define HAVE_GAI_STRERROR 1 + +/* Define to 1 if you have the `gamma' function. */ +#define HAVE_GAMMA 1 + +/* Define if we can use gcc inline assembler to get and set x87 control word + */ +#define HAVE_GCC_ASM_FOR_X87 1 + +/* Define if you have the getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `getcwd' function. */ +#define HAVE_GETCWD 1 + +/* Define this if you have flockfile(), getc_unlocked(), and funlockfile() */ +#define HAVE_GETC_UNLOCKED 1 + +/* Define to 1 if you have the `getgroups' function. */ +#define HAVE_GETGROUPS 1 + +/* Define to 1 if you have the `gethostbyname' function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define this if you have some version of gethostbyname_r() */ +/* #undef HAVE_GETHOSTBYNAME_R */ + +/* Define this if you have the 3-arg version of gethostbyname_r(). */ +/* #undef HAVE_GETHOSTBYNAME_R_3_ARG */ + +/* Define this if you have the 5-arg version of gethostbyname_r(). */ +/* #undef HAVE_GETHOSTBYNAME_R_5_ARG */ + +/* Define this if you have the 6-arg version of gethostbyname_r(). */ +/* #undef HAVE_GETHOSTBYNAME_R_6_ARG */ + +/* Define to 1 if you have the `getitimer' function. */ +#define HAVE_GETITIMER 1 + +/* Define to 1 if you have the `getloadavg' function. */ +#define HAVE_GETLOADAVG 1 + +/* Define to 1 if you have the `getlogin' function. */ +#define HAVE_GETLOGIN 1 + +/* Define to 1 if you have the `getnameinfo' function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define if you have the 'getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define to 1 if you have the `getpeername' function. */ +#define HAVE_GETPEERNAME 1 + +/* Define to 1 if you have the `getpgid' function. */ +#define HAVE_GETPGID 1 + +/* Define to 1 if you have the `getpgrp' function. */ +#define HAVE_GETPGRP 1 + +/* Define to 1 if you have the `getpid' function. */ +#define HAVE_GETPID 1 + +/* Define to 1 if you have the `getpriority' function. */ +#define HAVE_GETPRIORITY 1 + +/* Define to 1 if you have the `getpwent' function. */ +#define HAVE_GETPWENT 1 + +/* Define to 1 if you have the `getresgid' function. */ +/* #undef HAVE_GETRESGID */ + +/* Define to 1 if you have the `getresuid' function. */ +/* #undef HAVE_GETRESUID */ + +/* Define to 1 if you have the `getsid' function. */ +#define HAVE_GETSID 1 + +/* Define to 1 if you have the `getspent' function. */ +/* #undef HAVE_GETSPENT */ + +/* Define to 1 if you have the `getspnam' function. */ +/* #undef HAVE_GETSPNAM */ + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `getwd' function. */ +#define HAVE_GETWD 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_GRP_H 1 + +/* Define if you have the 'hstrerror' function. */ +#define HAVE_HSTRERROR 1 + +/* Define to 1 if you have the `hypot' function. */ +#define HAVE_HYPOT 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IEEEFP_H */ + +/* Define if you have the 'inet_aton' function. */ +#define HAVE_INET_ATON 1 + +/* Define if you have the 'inet_pton' function. */ +#define HAVE_INET_PTON 1 + +/* Define to 1 if you have the `initgroups' function. */ +#define HAVE_INITGROUPS 1 + +/* Define if your compiler provides int32_t. */ +#define HAVE_INT32_T 1 + +/* Define if your compiler provides int64_t. */ +#define HAVE_INT64_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IO_H */ + +/* Define to 1 if you have the `kill' function. */ +#define HAVE_KILL 1 + +/* Define to 1 if you have the `killpg' function. */ +#define HAVE_KILLPG 1 + +/* Define if you have the 'kqueue' functions. */ +#define HAVE_KQUEUE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LANGINFO_H 1 + +/* Defined to enable large file support when an off_t is bigger than a long + and long long is available and at least as big as an off_t. You may need to + add some flags for configuration and compilation to enable this mode. (For + Solaris and Linux, the necessary defines are already defined.) */ +/* #undef HAVE_LARGEFILE_SUPPORT */ + +/* Define to 1 if you have the 'lchflags' function. */ +#define HAVE_LCHFLAGS 1 + +/* Define to 1 if you have the `lchmod' function. */ +#define HAVE_LCHMOD 1 + +/* Define to 1 if you have the `lchown' function. */ +#define HAVE_LCHOWN 1 + +/* Define to 1 if you have the `lgamma' function. */ +#define HAVE_LGAMMA 1 + +/* Define to 1 if you have the `dl' library (-ldl). */ +#define HAVE_LIBDL 1 + +/* Define to 1 if you have the `dld' library (-ldld). */ +/* #undef HAVE_LIBDLD */ + +/* Define to 1 if you have the `ieee' library (-lieee). */ +/* #undef HAVE_LIBIEEE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBINTL_H */ + +/* Define if you have the readline library (-lreadline). */ +#define HAVE_LIBREADLINE 1 + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +/* #undef HAVE_LIBRESOLV */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBUTIL_H */ + +/* Define if you have the 'link' function. */ +#define HAVE_LINK 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_NETLINK_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_TIPC_H */ + +/* Define to 1 if you have the `log1p' function. */ +#define HAVE_LOG1P 1 + +/* Define this if you have the type long double. */ +#define HAVE_LONG_DOUBLE 1 + +/* Define this if you have the type long long. */ +#define HAVE_LONG_LONG 1 + +/* Define to 1 if you have the `lstat' function. */ +#define HAVE_LSTAT 1 + +/* Define this if you have the makedev macro. */ +#define HAVE_MAKEDEV 1 + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mkfifo' function. */ +#define HAVE_MKFIFO 1 + +/* Define to 1 if you have the `mknod' function. */ +#define HAVE_MKNOD 1 + +/* Define to 1 if you have the `mktime' function. */ +#define HAVE_MKTIME 1 + +/* Define to 1 if you have the `mremap' function. */ +/* #undef HAVE_MREMAP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_NCURSES_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +/* #undef HAVE_NDIR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETPACKET_PACKET_H */ + +/* Define to 1 if you have the `nice' function. */ +#define HAVE_NICE 1 + +/* Define to 1 if you have the `openpty' function. */ +#define HAVE_OPENPTY 1 + +/* Define if compiling using MacOS X 10.5 SDK or later. */ +#define HAVE_OSX105_SDK 1 + +/* Define to 1 if you have the `pathconf' function. */ +#define HAVE_PATHCONF 1 + +/* Define to 1 if you have the `pause' function. */ +#define HAVE_PAUSE 1 + +/* Define to 1 if you have the `plock' function. */ +/* #undef HAVE_PLOCK */ + +/* Define to 1 if you have the `poll' function. */ +#undef HAVE_POLL + +/* Define to 1 if you have the header file. */ +#undef HAVE_POLL_H + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PROCESS_H */ + +/* Define if your compiler supports function prototype */ +#define HAVE_PROTOTYPES 1 + +/* Define if you have GNU PTH threads. */ +/* #undef HAVE_PTH */ + +/* Defined for Solaris 2.6 bug in pthread header. */ +/* #undef HAVE_PTHREAD_DESTRUCTOR */ + +/* Define to 1 if you have the header file. */ +#define HAVE_PTHREAD_H 1 + +/* Define to 1 if you have the `pthread_init' function. */ +#define HAVE_PTHREAD_INIT 1 + +/* Define to 1 if you have the `pthread_sigmask' function. */ +#define HAVE_PTHREAD_SIGMASK 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PTY_H */ + +/* Define to 1 if you have the `putenv' function. */ +#define HAVE_PUTENV 1 + +/* Define to 1 if you have the `readlink' function. */ +#define HAVE_READLINK 1 + +/* Define to 1 if you have the `realpath' function. */ +#define HAVE_REALPATH 1 + +/* Define if you have readline 2.1 */ +#define HAVE_RL_CALLBACK 1 + +/* Define if you can turn off readline's signal handling. */ +#define HAVE_RL_CATCH_SIGNAL 1 + +/* Define if you have readline 2.2 */ +#define HAVE_RL_COMPLETION_APPEND_CHARACTER 1 + +/* Define if you have readline 4.0 */ +#define HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK 1 + +/* Define if you have readline 4.2 */ +#define HAVE_RL_COMPLETION_MATCHES 1 + +/* Define if you have rl_completion_suppress_append */ +#define HAVE_RL_COMPLETION_SUPPRESS_APPEND 1 + +/* Define if you have readline 4.0 */ +#define HAVE_RL_PRE_INPUT_HOOK 1 + +/* Define to 1 if you have the `round' function. */ +#define HAVE_ROUND 1 + +/* Define to 1 if you have the `select' function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the `sem_getvalue' function. */ +#define HAVE_SEM_GETVALUE 1 + +/* Define to 1 if you have the `sem_open' function. */ +#define HAVE_SEM_OPEN 1 + +/* Define to 1 if you have the `sem_timedwait' function. */ +/* #undef HAVE_SEM_TIMEDWAIT */ + +/* Define to 1 if you have the `sem_unlink' function. */ +#define HAVE_SEM_UNLINK 1 + +/* Define to 1 if you have the `setegid' function. */ +#define HAVE_SETEGID 1 + +/* Define to 1 if you have the `seteuid' function. */ +#define HAVE_SETEUID 1 + +/* Define to 1 if you have the `setgid' function. */ +#define HAVE_SETGID 1 + +/* Define if you have the 'setgroups' function. */ +#define HAVE_SETGROUPS 1 + +/* Define to 1 if you have the `setitimer' function. */ +#define HAVE_SETITIMER 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setpgid' function. */ +#define HAVE_SETPGID 1 + +/* Define to 1 if you have the `setpgrp' function. */ +#define HAVE_SETPGRP 1 + +/* Define to 1 if you have the `setregid' function. */ +#define HAVE_SETREGID 1 + +/* Define to 1 if you have the `setresgid' function. */ +/* #undef HAVE_SETRESGID */ + +/* Define to 1 if you have the `setresuid' function. */ +/* #undef HAVE_SETRESUID */ + +/* Define to 1 if you have the `setreuid' function. */ +#define HAVE_SETREUID 1 + +/* Define to 1 if you have the `setsid' function. */ +#define HAVE_SETSID 1 + +/* Define to 1 if you have the `setuid' function. */ +#define HAVE_SETUID 1 + +/* Define to 1 if you have the `setvbuf' function. */ +#define HAVE_SETVBUF 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SHADOW_H */ + +/* Define to 1 if you have the `sigaction' function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the `siginterrupt' function. */ +#define HAVE_SIGINTERRUPT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the `sigrelse' function. */ +#define HAVE_SIGRELSE 1 + +/* Define to 1 if you have the `snprintf' function. */ +#define HAVE_SNPRINTF 1 + +/* Define if sockaddr has sa_len member */ +#define HAVE_SOCKADDR_SA_LEN 1 + +/* struct sockaddr_storage (sys/socket.h) */ +#define HAVE_SOCKADDR_STORAGE 1 + +/* Define if you have the 'socketpair' function. */ +#define HAVE_SOCKETPAIR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SPAWN_H 1 + +/* Define if your compiler provides ssize_t */ +#define HAVE_SSIZE_T 1 + +/* Define to 1 if you have the `statvfs' function. */ +#define HAVE_STATVFS 1 + +/* Define if you have struct stat.st_mtim.tv_nsec */ +/* #undef HAVE_STAT_TV_NSEC */ + +/* Define if you have struct stat.st_mtimensec */ +#define HAVE_STAT_TV_NSEC2 1 + +/* Define if your compiler supports variable length function prototypes (e.g. + void fprintf(FILE *, char *, ...);) *and* */ +#define HAVE_STDARG_PROTOTYPES 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strftime' function. */ +#define HAVE_STRFTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STROPTS_H */ + +/* Define to 1 if `st_birthtime' is a member of `struct stat'. */ +#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1 + +/* Define to 1 if `st_blksize' is a member of `struct stat'. */ +#define HAVE_STRUCT_STAT_ST_BLKSIZE 1 + +/* Define to 1 if `st_blocks' is a member of `struct stat'. */ +#define HAVE_STRUCT_STAT_ST_BLOCKS 1 + +/* Define to 1 if `st_flags' is a member of `struct stat'. */ +#define HAVE_STRUCT_STAT_ST_FLAGS 1 + +/* Define to 1 if `st_gen' is a member of `struct stat'. */ +#define HAVE_STRUCT_STAT_ST_GEN 1 + +/* Define to 1 if `st_rdev' is a member of `struct stat'. */ +#define HAVE_STRUCT_STAT_ST_RDEV 1 + +/* Define to 1 if `tm_zone' is a member of `struct tm'. */ +#define HAVE_STRUCT_TM_TM_ZONE 1 + +/* Define to 1 if your `struct stat' has `st_blocks'. Deprecated, use + `HAVE_STRUCT_STAT_ST_BLOCKS' instead. */ +#define HAVE_ST_BLOCKS 1 + +/* Define if you have the 'symlink' function. */ +#define HAVE_SYMLINK 1 + +/* Define to 1 if you have the `sysconf' function. */ +#define HAVE_SYSCONF 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYSEXITS_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_AUDIOIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_BSDTTY_H */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_DIR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_EPOLL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_EVENT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILE_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_LOADAVG_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_LOCK_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_MKDEV_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_MODEM_H */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_NDIR_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STATVFS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_TERMIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIMES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UTSNAME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the `tcgetpgrp' function. */ +#define HAVE_TCGETPGRP 1 + +/* Define to 1 if you have the `tcsetpgrp' function. */ +#define HAVE_TCSETPGRP 1 + +/* Define to 1 if you have the `tempnam' function. */ +#define HAVE_TEMPNAM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERM_H 1 + +/* Define to 1 if you have the `tgamma' function. */ +#define HAVE_TGAMMA 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_THREAD_H */ + +/* Define to 1 if you have the `timegm' function. */ +#define HAVE_TIMEGM 1 + +/* Define to 1 if you have the `times' function. */ +#define HAVE_TIMES 1 + +/* Define to 1 if you have the `tmpfile' function. */ +#define HAVE_TMPFILE 1 + +/* Define to 1 if you have the `tmpnam' function. */ +#define HAVE_TMPNAM 1 + +/* Define to 1 if you have the `tmpnam_r' function. */ +/* #undef HAVE_TMPNAM_R */ + +/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use + `HAVE_STRUCT_TM_TM_ZONE' instead. */ +#define HAVE_TM_ZONE 1 + +/* Define to 1 if you have the `truncate' function. */ +#define HAVE_TRUNCATE 1 + +/* Define to 1 if you don't have `tm_zone' but do have the external array + `tzname'. */ +/* #undef HAVE_TZNAME */ + +/* Define this if you have tcl and TCL_UTF_MAX==6 */ +/* #undef HAVE_UCS4_TCL */ + +/* Define if your compiler provides uint32_t. */ +#define HAVE_UINT32_T 1 + +/* Define if your compiler provides uint64_t. */ +#define HAVE_UINT64_T 1 + +/* Define to 1 if the system has the type `uintptr_t'. */ +#define HAVE_UINTPTR_T 1 + +/* Define to 1 if you have the `uname' function. */ +#define HAVE_UNAME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `unsetenv' function. */ +#define HAVE_UNSETENV 1 + +/* Define if you have a useable wchar_t type defined in wchar.h; useable means + wchar_t must be an unsigned type with at least 16 bits. (see + Include/unicodeobject.h). */ +/* #undef HAVE_USABLE_WCHAR_T */ + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIL_H 1 + +/* Define to 1 if you have the `utimes' function. */ +#define HAVE_UTIMES 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if you have the `wait3' function. */ +#define HAVE_WAIT3 1 + +/* Define to 1 if you have the `wait4' function. */ +#define HAVE_WAIT4 1 + +/* Define to 1 if you have the `waitpid' function. */ +#define HAVE_WAITPID 1 + +/* Define if the compiler provides a wchar.h header file. */ +#define HAVE_WCHAR_H 1 + +/* Define to 1 if you have the `wcscoll' function. */ +#define HAVE_WCSCOLL 1 + +/* Define if tzset() actually switches the local timezone in a meaningful way. + */ +#define HAVE_WORKING_TZSET 1 + +/* Define if the zlib library has inflateCopy */ +#define HAVE_ZLIB_COPY 1 + +/* Define to 1 if you have the `_getpty' function. */ +/* #undef HAVE__GETPTY */ + +/* Define if you are using Mach cthreads directly under /include */ +/* #undef HURD_C_THREADS */ + +/* Define if you are using Mach cthreads under mach / */ +/* #undef MACH_C_THREADS */ + +/* Define to 1 if `major', `minor', and `makedev' are declared in . + */ +/* #undef MAJOR_IN_MKDEV */ + +/* Define to 1 if `major', `minor', and `makedev' are declared in + . */ +/* #undef MAJOR_IN_SYSMACROS */ + +/* Define if mvwdelch in curses.h is an expression. */ +#define MVWDELCH_IS_EXPRESSION 1 + +/* Define to the address where bug reports for this package should be sent. */ +/* #undef PACKAGE_BUGREPORT */ + +/* Define to the full name of this package. */ +/* #undef PACKAGE_NAME */ + +/* Define to the full name and version of this package. */ +/* #undef PACKAGE_STRING */ + +/* Define to the one symbol short name of this package. */ +/* #undef PACKAGE_TARNAME */ + +/* Define to the home page for this package. */ +/* #undef PACKAGE_URL */ + +/* Define to the version of this package. */ +/* #undef PACKAGE_VERSION */ + +/* Define if POSIX semaphores aren't enabled on your system */ +/* #undef POSIX_SEMAPHORES_NOT_ENABLED */ + +/* Defined if PTHREAD_SCOPE_SYSTEM supported. */ +#define PTHREAD_SYSTEM_SCHED_SUPPORTED 1 + +/* Define as the preferred size in bits of long digits */ +/* #undef PYLONG_BITS_IN_DIGIT */ + +/* Define to printf format modifier for long long type */ +#define PY_FORMAT_LONG_LONG "ll" + +/* Define to printf format modifier for Py_ssize_t */ +#define PY_FORMAT_SIZE_T "z" + +/* Define as the integral type used for Unicode representation. */ +#define PY_UNICODE_TYPE unsigned short + +/* Define if you want to build an interpreter with many run-time checks. */ +/* #undef Py_DEBUG */ + +/* Defined if Python is built as a shared library. */ +/* #undef Py_ENABLE_SHARED */ + +/* Define as the size of the unicode type. */ +#define Py_UNICODE_SIZE 2 + +/* Define if you want to have a Unicode type. */ +#define Py_USING_UNICODE 1 + +/* assume C89 semantics that RETSIGTYPE is always void */ +#define RETSIGTYPE void + +/* Define if setpgrp() must be called as setpgrp(0, 0). */ +/* #undef SETPGRP_HAVE_ARG */ + +/* Define this to be extension of shared libraries (including the dot!). */ +#define SHLIB_EXT ".so" + +/* Define if i>>j for signed int i does not extend the sign bit when i < 0 */ +/* #undef SIGNED_RIGHT_SHIFT_ZERO_FILLS */ + +/* The size of `double', as computed by sizeof. */ +#define SIZEOF_DOUBLE 8 + +/* The size of `float', as computed by sizeof. */ +#define SIZEOF_FLOAT 4 + +/* The size of `fpos_t', as computed by sizeof. */ +#define SIZEOF_FPOS_T 8 + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 8 + +/* The size of `long double', as computed by sizeof. */ +#define SIZEOF_LONG_DOUBLE 16 + +/* The size of `long long', as computed by sizeof. */ +#define SIZEOF_LONG_LONG 8 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `pid_t', as computed by sizeof. */ +#define SIZEOF_PID_T 4 + +/* The size of `pthread_t', as computed by sizeof. */ +#define SIZEOF_PTHREAD_T 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 8 + +/* The size of `uintptr_t', as computed by sizeof. */ +#define SIZEOF_UINTPTR_T 8 + +/* The size of `void *', as computed by sizeof. */ +#define SIZEOF_VOID_P 8 + +/* The size of `wchar_t', as computed by sizeof. */ +#define SIZEOF_WCHAR_T 4 + +/* The size of `_Bool', as computed by sizeof. */ +#define SIZEOF__BOOL 1 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and + (which you can't on SCO ODT 3.0). */ +#define SYS_SELECT_WITH_SYS_TIME 1 + +/* Define if tanh(-0.) is -0., or if platform doesn't have signed zeros */ +#define TANH_PRESERVES_ZERO_SIGN 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to 1 if your declares `struct tm'. */ +/* #undef TM_IN_SYS_TIME */ + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif + + +/* Define if you want to use MacPython modules on MacOSX in unix-Python. */ +#define USE_TOOLBOX_OBJECT_GLUE 1 + +/* Define if a va_list is an array of some kind */ +#define VA_LIST_IS_ARRAY 1 + +/* Define if you want SIGFPE handled (see Include/pyfpe.h). */ +/* #undef WANT_SIGFPE_HANDLER */ + +/* Define if you want wctype.h functions to be used instead of the one + supplied by Python itself. (see Include/unicodectype.h). */ +/* #undef WANT_WCTYPE_FUNCTIONS */ + +/* Define if WINDOW in curses.h offers a field _flags. */ +/* #undef WINDOW_HAS_FLAGS */ + +/* Define if you want documentation strings in extension modules */ +#define WITH_DOC_STRINGS 1 + +/* Define if you want to use the new-style (Openstep, Rhapsody, MacOS) dynamic + linker (dyld) instead of the old-style (NextStep) dynamic linker (rld). + Dyld is necessary to support frameworks. */ +#define WITH_DYLD 1 + +/* Define to 1 if libintl is needed for locale functions. */ +/* #undef WITH_LIBINTL */ + +/* Define if you want to produce an OpenStep/Rhapsody framework (shared + library plus accessory files). */ +#define WITH_NEXT_FRAMEWORK 1 + +/* Define if you want to compile in Python-specific mallocs */ +#define WITH_PYMALLOC 1 + +/* Define if you want to compile in rudimentary thread support */ +#define WITH_THREAD 1 + +/* Define to profile with the Pentium timestamp counter */ +/* #undef WITH_TSC */ + +/* Define if you want pymalloc to be disabled when running under valgrind */ +/* #undef WITH_VALGRIND */ + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define if arithmetic is subject to x87-style double rounding issue */ +/* #undef X87_DOUBLE_ROUNDING */ + +/* Define on OpenBSD to activate all library features */ +/* #undef _BSD_SOURCE */ + +/* Define on Irix to enable u_int */ +#define _BSD_TYPES 1 + +/* Define on Darwin to activate all library features */ +#define _DARWIN_C_SOURCE 1 + +/* This must be set to 64 on some systems to enable large file support. */ +#define _FILE_OFFSET_BITS 64 + +/* Define on Linux to activate all library features */ +#define _GNU_SOURCE 1 + +/* This must be defined on some systems to enable large file support. */ +#define _LARGEFILE_SOURCE 1 + +/* This must be defined on AIX systems to enable large file support. */ +/* #undef _LARGE_FILES */ + +/* Define to 1 if on MINIX. */ +/* #undef _MINIX */ + +/* Define on NetBSD to activate all library features */ +#define _NETBSD_SOURCE 1 + +/* Define _OSF_SOURCE to get the makedev macro. */ +/* #undef _OSF_SOURCE */ + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +/* #undef _POSIX_1_SOURCE */ + +/* Define to activate features from IEEE Stds 1003.1-2001 */ +/* #undef _POSIX_C_SOURCE */ + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +/* #undef _POSIX_SOURCE */ + +/* Define if you have POSIX threads, and your system does not define that. */ +/* #undef _POSIX_THREADS */ + +/* Define to force use of thread-safe errno, h_errno, and other functions */ +#define _REENTRANT 1 + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT32_T */ + +/* Define for Solaris 2.5.1 so the uint64_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT64_T */ + +/* Define to the level of X/Open that your system supports */ +/* #undef _XOPEN_SOURCE */ + +/* Define to activate Unix95-and-earlier features */ +/* #undef _XOPEN_SOURCE_EXTENDED */ + +/* Define on FreeBSD to activate all library features */ +#define __BSD_VISIBLE 1 + +/* Define to 1 if type `char' is unsigned and you are not using gcc. */ +#ifndef __CHAR_UNSIGNED__ +/* # undef __CHAR_UNSIGNED__ */ +#endif + +/* Defined on Solaris to see additional function prototypes. */ +#define __EXTENSIONS__ 1 + +/* Define to 'long' if doesn't define. */ +/* #undef clock_t */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `int' if doesn't define. */ +/* #undef gid_t */ + +/* Define to the type of a signed integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +/* #undef int32_t */ + +/* Define to the type of a signed integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +/* #undef int64_t */ + +/* Define to `int' if does not define. */ +/* #undef mode_t */ + +/* Define to `long int' if does not define. */ +/* #undef off_t */ + +/* Define to `int' if does not define. */ +/* #undef pid_t */ + +/* Define to empty if the keyword does not work. */ +/* #undef signed */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* Define to `int' if does not define. */ +/* #undef socklen_t */ + +/* Define to `int' if doesn't define. */ +/* #undef uid_t */ + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint32_t */ + +/* Define to the type of an unsigned integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint64_t */ + +/* Define to empty if the keyword does not work. */ +/* #undef volatile */ + + +/* Define the macros needed if on a UnixWare 7.x system. */ +#if defined(__USLC__) && defined(__SCO_VERSION__) +#define STRICT_SYSV_CURSES /* Don't use ncurses extensions */ +#endif + +#endif /*Py_PYCONFIG_H*/ + diff --git a/FeedTheMonkey.app/Contents/Frameworks/Python.framework/Versions/2.7/lib/python2.7/config/Makefile b/FeedTheMonkey.app/Contents/Frameworks/Python.framework/Versions/2.7/lib/python2.7/config/Makefile new file mode 100644 index 0000000..268b2c1 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/Python.framework/Versions/2.7/lib/python2.7/config/Makefile @@ -0,0 +1,1397 @@ +# Generated automatically from Makefile.pre by makesetup. +# Top-level Makefile for Python +# +# As distributed, this file is called Makefile.pre.in; it is processed +# into the real Makefile by running the script ./configure, which +# replaces things like @spam@ with values appropriate for your system. +# This means that if you edit Makefile, your changes get lost the next +# time you run the configure script. Ideally, you can do: +# +# ./configure +# make +# make test +# make install +# +# If you have a previous version of Python installed that you don't +# want to overwrite, you can use "make altinstall" instead of "make +# install". Refer to the "Installing" section in the README file for +# additional details. +# +# See also the section "Build instructions" in the README file. + +# === Variables set by makesetup === + +MODOBJS= Modules/threadmodule.o Modules/signalmodule.o Modules/posixmodule.o Modules/errnomodule.o Modules/pwdmodule.o Modules/_sre.o Modules/_codecsmodule.o Modules/_weakref.o Modules/zipimport.o Modules/symtablemodule.o Modules/xxsubtype.o +MODLIBS= $(LOCALMODLIBS) $(BASEMODLIBS) + +# === Variables set by configure +VERSION= 2.7 +srcdir= . + +abs_srcdir= /private/tmp/python-Yar9/Python-2.7.5 +abs_builddir= /private/tmp/python-Yar9/Python-2.7.5 +build= x86_64-apple-darwin12.5.0 +host= x86_64-apple-darwin12.5.0 + +CC= cc +CXX= c++ +MAINCC= $(CC) +LINKCC= $(PURIFY) $(MAINCC) +AR= ar +RANLIB= ranlib +SVNVERSION= svnversion $(srcdir) +HGVERSION= +HGTAG= +HGBRANCH= + +GNULD= no + +# Shell used by make (some versions default to the login shell, which is bad) +SHELL= /bin/sh + +# Use this to make a link between python$(VERSION) and python in $(BINDIR) +LN= ln + +# Portable install script (configure doesn't always guess right) +INSTALL= /usr/bin/install -c +INSTALL_PROGRAM=${INSTALL} +INSTALL_SCRIPT= ${INSTALL} +INSTALL_DATA= ${INSTALL} -m 644 +# Shared libraries must be installed with executable mode on some systems; +# rather than figuring out exactly which, we always give them executable mode. +# Also, making them read-only seems to be a good idea... +INSTALL_SHARED= ${INSTALL} -m 555 + +MKDIR_P= ./install-sh -c -d + +MAKESETUP= $(srcdir)/Modules/makesetup + +# Compiler options +OPT= -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes +BASECFLAGS= -fno-strict-aliasing -fno-common -dynamic +CFLAGS= $(BASECFLAGS) -I/usr/local/include -I/usr/local/opt/sqlite/include $(OPT) $(EXTRA_CFLAGS) +# Both CPPFLAGS and LDFLAGS need to contain the shell's value for setup.py to +# be able to build extension modules using the directories specified in the +# environment variables +CPPFLAGS= -I. -IInclude -I$(srcdir)/Include +LDFLAGS= -L/usr/local/lib -L/usr/local/opt/sqlite/lib +LDLAST= +SGI_ABI= +CCSHARED= +LINKFORSHARED=-u _PyMac_Error $(PYTHONFRAMEWORKINSTALLDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK) +ARFLAGS= rc +# Extra C flags added for building the interpreter object files. +CFLAGSFORSHARED=$(CCSHARED) +# C flags used for building the interpreter object files +PY_CFLAGS= $(CFLAGS) $(CPPFLAGS) $(CFLAGSFORSHARED) -DPy_BUILD_CORE + + +# Machine-dependent subdirectories +MACHDEP= darwin + +# Multiarch directory (may be empty) +MULTIARCH= + +# Install prefix for architecture-independent files +prefix= /usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7 + +# Install prefix for architecture-dependent files +exec_prefix= ${prefix} + +# Install prefix for data files +datarootdir= /usr/local/Cellar/python/2.7.5/share + +# Expanded directories +BINDIR= ${exec_prefix}/bin +LIBDIR= ${exec_prefix}/lib +MANDIR= ${datarootdir}/man +INCLUDEDIR= ${prefix}/include +CONFINCLUDEDIR= $(exec_prefix)/include +SCRIPTDIR= $(prefix)/lib + +# Detailed destination directories +BINLIBDEST= $(LIBDIR)/python$(VERSION) +LIBDEST= $(SCRIPTDIR)/python$(VERSION) +INCLUDEPY= $(INCLUDEDIR)/python$(VERSION) +CONFINCLUDEPY= $(CONFINCLUDEDIR)/python$(VERSION) +LIBP= $(LIBDIR)/python$(VERSION) + +# Symbols used for using shared libraries +SO= .so +LDSHARED= $(CC) -bundle -undefined dynamic_lookup $(LDFLAGS) +BLDSHARED= $(CC) -bundle -undefined dynamic_lookup $(LDFLAGS) +LDCXXSHARED= $(CXX) -bundle -undefined dynamic_lookup +DESTSHARED= $(BINLIBDEST)/lib-dynload + +# Executable suffix (.exe on Windows and Mac OS X) +EXE= +BUILDEXE= .exe + +# Short name and location for Mac OS X Python framework +UNIVERSALSDK= +PYTHONFRAMEWORK= Python +PYTHONFRAMEWORKDIR= Python.framework +PYTHONFRAMEWORKPREFIX= /usr/local/Cellar/python/2.7.5/Frameworks +PYTHONFRAMEWORKINSTALLDIR= /usr/local/Cellar/python/2.7.5/Frameworks/Python.framework +# Deployment target selected during configure, to be checked +# by distutils. The export statement is needed to ensure that the +# deployment target is active during build. +MACOSX_DEPLOYMENT_TARGET=10.8 +export MACOSX_DEPLOYMENT_TARGET + +# Options to enable prebinding (for fast startup prior to Mac OS X 10.3) +OTHER_LIBTOOL_OPT= + +# Environment to run shared python without installed libraries +RUNSHARED= DYLD_FRAMEWORK_PATH=/private/tmp/python-Yar9/Python-2.7.5: + +# Modes for directories, executables and data files created by the +# install process. Default to user-only-writable for all file types. +DIRMODE= 755 +EXEMODE= 755 +FILEMODE= 644 + +# configure script arguments +CONFIG_ARGS= '--prefix=/usr/local/Cellar/python/2.7.5' '--enable-ipv6' '--datarootdir=/usr/local/Cellar/python/2.7.5/share' '--datadir=/usr/local/Cellar/python/2.7.5/share' '--enable-framework=/usr/local/Cellar/python/2.7.5/Frameworks' '--without-gcc' 'CFLAGS=-I/usr/local/include -I/usr/local/opt/sqlite/include' 'LDFLAGS=-L/usr/local/lib -L/usr/local/opt/sqlite/lib' 'MACOSX_DEPLOYMENT_TARGET=10.8' 'CC=cc' + + +# Subdirectories with code +SRCDIRS= Parser Grammar Objects Python Modules Mac + +# Other subdirectories +SUBDIRSTOO= Include Lib Misc Demo + +# Files and directories to be distributed +CONFIGFILES= configure configure.ac acconfig.h pyconfig.h.in Makefile.pre.in +DISTFILES= README ChangeLog $(CONFIGFILES) +DISTDIRS= $(SUBDIRS) $(SUBDIRSTOO) Ext-dummy +DIST= $(DISTFILES) $(DISTDIRS) + + +LIBRARY= libpython$(VERSION).a +LDLIBRARY= $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK) +BLDLIBRARY= +DLLLIBRARY= +LDLIBRARYDIR= +INSTSONAME= $(LDLIBRARY) + + +LIBS= -ldl -framework CoreFoundation +LIBM= +LIBC= +SYSLIBS= $(LIBM) $(LIBC) +SHLIBS= $(LIBS) + +THREADOBJ= Python/thread.o +DLINCLDIR= . +DYNLOADFILE= dynload_shlib.o +MACHDEP_OBJS= Python/mactoolboxglue.o +LIBOBJDIR= Python/ +LIBOBJS= +UNICODE_OBJS= Objects/unicodeobject.o Objects/unicodectype.o + +PYTHON= python$(EXE) +BUILDPYTHON= python$(BUILDEXE) + +PYTHON_FOR_BUILD=./$(BUILDPYTHON) -E +_PYTHON_HOST_PLATFORM= +HOST_GNU_TYPE= x86_64-apple-darwin12.5.0 + +# The task to run while instrument when building the profile-opt target +PROFILE_TASK= $(srcdir)/Tools/pybench/pybench.py -n 2 --with-gc --with-syscheck +#PROFILE_TASK= $(srcdir)/Lib/test/regrtest.py + +# === Definitions added by makesetup === + +LOCALMODLIBS= +BASEMODLIBS= +GLHACK=-Dclear=__GLclear +PYTHONPATH=$(COREPYTHONPATH) +COREPYTHONPATH=$(DESTPATH)$(SITEPATH)$(TESTPATH)$(MACHDEPPATH)$(EXTRAMACHDEPPATH)$(TKPATH)$(OLDPATH) +OLDPATH=:lib-old +TKPATH=:lib-tk +EXTRAMACHDEPPATH= +MACHDEPPATH=:plat-$(MACHDEP) +TESTPATH= +SITEPATH= +DESTPATH= +MACHDESTLIB=$(BINLIBDEST) +DESTLIB=$(LIBDEST) + + +########################################################################## +# Modules +MODULE_OBJS= \ + Modules/config.o \ + Modules/getpath.o \ + Modules/main.o \ + Modules/gcmodule.o + +# Used of signalmodule.o is not available +SIGNAL_OBJS= + + +########################################################################## +# Grammar +GRAMMAR_H= Include/graminit.h +GRAMMAR_C= Python/graminit.c +GRAMMAR_INPUT= $(srcdir)/Grammar/Grammar + + +LIBFFI_INCLUDEDIR= + +########################################################################## +# Parser +PGEN= Parser/pgen$(EXE) + +PSRCS= \ + Parser/acceler.c \ + Parser/grammar1.c \ + Parser/listnode.c \ + Parser/node.c \ + Parser/parser.c \ + Parser/parsetok.c \ + Parser/bitset.c \ + Parser/metagrammar.c \ + Parser/firstsets.c \ + Parser/grammar.c \ + Parser/pgen.c + +POBJS= \ + Parser/acceler.o \ + Parser/grammar1.o \ + Parser/listnode.o \ + Parser/node.o \ + Parser/parser.o \ + Parser/parsetok.o \ + Parser/bitset.o \ + Parser/metagrammar.o \ + Parser/firstsets.o \ + Parser/grammar.o \ + Parser/pgen.o + +PARSER_OBJS= $(POBJS) Parser/myreadline.o Parser/tokenizer.o + +PGSRCS= \ + Objects/obmalloc.c \ + Python/mysnprintf.c \ + Python/pyctype.c \ + Parser/tokenizer_pgen.c \ + Parser/printgrammar.c \ + Parser/pgenmain.c + +PGOBJS= \ + Objects/obmalloc.o \ + Python/mysnprintf.o \ + Python/pyctype.o \ + Parser/tokenizer_pgen.o \ + Parser/printgrammar.o \ + Parser/pgenmain.o + +PARSER_HEADERS= \ + Parser/parser.h \ + Parser/tokenizer.h + +PGENSRCS= $(PSRCS) $(PGSRCS) +PGENOBJS= $(POBJS) $(PGOBJS) + +########################################################################## +# AST +AST_H_DIR= Include +AST_H= $(AST_H_DIR)/Python-ast.h +AST_C_DIR= Python +AST_C= $(AST_C_DIR)/Python-ast.c +AST_ASDL= $(srcdir)/Parser/Python.asdl + +ASDLGEN_FILES= $(srcdir)/Parser/asdl.py $(srcdir)/Parser/asdl_c.py +# XXX Note that a build now requires Python exist before the build starts +ASDLGEN= $(srcdir)/Parser/asdl_c.py + +########################################################################## +# Python +PYTHON_OBJS= \ + Python/_warnings.o \ + Python/Python-ast.o \ + Python/asdl.o \ + Python/ast.o \ + Python/bltinmodule.o \ + Python/ceval.o \ + Python/compile.o \ + Python/codecs.o \ + Python/errors.o \ + Python/frozen.o \ + Python/frozenmain.o \ + Python/future.o \ + Python/getargs.o \ + Python/getcompiler.o \ + Python/getcopyright.o \ + Python/getplatform.o \ + Python/getversion.o \ + Python/graminit.o \ + Python/import.o \ + Python/importdl.o \ + Python/marshal.o \ + Python/modsupport.o \ + Python/mystrtoul.o \ + Python/mysnprintf.o \ + Python/peephole.o \ + Python/pyarena.o \ + Python/pyctype.o \ + Python/pyfpe.o \ + Python/pymath.o \ + Python/pystate.o \ + Python/pythonrun.o \ + Python/random.o \ + Python/structmember.o \ + Python/symtable.o \ + Python/sysmodule.o \ + Python/traceback.o \ + Python/getopt.o \ + Python/pystrcmp.o \ + Python/pystrtod.o \ + Python/dtoa.o \ + Python/formatter_unicode.o \ + Python/formatter_string.o \ + Python/$(DYNLOADFILE) \ + $(LIBOBJS) \ + $(MACHDEP_OBJS) \ + $(THREADOBJ) + + +########################################################################## +# Objects +OBJECT_OBJS= \ + Objects/abstract.o \ + Objects/boolobject.o \ + Objects/bufferobject.o \ + Objects/bytes_methods.o \ + Objects/bytearrayobject.o \ + Objects/capsule.o \ + Objects/cellobject.o \ + Objects/classobject.o \ + Objects/cobject.o \ + Objects/codeobject.o \ + Objects/complexobject.o \ + Objects/descrobject.o \ + Objects/enumobject.o \ + Objects/exceptions.o \ + Objects/genobject.o \ + Objects/fileobject.o \ + Objects/floatobject.o \ + Objects/frameobject.o \ + Objects/funcobject.o \ + Objects/intobject.o \ + Objects/iterobject.o \ + Objects/listobject.o \ + Objects/longobject.o \ + Objects/dictobject.o \ + Objects/memoryobject.o \ + Objects/methodobject.o \ + Objects/moduleobject.o \ + Objects/object.o \ + Objects/obmalloc.o \ + Objects/rangeobject.o \ + Objects/setobject.o \ + Objects/sliceobject.o \ + Objects/stringobject.o \ + Objects/structseq.o \ + Objects/tupleobject.o \ + Objects/typeobject.o \ + Objects/weakrefobject.o \ + $(UNICODE_OBJS) + + +########################################################################## +# objects that get linked into the Python library +LIBRARY_OBJS= \ + Modules/getbuildinfo.o \ + $(PARSER_OBJS) \ + $(OBJECT_OBJS) \ + $(PYTHON_OBJS) \ + $(MODULE_OBJS) \ + $(SIGNAL_OBJS) \ + $(MODOBJS) + +######################################################################### +# Rules + +# Default target +all: build_all +build_all: $(BUILDPYTHON) oldsharedmods sharedmods gdbhooks + +# Compile a binary with gcc profile guided optimization. +profile-opt: + @echo "Building with support for profile generation:" + $(MAKE) clean + $(MAKE) build_all_generate_profile + @echo "Running benchmark to generate profile data:" + $(MAKE) profile-removal + $(MAKE) run_profile_task + @echo "Rebuilding with profile guided optimizations:" + $(MAKE) clean + $(MAKE) build_all_use_profile + +build_all_generate_profile: + $(MAKE) all CFLAGS="$(CFLAGS) -fprofile-generate" LIBS="$(LIBS) -lgcov" + +run_profile_task: + : # FIXME: can't run for a cross build + ./$(BUILDPYTHON) $(PROFILE_TASK) + +build_all_use_profile: + $(MAKE) all CFLAGS="$(CFLAGS) -fprofile-use" + +coverage: + @echo "Building with support for coverage checking:" + $(MAKE) clean + $(MAKE) all CFLAGS="$(CFLAGS) -O0 -pg -fprofile-arcs -ftest-coverage" LIBS="$(LIBS) -lgcov" + + +# Build the interpreter +$(BUILDPYTHON): Modules/python.o $(LIBRARY) $(LDLIBRARY) + $(LINKCC) $(LDFLAGS) $(LINKFORSHARED) -o $@ \ + Modules/python.o \ + $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST) + +platform: $(BUILDPYTHON) pybuilddir.txt + $(RUNSHARED) $(PYTHON_FOR_BUILD) -c 'import sys ; from sysconfig import get_platform ; print get_platform()+"-"+sys.version[0:3]' >platform + +# Create build directory and generate the sysconfig build-time data there. +# pybuilddir.txt contains the name of the build dir and is used for +# sys.path fixup -- see Modules/getpath.c. +pybuilddir.txt: $(BUILDPYTHON) + $(RUNSHARED) $(PYTHON_FOR_BUILD) -S -m sysconfig --generate-posix-vars + +# Build the shared modules +# Under GNU make, MAKEFLAGS are sorted and normalized; the 's' for +# -s, --silent or --quiet is always the first char. +# Under BSD make, MAKEFLAGS might be " -s -v x=y". +sharedmods: $(BUILDPYTHON) pybuilddir.txt + @case "$$MAKEFLAGS" in \ + *\ -s*|s*) quiet="-q";; \ + *) quiet="";; \ + esac; \ + $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ + $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build + +# Build static library +# avoid long command lines, same as LIBRARY_OBJS +$(LIBRARY): $(LIBRARY_OBJS) + -rm -f $@ + $(AR) $(ARFLAGS) $@ Modules/getbuildinfo.o + $(AR) $(ARFLAGS) $@ $(PARSER_OBJS) + $(AR) $(ARFLAGS) $@ $(OBJECT_OBJS) + $(AR) $(ARFLAGS) $@ $(PYTHON_OBJS) + $(AR) $(ARFLAGS) $@ $(MODULE_OBJS) $(SIGNAL_OBJS) + $(AR) $(ARFLAGS) $@ $(MODOBJS) + $(RANLIB) $@ + +libpython$(VERSION).so: $(LIBRARY_OBJS) + if test $(INSTSONAME) != $(LDLIBRARY); then \ + $(BLDSHARED) -Wl,-h$(INSTSONAME) -o $(INSTSONAME) $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \ + $(LN) -f $(INSTSONAME) $@; \ + else \ + $(BLDSHARED) -o $@ $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \ + fi + +libpython$(VERSION).dylib: $(LIBRARY_OBJS) + $(CC) -dynamiclib -Wl,-single_module $(LDFLAGS) -undefined dynamic_lookup -Wl,-install_name,$(prefix)/lib/libpython$(VERSION).dylib -Wl,-compatibility_version,$(VERSION) -Wl,-current_version,$(VERSION) -o $@ $(LIBRARY_OBJS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \ + + +libpython$(VERSION).sl: $(LIBRARY_OBJS) + $(LDSHARED) -o $@ $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST) + +# Copy up the gdb python hooks into a position where they can be automatically +# loaded by gdb during Lib/test/test_gdb.py +# +# Distributors are likely to want to install this somewhere else e.g. relative +# to the stripped DWARF data for the shared library. +gdbhooks: $(BUILDPYTHON)-gdb.py + +SRC_GDB_HOOKS=$(srcdir)/Tools/gdb/libpython.py +$(BUILDPYTHON)-gdb.py: $(SRC_GDB_HOOKS) + $(INSTALL_DATA) $(SRC_GDB_HOOKS) $(BUILDPYTHON)-gdb.py + +# This rule is here for OPENSTEP/Rhapsody/MacOSX. It builds a temporary +# minimal framework (not including the Lib directory and such) in the current +# directory. +RESSRCDIR=Mac/Resources/framework +$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK): \ + $(LIBRARY) \ + $(RESSRCDIR)/Info.plist + $(INSTALL) -d -m $(DIRMODE) $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION) + $(CC) -o $(LDLIBRARY) $(LDFLAGS) -dynamiclib \ + -all_load $(LIBRARY) -Wl,-single_module \ + -install_name $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK) \ + -compatibility_version $(VERSION) \ + -current_version $(VERSION); + $(INSTALL) -d -m $(DIRMODE) \ + $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/Resources/English.lproj + $(INSTALL_DATA) $(RESSRCDIR)/Info.plist \ + $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/Resources/Info.plist + $(LN) -fsn $(VERSION) $(PYTHONFRAMEWORKDIR)/Versions/Current + $(LN) -fsn Versions/Current/$(PYTHONFRAMEWORK) $(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK) + $(LN) -fsn Versions/Current/Headers $(PYTHONFRAMEWORKDIR)/Headers + $(LN) -fsn Versions/Current/Resources $(PYTHONFRAMEWORKDIR)/Resources + +# This rule builds the Cygwin Python DLL and import library if configured +# for a shared core library; otherwise, this rule is a noop. +$(DLLLIBRARY) libpython$(VERSION).dll.a: $(LIBRARY_OBJS) + if test -n "$(DLLLIBRARY)"; then \ + $(LDSHARED) -Wl,--out-implib=$@ -o $(DLLLIBRARY) $^ \ + $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST); \ + else true; \ + fi + + +oldsharedmods: $(SHAREDMODS) + + +Makefile Modules/config.c: Makefile.pre \ + $(srcdir)/Modules/config.c.in \ + $(MAKESETUP) \ + Modules/Setup.config \ + Modules/Setup \ + Modules/Setup.local + $(SHELL) $(MAKESETUP) -c $(srcdir)/Modules/config.c.in \ + -s Modules \ + Modules/Setup.config \ + Modules/Setup.local \ + Modules/Setup + @mv config.c Modules + @echo "The Makefile was updated, you may need to re-run make." + + +Modules/Setup: $(srcdir)/Modules/Setup.dist + @if test -f Modules/Setup; then \ + echo "-----------------------------------------------"; \ + echo "Modules/Setup.dist is newer than Modules/Setup;"; \ + echo "check to make sure you have all the updates you"; \ + echo "need in your Modules/Setup file."; \ + echo "Usually, copying Modules/Setup.dist to Modules/Setup will work."; \ + echo "-----------------------------------------------"; \ + fi + +############################################################################ +# Special rules for object files + +Modules/getbuildinfo.o: $(PARSER_OBJS) \ + $(OBJECT_OBJS) \ + $(PYTHON_OBJS) \ + $(MODULE_OBJS) \ + $(SIGNAL_OBJS) \ + $(MODOBJS) \ + $(srcdir)/Modules/getbuildinfo.c + $(CC) -c $(PY_CFLAGS) \ + -DSVNVERSION="\"`LC_ALL=C $(SVNVERSION)`\"" \ + -DHGVERSION="\"`LC_ALL=C $(HGVERSION)`\"" \ + -DHGTAG="\"`LC_ALL=C $(HGTAG)`\"" \ + -DHGBRANCH="\"`LC_ALL=C $(HGBRANCH)`\"" \ + -o $@ $(srcdir)/Modules/getbuildinfo.c + +Modules/getpath.o: $(srcdir)/Modules/getpath.c Makefile + $(CC) -c $(PY_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \ + -DPREFIX='"$(prefix)"' \ + -DEXEC_PREFIX='"$(exec_prefix)"' \ + -DVERSION='"$(VERSION)"' \ + -DVPATH='"$(VPATH)"' \ + -o $@ $(srcdir)/Modules/getpath.c + +Modules/python.o: $(srcdir)/Modules/python.c + $(MAINCC) -c $(PY_CFLAGS) -o $@ $(srcdir)/Modules/python.c + +Modules/posixmodule.o: $(srcdir)/Modules/posixmodule.c $(srcdir)/Modules/posixmodule.h + +Modules/grpmodule.o: $(srcdir)/Modules/grpmodule.c $(srcdir)/Modules/posixmodule.h + +Modules/pwdmodule.o: $(srcdir)/Modules/pwdmodule.c $(srcdir)/Modules/posixmodule.h + +$(GRAMMAR_H): $(GRAMMAR_INPUT) $(PGENSRCS) + @$(MKDIR_P) Include + $(MAKE) $(PGEN) + $(PGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C) +$(GRAMMAR_C): $(GRAMMAR_H) $(GRAMMAR_INPUT) $(PGENSRCS) + $(MAKE) $(GRAMMAR_H) + touch $(GRAMMAR_C) + +$(PGEN): $(PGENOBJS) + $(CC) $(OPT) $(LDFLAGS) $(PGENOBJS) $(LIBS) -o $(PGEN) + +Parser/grammar.o: $(srcdir)/Parser/grammar.c \ + $(srcdir)/Include/token.h \ + $(srcdir)/Include/grammar.h +Parser/metagrammar.o: $(srcdir)/Parser/metagrammar.c + +Parser/tokenizer_pgen.o: $(srcdir)/Parser/tokenizer.c + +Parser/pgenmain.o: $(srcdir)/Include/parsetok.h + +$(AST_H): $(AST_ASDL) $(ASDLGEN_FILES) + $(MKDIR_P) $(AST_H_DIR) + $(ASDLGEN) -h $(AST_H_DIR) $(AST_ASDL) + +$(AST_C): $(AST_ASDL) $(ASDLGEN_FILES) + $(MKDIR_P) $(AST_C_DIR) + $(ASDLGEN) -c $(AST_C_DIR) $(AST_ASDL) + +Python/compile.o Python/symtable.o Python/ast.o: $(GRAMMAR_H) $(AST_H) + +Python/getplatform.o: $(srcdir)/Python/getplatform.c + $(CC) -c $(PY_CFLAGS) -DPLATFORM='"$(MACHDEP)"' -o $@ $(srcdir)/Python/getplatform.c + +Python/importdl.o: $(srcdir)/Python/importdl.c + $(CC) -c $(PY_CFLAGS) -I$(DLINCLDIR) -o $@ $(srcdir)/Python/importdl.c + +Objects/unicodectype.o: $(srcdir)/Objects/unicodectype.c \ + $(srcdir)/Objects/unicodetype_db.h + +STRINGLIB_HEADERS= \ + $(srcdir)/Include/bytes_methods.h \ + $(srcdir)/Objects/stringlib/count.h \ + $(srcdir)/Objects/stringlib/ctype.h \ + $(srcdir)/Objects/stringlib/fastsearch.h \ + $(srcdir)/Objects/stringlib/find.h \ + $(srcdir)/Objects/stringlib/formatter.h \ + $(srcdir)/Objects/stringlib/partition.h \ + $(srcdir)/Objects/stringlib/split.h \ + $(srcdir)/Objects/stringlib/stringdefs.h \ + $(srcdir)/Objects/stringlib/string_format.h \ + $(srcdir)/Objects/stringlib/transmogrify.h \ + $(srcdir)/Objects/stringlib/unicodedefs.h \ + $(srcdir)/Objects/stringlib/localeutil.h + +Objects/unicodeobject.o: $(srcdir)/Objects/unicodeobject.c \ + $(STRINGLIB_HEADERS) + +Objects/bytearrayobject.o: $(srcdir)/Objects/bytearrayobject.c \ + $(STRINGLIB_HEADERS) + +Objects/stringobject.o: $(srcdir)/Objects/stringobject.c \ + $(STRINGLIB_HEADERS) + +Python/formatter_unicode.o: $(srcdir)/Python/formatter_unicode.c \ + $(STRINGLIB_HEADERS) + +Python/formatter_string.o: $(srcdir)/Python/formatter_string.c \ + $(STRINGLIB_HEADERS) + +############################################################################ +# Header files + +PYTHON_HEADERS= \ + Include/Python-ast.h \ + Include/Python.h \ + Include/abstract.h \ + Include/asdl.h \ + Include/ast.h \ + Include/bitset.h \ + Include/boolobject.h \ + Include/bytearrayobject.h \ + Include/bytes_methods.h \ + Include/bytesobject.h \ + Include/bufferobject.h \ + Include/cellobject.h \ + Include/ceval.h \ + Include/classobject.h \ + Include/cobject.h \ + Include/code.h \ + Include/codecs.h \ + Include/compile.h \ + Include/complexobject.h \ + Include/descrobject.h \ + Include/dictobject.h \ + Include/dtoa.h \ + Include/enumobject.h \ + Include/errcode.h \ + Include/eval.h \ + Include/fileobject.h \ + Include/floatobject.h \ + Include/frameobject.h \ + Include/funcobject.h \ + Include/genobject.h \ + Include/import.h \ + Include/intobject.h \ + Include/intrcheck.h \ + Include/iterobject.h \ + Include/listobject.h \ + Include/longintrepr.h \ + Include/longobject.h \ + Include/marshal.h \ + Include/memoryobject.h \ + Include/metagrammar.h \ + Include/methodobject.h \ + Include/modsupport.h \ + Include/moduleobject.h \ + Include/node.h \ + Include/object.h \ + Include/objimpl.h \ + Include/opcode.h \ + Include/osdefs.h \ + Include/parsetok.h \ + Include/patchlevel.h \ + Include/pgen.h \ + Include/pgenheaders.h \ + Include/pyarena.h \ + Include/pycapsule.h \ + Include/pyctype.h \ + Include/pydebug.h \ + Include/pyerrors.h \ + Include/pyfpe.h \ + Include/pymath.h \ + Include/pygetopt.h \ + Include/pymem.h \ + Include/pyport.h \ + Include/pystate.h \ + Include/pystrcmp.h \ + Include/pystrtod.h \ + Include/pythonrun.h \ + Include/pythread.h \ + Include/rangeobject.h \ + Include/setobject.h \ + Include/sliceobject.h \ + Include/stringobject.h \ + Include/structmember.h \ + Include/structseq.h \ + Include/symtable.h \ + Include/sysmodule.h \ + Include/traceback.h \ + Include/tupleobject.h \ + Include/ucnhash.h \ + Include/unicodeobject.h \ + Include/warnings.h \ + Include/weakrefobject.h \ + pyconfig.h \ + $(PARSER_HEADERS) + +$(LIBRARY_OBJS) $(MODOBJS) Modules/python.o: $(PYTHON_HEADERS) + + +###################################################################### + +# Test the interpreter (twice, once without .pyc files, once with) +# In the past, we've had problems where bugs in the marshalling or +# elsewhere caused bytecode read from .pyc files to behave differently +# than bytecode generated directly from a .py source file. Sometimes +# the bytecode read from a .pyc file had the bug, sometimes the directly +# generated bytecode. This is sometimes a very shy bug needing a lot of +# sample data. + +TESTOPTS= -l $(EXTRATESTOPTS) +TESTPROG= $(srcdir)/Lib/test/regrtest.py +TESTPYTHON= $(RUNSHARED) ./$(BUILDPYTHON) -Wd -3 -E -tt $(TESTPYTHONOPTS) +test: all platform + -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f + -$(TESTPYTHON) $(TESTPROG) $(TESTOPTS) + $(TESTPYTHON) $(TESTPROG) $(TESTOPTS) + +testall: all platform + -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f + $(TESTPYTHON) $(srcdir)/Lib/compileall.py + -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f + -$(TESTPYTHON) $(TESTPROG) -uall $(TESTOPTS) + $(TESTPYTHON) $(TESTPROG) -uall $(TESTOPTS) + +# Run the unitests for both architectures in a Universal build on OSX +# Must be run on an Intel box. +testuniversal: all platform + if [ `arch` != 'i386' ];then \ + echo "This can only be used on OSX/i386" ;\ + exit 1 ;\ + fi + -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f + -$(TESTPYTHON) $(TESTPROG) -uall $(TESTOPTS) + $(TESTPYTHON) $(TESTPROG) -uall $(TESTOPTS) + $(RUNSHARED) /usr/libexec/oah/translate ./$(BUILDPYTHON) -E -tt $(TESTPROG) -uall $(TESTOPTS) + + +# Like testall, but with a single pass only +# run an optional script to include some information about the build environment +buildbottest: all platform + -@if which pybuildbot.identify >/dev/null 2>&1; then \ + pybuildbot.identify "CC='$(CC)'" "CXX='$(CXX)'"; \ + fi + $(TESTPYTHON) -R $(TESTPROG) -uall -rwW $(TESTOPTS) + +QUICKTESTOPTS= $(TESTOPTS) -x test_subprocess test_io test_lib2to3 \ + test_multibytecodec test_urllib2_localnet test_itertools \ + test_multiprocessing test_mailbox test_socket test_poll \ + test_select test_zipfile +quicktest: all platform + -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f + -$(TESTPYTHON) $(TESTPROG) $(QUICKTESTOPTS) + $(TESTPYTHON) $(TESTPROG) $(QUICKTESTOPTS) + +MEMTESTOPTS= $(QUICKTESTOPTS) -x test_dl test___all__ test_fork1 \ + test_longexp +memtest: all platform + -rm -f $(srcdir)/Lib/test/*.py[co] + -$(TESTPYTHON) $(TESTPROG) $(MEMTESTOPTS) + $(TESTPYTHON) $(TESTPROG) $(MEMTESTOPTS) + +# Install everything +install: frameworkinstallstructure altinstall bininstall maninstall frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools + +# Install almost everything without disturbing previous versions +altinstall: frameworkinstallstructure bininstall maninstall altbininstall libinstall inclinstall \ + libainstall altmaninstall \ + sharedinstall oldsharedinstall frameworkinstallmaclib frameworkinstallapps frameworkaltinstallunixtools + +# Install shared libraries enabled by Setup +DESTDIRS= $(exec_prefix) $(LIBDIR) $(BINLIBDEST) $(DESTSHARED) + +oldsharedinstall: $(DESTSHARED) $(SHAREDMODS) + @for i in X $(SHAREDMODS); do \ + if test $$i != X; then \ + echo $(INSTALL_SHARED) $$i $(DESTSHARED)/`basename $$i`; \ + $(INSTALL_SHARED) $$i $(DESTDIR)$(DESTSHARED)/`basename $$i`; \ + fi; \ + done + +$(DESTSHARED): + @for i in $(DESTDIRS); \ + do \ + if test ! -d $(DESTDIR)$$i; then \ + echo "Creating directory $$i"; \ + $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \ + else true; \ + fi; \ + done + + +# Install the interpreter by creating a symlink chain: +# $(PYTHON) -> python2 -> python$(VERSION)) +# Also create equivalent chains for other installed files +bininstall: altbininstall + -if test -f $(DESTDIR)$(BINDIR)/$(PYTHON) -o -h $(DESTDIR)$(BINDIR)/$(PYTHON); \ + then rm -f $(DESTDIR)$(BINDIR)/$(PYTHON); \ + else true; \ + fi + (cd $(DESTDIR)$(BINDIR); $(LN) -s python2$(EXE) $(PYTHON)) + -rm -f $(DESTDIR)$(BINDIR)/python2$(EXE) + (cd $(DESTDIR)$(BINDIR); $(LN) -s python$(VERSION)$(EXE) python2$(EXE)) + -rm -f $(DESTDIR)$(BINDIR)/python2-config + (cd $(DESTDIR)$(BINDIR); $(LN) -s python$(VERSION)-config python2-config) + -rm -f $(DESTDIR)$(BINDIR)/python-config + (cd $(DESTDIR)$(BINDIR); $(LN) -s python2-config python-config) + -test -d $(DESTDIR)$(LIBPC) || $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$(LIBPC) + -rm -f $(DESTDIR)$(LIBPC)/python2.pc + (cd $(DESTDIR)$(LIBPC); $(LN) -s python-$(VERSION).pc python2.pc) + -rm -f $(DESTDIR)$(LIBPC)/python.pc + (cd $(DESTDIR)$(LIBPC); $(LN) -s python2.pc python.pc) + +# Install the interpreter with $(VERSION) affixed +# This goes into $(exec_prefix) +altbininstall: $(BUILDPYTHON) + @for i in $(BINDIR) $(LIBDIR); \ + do \ + if test ! -d $(DESTDIR)$$i; then \ + echo "Creating directory $$i"; \ + $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \ + else true; \ + fi; \ + done + $(INSTALL_PROGRAM) $(BUILDPYTHON) $(DESTDIR)$(BINDIR)/python$(VERSION)$(EXE) + if test -f $(LDLIBRARY); then \ + if test -n "$(DLLLIBRARY)" ; then \ + $(INSTALL_SHARED) $(DLLLIBRARY) $(DESTDIR)$(BINDIR); \ + else \ + $(INSTALL_SHARED) $(LDLIBRARY) $(DESTDIR)$(LIBDIR)/$(INSTSONAME); \ + if test $(LDLIBRARY) != $(INSTSONAME); then \ + (cd $(DESTDIR)$(LIBDIR); $(LN) -sf $(INSTSONAME) $(LDLIBRARY)) \ + fi \ + fi; \ + else true; \ + fi + +# Install the versioned manual page +altmaninstall: + @for i in $(MANDIR) $(MANDIR)/man1; \ + do \ + if test ! -d $(DESTDIR)$$i; then \ + echo "Creating directory $$i"; \ + $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \ + else true; \ + fi; \ + done + $(INSTALL_DATA) $(srcdir)/Misc/python.man \ + $(DESTDIR)$(MANDIR)/man1/python$(VERSION).1 + +# Install the unversioned manual pages +maninstall: altmaninstall + -rm -f $(DESTDIR)$(MANDIR)/man1/python2.1 + (cd $(DESTDIR)$(MANDIR)/man1; $(LN) -s python$(VERSION).1 python2.1) + -rm -f $(DESTDIR)$(MANDIR)/man1/python.1 + (cd $(DESTDIR)$(MANDIR)/man1; $(LN) -s python2.1 python.1) + +# Install the library +PLATDIR= plat-$(MACHDEP) +EXTRAPLATDIR= $(PLATMACDIRS) +EXTRAMACHDEPPATH=$(PLATMACPATH) +MACHDEPS= $(PLATDIR) $(EXTRAPLATDIR) +XMLLIBSUBDIRS= xml xml/dom xml/etree xml/parsers xml/sax +PLATMACDIRS= plat-mac plat-mac/Carbon plat-mac/lib-scriptpackages \ + plat-mac/lib-scriptpackages/_builtinSuites \ + plat-mac/lib-scriptpackages/CodeWarrior \ + plat-mac/lib-scriptpackages/Explorer \ + plat-mac/lib-scriptpackages/Finder \ + plat-mac/lib-scriptpackages/Netscape \ + plat-mac/lib-scriptpackages/StdSuites \ + plat-mac/lib-scriptpackages/SystemEvents \ + plat-mac/lib-scriptpackages/Terminal +PLATMACPATH=:plat-mac:plat-mac/lib-scriptpackages +LIBSUBDIRS= lib-tk lib-tk/test lib-tk/test/test_tkinter \ + lib-tk/test/test_ttk site-packages test test/data \ + test/cjkencodings test/decimaltestdata test/xmltestdata test/subprocessdata \ + test/tracedmodules \ + encodings compiler hotshot \ + email email/mime email/test email/test/data \ + json json/tests \ + sqlite3 sqlite3/test \ + logging bsddb bsddb/test csv importlib wsgiref \ + lib2to3 lib2to3/fixes lib2to3/pgen2 lib2to3/tests \ + lib2to3/tests/data lib2to3/tests/data/fixers lib2to3/tests/data/fixers/myfixes \ + ctypes ctypes/test ctypes/macholib idlelib idlelib/Icons \ + distutils distutils/command distutils/tests $(XMLLIBSUBDIRS) \ + multiprocessing multiprocessing/dummy \ + unittest unittest/test \ + lib-old \ + curses pydoc_data $(MACHDEPS) +libinstall: build_all $(srcdir)/Lib/$(PLATDIR) $(srcdir)/Modules/xxmodule.c + @for i in $(SCRIPTDIR) $(LIBDEST); \ + do \ + if test ! -d $(DESTDIR)$$i; then \ + echo "Creating directory $$i"; \ + $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \ + else true; \ + fi; \ + done + @for d in $(LIBSUBDIRS); \ + do \ + a=$(srcdir)/Lib/$$d; \ + if test ! -d $$a; then continue; else true; fi; \ + b=$(LIBDEST)/$$d; \ + if test ! -d $(DESTDIR)$$b; then \ + echo "Creating directory $$b"; \ + $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$b; \ + else true; \ + fi; \ + done + @for i in $(srcdir)/Lib/*.py `cat pybuilddir.txt`/_sysconfigdata.py $(srcdir)/Lib/*.doc $(srcdir)/Lib/*.egg-info ; \ + do \ + if test -x $$i; then \ + $(INSTALL_SCRIPT) $$i $(DESTDIR)$(LIBDEST); \ + echo $(INSTALL_SCRIPT) $$i $(LIBDEST); \ + else \ + $(INSTALL_DATA) $$i $(DESTDIR)$(LIBDEST); \ + echo $(INSTALL_DATA) $$i $(LIBDEST); \ + fi; \ + done + @for d in $(LIBSUBDIRS); \ + do \ + a=$(srcdir)/Lib/$$d; \ + if test ! -d $$a; then continue; else true; fi; \ + if test `ls $$a | wc -l` -lt 1; then continue; fi; \ + b=$(LIBDEST)/$$d; \ + for i in $$a/*; \ + do \ + case $$i in \ + *CVS) ;; \ + *.py[co]) ;; \ + *.orig) ;; \ + *~) ;; \ + *) \ + if test -d $$i; then continue; fi; \ + if test -x $$i; then \ + echo $(INSTALL_SCRIPT) $$i $$b; \ + $(INSTALL_SCRIPT) $$i $(DESTDIR)$$b; \ + else \ + echo $(INSTALL_DATA) $$i $$b; \ + $(INSTALL_DATA) $$i $(DESTDIR)$$b; \ + fi;; \ + esac; \ + done; \ + done + $(INSTALL_DATA) $(srcdir)/LICENSE $(DESTDIR)$(LIBDEST)/LICENSE.txt + if test -d $(DESTDIR)$(LIBDEST)/distutils/tests; then \ + $(INSTALL_DATA) $(srcdir)/Modules/xxmodule.c \ + $(DESTDIR)$(LIBDEST)/distutils/tests ; \ + fi + PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -Wi -tt $(DESTDIR)$(LIBDEST)/compileall.py \ + -d $(LIBDEST) -f \ + -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ + $(DESTDIR)$(LIBDEST) + PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -Wi -tt -O $(DESTDIR)$(LIBDEST)/compileall.py \ + -d $(LIBDEST) -f \ + -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ + $(DESTDIR)$(LIBDEST) + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -Wi -t $(DESTDIR)$(LIBDEST)/compileall.py \ + -d $(LIBDEST)/site-packages -f \ + -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -Wi -t -O $(DESTDIR)$(LIBDEST)/compileall.py \ + -d $(LIBDEST)/site-packages -f \ + -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/Grammar.txt + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/PatternGrammar.txt + +# Create the PLATDIR source directory, if one wasn't distributed.. +$(srcdir)/Lib/$(PLATDIR): + mkdir $(srcdir)/Lib/$(PLATDIR) + cp $(srcdir)/Lib/plat-generic/regen $(srcdir)/Lib/$(PLATDIR)/regen + export PATH; PATH="`pwd`:$$PATH"; \ + export PYTHONPATH; PYTHONPATH="$(srcdir)/Lib:$(abs_builddir)/`cat pybuilddir.txt`"; \ + export DYLD_FRAMEWORK_PATH; DYLD_FRAMEWORK_PATH="`pwd`"; \ + export EXE; EXE="$(BUILDEXE)"; \ + if [ -n "$(MULTIARCH)" ]; then export MULTIARCH; MULTIARCH=$(MULTIARCH); fi; \ + export PYTHON_FOR_BUILD; \ + if [ "$(build)" = "$(host)" ]; then \ + PYTHON_FOR_BUILD="$(BUILDPYTHON)"; \ + else \ + PYTHON_FOR_BUILD="$(PYTHON_FOR_BUILD)"; \ + fi; \ + cd $(srcdir)/Lib/$(PLATDIR); $(RUNSHARED) ./regen + +python-config: $(srcdir)/Misc/python-config.in + # Substitution happens here, as the completely-expanded BINDIR + # is not available in configure + sed -e "s,@EXENAME@,$(BINDIR)/python$(VERSION)$(EXE)," < $(srcdir)/Misc/python-config.in >python-config + +# Install the include files +INCLDIRSTOMAKE=$(INCLUDEDIR) $(CONFINCLUDEDIR) $(INCLUDEPY) $(CONFINCLUDEPY) +inclinstall: + @for i in $(INCLDIRSTOMAKE); \ + do \ + if test ! -d $(DESTDIR)$$i; then \ + echo "Creating directory $$i"; \ + $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \ + else true; \ + fi; \ + done + @for i in $(srcdir)/Include/*.h; \ + do \ + echo $(INSTALL_DATA) $$i $(INCLUDEPY); \ + $(INSTALL_DATA) $$i $(DESTDIR)$(INCLUDEPY); \ + done + $(INSTALL_DATA) pyconfig.h $(DESTDIR)$(CONFINCLUDEPY)/pyconfig.h + +# Install the library and miscellaneous stuff needed for extending/embedding +# This goes into $(exec_prefix) +LIBPL= $(LIBP)/config + +# pkgconfig directory +LIBPC= $(LIBDIR)/pkgconfig + +libainstall: all python-config + @for i in $(LIBDIR) $(LIBP) $(LIBPL) $(LIBPC); \ + do \ + if test ! -d $(DESTDIR)$$i; then \ + echo "Creating directory $$i"; \ + $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \ + else true; \ + fi; \ + done + @if test -d $(LIBRARY); then :; else \ + if test "$(PYTHONFRAMEWORKDIR)" = no-framework; then \ + if test "$(SO)" = .dll; then \ + $(INSTALL_DATA) $(LDLIBRARY) $(DESTDIR)$(LIBPL) ; \ + else \ + $(INSTALL_DATA) $(LIBRARY) $(DESTDIR)$(LIBPL)/$(LIBRARY) ; \ + $(RANLIB) $(DESTDIR)$(LIBPL)/$(LIBRARY) ; \ + fi; \ + else \ + echo Skip install of $(LIBRARY) - use make frameworkinstall; \ + fi; \ + fi + $(INSTALL_DATA) Modules/config.c $(DESTDIR)$(LIBPL)/config.c + $(INSTALL_DATA) Modules/python.o $(DESTDIR)$(LIBPL)/python.o + $(INSTALL_DATA) $(srcdir)/Modules/config.c.in $(DESTDIR)$(LIBPL)/config.c.in + $(INSTALL_DATA) Makefile $(DESTDIR)$(LIBPL)/Makefile + $(INSTALL_DATA) Modules/Setup $(DESTDIR)$(LIBPL)/Setup + $(INSTALL_DATA) Modules/Setup.local $(DESTDIR)$(LIBPL)/Setup.local + $(INSTALL_DATA) Modules/Setup.config $(DESTDIR)$(LIBPL)/Setup.config + $(INSTALL_DATA) Misc/python.pc $(DESTDIR)$(LIBPC)/python-$(VERSION).pc + $(INSTALL_SCRIPT) $(srcdir)/Modules/makesetup $(DESTDIR)$(LIBPL)/makesetup + $(INSTALL_SCRIPT) $(srcdir)/install-sh $(DESTDIR)$(LIBPL)/install-sh + $(INSTALL_SCRIPT) python-config $(DESTDIR)$(BINDIR)/python$(VERSION)-config + rm python-config + @if [ -s Modules/python.exp -a \ + "`echo $(MACHDEP) | sed 's/^\(...\).*/\1/'`" = "aix" ]; then \ + echo; echo "Installing support files for building shared extension modules on AIX:"; \ + $(INSTALL_DATA) Modules/python.exp \ + $(DESTDIR)$(LIBPL)/python.exp; \ + echo; echo "$(LIBPL)/python.exp"; \ + $(INSTALL_SCRIPT) $(srcdir)/Modules/makexp_aix \ + $(DESTDIR)$(LIBPL)/makexp_aix; \ + echo "$(LIBPL)/makexp_aix"; \ + $(INSTALL_SCRIPT) $(srcdir)/Modules/ld_so_aix \ + $(DESTDIR)$(LIBPL)/ld_so_aix; \ + echo "$(LIBPL)/ld_so_aix"; \ + echo; echo "See Misc/AIX-NOTES for details."; \ + else true; \ + fi + @case "$(MACHDEP)" in beos*) \ + echo; echo "Installing support files for building shared extension modules on BeOS:"; \ + $(INSTALL_DATA) Misc/BeOS-NOTES $(DESTDIR)$(LIBPL)/README; \ + echo; echo "$(LIBPL)/README"; \ + $(INSTALL_SCRIPT) Modules/ar_beos $(DESTDIR)$(LIBPL)/ar_beos; \ + echo "$(LIBPL)/ar_beos"; \ + $(INSTALL_SCRIPT) Modules/ld_so_beos $(DESTDIR)$(LIBPL)/ld_so_beos; \ + echo "$(LIBPL)/ld_so_beos"; \ + echo; echo "See Misc/BeOS-NOTES for details."; \ + ;; \ + esac + +# Install the dynamically loadable modules +# This goes into $(exec_prefix) +sharedinstall: sharedmods + $(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/setup.py install \ + --prefix=$(prefix) \ + --install-scripts=$(BINDIR) \ + --install-platlib=$(DESTSHARED) \ + --root=$(DESTDIR)/ + -rm $(DESTDIR)$(DESTSHARED)/_sysconfigdata.py* + +# Here are a couple of targets for MacOSX again, to install a full +# framework-based Python. frameworkinstall installs everything, the +# subtargets install specific parts. Much of the actual work is offloaded to +# the Makefile in Mac +# +# +# This target is here for backward compatiblity, previous versions of Python +# hadn't integrated framework installation in the normal install process. +frameworkinstall: install + +# On install, we re-make the framework +# structure in the install location, /Library/Frameworks/ or the argument to +# --enable-framework. If --enable-framework has been specified then we have +# automatically set prefix to the location deep down in the framework, so we +# only have to cater for the structural bits of the framework. + +frameworkinstallframework: frameworkinstallstructure install frameworkinstallmaclib + +frameworkinstallstructure: $(LDLIBRARY) + @if test "$(PYTHONFRAMEWORKDIR)" = no-framework; then \ + echo Not configured with --enable-framework; \ + exit 1; \ + else true; \ + fi + @for i in $(prefix)/Resources/English.lproj $(prefix)/lib; do\ + if test ! -d $(DESTDIR)$$i; then \ + echo "Creating directory $(DESTDIR)$$i"; \ + $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \ + else true; \ + fi; \ + done + $(LN) -fsn include/python$(VERSION) $(DESTDIR)$(prefix)/Headers + sed 's/%VERSION%/'"`$(RUNSHARED) ./$(BUILDPYTHON) -c 'import platform; print platform.python_version()'`"'/g' < $(RESSRCDIR)/Info.plist > $(DESTDIR)$(prefix)/Resources/Info.plist + $(LN) -fsn $(VERSION) $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Versions/Current + $(LN) -fsn Versions/Current/$(PYTHONFRAMEWORK) $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/$(PYTHONFRAMEWORK) + $(LN) -fsn Versions/Current/Headers $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Headers + $(LN) -fsn Versions/Current/Resources $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Resources + $(INSTALL_SHARED) $(LDLIBRARY) $(DESTDIR)$(PYTHONFRAMEWORKPREFIX)/$(LDLIBRARY) + +# This installs Mac/Lib into the framework +# Install a number of symlinks to keep software that expects a normal unix +# install (which includes python-config) happy. +frameworkinstallmaclib: + ln -fs "../../../$(PYTHONFRAMEWORK)" "$(DESTDIR)$(prefix)/lib/python$(VERSION)/config/libpython$(VERSION).a" + ln -fs "../../../$(PYTHONFRAMEWORK)" "$(DESTDIR)$(prefix)/lib/python$(VERSION)/config/libpython$(VERSION).dylib" + ln -fs "../$(PYTHONFRAMEWORK)" "$(DESTDIR)$(prefix)/lib/libpython$(VERSION).dylib" + cd Mac && $(MAKE) installmacsubtree DESTDIR="$(DESTDIR)" + +# This installs the IDE, the Launcher and other apps into /Applications +frameworkinstallapps: + cd Mac && $(MAKE) installapps DESTDIR="$(DESTDIR)" + +# This install the unix python and pythonw tools in /usr/local/bin +frameworkinstallunixtools: + cd Mac && $(MAKE) installunixtools DESTDIR="$(DESTDIR)" + +frameworkaltinstallunixtools: + cd Mac && $(MAKE) altinstallunixtools DESTDIR="$(DESTDIR)" + +# This installs the Demos and Tools into the applications directory. +# It is not part of a normal frameworkinstall +frameworkinstallextras: + cd Mac && $(MAKE) installextras DESTDIR="$(DESTDIR)" + +# This installs a few of the useful scripts in Tools/scripts +scriptsinstall: + SRCDIR=$(srcdir) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) $(srcdir)/Tools/scripts/setup.py install \ + --prefix=$(prefix) \ + --install-scripts=$(BINDIR) \ + --root=$(DESTDIR)/ + +# Build the toplevel Makefile +Makefile.pre: Makefile.pre.in config.status + CONFIG_FILES=Makefile.pre CONFIG_HEADERS= $(SHELL) config.status + $(MAKE) -f Makefile.pre Makefile + +# Run the configure script. +config.status: $(srcdir)/configure + $(SHELL) $(srcdir)/configure $(CONFIG_ARGS) + +.PRECIOUS: config.status $(BUILDPYTHON) Makefile Makefile.pre + +# Some make's put the object file in the current directory +.c.o: + $(CC) -c $(PY_CFLAGS) -o $@ $< + +# Run reindent on the library +reindent: + ./$(BUILDPYTHON) $(srcdir)/Tools/scripts/reindent.py -r $(srcdir)/Lib + +# Rerun configure with the same options as it was run last time, +# provided the config.status script exists +recheck: + $(SHELL) config.status --recheck + $(SHELL) config.status + +# Rebuild the configure script from configure.ac; also rebuild pyconfig.h.in +autoconf: + (cd $(srcdir); autoconf) + (cd $(srcdir); autoheader) + +# Create a tags file for vi +tags:: + cd $(srcdir); \ + ctags -w -t Include/*.h; \ + for i in $(SRCDIRS); do ctags -w -t -a $$i/*.[ch]; \ + done; \ + sort -o tags tags + +# Create a tags file for GNU Emacs +TAGS:: + cd $(srcdir); \ + etags Include/*.h; \ + for i in $(SRCDIRS); do etags -a $$i/*.[ch]; done + +# Touch generated files +touch: + touch Include/Python-ast.h Python/Python-ast.c + +# Sanitation targets -- clean leaves libraries, executables and tags +# files, which clobber removes as well +pycremoval: + find $(srcdir) -name '*.py[co]' -exec rm -f {} ';' + +clean: pycremoval + find . -name '*.[oa]' -exec rm -f {} ';' + find . -name '*.s[ol]' -exec rm -f {} ';' + find . -name '*.so.[0-9]*.[0-9]*' -exec rm -f {} ';' + find build -name 'fficonfig.h' -exec rm -f {} ';' || true + find build -name 'fficonfig.py' -exec rm -f {} ';' || true + -rm -f Lib/lib2to3/*Grammar*.pickle + +profile-removal: + find . -name '*.gc??' -exec rm -f {} ';' + +clobber: clean profile-removal + -rm -f $(BUILDPYTHON) $(PGEN) $(LIBRARY) $(LDLIBRARY) $(DLLLIBRARY) \ + tags TAGS \ + config.cache config.log pyconfig.h Modules/config.c + -rm -rf build platform + -rm -rf $(PYTHONFRAMEWORKDIR) + +# Make things extra clean, before making a distribution: +# remove all generated files, even Makefile[.pre] +# Keep configure and Python-ast.[ch], it's possible they can't be generated +distclean: clobber + for file in Lib/test/data/* ; do \ + if test "$$file" != "Lib/test/data/README"; then rm "$$file"; fi; \ + done + -rm -f core Makefile Makefile.pre config.status \ + Modules/Setup Modules/Setup.local Modules/Setup.config \ + Modules/ld_so_aix Modules/python.exp Misc/python.pc + -rm -f python*-gdb.py + -rm -f pybuilddir.txt + find $(srcdir) '(' -name '*.fdc' -o -name '*~' \ + -o -name '[@,#]*' -o -name '*.old' \ + -o -name '*.orig' -o -name '*.rej' \ + -o -name '*.bak' ')' \ + -exec rm -f {} ';' + +# Check for smelly exported symbols (not starting with Py/_Py) +smelly: all + nm -p $(LIBRARY) | \ + sed -n "/ [TDB] /s/.* //p" | grep -v "^_*Py" | sort -u; \ + +# Find files with funny names +funny: + find $(SUBDIRS) $(SUBDIRSTOO) -type d \ + -o -name '*.[chs]' \ + -o -name '*.py' \ + -o -name '*.doc' \ + -o -name '*.sty' \ + -o -name '*.bib' \ + -o -name '*.dat' \ + -o -name '*.el' \ + -o -name '*.fd' \ + -o -name '*.in' \ + -o -name '*.tex' \ + -o -name '*,[vpt]' \ + -o -name 'Setup' \ + -o -name 'Setup.*' \ + -o -name README \ + -o -name Makefile \ + -o -name ChangeLog \ + -o -name Repository \ + -o -name Root \ + -o -name Entries \ + -o -name Tag \ + -o -name tags \ + -o -name TAGS \ + -o -name .cvsignore \ + -o -name MANIFEST \ + -o -print + +# Perform some verification checks on any modified files. +patchcheck: + $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/scripts/patchcheck.py + +# Dependencies + +Python/thread.o: $(srcdir)/Python/thread_atheos.h $(srcdir)/Python/thread_beos.h $(srcdir)/Python/thread_cthread.h $(srcdir)/Python/thread_foobar.h $(srcdir)/Python/thread_lwp.h $(srcdir)/Python/thread_nt.h $(srcdir)/Python/thread_os2.h $(srcdir)/Python/thread_pth.h $(srcdir)/Python/thread_pthread.h $(srcdir)/Python/thread_sgi.h $(srcdir)/Python/thread_solaris.h $(srcdir)/Python/thread_wince.h + +# Declare targets that aren't real files +.PHONY: all build_all sharedmods oldsharedmods test quicktest memtest +.PHONY: install altinstall oldsharedinstall bininstall altbininstall +.PHONY: maninstall libinstall inclinstall libainstall sharedinstall +.PHONY: frameworkinstall frameworkinstallframework frameworkinstallstructure +.PHONY: frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools +.PHONY: frameworkaltinstallunixtools recheck autoconf clean clobber distclean +.PHONY: smelly funny patchcheck touch altmaninstall +.PHONY: gdbhooks + +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY + +# Rules appended by makedepend + +Modules/threadmodule.o: $(srcdir)/Modules/threadmodule.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/threadmodule.c -o Modules/threadmodule.o +Modules/threadmodule$(SO): Modules/threadmodule.o; $(BLDSHARED) Modules/threadmodule.o -o Modules/threadmodule$(SO) +Modules/signalmodule.o: $(srcdir)/Modules/signalmodule.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/signalmodule.c -o Modules/signalmodule.o +Modules/signalmodule$(SO): Modules/signalmodule.o; $(BLDSHARED) Modules/signalmodule.o -o Modules/signalmodule$(SO) +Modules/posixmodule.o: $(srcdir)/Modules/posixmodule.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/posixmodule.c -o Modules/posixmodule.o +Modules/posixmodule$(SO): Modules/posixmodule.o; $(BLDSHARED) Modules/posixmodule.o -o Modules/posixmodule$(SO) +Modules/errnomodule.o: $(srcdir)/Modules/errnomodule.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/errnomodule.c -o Modules/errnomodule.o +Modules/errnomodule$(SO): Modules/errnomodule.o; $(BLDSHARED) Modules/errnomodule.o -o Modules/errnomodule$(SO) +Modules/pwdmodule.o: $(srcdir)/Modules/pwdmodule.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/pwdmodule.c -o Modules/pwdmodule.o +Modules/pwdmodule$(SO): Modules/pwdmodule.o; $(BLDSHARED) Modules/pwdmodule.o -o Modules/pwdmodule$(SO) +Modules/_sre.o: $(srcdir)/Modules/_sre.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/_sre.c -o Modules/_sre.o +Modules/_sre$(SO): Modules/_sre.o; $(BLDSHARED) Modules/_sre.o -o Modules/_sre$(SO) +Modules/_codecsmodule.o: $(srcdir)/Modules/_codecsmodule.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/_codecsmodule.c -o Modules/_codecsmodule.o +Modules/_codecsmodule$(SO): Modules/_codecsmodule.o; $(BLDSHARED) Modules/_codecsmodule.o -o Modules/_codecsmodule$(SO) +Modules/_weakref.o: $(srcdir)/Modules/_weakref.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/_weakref.c -o Modules/_weakref.o +Modules/_weakref$(SO): Modules/_weakref.o; $(BLDSHARED) Modules/_weakref.o -o Modules/_weakref$(SO) +Modules/zipimport.o: $(srcdir)/Modules/zipimport.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/zipimport.c -o Modules/zipimport.o +Modules/zipimport$(SO): Modules/zipimport.o; $(BLDSHARED) Modules/zipimport.o -o Modules/zipimport$(SO) +Modules/symtablemodule.o: $(srcdir)/Modules/symtablemodule.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/symtablemodule.c -o Modules/symtablemodule.o +Modules/_symtablemodule$(SO): Modules/symtablemodule.o; $(BLDSHARED) Modules/symtablemodule.o -o Modules/_symtablemodule$(SO) +Modules/xxsubtype.o: $(srcdir)/Modules/xxsubtype.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/xxsubtype.c -o Modules/xxsubtype.o +Modules/xxsubtype$(SO): Modules/xxsubtype.o; $(BLDSHARED) Modules/xxsubtype.o -o Modules/xxsubtype$(SO) diff --git a/FeedTheMonkey.app/Contents/Frameworks/Python.framework/Versions/Current b/FeedTheMonkey.app/Contents/Frameworks/Python.framework/Versions/Current new file mode 120000 index 0000000..e6b7b62 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/Python.framework/Versions/Current @@ -0,0 +1 @@ +2.7 \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtCore.framework/Contents/Info.plist b/FeedTheMonkey.app/Contents/Frameworks/QtCore.framework/Contents/Info.plist new file mode 100644 index 0000000..967cf94 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtCore.framework/Contents/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.8 + CFBundleGetInfoString + Created by Qt/QMake + CFBundleSignature + ???? + CFBundleExecutable + QtCore + NOTE + Please, do NOT change this file -- It was generated by Qt/QMake. + + diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtCore.framework/QtCore b/FeedTheMonkey.app/Contents/Frameworks/QtCore.framework/QtCore new file mode 120000 index 0000000..a002a13 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtCore.framework/QtCore @@ -0,0 +1 @@ +Versions/4/QtCore \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtCore.framework/QtCore.prl b/FeedTheMonkey.app/Contents/Frameworks/QtCore.framework/QtCore.prl new file mode 100644 index 0000000..75e5e9a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtCore.framework/QtCore.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/corelib +QMAKE_PRO_INPUT = corelib.pro +QMAKE_PRL_TARGET = QtCore +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on uic resources sdk rez release ReleaseBuild Release build_pass qt warn_on release app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend release stl qt_framework x86_64 release largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build release ReleaseBuild Release build_pass qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib release ReleaseBuild Release build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtCore.framework/QtCore_debug.prl b/FeedTheMonkey.app/Contents/Frameworks/QtCore.framework/QtCore_debug.prl new file mode 100644 index 0000000..fe18def --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtCore.framework/QtCore_debug.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/corelib +QMAKE_PRO_INPUT = corelib.pro +QMAKE_PRL_TARGET = QtCore_debug +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on debug uic resources sdk rez debug DebugBuild Debug build_pass qt warn_on app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend stl qt_framework x86_64 largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build debug DebugBuild Debug build_pass qt_install_headers qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib debug DebugBuild Debug build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtCore.framework/Versions/4/QtCore b/FeedTheMonkey.app/Contents/Frameworks/QtCore.framework/Versions/4/QtCore new file mode 100644 index 0000000..0bfaebc Binary files /dev/null and b/FeedTheMonkey.app/Contents/Frameworks/QtCore.framework/Versions/4/QtCore differ diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtCore.framework/Versions/Current b/FeedTheMonkey.app/Contents/Frameworks/QtCore.framework/Versions/Current new file mode 120000 index 0000000..bf0d87a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtCore.framework/Versions/Current @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtDeclarative.framework/Contents/Info.plist b/FeedTheMonkey.app/Contents/Frameworks/QtDeclarative.framework/Contents/Info.plist new file mode 100644 index 0000000..b50df06 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtDeclarative.framework/Contents/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.8 + CFBundleGetInfoString + Created by Qt/QMake + CFBundleSignature + ???? + CFBundleExecutable + QtDeclarative + NOTE + Please, do NOT change this file -- It was generated by Qt/QMake. + + diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtDeclarative.framework/QtDeclarative b/FeedTheMonkey.app/Contents/Frameworks/QtDeclarative.framework/QtDeclarative new file mode 120000 index 0000000..01eff38 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtDeclarative.framework/QtDeclarative @@ -0,0 +1 @@ +Versions/4/QtDeclarative \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtDeclarative.framework/QtDeclarative.prl b/FeedTheMonkey.app/Contents/Frameworks/QtDeclarative.framework/QtDeclarative.prl new file mode 100644 index 0000000..822d883 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtDeclarative.framework/QtDeclarative.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/src/declarative/ +QMAKE_PRO_INPUT = declarative.pro +QMAKE_PRL_TARGET = QtDeclarative +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on uic resources sdk rez release ReleaseBuild Release build_pass qt warn_on release app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend release stl qt_framework x86_64 release largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build release ReleaseBuild Release build_pass qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib release ReleaseBuild Release build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib -F/usr/local/Cellar/qt/4.8.5/lib -framework QtScript -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib -F/usr/local/Cellar/qt/4.8.5/lib -framework QtCore -framework QtSvg -framework QtGui -framework QtSql -framework QtXmlPatterns -framework QtNetwork diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtDeclarative.framework/QtDeclarative_debug.prl b/FeedTheMonkey.app/Contents/Frameworks/QtDeclarative.framework/QtDeclarative_debug.prl new file mode 100644 index 0000000..ba919af --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtDeclarative.framework/QtDeclarative_debug.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/src/declarative/ +QMAKE_PRO_INPUT = declarative.pro +QMAKE_PRL_TARGET = QtDeclarative_debug +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on debug uic resources sdk rez debug DebugBuild Debug build_pass qt warn_on app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend stl qt_framework x86_64 largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build debug DebugBuild Debug build_pass qt_install_headers qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib debug DebugBuild Debug build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -F/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -framework QtScript -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -F/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -framework QtCore -framework QtSvg -framework QtGui -framework QtSql -framework QtXmlPatterns -framework QtNetwork diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtDeclarative.framework/Versions/4/QtDeclarative b/FeedTheMonkey.app/Contents/Frameworks/QtDeclarative.framework/Versions/4/QtDeclarative new file mode 100644 index 0000000..41656fe Binary files /dev/null and b/FeedTheMonkey.app/Contents/Frameworks/QtDeclarative.framework/Versions/4/QtDeclarative differ diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtDeclarative.framework/Versions/Current b/FeedTheMonkey.app/Contents/Frameworks/QtDeclarative.framework/Versions/Current new file mode 120000 index 0000000..bf0d87a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtDeclarative.framework/Versions/Current @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Contents/Info.plist b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Contents/Info.plist new file mode 100644 index 0000000..fd43fbd --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Contents/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.8 + CFBundleGetInfoString + Created by Qt/QMake + CFBundleSignature + ???? + CFBundleExecutable + QtGui + NOTE + Please, do NOT change this file -- It was generated by Qt/QMake. + + diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/QtGui b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/QtGui new file mode 120000 index 0000000..6fe6929 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/QtGui @@ -0,0 +1 @@ +Versions/4/QtGui \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/QtGui.prl b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/QtGui.prl new file mode 100644 index 0000000..d1ad6f8 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/QtGui.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/gui +QMAKE_PRO_INPUT = gui.pro +QMAKE_PRL_TARGET = QtGui +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on uic resources sdk rez release ReleaseBuild Release build_pass qt warn_on release app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend release stl qt_framework x86_64 release largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build release ReleaseBuild Release build_pass qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib release ReleaseBuild Release build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib -F/usr/local/Cellar/qt/4.8.5/lib -framework QtCore -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/QtGui_debug.prl b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/QtGui_debug.prl new file mode 100644 index 0000000..d2e8e86 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/QtGui_debug.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/gui +QMAKE_PRO_INPUT = gui.pro +QMAKE_PRL_TARGET = QtGui_debug +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on debug uic resources sdk rez debug DebugBuild Debug build_pass qt warn_on app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend stl qt_framework x86_64 largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build debug DebugBuild Debug build_pass qt_install_headers qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib debug DebugBuild Debug build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -F/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -framework QtCore -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Resources b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Resources new file mode 120000 index 0000000..d716e79 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Resources @@ -0,0 +1 @@ +Versions/4/Resources \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Versions/4/QtGui b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Versions/4/QtGui new file mode 100644 index 0000000..5bfd0a5 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Versions/4/QtGui differ diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Versions/4/Resources/qt_menu.nib/classes.nib b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Versions/4/Resources/qt_menu.nib/classes.nib new file mode 100644 index 0000000..0031e0e --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Versions/4/Resources/qt_menu.nib/classes.nib @@ -0,0 +1,59 @@ + + + + + IBClasses + + + ACTIONS + + hide + id + hideOtherApplications + id + orderFrontStandardAboutPanel + id + qtDispatcherToQAction + id + terminate + id + unhideAllApplications + id + + CLASS + QCocoaMenuLoader + LANGUAGE + ObjC + OUTLETS + + aboutItem + NSMenuItem + aboutQtItem + NSMenuItem + appMenu + NSMenu + hideItem + NSMenuItem + preferencesItem + NSMenuItem + quitItem + NSMenuItem + theMenu + NSMenu + + SUPERCLASS + NSResponder + + + CLASS + FirstResponder + LANGUAGE + ObjC + SUPERCLASS + NSObject + + + IBVersion + 1 + + diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Versions/4/Resources/qt_menu.nib/info.nib b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Versions/4/Resources/qt_menu.nib/info.nib new file mode 100644 index 0000000..02e5cca --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Versions/4/Resources/qt_menu.nib/info.nib @@ -0,0 +1,18 @@ + + + + + IBFramework Version + 672 + IBOldestOS + 5 + IBOpenObjects + + 57 + + IBSystem Version + 9L31a + targetFramework + IBCocoaFramework + + diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Versions/4/Resources/qt_menu.nib/keyedobjects.nib b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Versions/4/Resources/qt_menu.nib/keyedobjects.nib new file mode 100644 index 0000000..67207ca Binary files /dev/null and b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Versions/4/Resources/qt_menu.nib/keyedobjects.nib differ diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Versions/Current b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Versions/Current new file mode 120000 index 0000000..bf0d87a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtGui.framework/Versions/Current @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtHelp.framework/Contents/Info.plist b/FeedTheMonkey.app/Contents/Frameworks/QtHelp.framework/Contents/Info.plist new file mode 100644 index 0000000..33ec1a7 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtHelp.framework/Contents/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.8 + CFBundleGetInfoString + Created by Qt/QMake + CFBundleSignature + ???? + CFBundleExecutable + QtHelp + NOTE + Please, do NOT change this file -- It was generated by Qt/QMake. + + diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtHelp.framework/QtHelp b/FeedTheMonkey.app/Contents/Frameworks/QtHelp.framework/QtHelp new file mode 120000 index 0000000..b639360 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtHelp.framework/QtHelp @@ -0,0 +1 @@ +Versions/4/QtHelp \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtHelp.framework/QtHelp.prl b/FeedTheMonkey.app/Contents/Frameworks/QtHelp.framework/QtHelp.prl new file mode 100644 index 0000000..8b237d6 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtHelp.framework/QtHelp.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./tools/assistant/lib +QMAKE_PRO_INPUT = lib.pro +QMAKE_PRL_TARGET = QtHelp +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on uic resources sdk rez release ReleaseBuild Release build_pass qt warn_on release app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend release stl qt_framework x86_64 release largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build release ReleaseBuild Release build_pass qt warn_on qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib release ReleaseBuild Release build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib -F/usr/local/Cellar/qt/4.8.5/lib -framework QtSql -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib -F/usr/local/Cellar/qt/4.8.5/lib -framework QtCore -framework QtGui -framework QtNetwork diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtHelp.framework/QtHelp_debug.prl b/FeedTheMonkey.app/Contents/Frameworks/QtHelp.framework/QtHelp_debug.prl new file mode 100644 index 0000000..7e9aa3d --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtHelp.framework/QtHelp_debug.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./tools/assistant/lib +QMAKE_PRO_INPUT = lib.pro +QMAKE_PRL_TARGET = QtHelp_debug +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on debug uic resources sdk rez debug DebugBuild Debug build_pass qt warn_on app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend stl qt_framework x86_64 largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build debug DebugBuild Debug build_pass qt warn_on qt_install_headers qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib debug DebugBuild Debug build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -F/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -framework QtSql -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -F/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -framework QtCore -framework QtGui -framework QtNetwork diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtHelp.framework/Versions/4/QtHelp b/FeedTheMonkey.app/Contents/Frameworks/QtHelp.framework/Versions/4/QtHelp new file mode 100644 index 0000000..a30667f Binary files /dev/null and b/FeedTheMonkey.app/Contents/Frameworks/QtHelp.framework/Versions/4/QtHelp differ diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtHelp.framework/Versions/Current b/FeedTheMonkey.app/Contents/Frameworks/QtHelp.framework/Versions/Current new file mode 120000 index 0000000..bf0d87a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtHelp.framework/Versions/Current @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtMultimedia.framework/Contents/Info.plist b/FeedTheMonkey.app/Contents/Frameworks/QtMultimedia.framework/Contents/Info.plist new file mode 100644 index 0000000..1196ad9 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtMultimedia.framework/Contents/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.8 + CFBundleGetInfoString + Created by Qt/QMake + CFBundleSignature + ???? + CFBundleExecutable + QtMultimedia + NOTE + Please, do NOT change this file -- It was generated by Qt/QMake. + + diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtMultimedia.framework/QtMultimedia b/FeedTheMonkey.app/Contents/Frameworks/QtMultimedia.framework/QtMultimedia new file mode 120000 index 0000000..6141cfe --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtMultimedia.framework/QtMultimedia @@ -0,0 +1 @@ +Versions/4/QtMultimedia \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtMultimedia.framework/QtMultimedia.prl b/FeedTheMonkey.app/Contents/Frameworks/QtMultimedia.framework/QtMultimedia.prl new file mode 100644 index 0000000..ec891a1 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtMultimedia.framework/QtMultimedia.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/multimedia +QMAKE_PRO_INPUT = multimedia.pro +QMAKE_PRL_TARGET = QtMultimedia +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on uic resources sdk rez release ReleaseBuild Release build_pass qt warn_on release app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend release stl qt_framework x86_64 release largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build release ReleaseBuild Release build_pass qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib release ReleaseBuild Release build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib -F/usr/local/Cellar/qt/4.8.5/lib -framework ApplicationServices -framework CoreAudio -framework AudioUnit -framework AudioToolbox -framework QtGui -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib -F/usr/local/Cellar/qt/4.8.5/lib -framework QtCore diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtMultimedia.framework/QtMultimedia_debug.prl b/FeedTheMonkey.app/Contents/Frameworks/QtMultimedia.framework/QtMultimedia_debug.prl new file mode 100644 index 0000000..e746785 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtMultimedia.framework/QtMultimedia_debug.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/multimedia +QMAKE_PRO_INPUT = multimedia.pro +QMAKE_PRL_TARGET = QtMultimedia_debug +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on debug uic resources sdk rez debug DebugBuild Debug build_pass qt warn_on app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend stl qt_framework x86_64 largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build debug DebugBuild Debug build_pass qt_install_headers qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib debug DebugBuild Debug build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -F/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -framework ApplicationServices -framework CoreAudio -framework AudioUnit -framework AudioToolbox -framework QtGui -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -F/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -framework QtCore diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtMultimedia.framework/Versions/4/QtMultimedia b/FeedTheMonkey.app/Contents/Frameworks/QtMultimedia.framework/Versions/4/QtMultimedia new file mode 100644 index 0000000..a22c304 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Frameworks/QtMultimedia.framework/Versions/4/QtMultimedia differ diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtMultimedia.framework/Versions/Current b/FeedTheMonkey.app/Contents/Frameworks/QtMultimedia.framework/Versions/Current new file mode 120000 index 0000000..bf0d87a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtMultimedia.framework/Versions/Current @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtNetwork.framework/Contents/Info.plist b/FeedTheMonkey.app/Contents/Frameworks/QtNetwork.framework/Contents/Info.plist new file mode 100644 index 0000000..e36265c --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtNetwork.framework/Contents/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.8 + CFBundleGetInfoString + Created by Qt/QMake + CFBundleSignature + ???? + CFBundleExecutable + QtNetwork + NOTE + Please, do NOT change this file -- It was generated by Qt/QMake. + + diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtNetwork.framework/QtNetwork b/FeedTheMonkey.app/Contents/Frameworks/QtNetwork.framework/QtNetwork new file mode 120000 index 0000000..1c38727 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtNetwork.framework/QtNetwork @@ -0,0 +1 @@ +Versions/4/QtNetwork \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtNetwork.framework/QtNetwork.prl b/FeedTheMonkey.app/Contents/Frameworks/QtNetwork.framework/QtNetwork.prl new file mode 100644 index 0000000..8aedb47 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtNetwork.framework/QtNetwork.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/network +QMAKE_PRO_INPUT = network.pro +QMAKE_PRL_TARGET = QtNetwork +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on uic resources sdk rez release ReleaseBuild Release build_pass qt warn_on release app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend release stl qt_framework x86_64 release largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build release ReleaseBuild Release build_pass qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib release ReleaseBuild Release build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib -F/usr/local/Cellar/qt/4.8.5/lib -framework QtCore -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtNetwork.framework/QtNetwork_debug.prl b/FeedTheMonkey.app/Contents/Frameworks/QtNetwork.framework/QtNetwork_debug.prl new file mode 100644 index 0000000..2359e88 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtNetwork.framework/QtNetwork_debug.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/network +QMAKE_PRO_INPUT = network.pro +QMAKE_PRL_TARGET = QtNetwork_debug +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on debug uic resources sdk rez debug DebugBuild Debug build_pass qt warn_on app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend stl qt_framework x86_64 largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build debug DebugBuild Debug build_pass qt_install_headers qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib debug DebugBuild Debug build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -F/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -framework QtCore -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtNetwork.framework/Versions/4/QtNetwork b/FeedTheMonkey.app/Contents/Frameworks/QtNetwork.framework/Versions/4/QtNetwork new file mode 100644 index 0000000..91b5f3a Binary files /dev/null and b/FeedTheMonkey.app/Contents/Frameworks/QtNetwork.framework/Versions/4/QtNetwork differ diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtNetwork.framework/Versions/Current b/FeedTheMonkey.app/Contents/Frameworks/QtNetwork.framework/Versions/Current new file mode 120000 index 0000000..bf0d87a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtNetwork.framework/Versions/Current @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtScript.framework/Contents/Info.plist b/FeedTheMonkey.app/Contents/Frameworks/QtScript.framework/Contents/Info.plist new file mode 100644 index 0000000..fa25169 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtScript.framework/Contents/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.8 + CFBundleGetInfoString + Created by Qt/QMake + CFBundleSignature + ???? + CFBundleExecutable + QtScript + NOTE + Please, do NOT change this file -- It was generated by Qt/QMake. + + diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtScript.framework/QtScript b/FeedTheMonkey.app/Contents/Frameworks/QtScript.framework/QtScript new file mode 120000 index 0000000..28a40f4 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtScript.framework/QtScript @@ -0,0 +1 @@ +Versions/4/QtScript \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtScript.framework/QtScript.prl b/FeedTheMonkey.app/Contents/Frameworks/QtScript.framework/QtScript.prl new file mode 100644 index 0000000..b5ddb75 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtScript.framework/QtScript.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/script +QMAKE_PRO_INPUT = script.pro +QMAKE_PRL_TARGET = QtScript +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc uic resources sdk rez release ReleaseBuild Release build_pass qt release app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend release stl qt_framework x86_64 release largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build release ReleaseBuild Release build_pass qt depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib building-libs standalone_package depend_includepath release ReleaseBuild Release build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib -F/usr/local/Cellar/qt/4.8.5/lib -framework QtCore -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtScript.framework/QtScript_debug.prl b/FeedTheMonkey.app/Contents/Frameworks/QtScript.framework/QtScript_debug.prl new file mode 100644 index 0000000..719782a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtScript.framework/QtScript_debug.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/script +QMAKE_PRO_INPUT = script.pro +QMAKE_PRL_TARGET = QtScript_debug +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc debug uic resources sdk rez debug DebugBuild Debug build_pass qt app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend stl qt_framework x86_64 largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build debug DebugBuild Debug build_pass qt_install_headers qt depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib building-libs standalone_package depend_includepath debug DebugBuild Debug build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -F/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -framework QtCore -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtScript.framework/Versions/4/QtScript b/FeedTheMonkey.app/Contents/Frameworks/QtScript.framework/Versions/4/QtScript new file mode 100644 index 0000000..5d71872 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Frameworks/QtScript.framework/Versions/4/QtScript differ diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtScript.framework/Versions/Current b/FeedTheMonkey.app/Contents/Frameworks/QtScript.framework/Versions/Current new file mode 120000 index 0000000..bf0d87a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtScript.framework/Versions/Current @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtScriptTools.framework/Contents/Info.plist b/FeedTheMonkey.app/Contents/Frameworks/QtScriptTools.framework/Contents/Info.plist new file mode 100644 index 0000000..9b2d1af --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtScriptTools.framework/Contents/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.8 + CFBundleGetInfoString + Created by Qt/QMake + CFBundleSignature + ???? + CFBundleExecutable + QtScriptTools + NOTE + Please, do NOT change this file -- It was generated by Qt/QMake. + + diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtScriptTools.framework/QtScriptTools b/FeedTheMonkey.app/Contents/Frameworks/QtScriptTools.framework/QtScriptTools new file mode 120000 index 0000000..9e7de17 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtScriptTools.framework/QtScriptTools @@ -0,0 +1 @@ +Versions/4/QtScriptTools \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtScriptTools.framework/QtScriptTools.prl b/FeedTheMonkey.app/Contents/Frameworks/QtScriptTools.framework/QtScriptTools.prl new file mode 100644 index 0000000..e7c0620 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtScriptTools.framework/QtScriptTools.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/scripttools +QMAKE_PRO_INPUT = scripttools.pro +QMAKE_PRL_TARGET = QtScriptTools +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on uic resources sdk rez release ReleaseBuild Release build_pass qt warn_on release app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend release stl qt_framework x86_64 release largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build release ReleaseBuild Release build_pass qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib release ReleaseBuild Release build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib -F/usr/local/Cellar/qt/4.8.5/lib -framework QtScript -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib -F/usr/local/Cellar/qt/4.8.5/lib -framework QtCore -framework QtGui diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtScriptTools.framework/QtScriptTools_debug.prl b/FeedTheMonkey.app/Contents/Frameworks/QtScriptTools.framework/QtScriptTools_debug.prl new file mode 100644 index 0000000..0178e17 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtScriptTools.framework/QtScriptTools_debug.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/scripttools +QMAKE_PRO_INPUT = scripttools.pro +QMAKE_PRL_TARGET = QtScriptTools_debug +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on debug uic resources sdk rez debug DebugBuild Debug build_pass qt warn_on app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend stl qt_framework x86_64 largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build debug DebugBuild Debug build_pass qt_install_headers qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib debug DebugBuild Debug build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -F/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -framework QtScript -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -F/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -framework QtCore -framework QtGui diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtScriptTools.framework/Versions/4/QtScriptTools b/FeedTheMonkey.app/Contents/Frameworks/QtScriptTools.framework/Versions/4/QtScriptTools new file mode 100644 index 0000000..48fb586 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Frameworks/QtScriptTools.framework/Versions/4/QtScriptTools differ diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtScriptTools.framework/Versions/Current b/FeedTheMonkey.app/Contents/Frameworks/QtScriptTools.framework/Versions/Current new file mode 120000 index 0000000..bf0d87a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtScriptTools.framework/Versions/Current @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtSql.framework/Contents/Info.plist b/FeedTheMonkey.app/Contents/Frameworks/QtSql.framework/Contents/Info.plist new file mode 100644 index 0000000..14661e9 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtSql.framework/Contents/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.8 + CFBundleGetInfoString + Created by Qt/QMake + CFBundleSignature + ???? + CFBundleExecutable + QtSql + NOTE + Please, do NOT change this file -- It was generated by Qt/QMake. + + diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtSql.framework/QtSql b/FeedTheMonkey.app/Contents/Frameworks/QtSql.framework/QtSql new file mode 120000 index 0000000..b507a40 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtSql.framework/QtSql @@ -0,0 +1 @@ +Versions/4/QtSql \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtSql.framework/QtSql.prl b/FeedTheMonkey.app/Contents/Frameworks/QtSql.framework/QtSql.prl new file mode 100644 index 0000000..8043aac --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtSql.framework/QtSql.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/sql +QMAKE_PRO_INPUT = sql.pro +QMAKE_PRL_TARGET = QtSql +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on uic resources sdk rez release ReleaseBuild Release build_pass qt warn_on release app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend release stl qt_framework x86_64 release largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build release ReleaseBuild Release build_pass qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib release ReleaseBuild Release build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib -F/usr/local/Cellar/qt/4.8.5/lib -framework QtCore -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtSql.framework/QtSql_debug.prl b/FeedTheMonkey.app/Contents/Frameworks/QtSql.framework/QtSql_debug.prl new file mode 100644 index 0000000..29c7e11 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtSql.framework/QtSql_debug.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/sql +QMAKE_PRO_INPUT = sql.pro +QMAKE_PRL_TARGET = QtSql_debug +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on debug uic resources sdk rez debug DebugBuild Debug build_pass qt warn_on app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend stl qt_framework x86_64 largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build debug DebugBuild Debug build_pass qt_install_headers qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib debug DebugBuild Debug build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -F/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -framework QtCore -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtSql.framework/Versions/4/QtSql b/FeedTheMonkey.app/Contents/Frameworks/QtSql.framework/Versions/4/QtSql new file mode 100644 index 0000000..3e15c85 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Frameworks/QtSql.framework/Versions/4/QtSql differ diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtSql.framework/Versions/Current b/FeedTheMonkey.app/Contents/Frameworks/QtSql.framework/Versions/Current new file mode 120000 index 0000000..bf0d87a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtSql.framework/Versions/Current @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtSvg.framework/Contents/Info.plist b/FeedTheMonkey.app/Contents/Frameworks/QtSvg.framework/Contents/Info.plist new file mode 100644 index 0000000..7f2f1ae --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtSvg.framework/Contents/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.8 + CFBundleGetInfoString + Created by Qt/QMake + CFBundleSignature + ???? + CFBundleExecutable + QtSvg + NOTE + Please, do NOT change this file -- It was generated by Qt/QMake. + + diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtSvg.framework/QtSvg b/FeedTheMonkey.app/Contents/Frameworks/QtSvg.framework/QtSvg new file mode 120000 index 0000000..da887c0 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtSvg.framework/QtSvg @@ -0,0 +1 @@ +Versions/4/QtSvg \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtSvg.framework/QtSvg.prl b/FeedTheMonkey.app/Contents/Frameworks/QtSvg.framework/QtSvg.prl new file mode 100644 index 0000000..c824851 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtSvg.framework/QtSvg.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/svg +QMAKE_PRO_INPUT = svg.pro +QMAKE_PRL_TARGET = QtSvg +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on uic resources sdk rez release ReleaseBuild Release build_pass qt warn_on release app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend release stl qt_framework x86_64 release largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build release ReleaseBuild Release build_pass qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib release ReleaseBuild Release build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib -F/usr/local/Cellar/qt/4.8.5/lib -framework QtGui -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib -F/usr/local/Cellar/qt/4.8.5/lib -framework QtCore diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtSvg.framework/QtSvg_debug.prl b/FeedTheMonkey.app/Contents/Frameworks/QtSvg.framework/QtSvg_debug.prl new file mode 100644 index 0000000..24bcb2b --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtSvg.framework/QtSvg_debug.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/svg +QMAKE_PRO_INPUT = svg.pro +QMAKE_PRL_TARGET = QtSvg_debug +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on debug uic resources sdk rez debug DebugBuild Debug build_pass qt warn_on app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend stl qt_framework x86_64 largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build debug DebugBuild Debug build_pass qt_install_headers qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib debug DebugBuild Debug build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -F/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -framework QtGui -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -F/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -framework QtCore diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtSvg.framework/Versions/4/QtSvg b/FeedTheMonkey.app/Contents/Frameworks/QtSvg.framework/Versions/4/QtSvg new file mode 100644 index 0000000..b6a6f0c Binary files /dev/null and b/FeedTheMonkey.app/Contents/Frameworks/QtSvg.framework/Versions/4/QtSvg differ diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtSvg.framework/Versions/Current b/FeedTheMonkey.app/Contents/Frameworks/QtSvg.framework/Versions/Current new file mode 120000 index 0000000..bf0d87a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtSvg.framework/Versions/Current @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtWebKit.framework/Contents/Info.plist b/FeedTheMonkey.app/Contents/Frameworks/QtWebKit.framework/Contents/Info.plist new file mode 100644 index 0000000..0537d6b --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtWebKit.framework/Contents/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.9 + CFBundleGetInfoString + Created by Qt/QMake + CFBundleSignature + ???? + CFBundleExecutable + QtWebKit + NOTE + Please, do NOT change this file -- It was generated by Qt/QMake. + + diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtWebKit.framework/QtWebKit b/FeedTheMonkey.app/Contents/Frameworks/QtWebKit.framework/QtWebKit new file mode 120000 index 0000000..1222aed --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtWebKit.framework/QtWebKit @@ -0,0 +1 @@ +Versions/4/QtWebKit \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtWebKit.framework/QtWebKit.prl b/FeedTheMonkey.app/Contents/Frameworks/QtWebKit.framework/QtWebKit.prl new file mode 100644 index 0000000..829bb2a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtWebKit.framework/QtWebKit.prl @@ -0,0 +1,6 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/src/3rdparty/webkit/Source/WebKit/qt/ +QMAKE_PRO_INPUT = QtWebKit.pro +QMAKE_PRL_TARGET = QtWebKit +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc uic resources sdk rez release ReleaseBuild Release build_pass qt release app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend release stl qt_framework x86_64 release largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build release ReleaseBuild Release build_pass building-libs depend_includepath standalone_package debug_and_release depend_includepath include_webinspector production production no_debug_info production qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework create_pc create_libtool release ReleaseBuild Release build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.9.4 diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtWebKit.framework/QtWebKit_debug.prl b/FeedTheMonkey.app/Contents/Frameworks/QtWebKit.framework/QtWebKit_debug.prl new file mode 100644 index 0000000..e94f6b1 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtWebKit.framework/QtWebKit_debug.prl @@ -0,0 +1,6 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/src/3rdparty/webkit/Source/WebKit/qt/ +QMAKE_PRO_INPUT = QtWebKit.pro +QMAKE_PRL_TARGET = QtWebKit_debug +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc debug uic resources sdk rez debug DebugBuild Debug build_pass qt app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend stl qt_framework x86_64 largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build debug DebugBuild Debug build_pass building-libs depend_includepath standalone_package debug_and_release depend_includepath include_webinspector production production no_debug_info production qt_install_headers qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework create_pc create_libtool debug DebugBuild Debug build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.9.4 diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtWebKit.framework/Versions/4/QtWebKit b/FeedTheMonkey.app/Contents/Frameworks/QtWebKit.framework/Versions/4/QtWebKit new file mode 100644 index 0000000..04ae21e Binary files /dev/null and b/FeedTheMonkey.app/Contents/Frameworks/QtWebKit.framework/Versions/4/QtWebKit differ diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtWebKit.framework/Versions/Current b/FeedTheMonkey.app/Contents/Frameworks/QtWebKit.framework/Versions/Current new file mode 120000 index 0000000..bf0d87a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtWebKit.framework/Versions/Current @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtXml.framework/Contents/Info.plist b/FeedTheMonkey.app/Contents/Frameworks/QtXml.framework/Contents/Info.plist new file mode 100644 index 0000000..8ddd3f5 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtXml.framework/Contents/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.8 + CFBundleGetInfoString + Created by Qt/QMake + CFBundleSignature + ???? + CFBundleExecutable + QtXml + NOTE + Please, do NOT change this file -- It was generated by Qt/QMake. + + diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtXml.framework/QtXml b/FeedTheMonkey.app/Contents/Frameworks/QtXml.framework/QtXml new file mode 120000 index 0000000..13dddf0 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtXml.framework/QtXml @@ -0,0 +1 @@ +Versions/4/QtXml \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtXml.framework/QtXml.prl b/FeedTheMonkey.app/Contents/Frameworks/QtXml.framework/QtXml.prl new file mode 100644 index 0000000..26e1089 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtXml.framework/QtXml.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/xml +QMAKE_PRO_INPUT = xml.pro +QMAKE_PRL_TARGET = QtXml +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on uic resources sdk rez release ReleaseBuild Release build_pass qt warn_on release app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend release stl qt_framework x86_64 release largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build release ReleaseBuild Release build_pass qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib release ReleaseBuild Release build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib -F/usr/local/Cellar/qt/4.8.5/lib -framework QtCore -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtXml.framework/QtXml_debug.prl b/FeedTheMonkey.app/Contents/Frameworks/QtXml.framework/QtXml_debug.prl new file mode 100644 index 0000000..63bdcb0 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtXml.framework/QtXml_debug.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/xml +QMAKE_PRO_INPUT = xml.pro +QMAKE_PRL_TARGET = QtXml_debug +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on debug uic resources sdk rez debug DebugBuild Debug build_pass qt warn_on app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend stl qt_framework x86_64 largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build debug DebugBuild Debug build_pass qt_install_headers qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib debug DebugBuild Debug build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -F/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -framework QtCore -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtXml.framework/Versions/4/QtXml b/FeedTheMonkey.app/Contents/Frameworks/QtXml.framework/Versions/4/QtXml new file mode 100644 index 0000000..3329ab0 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Frameworks/QtXml.framework/Versions/4/QtXml differ diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtXml.framework/Versions/Current b/FeedTheMonkey.app/Contents/Frameworks/QtXml.framework/Versions/Current new file mode 120000 index 0000000..bf0d87a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtXml.framework/Versions/Current @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtXmlPatterns.framework/Contents/Info.plist b/FeedTheMonkey.app/Contents/Frameworks/QtXmlPatterns.framework/Contents/Info.plist new file mode 100644 index 0000000..2d62e86 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtXmlPatterns.framework/Contents/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.8 + CFBundleGetInfoString + Created by Qt/QMake + CFBundleSignature + ???? + CFBundleExecutable + QtXmlPatterns + NOTE + Please, do NOT change this file -- It was generated by Qt/QMake. + + diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtXmlPatterns.framework/QtXmlPatterns b/FeedTheMonkey.app/Contents/Frameworks/QtXmlPatterns.framework/QtXmlPatterns new file mode 120000 index 0000000..4247d18 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtXmlPatterns.framework/QtXmlPatterns @@ -0,0 +1 @@ +Versions/4/QtXmlPatterns \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtXmlPatterns.framework/QtXmlPatterns.prl b/FeedTheMonkey.app/Contents/Frameworks/QtXmlPatterns.framework/QtXmlPatterns.prl new file mode 100644 index 0000000..bf23f21 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtXmlPatterns.framework/QtXmlPatterns.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/xmlpatterns +QMAKE_PRO_INPUT = xmlpatterns.pro +QMAKE_PRL_TARGET = QtXmlPatterns +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on uic resources sdk rez release ReleaseBuild Release build_pass qt warn_on release app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend release stl qt_framework x86_64 release largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build release ReleaseBuild Release build_pass qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib release ReleaseBuild Release build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib -F/usr/local/Cellar/qt/4.8.5/lib -framework QtNetwork -L/opt/X11/lib -L/usr/local/Cellar/qt/4.8.5/lib -F/usr/local/Cellar/qt/4.8.5/lib -framework QtCore diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtXmlPatterns.framework/QtXmlPatterns_debug.prl b/FeedTheMonkey.app/Contents/Frameworks/QtXmlPatterns.framework/QtXmlPatterns_debug.prl new file mode 100644 index 0000000..59a52bb --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtXmlPatterns.framework/QtXmlPatterns_debug.prl @@ -0,0 +1,7 @@ +QMAKE_PRL_BUILD_DIR = /private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/./src/xmlpatterns +QMAKE_PRO_INPUT = xmlpatterns.pro +QMAKE_PRL_TARGET = QtXmlPatterns_debug +QMAKE_PRL_DEFINES = QT_SHARED +QMAKE_PRL_CONFIG = lex yacc warn_on debug uic resources sdk rez debug DebugBuild Debug build_pass qt warn_on app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl clang_pch_style shared def_files_disabled exceptions no_mocdepend stl qt_framework x86_64 largefile stl mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx x86_64 absolute_library_soname dylib create_prl link_prl depend_includepath QTDIR_build debug DebugBuild Debug build_pass qt_install_headers qt warn_on depend_includepath qmake_cache target_qt debug_and_release hide_symbols lib_bundle qt_no_framework_direct_includes qt_framework explicitlib create_pc create_libtool explicitlib debug DebugBuild Debug build_pass objective_c x86_64 no_autoqmake moc thread dll shared +QMAKE_PRL_VERSION = 4.8.5 +QMAKE_PRL_LIBS = -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -F/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -framework QtNetwork -L/opt/X11/lib -L/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -F/private/tmp/qt-FECA/qt-everywhere-opensource-src-4.8.5/lib -framework QtCore diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtXmlPatterns.framework/Versions/4/QtXmlPatterns b/FeedTheMonkey.app/Contents/Frameworks/QtXmlPatterns.framework/Versions/4/QtXmlPatterns new file mode 100644 index 0000000..fd78a4f Binary files /dev/null and b/FeedTheMonkey.app/Contents/Frameworks/QtXmlPatterns.framework/Versions/4/QtXmlPatterns differ diff --git a/FeedTheMonkey.app/Contents/Frameworks/QtXmlPatterns.framework/Versions/Current b/FeedTheMonkey.app/Contents/Frameworks/QtXmlPatterns.framework/Versions/Current new file mode 120000 index 0000000..bf0d87a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/QtXmlPatterns.framework/Versions/Current @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Frameworks/libQtCLucene.4.8.5.dylib b/FeedTheMonkey.app/Contents/Frameworks/libQtCLucene.4.8.5.dylib new file mode 100644 index 0000000..2f901c6 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Frameworks/libQtCLucene.4.8.5.dylib differ diff --git a/FeedTheMonkey.app/Contents/Frameworks/libQtCLucene.4.dylib b/FeedTheMonkey.app/Contents/Frameworks/libQtCLucene.4.dylib new file mode 120000 index 0000000..0c17d79 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Frameworks/libQtCLucene.4.dylib @@ -0,0 +1 @@ +libQtCLucene.4.8.5.dylib \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Info.plist b/FeedTheMonkey.app/Contents/Info.plist new file mode 100644 index 0000000..fda87a2 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Info.plist @@ -0,0 +1,98 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + FeedTheMonkey + CFBundleExecutable + FeedTheMonkey + CFBundleIconFile + Icon.icns + CFBundleIdentifier + nu.jabs.apps.feedthemonkey + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + FeedTheMonkey + CFBundlePackageType + APPL + CFBundleShortVersionString + 0.1.1 + CFBundleSignature + ???? + CFBundleURLTypes + + + CFBundleURLName + nu.jabs.apps.feedthemonkey.handler + CFBundleURLSchemes + + feedthemonkey + + + + CFBundleVersion + 0.1.1 + LSHasLocalizedDisplayName + + LSMinimumSystemVersion + 10.4 + NSAppleScriptEnabled + + NSHumanReadableCopyright + Copyright not specified + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + PyMainFileNames + + __boot__ + + PyOptions + + alias + + argv_emulation + + emulate_shell_environment + + no_chdir + + prefer_ppc + + site_packages + + use_pythonpath + + + PyResourcePackages + + + PyRuntimeLocations + + @executable_path/../Frameworks/Python.framework/Versions/2.7/Python + + PythonInfoDict + + PythonExecutable + /usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python + PythonLongVersion + 2.7.5 (default, Sep 14 2013, 22:19:06) +[GCC 4.2.1 Compatible Apple LLVM 4.2 (clang-425.0.28)] + PythonShortVersion + 2.7 + py2app + + alias + + template + app + version + 0.7.3 + + + + diff --git a/FeedTheMonkey.app/Contents/MacOS/FeedTheMonkey b/FeedTheMonkey.app/Contents/MacOS/FeedTheMonkey new file mode 100755 index 0000000..ccd180e Binary files /dev/null and b/FeedTheMonkey.app/Contents/MacOS/FeedTheMonkey differ diff --git a/FeedTheMonkey.app/Contents/MacOS/python b/FeedTheMonkey.app/Contents/MacOS/python new file mode 100755 index 0000000..4ed976a Binary files /dev/null and b/FeedTheMonkey.app/Contents/MacOS/python differ diff --git a/FeedTheMonkey.app/Contents/PkgInfo b/FeedTheMonkey.app/Contents/PkgInfo new file mode 100644 index 0000000..bd04210 --- /dev/null +++ b/FeedTheMonkey.app/Contents/PkgInfo @@ -0,0 +1 @@ +APPL???? \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Resources/Icon.icns b/FeedTheMonkey.app/Contents/Resources/Icon.icns new file mode 100644 index 0000000..c365038 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/Icon.icns differ diff --git a/FeedTheMonkey.app/Contents/Resources/__boot__.py b/FeedTheMonkey.app/Contents/Resources/__boot__.py new file mode 100644 index 0000000..1277f7d --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/__boot__.py @@ -0,0 +1,43 @@ +def _reset_sys_path(): + # Clear generic sys.path[0] + import sys, os + resources = os.environ['RESOURCEPATH'] + while sys.path[0] == resources: + del sys.path[0] +_reset_sys_path() + + +def _chdir_resource(): + import os + os.chdir(os.environ['RESOURCEPATH']) +_chdir_resource() + + +def _disable_linecache(): + import linecache + def fake_getline(*args, **kwargs): + return '' + linecache.orig_getline = linecache.getline + linecache.getline = fake_getline +_disable_linecache() + + +def _run(): + global __file__ + import os, sys, site + sys.frozen = 'macosx_app' + base = os.environ['RESOURCEPATH'] + + argv0 = os.path.basename(os.environ['ARGVZERO']) + script = SCRIPT_MAP.get(argv0, DEFAULT_SCRIPT) + + path = os.path.join(base, script) + sys.argv[0] = __file__ = path + with open(path, 'rU') as fp: + source = fp.read() + "\n" + exec(compile(source, path, 'exec'), globals(), globals()) + + +DEFAULT_SCRIPT='feedthemonkey' +SCRIPT_MAP={} +_run() diff --git a/FeedTheMonkey.app/Contents/Resources/__error__.sh b/FeedTheMonkey.app/Contents/Resources/__error__.sh new file mode 100755 index 0000000..f1122a6 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/__error__.sh @@ -0,0 +1,19 @@ +#!/bin/sh +# +# This is the default apptemplate error script +# +if ( test -n "$2" ) ; then + echo "$1 Error" + echo "An unexpected error has occurred during execution of the main script" + echo "" + echo "$2: $3" + echo "" + echo "See the Console for a detailed traceback." +else + echo "$1 Error" + + # Usage: ERRORURL , this is used by the + # bundle runner to put up a dialog. + #echo "ERRORURL: http://www.python.org/ Visit the Python Website +# echo "ERRORURL: http://homepages.cwi.nl/~jack/macpython/index.html Visit the MacPython Website" +fi diff --git a/FeedTheMonkey.app/Contents/Resources/feedthemonkey b/FeedTheMonkey.app/Contents/Resources/feedthemonkey new file mode 100755 index 0000000..745e0c9 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/feedthemonkey @@ -0,0 +1,537 @@ +#!/usr/bin/env python2 + +import sys, os, json, tempfile, urllib2, urllib, json +from PyQt4 import QtGui, QtCore, QtWebKit, QtNetwork +from threading import Thread +from sys import platform as _platform + +settings = QtCore.QSettings("jabs.nu", "feedthemonkey") + +class MainWindow(QtGui.QMainWindow): + def __init__(self): + QtGui.QMainWindow.__init__(self) + self.setWindowIcon(QtGui.QIcon("feedmonkey")) + self.addAction(QtGui.QAction("Full Screen", self, checkable=True, toggled=lambda v: self.showFullScreen() if v else self.showNormal(), shortcut="F11")) + self.history = self.get("history", []) + self.restoreGeometry(QtCore.QByteArray.fromRawData(settings.value("geometry").toByteArray())) + self.restoreState(QtCore.QByteArray.fromRawData(settings.value("state").toByteArray())) + + self.initUI() + + session_id = self.get("session_id") + server_url = self.get("server_url") + + if not (session_id and server_url): + self.authenticate() + else: + self.initApp() + + + def initUI(self): + self.list = List(self) + self.content = Content(self) + + self.splitter = QtGui.QSplitter(QtCore.Qt.Vertical, self) + self.splitter.setHandleWidth(1) + self.splitter.addWidget(self.list) + self.splitter.addWidget(self.content) + self.splitter.restoreState(settings.value("splitterSizes").toByteArray()); + self.splitter.splitterMoved.connect(self.splitterMoved) + + self.setCentralWidget(self.splitter) + + def mkAction(name, connect, shortcut=None): + action = QtGui.QAction(name, self) + action.triggered.connect(connect) + if shortcut: + action.setShortcut(shortcut) + return action + + mb = self.menuBar() + + fileMenu = mb.addMenu("&File") + fileMenu.addAction(mkAction("&Close", self.close, "Ctrl+W")) + fileMenu.addAction(mkAction("&Log Out", self.logOut)) + fileMenu.addSeparator() + fileMenu.addAction(mkAction("&Exit", self.close, "Ctrl+Q")) + + actionMenu = mb.addMenu("&Action") + actionMenu.addAction(mkAction("&Reload", self.content.reload, "R")) + actionMenu.addAction(mkAction("Set &Unread", self.content.setUnread, "U")) + actionMenu.addAction(mkAction("&Next", self.content.showNext, "J")) + actionMenu.addAction(mkAction("&Previous", self.content.showPrevious, "K")) + actionMenu.addAction(mkAction("&Open in Browser", self.content.openCurrent, "N")) + + viewMenu = mb.addMenu("&View") + viewMenu.addAction(mkAction("Zoom &In", lambda: self.content.wb.setZoomFactor(self.content.wb.zoomFactor() + 0.2), "Ctrl++")) + viewMenu.addAction(mkAction("Zoom &Out", lambda: self.content.wb.setZoomFactor(self.content.wb.zoomFactor() - 0.2), "Ctrl+-")) + viewMenu.addAction(mkAction("&Reset", lambda: self.content.wb.setZoomFactor(1), "Ctrl+0")) + + windowMenu = mb.addMenu("&Window") + windowMenu.addAction(mkAction("Default", self.resetSplitter, "Ctrl+D")) + + helpMenu = mb.addMenu("&Help") + helpMenu.addAction(mkAction("&About", lambda: QtGui.QDesktopServices.openUrl(QtCore.QUrl("http://jabs.nu/feedthemonkey", QtCore.QUrl.TolerantMode)) )) + + def initApp(self): + session_id = self.get("session_id") + server_url = self.get("server_url") + self.tinyTinyRSS = TinyTinyRSS(self, server_url, session_id) + + self.content.evaluateJavaScript("setArticle('loading')") + self.content.reload() + self.show() + + def closeEvent(self, ev): + settings.setValue("geometry", self.saveGeometry()) + settings.setValue("state", self.saveState()) + return QtGui.QMainWindow.closeEvent(self, ev) + + def put(self, key, value): + "Persist an object somewhere under a given key" + settings.setValue(key, json.dumps(value)) + settings.sync() + + def get(self, key, default=None): + "Get the object stored under 'key' in persistent storage, or the default value" + v = settings.value(key) + return json.loads(unicode(v.toString())) if v.isValid() else default + + def setWindowTitle(self, t): + super(QtGui.QMainWindow, self).setWindowTitle("Feed the Monkey" + t) + + def splitterMoved(self, pos, index): + settings.setValue("splitterSizes", self.splitter.saveState()); + + def resetSplitter(self): + sizes = self.splitter.sizes() + top = sizes[0] + bottom = sizes[1] + sizes[0] = 200 + sizes[1] = bottom + top - 200 + self.splitter.setSizes(sizes) + + def authenticate(self): + + dialog = Login() + + def callback(): + + server_url = str(dialog.textServerUrl.text()) + user = str(dialog.textName.text()) + password = str(dialog.textPass.text()) + + session_id = TinyTinyRSS.login(server_url, user, password) + if session_id: + self.put("session_id", session_id) + self.put("server_url", server_url) + self.initApp() + else: + self.authenticate() + + dialog.accepted.connect(callback) + + dialog.exec_() + + def logOut(self): + self.hide() + self.content.evaluateJavaScript("setArticle('logout')") + self.tinyTinyRSS.logOut() + self.tinyTinyRSS = None + self.put("session_id", None) + self.put("server_url", None) + self.authenticate() + +class List(QtGui.QTableWidget): + def __init__(self, container): + QtGui.QTableWidget.__init__(self) + self.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) + self.app = container + self.itemSelectionChanged.connect(self.rowSelected) + self.setShowGrid(False) + + def initHeader(self): + self.clear() + self.setColumnCount(3) + self.setHorizontalHeaderLabels(("Feed", "Title", "Date")) + self.horizontalHeader().setResizeMode(0, QtGui.QHeaderView.ResizeToContents) + self.horizontalHeader().setResizeMode(1, QtGui.QHeaderView.Stretch) + self.horizontalHeader().setResizeMode(2, QtGui.QHeaderView.ResizeToContents) + self.verticalHeader().hide() + + def setItems(self, articles): + self.initHeader() + self.setRowCount(len(articles)) + row = 0 + for article in articles: + if "feed_title" in article: + feed_title = QtGui.QTableWidgetItem(article["feed_title"]) + feed_title.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + self.setItem(row, 0, feed_title) + if "title" in article: + title = QtGui.QTableWidgetItem(article["title"]) + title.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + self.setItem(row, 1, title) + if "updated" in article: + date = QtCore.QDateTime.fromTime_t(article["updated"]).toString(QtCore.Qt.SystemLocaleShortDate) + d = QtGui.QTableWidgetItem(date) + d.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + self.setItem(row, 2, d) + if "author" in article: + author = QtGui.QTableWidgetItem(article["author"]) + author.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + self.setItem(row, 3, author) + self.resizeRowToContents(row) + row += 1 + self.selectRow(0) + + def rowSelected(self): + indexes = self.selectedIndexes() + if len(indexes) > 0: + row = indexes[0].row() + self.app.content.showIndex(row) + + def updateRead(self): + for row, article in enumerate(self.app.content.unread_articles): + for x in xrange(0,3): + item = self.item(row, x) + font = item.font() + font.setBold(article["unread"]) + item.setFont(font) + + +class Content(QtGui.QWidget): + def __init__(self, container): + QtGui.QWidget.__init__(self) + + self.app = container + self.index = 0 + + self.wb = QtWebKit.QWebView(titleChanged=lambda t: container.setWindowTitle(t)) + self.wb.page().setLinkDelegationPolicy(QtWebKit.QWebPage.DelegateAllLinks) + self.wb.linkClicked.connect(lambda url: self.openLink(url)) + + self.setLayout(QtGui.QVBoxLayout(spacing=0)) + self.layout().setContentsMargins(0, 0, 0, 0) + self.layout().addWidget(self.wb) + + self.do_show_next = QtGui.QShortcut(QtCore.Qt.Key_Right, self, activated=self.showNext) + self.do_show_previous = QtGui.QShortcut(QtCore.Qt.Key_Left, self, activated=self.showPrevious) + self.do_open = QtGui.QShortcut("Return", self, activated=self.openCurrent) + + self.wb.settings().setAttribute(QtWebKit.QWebSettings.PluginsEnabled, True) + self.wb.settings().setIconDatabasePath(tempfile.mkdtemp()) + self.wb.setHtml(self.templateString()) + + self.unread_articles = [] + + def openLink(self, url): + QtGui.QDesktopServices.openUrl(url) + + def reload(self): + w = WorkerThread(self.app, self._reload) + self.connect(w, QtCore.SIGNAL("reload_done()"), self.reload_done) + w.start() + + def setUnread(self): + article = self.unread_articles[self.index] + article["unread"] = True + article["set_unread"] = True + self.app.list.updateRead() + + def _reload(self): + self.unread_articles = self.app.tinyTinyRSS.getUnreadFeeds() + self.index = -1 + + def reload_done(self): + self.setUnreadCount() + if len(self.unread_articles) > 0: + self.showNext() + self.app.list.setItems(self.unread_articles) + + def showIndex(self, index): + previous = self.unread_articles[self.index] + if not "set_unread" in previous or not previous["set_unread"]: + self.app.tinyTinyRSS.setArticleRead(previous["id"]) + previous["unread"] = False + self.app.list.updateRead() + else: + previous["set_unread"] = False + self.index = index + current = self.unread_articles[self.index] + self.setArticle(current) + self.setUnreadCount() + + def showNext(self): + if self.index >= 0 and self.index < len(self.unread_articles): + previous = self.unread_articles[self.index] + if not "set_unread" in previous or not previous["set_unread"]: + self.app.tinyTinyRSS.setArticleRead(previous["id"]) + previous["unread"] = False + self.app.list.updateRead() + else: + previous["set_unread"] = False + + if len(self.unread_articles) > self.index + 1: + self.index += 1 + current = self.unread_articles[self.index] + self.setArticle(current) + else: + if self.index < len(self.unread_articles): + self.index += 1 + + self.setUnreadCount() + self.app.list.selectRow(self.index) + + def showPrevious(self): + if self.index > 0: + self.index -= 1 + previous = self.unread_articles[self.index] + self.setArticle(previous) + self.setUnreadCount() + self.app.list.selectRow(self.index) + + def openCurrent(self): + current = self.unread_articles[self.index] + url = QtCore.QUrl(current["link"]) + self.openLink(url) + + def setArticle(self, article): + func = u"setArticle({});".format(json.dumps(article)) + self.evaluateJavaScript(func) + + def evaluateJavaScript(self, func): + return self.wb.page().mainFrame().evaluateJavaScript(func) + + def setUnreadCount(self): + length = len(self.unread_articles) + i = 0 + if self.index > 0: + i = self.index + unread = length - i + + self.app.setWindowTitle(" (" + str(unread) + "/" + str(length) + ")") + if unread < 1: + self.evaluateJavaScript("setArticle('empty')") + + def templateString(self): + html=""" + + + + + ttrssl + + + + +
+

+

+

+
+
+ + """ + return html # string.replace(html, " header file. */ +/* #undef HAVE_ASM_TYPES_H */ + +/* Define to 1 if you have the `atanh' function. */ +#define HAVE_ATANH 1 + +/* Define if GCC supports __attribute__((format(PyArg_ParseTuple, 2, 3))) */ +/* #undef HAVE_ATTRIBUTE_FORMAT_PARSETUPLE */ + +/* Define to 1 if you have the `bind_textdomain_codeset' function. */ +/* #undef HAVE_BIND_TEXTDOMAIN_CODESET */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_BLUETOOTH_BLUETOOTH_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_BLUETOOTH_H */ + +/* Define if nice() returns success/failure instead of the new priority. */ +/* #undef HAVE_BROKEN_NICE */ + +/* Define if the system reports an invalid PIPE_BUF value. */ +/* #undef HAVE_BROKEN_PIPE_BUF */ + +/* Define if poll() sets errno on invalid file descriptors. */ +/* #undef HAVE_BROKEN_POLL */ + +/* Define if the Posix semaphores do not work on your system */ +/* #undef HAVE_BROKEN_POSIX_SEMAPHORES */ + +/* Define if pthread_sigmask() does not work on your system. */ +/* #undef HAVE_BROKEN_PTHREAD_SIGMASK */ + +/* define to 1 if your sem_getvalue is broken. */ +#define HAVE_BROKEN_SEM_GETVALUE 1 + +/* Define if `unsetenv` does not return an int. */ +/* #undef HAVE_BROKEN_UNSETENV */ + +/* Define this if you have the type _Bool. */ +#define HAVE_C99_BOOL 1 + +/* Define to 1 if you have the 'chflags' function. */ +#define HAVE_CHFLAGS 1 + +/* Define to 1 if you have the `chown' function. */ +#define HAVE_CHOWN 1 + +/* Define if you have the 'chroot' function. */ +#define HAVE_CHROOT 1 + +/* Define to 1 if you have the `clock' function. */ +#define HAVE_CLOCK 1 + +/* Define to 1 if you have the `confstr' function. */ +#define HAVE_CONFSTR 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CONIO_H */ + +/* Define to 1 if you have the `copysign' function. */ +#define HAVE_COPYSIGN 1 + +/* Define to 1 if you have the `ctermid' function. */ +#define HAVE_CTERMID 1 + +/* Define if you have the 'ctermid_r' function. */ +#define HAVE_CTERMID_R 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CURSES_H 1 + +/* Define if you have the 'is_term_resized' function. */ +#define HAVE_CURSES_IS_TERM_RESIZED 1 + +/* Define if you have the 'resizeterm' function. */ +#define HAVE_CURSES_RESIZETERM 1 + +/* Define if you have the 'resize_term' function. */ +#define HAVE_CURSES_RESIZE_TERM 1 + +/* Define to 1 if you have the declaration of `isfinite', and to 0 if you + don't. */ +#define HAVE_DECL_ISFINITE 1 + +/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't. + */ +#define HAVE_DECL_ISINF 1 + +/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't. + */ +#define HAVE_DECL_ISNAN 1 + +/* Define to 1 if you have the declaration of `tzname', and to 0 if you don't. + */ +/* #undef HAVE_DECL_TZNAME */ + +/* Define to 1 if you have the device macros. */ +#define HAVE_DEVICE_MACROS 1 + +/* Define to 1 if you have the /dev/ptc device file. */ +/* #undef HAVE_DEV_PTC */ + +/* Define to 1 if you have the /dev/ptmx device file. */ +#define HAVE_DEV_PTMX 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DIRECT_H */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#define HAVE_DIRENT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `dlopen' function. */ +#define HAVE_DLOPEN 1 + +/* Define to 1 if you have the `dup2' function. */ +#define HAVE_DUP2 1 + +/* Defined when any dynamic module loading is enabled. */ +#define HAVE_DYNAMIC_LOADING 1 + +/* Define if you have the 'epoll' functions. */ +/* #undef HAVE_EPOLL */ + +/* Define to 1 if you have the `erf' function. */ +#define HAVE_ERF 1 + +/* Define to 1 if you have the `erfc' function. */ +#define HAVE_ERFC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the `execv' function. */ +#define HAVE_EXECV 1 + +/* Define to 1 if you have the `expm1' function. */ +#define HAVE_EXPM1 1 + +/* Define if you have the 'fchdir' function. */ +#define HAVE_FCHDIR 1 + +/* Define to 1 if you have the `fchmod' function. */ +#define HAVE_FCHMOD 1 + +/* Define to 1 if you have the `fchown' function. */ +#define HAVE_FCHOWN 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the 'fdatasync' function. */ +/* #undef HAVE_FDATASYNC */ + +/* Define to 1 if you have the `finite' function. */ +#define HAVE_FINITE 1 + +/* Define to 1 if you have the `flock' function. */ +#define HAVE_FLOCK 1 + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Define to 1 if you have the `forkpty' function. */ +#define HAVE_FORKPTY 1 + +/* Define to 1 if you have the `fpathconf' function. */ +#define HAVE_FPATHCONF 1 + +/* Define to 1 if you have the `fseek64' function. */ +/* #undef HAVE_FSEEK64 */ + +/* Define to 1 if you have the `fseeko' function. */ +#define HAVE_FSEEKO 1 + +/* Define to 1 if you have the `fstatvfs' function. */ +#define HAVE_FSTATVFS 1 + +/* Define if you have the 'fsync' function. */ +#define HAVE_FSYNC 1 + +/* Define to 1 if you have the `ftell64' function. */ +/* #undef HAVE_FTELL64 */ + +/* Define to 1 if you have the `ftello' function. */ +#define HAVE_FTELLO 1 + +/* Define to 1 if you have the `ftime' function. */ +#define HAVE_FTIME 1 + +/* Define to 1 if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the `gai_strerror' function. */ +#define HAVE_GAI_STRERROR 1 + +/* Define to 1 if you have the `gamma' function. */ +#define HAVE_GAMMA 1 + +/* Define if we can use gcc inline assembler to get and set x87 control word + */ +#define HAVE_GCC_ASM_FOR_X87 1 + +/* Define if you have the getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `getcwd' function. */ +#define HAVE_GETCWD 1 + +/* Define this if you have flockfile(), getc_unlocked(), and funlockfile() */ +#define HAVE_GETC_UNLOCKED 1 + +/* Define to 1 if you have the `getgroups' function. */ +#define HAVE_GETGROUPS 1 + +/* Define to 1 if you have the `gethostbyname' function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define this if you have some version of gethostbyname_r() */ +/* #undef HAVE_GETHOSTBYNAME_R */ + +/* Define this if you have the 3-arg version of gethostbyname_r(). */ +/* #undef HAVE_GETHOSTBYNAME_R_3_ARG */ + +/* Define this if you have the 5-arg version of gethostbyname_r(). */ +/* #undef HAVE_GETHOSTBYNAME_R_5_ARG */ + +/* Define this if you have the 6-arg version of gethostbyname_r(). */ +/* #undef HAVE_GETHOSTBYNAME_R_6_ARG */ + +/* Define to 1 if you have the `getitimer' function. */ +#define HAVE_GETITIMER 1 + +/* Define to 1 if you have the `getloadavg' function. */ +#define HAVE_GETLOADAVG 1 + +/* Define to 1 if you have the `getlogin' function. */ +#define HAVE_GETLOGIN 1 + +/* Define to 1 if you have the `getnameinfo' function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define if you have the 'getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define to 1 if you have the `getpeername' function. */ +#define HAVE_GETPEERNAME 1 + +/* Define to 1 if you have the `getpgid' function. */ +#define HAVE_GETPGID 1 + +/* Define to 1 if you have the `getpgrp' function. */ +#define HAVE_GETPGRP 1 + +/* Define to 1 if you have the `getpid' function. */ +#define HAVE_GETPID 1 + +/* Define to 1 if you have the `getpriority' function. */ +#define HAVE_GETPRIORITY 1 + +/* Define to 1 if you have the `getpwent' function. */ +#define HAVE_GETPWENT 1 + +/* Define to 1 if you have the `getresgid' function. */ +/* #undef HAVE_GETRESGID */ + +/* Define to 1 if you have the `getresuid' function. */ +/* #undef HAVE_GETRESUID */ + +/* Define to 1 if you have the `getsid' function. */ +#define HAVE_GETSID 1 + +/* Define to 1 if you have the `getspent' function. */ +/* #undef HAVE_GETSPENT */ + +/* Define to 1 if you have the `getspnam' function. */ +/* #undef HAVE_GETSPNAM */ + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `getwd' function. */ +#define HAVE_GETWD 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_GRP_H 1 + +/* Define if you have the 'hstrerror' function. */ +#define HAVE_HSTRERROR 1 + +/* Define to 1 if you have the `hypot' function. */ +#define HAVE_HYPOT 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IEEEFP_H */ + +/* Define if you have the 'inet_aton' function. */ +#define HAVE_INET_ATON 1 + +/* Define if you have the 'inet_pton' function. */ +#define HAVE_INET_PTON 1 + +/* Define to 1 if you have the `initgroups' function. */ +#define HAVE_INITGROUPS 1 + +/* Define if your compiler provides int32_t. */ +#define HAVE_INT32_T 1 + +/* Define if your compiler provides int64_t. */ +#define HAVE_INT64_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IO_H */ + +/* Define to 1 if you have the `kill' function. */ +#define HAVE_KILL 1 + +/* Define to 1 if you have the `killpg' function. */ +#define HAVE_KILLPG 1 + +/* Define if you have the 'kqueue' functions. */ +#define HAVE_KQUEUE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LANGINFO_H 1 + +/* Defined to enable large file support when an off_t is bigger than a long + and long long is available and at least as big as an off_t. You may need to + add some flags for configuration and compilation to enable this mode. (For + Solaris and Linux, the necessary defines are already defined.) */ +/* #undef HAVE_LARGEFILE_SUPPORT */ + +/* Define to 1 if you have the 'lchflags' function. */ +#define HAVE_LCHFLAGS 1 + +/* Define to 1 if you have the `lchmod' function. */ +#define HAVE_LCHMOD 1 + +/* Define to 1 if you have the `lchown' function. */ +#define HAVE_LCHOWN 1 + +/* Define to 1 if you have the `lgamma' function. */ +#define HAVE_LGAMMA 1 + +/* Define to 1 if you have the `dl' library (-ldl). */ +#define HAVE_LIBDL 1 + +/* Define to 1 if you have the `dld' library (-ldld). */ +/* #undef HAVE_LIBDLD */ + +/* Define to 1 if you have the `ieee' library (-lieee). */ +/* #undef HAVE_LIBIEEE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBINTL_H */ + +/* Define if you have the readline library (-lreadline). */ +#define HAVE_LIBREADLINE 1 + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +/* #undef HAVE_LIBRESOLV */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBUTIL_H */ + +/* Define if you have the 'link' function. */ +#define HAVE_LINK 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_NETLINK_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_TIPC_H */ + +/* Define to 1 if you have the `log1p' function. */ +#define HAVE_LOG1P 1 + +/* Define this if you have the type long double. */ +#define HAVE_LONG_DOUBLE 1 + +/* Define this if you have the type long long. */ +#define HAVE_LONG_LONG 1 + +/* Define to 1 if you have the `lstat' function. */ +#define HAVE_LSTAT 1 + +/* Define this if you have the makedev macro. */ +#define HAVE_MAKEDEV 1 + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mkfifo' function. */ +#define HAVE_MKFIFO 1 + +/* Define to 1 if you have the `mknod' function. */ +#define HAVE_MKNOD 1 + +/* Define to 1 if you have the `mktime' function. */ +#define HAVE_MKTIME 1 + +/* Define to 1 if you have the `mremap' function. */ +/* #undef HAVE_MREMAP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_NCURSES_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +/* #undef HAVE_NDIR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETPACKET_PACKET_H */ + +/* Define to 1 if you have the `nice' function. */ +#define HAVE_NICE 1 + +/* Define to 1 if you have the `openpty' function. */ +#define HAVE_OPENPTY 1 + +/* Define if compiling using MacOS X 10.5 SDK or later. */ +#define HAVE_OSX105_SDK 1 + +/* Define to 1 if you have the `pathconf' function. */ +#define HAVE_PATHCONF 1 + +/* Define to 1 if you have the `pause' function. */ +#define HAVE_PAUSE 1 + +/* Define to 1 if you have the `plock' function. */ +/* #undef HAVE_PLOCK */ + +/* Define to 1 if you have the `poll' function. */ +#undef HAVE_POLL + +/* Define to 1 if you have the header file. */ +#undef HAVE_POLL_H + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PROCESS_H */ + +/* Define if your compiler supports function prototype */ +#define HAVE_PROTOTYPES 1 + +/* Define if you have GNU PTH threads. */ +/* #undef HAVE_PTH */ + +/* Defined for Solaris 2.6 bug in pthread header. */ +/* #undef HAVE_PTHREAD_DESTRUCTOR */ + +/* Define to 1 if you have the header file. */ +#define HAVE_PTHREAD_H 1 + +/* Define to 1 if you have the `pthread_init' function. */ +#define HAVE_PTHREAD_INIT 1 + +/* Define to 1 if you have the `pthread_sigmask' function. */ +#define HAVE_PTHREAD_SIGMASK 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PTY_H */ + +/* Define to 1 if you have the `putenv' function. */ +#define HAVE_PUTENV 1 + +/* Define to 1 if you have the `readlink' function. */ +#define HAVE_READLINK 1 + +/* Define to 1 if you have the `realpath' function. */ +#define HAVE_REALPATH 1 + +/* Define if you have readline 2.1 */ +#define HAVE_RL_CALLBACK 1 + +/* Define if you can turn off readline's signal handling. */ +#define HAVE_RL_CATCH_SIGNAL 1 + +/* Define if you have readline 2.2 */ +#define HAVE_RL_COMPLETION_APPEND_CHARACTER 1 + +/* Define if you have readline 4.0 */ +#define HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK 1 + +/* Define if you have readline 4.2 */ +#define HAVE_RL_COMPLETION_MATCHES 1 + +/* Define if you have rl_completion_suppress_append */ +#define HAVE_RL_COMPLETION_SUPPRESS_APPEND 1 + +/* Define if you have readline 4.0 */ +#define HAVE_RL_PRE_INPUT_HOOK 1 + +/* Define to 1 if you have the `round' function. */ +#define HAVE_ROUND 1 + +/* Define to 1 if you have the `select' function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the `sem_getvalue' function. */ +#define HAVE_SEM_GETVALUE 1 + +/* Define to 1 if you have the `sem_open' function. */ +#define HAVE_SEM_OPEN 1 + +/* Define to 1 if you have the `sem_timedwait' function. */ +/* #undef HAVE_SEM_TIMEDWAIT */ + +/* Define to 1 if you have the `sem_unlink' function. */ +#define HAVE_SEM_UNLINK 1 + +/* Define to 1 if you have the `setegid' function. */ +#define HAVE_SETEGID 1 + +/* Define to 1 if you have the `seteuid' function. */ +#define HAVE_SETEUID 1 + +/* Define to 1 if you have the `setgid' function. */ +#define HAVE_SETGID 1 + +/* Define if you have the 'setgroups' function. */ +#define HAVE_SETGROUPS 1 + +/* Define to 1 if you have the `setitimer' function. */ +#define HAVE_SETITIMER 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setpgid' function. */ +#define HAVE_SETPGID 1 + +/* Define to 1 if you have the `setpgrp' function. */ +#define HAVE_SETPGRP 1 + +/* Define to 1 if you have the `setregid' function. */ +#define HAVE_SETREGID 1 + +/* Define to 1 if you have the `setresgid' function. */ +/* #undef HAVE_SETRESGID */ + +/* Define to 1 if you have the `setresuid' function. */ +/* #undef HAVE_SETRESUID */ + +/* Define to 1 if you have the `setreuid' function. */ +#define HAVE_SETREUID 1 + +/* Define to 1 if you have the `setsid' function. */ +#define HAVE_SETSID 1 + +/* Define to 1 if you have the `setuid' function. */ +#define HAVE_SETUID 1 + +/* Define to 1 if you have the `setvbuf' function. */ +#define HAVE_SETVBUF 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SHADOW_H */ + +/* Define to 1 if you have the `sigaction' function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the `siginterrupt' function. */ +#define HAVE_SIGINTERRUPT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the `sigrelse' function. */ +#define HAVE_SIGRELSE 1 + +/* Define to 1 if you have the `snprintf' function. */ +#define HAVE_SNPRINTF 1 + +/* Define if sockaddr has sa_len member */ +#define HAVE_SOCKADDR_SA_LEN 1 + +/* struct sockaddr_storage (sys/socket.h) */ +#define HAVE_SOCKADDR_STORAGE 1 + +/* Define if you have the 'socketpair' function. */ +#define HAVE_SOCKETPAIR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SPAWN_H 1 + +/* Define if your compiler provides ssize_t */ +#define HAVE_SSIZE_T 1 + +/* Define to 1 if you have the `statvfs' function. */ +#define HAVE_STATVFS 1 + +/* Define if you have struct stat.st_mtim.tv_nsec */ +/* #undef HAVE_STAT_TV_NSEC */ + +/* Define if you have struct stat.st_mtimensec */ +#define HAVE_STAT_TV_NSEC2 1 + +/* Define if your compiler supports variable length function prototypes (e.g. + void fprintf(FILE *, char *, ...);) *and* */ +#define HAVE_STDARG_PROTOTYPES 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strftime' function. */ +#define HAVE_STRFTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STROPTS_H */ + +/* Define to 1 if `st_birthtime' is a member of `struct stat'. */ +#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1 + +/* Define to 1 if `st_blksize' is a member of `struct stat'. */ +#define HAVE_STRUCT_STAT_ST_BLKSIZE 1 + +/* Define to 1 if `st_blocks' is a member of `struct stat'. */ +#define HAVE_STRUCT_STAT_ST_BLOCKS 1 + +/* Define to 1 if `st_flags' is a member of `struct stat'. */ +#define HAVE_STRUCT_STAT_ST_FLAGS 1 + +/* Define to 1 if `st_gen' is a member of `struct stat'. */ +#define HAVE_STRUCT_STAT_ST_GEN 1 + +/* Define to 1 if `st_rdev' is a member of `struct stat'. */ +#define HAVE_STRUCT_STAT_ST_RDEV 1 + +/* Define to 1 if `tm_zone' is a member of `struct tm'. */ +#define HAVE_STRUCT_TM_TM_ZONE 1 + +/* Define to 1 if your `struct stat' has `st_blocks'. Deprecated, use + `HAVE_STRUCT_STAT_ST_BLOCKS' instead. */ +#define HAVE_ST_BLOCKS 1 + +/* Define if you have the 'symlink' function. */ +#define HAVE_SYMLINK 1 + +/* Define to 1 if you have the `sysconf' function. */ +#define HAVE_SYSCONF 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYSEXITS_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_AUDIOIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_BSDTTY_H */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_DIR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_EPOLL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_EVENT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILE_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_LOADAVG_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_LOCK_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_MKDEV_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_MODEM_H */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_NDIR_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STATVFS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_TERMIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIMES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UTSNAME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the `tcgetpgrp' function. */ +#define HAVE_TCGETPGRP 1 + +/* Define to 1 if you have the `tcsetpgrp' function. */ +#define HAVE_TCSETPGRP 1 + +/* Define to 1 if you have the `tempnam' function. */ +#define HAVE_TEMPNAM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERM_H 1 + +/* Define to 1 if you have the `tgamma' function. */ +#define HAVE_TGAMMA 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_THREAD_H */ + +/* Define to 1 if you have the `timegm' function. */ +#define HAVE_TIMEGM 1 + +/* Define to 1 if you have the `times' function. */ +#define HAVE_TIMES 1 + +/* Define to 1 if you have the `tmpfile' function. */ +#define HAVE_TMPFILE 1 + +/* Define to 1 if you have the `tmpnam' function. */ +#define HAVE_TMPNAM 1 + +/* Define to 1 if you have the `tmpnam_r' function. */ +/* #undef HAVE_TMPNAM_R */ + +/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use + `HAVE_STRUCT_TM_TM_ZONE' instead. */ +#define HAVE_TM_ZONE 1 + +/* Define to 1 if you have the `truncate' function. */ +#define HAVE_TRUNCATE 1 + +/* Define to 1 if you don't have `tm_zone' but do have the external array + `tzname'. */ +/* #undef HAVE_TZNAME */ + +/* Define this if you have tcl and TCL_UTF_MAX==6 */ +/* #undef HAVE_UCS4_TCL */ + +/* Define if your compiler provides uint32_t. */ +#define HAVE_UINT32_T 1 + +/* Define if your compiler provides uint64_t. */ +#define HAVE_UINT64_T 1 + +/* Define to 1 if the system has the type `uintptr_t'. */ +#define HAVE_UINTPTR_T 1 + +/* Define to 1 if you have the `uname' function. */ +#define HAVE_UNAME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `unsetenv' function. */ +#define HAVE_UNSETENV 1 + +/* Define if you have a useable wchar_t type defined in wchar.h; useable means + wchar_t must be an unsigned type with at least 16 bits. (see + Include/unicodeobject.h). */ +/* #undef HAVE_USABLE_WCHAR_T */ + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIL_H 1 + +/* Define to 1 if you have the `utimes' function. */ +#define HAVE_UTIMES 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if you have the `wait3' function. */ +#define HAVE_WAIT3 1 + +/* Define to 1 if you have the `wait4' function. */ +#define HAVE_WAIT4 1 + +/* Define to 1 if you have the `waitpid' function. */ +#define HAVE_WAITPID 1 + +/* Define if the compiler provides a wchar.h header file. */ +#define HAVE_WCHAR_H 1 + +/* Define to 1 if you have the `wcscoll' function. */ +#define HAVE_WCSCOLL 1 + +/* Define if tzset() actually switches the local timezone in a meaningful way. + */ +#define HAVE_WORKING_TZSET 1 + +/* Define if the zlib library has inflateCopy */ +#define HAVE_ZLIB_COPY 1 + +/* Define to 1 if you have the `_getpty' function. */ +/* #undef HAVE__GETPTY */ + +/* Define if you are using Mach cthreads directly under /include */ +/* #undef HURD_C_THREADS */ + +/* Define if you are using Mach cthreads under mach / */ +/* #undef MACH_C_THREADS */ + +/* Define to 1 if `major', `minor', and `makedev' are declared in . + */ +/* #undef MAJOR_IN_MKDEV */ + +/* Define to 1 if `major', `minor', and `makedev' are declared in + . */ +/* #undef MAJOR_IN_SYSMACROS */ + +/* Define if mvwdelch in curses.h is an expression. */ +#define MVWDELCH_IS_EXPRESSION 1 + +/* Define to the address where bug reports for this package should be sent. */ +/* #undef PACKAGE_BUGREPORT */ + +/* Define to the full name of this package. */ +/* #undef PACKAGE_NAME */ + +/* Define to the full name and version of this package. */ +/* #undef PACKAGE_STRING */ + +/* Define to the one symbol short name of this package. */ +/* #undef PACKAGE_TARNAME */ + +/* Define to the home page for this package. */ +/* #undef PACKAGE_URL */ + +/* Define to the version of this package. */ +/* #undef PACKAGE_VERSION */ + +/* Define if POSIX semaphores aren't enabled on your system */ +/* #undef POSIX_SEMAPHORES_NOT_ENABLED */ + +/* Defined if PTHREAD_SCOPE_SYSTEM supported. */ +#define PTHREAD_SYSTEM_SCHED_SUPPORTED 1 + +/* Define as the preferred size in bits of long digits */ +/* #undef PYLONG_BITS_IN_DIGIT */ + +/* Define to printf format modifier for long long type */ +#define PY_FORMAT_LONG_LONG "ll" + +/* Define to printf format modifier for Py_ssize_t */ +#define PY_FORMAT_SIZE_T "z" + +/* Define as the integral type used for Unicode representation. */ +#define PY_UNICODE_TYPE unsigned short + +/* Define if you want to build an interpreter with many run-time checks. */ +/* #undef Py_DEBUG */ + +/* Defined if Python is built as a shared library. */ +/* #undef Py_ENABLE_SHARED */ + +/* Define as the size of the unicode type. */ +#define Py_UNICODE_SIZE 2 + +/* Define if you want to have a Unicode type. */ +#define Py_USING_UNICODE 1 + +/* assume C89 semantics that RETSIGTYPE is always void */ +#define RETSIGTYPE void + +/* Define if setpgrp() must be called as setpgrp(0, 0). */ +/* #undef SETPGRP_HAVE_ARG */ + +/* Define this to be extension of shared libraries (including the dot!). */ +#define SHLIB_EXT ".so" + +/* Define if i>>j for signed int i does not extend the sign bit when i < 0 */ +/* #undef SIGNED_RIGHT_SHIFT_ZERO_FILLS */ + +/* The size of `double', as computed by sizeof. */ +#define SIZEOF_DOUBLE 8 + +/* The size of `float', as computed by sizeof. */ +#define SIZEOF_FLOAT 4 + +/* The size of `fpos_t', as computed by sizeof. */ +#define SIZEOF_FPOS_T 8 + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 8 + +/* The size of `long double', as computed by sizeof. */ +#define SIZEOF_LONG_DOUBLE 16 + +/* The size of `long long', as computed by sizeof. */ +#define SIZEOF_LONG_LONG 8 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `pid_t', as computed by sizeof. */ +#define SIZEOF_PID_T 4 + +/* The size of `pthread_t', as computed by sizeof. */ +#define SIZEOF_PTHREAD_T 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 8 + +/* The size of `uintptr_t', as computed by sizeof. */ +#define SIZEOF_UINTPTR_T 8 + +/* The size of `void *', as computed by sizeof. */ +#define SIZEOF_VOID_P 8 + +/* The size of `wchar_t', as computed by sizeof. */ +#define SIZEOF_WCHAR_T 4 + +/* The size of `_Bool', as computed by sizeof. */ +#define SIZEOF__BOOL 1 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and + (which you can't on SCO ODT 3.0). */ +#define SYS_SELECT_WITH_SYS_TIME 1 + +/* Define if tanh(-0.) is -0., or if platform doesn't have signed zeros */ +#define TANH_PRESERVES_ZERO_SIGN 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to 1 if your declares `struct tm'. */ +/* #undef TM_IN_SYS_TIME */ + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif + + +/* Define if you want to use MacPython modules on MacOSX in unix-Python. */ +#define USE_TOOLBOX_OBJECT_GLUE 1 + +/* Define if a va_list is an array of some kind */ +#define VA_LIST_IS_ARRAY 1 + +/* Define if you want SIGFPE handled (see Include/pyfpe.h). */ +/* #undef WANT_SIGFPE_HANDLER */ + +/* Define if you want wctype.h functions to be used instead of the one + supplied by Python itself. (see Include/unicodectype.h). */ +/* #undef WANT_WCTYPE_FUNCTIONS */ + +/* Define if WINDOW in curses.h offers a field _flags. */ +/* #undef WINDOW_HAS_FLAGS */ + +/* Define if you want documentation strings in extension modules */ +#define WITH_DOC_STRINGS 1 + +/* Define if you want to use the new-style (Openstep, Rhapsody, MacOS) dynamic + linker (dyld) instead of the old-style (NextStep) dynamic linker (rld). + Dyld is necessary to support frameworks. */ +#define WITH_DYLD 1 + +/* Define to 1 if libintl is needed for locale functions. */ +/* #undef WITH_LIBINTL */ + +/* Define if you want to produce an OpenStep/Rhapsody framework (shared + library plus accessory files). */ +#define WITH_NEXT_FRAMEWORK 1 + +/* Define if you want to compile in Python-specific mallocs */ +#define WITH_PYMALLOC 1 + +/* Define if you want to compile in rudimentary thread support */ +#define WITH_THREAD 1 + +/* Define to profile with the Pentium timestamp counter */ +/* #undef WITH_TSC */ + +/* Define if you want pymalloc to be disabled when running under valgrind */ +/* #undef WITH_VALGRIND */ + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define if arithmetic is subject to x87-style double rounding issue */ +/* #undef X87_DOUBLE_ROUNDING */ + +/* Define on OpenBSD to activate all library features */ +/* #undef _BSD_SOURCE */ + +/* Define on Irix to enable u_int */ +#define _BSD_TYPES 1 + +/* Define on Darwin to activate all library features */ +#define _DARWIN_C_SOURCE 1 + +/* This must be set to 64 on some systems to enable large file support. */ +#define _FILE_OFFSET_BITS 64 + +/* Define on Linux to activate all library features */ +#define _GNU_SOURCE 1 + +/* This must be defined on some systems to enable large file support. */ +#define _LARGEFILE_SOURCE 1 + +/* This must be defined on AIX systems to enable large file support. */ +/* #undef _LARGE_FILES */ + +/* Define to 1 if on MINIX. */ +/* #undef _MINIX */ + +/* Define on NetBSD to activate all library features */ +#define _NETBSD_SOURCE 1 + +/* Define _OSF_SOURCE to get the makedev macro. */ +/* #undef _OSF_SOURCE */ + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +/* #undef _POSIX_1_SOURCE */ + +/* Define to activate features from IEEE Stds 1003.1-2001 */ +/* #undef _POSIX_C_SOURCE */ + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +/* #undef _POSIX_SOURCE */ + +/* Define if you have POSIX threads, and your system does not define that. */ +/* #undef _POSIX_THREADS */ + +/* Define to force use of thread-safe errno, h_errno, and other functions */ +#define _REENTRANT 1 + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT32_T */ + +/* Define for Solaris 2.5.1 so the uint64_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT64_T */ + +/* Define to the level of X/Open that your system supports */ +/* #undef _XOPEN_SOURCE */ + +/* Define to activate Unix95-and-earlier features */ +/* #undef _XOPEN_SOURCE_EXTENDED */ + +/* Define on FreeBSD to activate all library features */ +#define __BSD_VISIBLE 1 + +/* Define to 1 if type `char' is unsigned and you are not using gcc. */ +#ifndef __CHAR_UNSIGNED__ +/* # undef __CHAR_UNSIGNED__ */ +#endif + +/* Defined on Solaris to see additional function prototypes. */ +#define __EXTENSIONS__ 1 + +/* Define to 'long' if doesn't define. */ +/* #undef clock_t */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `int' if doesn't define. */ +/* #undef gid_t */ + +/* Define to the type of a signed integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +/* #undef int32_t */ + +/* Define to the type of a signed integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +/* #undef int64_t */ + +/* Define to `int' if does not define. */ +/* #undef mode_t */ + +/* Define to `long int' if does not define. */ +/* #undef off_t */ + +/* Define to `int' if does not define. */ +/* #undef pid_t */ + +/* Define to empty if the keyword does not work. */ +/* #undef signed */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* Define to `int' if does not define. */ +/* #undef socklen_t */ + +/* Define to `int' if doesn't define. */ +/* #undef uid_t */ + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint32_t */ + +/* Define to the type of an unsigned integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint64_t */ + +/* Define to empty if the keyword does not work. */ +/* #undef volatile */ + + +/* Define the macros needed if on a UnixWare 7.x system. */ +#if defined(__USLC__) && defined(__SCO_VERSION__) +#define STRICT_SYSV_CURSES /* Don't use ncurses extensions */ +#endif + +#endif /*Py_PYCONFIG_H*/ + diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/config/Makefile b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/config/Makefile new file mode 100644 index 0000000..268b2c1 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/config/Makefile @@ -0,0 +1,1397 @@ +# Generated automatically from Makefile.pre by makesetup. +# Top-level Makefile for Python +# +# As distributed, this file is called Makefile.pre.in; it is processed +# into the real Makefile by running the script ./configure, which +# replaces things like @spam@ with values appropriate for your system. +# This means that if you edit Makefile, your changes get lost the next +# time you run the configure script. Ideally, you can do: +# +# ./configure +# make +# make test +# make install +# +# If you have a previous version of Python installed that you don't +# want to overwrite, you can use "make altinstall" instead of "make +# install". Refer to the "Installing" section in the README file for +# additional details. +# +# See also the section "Build instructions" in the README file. + +# === Variables set by makesetup === + +MODOBJS= Modules/threadmodule.o Modules/signalmodule.o Modules/posixmodule.o Modules/errnomodule.o Modules/pwdmodule.o Modules/_sre.o Modules/_codecsmodule.o Modules/_weakref.o Modules/zipimport.o Modules/symtablemodule.o Modules/xxsubtype.o +MODLIBS= $(LOCALMODLIBS) $(BASEMODLIBS) + +# === Variables set by configure +VERSION= 2.7 +srcdir= . + +abs_srcdir= /private/tmp/python-Yar9/Python-2.7.5 +abs_builddir= /private/tmp/python-Yar9/Python-2.7.5 +build= x86_64-apple-darwin12.5.0 +host= x86_64-apple-darwin12.5.0 + +CC= cc +CXX= c++ +MAINCC= $(CC) +LINKCC= $(PURIFY) $(MAINCC) +AR= ar +RANLIB= ranlib +SVNVERSION= svnversion $(srcdir) +HGVERSION= +HGTAG= +HGBRANCH= + +GNULD= no + +# Shell used by make (some versions default to the login shell, which is bad) +SHELL= /bin/sh + +# Use this to make a link between python$(VERSION) and python in $(BINDIR) +LN= ln + +# Portable install script (configure doesn't always guess right) +INSTALL= /usr/bin/install -c +INSTALL_PROGRAM=${INSTALL} +INSTALL_SCRIPT= ${INSTALL} +INSTALL_DATA= ${INSTALL} -m 644 +# Shared libraries must be installed with executable mode on some systems; +# rather than figuring out exactly which, we always give them executable mode. +# Also, making them read-only seems to be a good idea... +INSTALL_SHARED= ${INSTALL} -m 555 + +MKDIR_P= ./install-sh -c -d + +MAKESETUP= $(srcdir)/Modules/makesetup + +# Compiler options +OPT= -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes +BASECFLAGS= -fno-strict-aliasing -fno-common -dynamic +CFLAGS= $(BASECFLAGS) -I/usr/local/include -I/usr/local/opt/sqlite/include $(OPT) $(EXTRA_CFLAGS) +# Both CPPFLAGS and LDFLAGS need to contain the shell's value for setup.py to +# be able to build extension modules using the directories specified in the +# environment variables +CPPFLAGS= -I. -IInclude -I$(srcdir)/Include +LDFLAGS= -L/usr/local/lib -L/usr/local/opt/sqlite/lib +LDLAST= +SGI_ABI= +CCSHARED= +LINKFORSHARED=-u _PyMac_Error $(PYTHONFRAMEWORKINSTALLDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK) +ARFLAGS= rc +# Extra C flags added for building the interpreter object files. +CFLAGSFORSHARED=$(CCSHARED) +# C flags used for building the interpreter object files +PY_CFLAGS= $(CFLAGS) $(CPPFLAGS) $(CFLAGSFORSHARED) -DPy_BUILD_CORE + + +# Machine-dependent subdirectories +MACHDEP= darwin + +# Multiarch directory (may be empty) +MULTIARCH= + +# Install prefix for architecture-independent files +prefix= /usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7 + +# Install prefix for architecture-dependent files +exec_prefix= ${prefix} + +# Install prefix for data files +datarootdir= /usr/local/Cellar/python/2.7.5/share + +# Expanded directories +BINDIR= ${exec_prefix}/bin +LIBDIR= ${exec_prefix}/lib +MANDIR= ${datarootdir}/man +INCLUDEDIR= ${prefix}/include +CONFINCLUDEDIR= $(exec_prefix)/include +SCRIPTDIR= $(prefix)/lib + +# Detailed destination directories +BINLIBDEST= $(LIBDIR)/python$(VERSION) +LIBDEST= $(SCRIPTDIR)/python$(VERSION) +INCLUDEPY= $(INCLUDEDIR)/python$(VERSION) +CONFINCLUDEPY= $(CONFINCLUDEDIR)/python$(VERSION) +LIBP= $(LIBDIR)/python$(VERSION) + +# Symbols used for using shared libraries +SO= .so +LDSHARED= $(CC) -bundle -undefined dynamic_lookup $(LDFLAGS) +BLDSHARED= $(CC) -bundle -undefined dynamic_lookup $(LDFLAGS) +LDCXXSHARED= $(CXX) -bundle -undefined dynamic_lookup +DESTSHARED= $(BINLIBDEST)/lib-dynload + +# Executable suffix (.exe on Windows and Mac OS X) +EXE= +BUILDEXE= .exe + +# Short name and location for Mac OS X Python framework +UNIVERSALSDK= +PYTHONFRAMEWORK= Python +PYTHONFRAMEWORKDIR= Python.framework +PYTHONFRAMEWORKPREFIX= /usr/local/Cellar/python/2.7.5/Frameworks +PYTHONFRAMEWORKINSTALLDIR= /usr/local/Cellar/python/2.7.5/Frameworks/Python.framework +# Deployment target selected during configure, to be checked +# by distutils. The export statement is needed to ensure that the +# deployment target is active during build. +MACOSX_DEPLOYMENT_TARGET=10.8 +export MACOSX_DEPLOYMENT_TARGET + +# Options to enable prebinding (for fast startup prior to Mac OS X 10.3) +OTHER_LIBTOOL_OPT= + +# Environment to run shared python without installed libraries +RUNSHARED= DYLD_FRAMEWORK_PATH=/private/tmp/python-Yar9/Python-2.7.5: + +# Modes for directories, executables and data files created by the +# install process. Default to user-only-writable for all file types. +DIRMODE= 755 +EXEMODE= 755 +FILEMODE= 644 + +# configure script arguments +CONFIG_ARGS= '--prefix=/usr/local/Cellar/python/2.7.5' '--enable-ipv6' '--datarootdir=/usr/local/Cellar/python/2.7.5/share' '--datadir=/usr/local/Cellar/python/2.7.5/share' '--enable-framework=/usr/local/Cellar/python/2.7.5/Frameworks' '--without-gcc' 'CFLAGS=-I/usr/local/include -I/usr/local/opt/sqlite/include' 'LDFLAGS=-L/usr/local/lib -L/usr/local/opt/sqlite/lib' 'MACOSX_DEPLOYMENT_TARGET=10.8' 'CC=cc' + + +# Subdirectories with code +SRCDIRS= Parser Grammar Objects Python Modules Mac + +# Other subdirectories +SUBDIRSTOO= Include Lib Misc Demo + +# Files and directories to be distributed +CONFIGFILES= configure configure.ac acconfig.h pyconfig.h.in Makefile.pre.in +DISTFILES= README ChangeLog $(CONFIGFILES) +DISTDIRS= $(SUBDIRS) $(SUBDIRSTOO) Ext-dummy +DIST= $(DISTFILES) $(DISTDIRS) + + +LIBRARY= libpython$(VERSION).a +LDLIBRARY= $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK) +BLDLIBRARY= +DLLLIBRARY= +LDLIBRARYDIR= +INSTSONAME= $(LDLIBRARY) + + +LIBS= -ldl -framework CoreFoundation +LIBM= +LIBC= +SYSLIBS= $(LIBM) $(LIBC) +SHLIBS= $(LIBS) + +THREADOBJ= Python/thread.o +DLINCLDIR= . +DYNLOADFILE= dynload_shlib.o +MACHDEP_OBJS= Python/mactoolboxglue.o +LIBOBJDIR= Python/ +LIBOBJS= +UNICODE_OBJS= Objects/unicodeobject.o Objects/unicodectype.o + +PYTHON= python$(EXE) +BUILDPYTHON= python$(BUILDEXE) + +PYTHON_FOR_BUILD=./$(BUILDPYTHON) -E +_PYTHON_HOST_PLATFORM= +HOST_GNU_TYPE= x86_64-apple-darwin12.5.0 + +# The task to run while instrument when building the profile-opt target +PROFILE_TASK= $(srcdir)/Tools/pybench/pybench.py -n 2 --with-gc --with-syscheck +#PROFILE_TASK= $(srcdir)/Lib/test/regrtest.py + +# === Definitions added by makesetup === + +LOCALMODLIBS= +BASEMODLIBS= +GLHACK=-Dclear=__GLclear +PYTHONPATH=$(COREPYTHONPATH) +COREPYTHONPATH=$(DESTPATH)$(SITEPATH)$(TESTPATH)$(MACHDEPPATH)$(EXTRAMACHDEPPATH)$(TKPATH)$(OLDPATH) +OLDPATH=:lib-old +TKPATH=:lib-tk +EXTRAMACHDEPPATH= +MACHDEPPATH=:plat-$(MACHDEP) +TESTPATH= +SITEPATH= +DESTPATH= +MACHDESTLIB=$(BINLIBDEST) +DESTLIB=$(LIBDEST) + + +########################################################################## +# Modules +MODULE_OBJS= \ + Modules/config.o \ + Modules/getpath.o \ + Modules/main.o \ + Modules/gcmodule.o + +# Used of signalmodule.o is not available +SIGNAL_OBJS= + + +########################################################################## +# Grammar +GRAMMAR_H= Include/graminit.h +GRAMMAR_C= Python/graminit.c +GRAMMAR_INPUT= $(srcdir)/Grammar/Grammar + + +LIBFFI_INCLUDEDIR= + +########################################################################## +# Parser +PGEN= Parser/pgen$(EXE) + +PSRCS= \ + Parser/acceler.c \ + Parser/grammar1.c \ + Parser/listnode.c \ + Parser/node.c \ + Parser/parser.c \ + Parser/parsetok.c \ + Parser/bitset.c \ + Parser/metagrammar.c \ + Parser/firstsets.c \ + Parser/grammar.c \ + Parser/pgen.c + +POBJS= \ + Parser/acceler.o \ + Parser/grammar1.o \ + Parser/listnode.o \ + Parser/node.o \ + Parser/parser.o \ + Parser/parsetok.o \ + Parser/bitset.o \ + Parser/metagrammar.o \ + Parser/firstsets.o \ + Parser/grammar.o \ + Parser/pgen.o + +PARSER_OBJS= $(POBJS) Parser/myreadline.o Parser/tokenizer.o + +PGSRCS= \ + Objects/obmalloc.c \ + Python/mysnprintf.c \ + Python/pyctype.c \ + Parser/tokenizer_pgen.c \ + Parser/printgrammar.c \ + Parser/pgenmain.c + +PGOBJS= \ + Objects/obmalloc.o \ + Python/mysnprintf.o \ + Python/pyctype.o \ + Parser/tokenizer_pgen.o \ + Parser/printgrammar.o \ + Parser/pgenmain.o + +PARSER_HEADERS= \ + Parser/parser.h \ + Parser/tokenizer.h + +PGENSRCS= $(PSRCS) $(PGSRCS) +PGENOBJS= $(POBJS) $(PGOBJS) + +########################################################################## +# AST +AST_H_DIR= Include +AST_H= $(AST_H_DIR)/Python-ast.h +AST_C_DIR= Python +AST_C= $(AST_C_DIR)/Python-ast.c +AST_ASDL= $(srcdir)/Parser/Python.asdl + +ASDLGEN_FILES= $(srcdir)/Parser/asdl.py $(srcdir)/Parser/asdl_c.py +# XXX Note that a build now requires Python exist before the build starts +ASDLGEN= $(srcdir)/Parser/asdl_c.py + +########################################################################## +# Python +PYTHON_OBJS= \ + Python/_warnings.o \ + Python/Python-ast.o \ + Python/asdl.o \ + Python/ast.o \ + Python/bltinmodule.o \ + Python/ceval.o \ + Python/compile.o \ + Python/codecs.o \ + Python/errors.o \ + Python/frozen.o \ + Python/frozenmain.o \ + Python/future.o \ + Python/getargs.o \ + Python/getcompiler.o \ + Python/getcopyright.o \ + Python/getplatform.o \ + Python/getversion.o \ + Python/graminit.o \ + Python/import.o \ + Python/importdl.o \ + Python/marshal.o \ + Python/modsupport.o \ + Python/mystrtoul.o \ + Python/mysnprintf.o \ + Python/peephole.o \ + Python/pyarena.o \ + Python/pyctype.o \ + Python/pyfpe.o \ + Python/pymath.o \ + Python/pystate.o \ + Python/pythonrun.o \ + Python/random.o \ + Python/structmember.o \ + Python/symtable.o \ + Python/sysmodule.o \ + Python/traceback.o \ + Python/getopt.o \ + Python/pystrcmp.o \ + Python/pystrtod.o \ + Python/dtoa.o \ + Python/formatter_unicode.o \ + Python/formatter_string.o \ + Python/$(DYNLOADFILE) \ + $(LIBOBJS) \ + $(MACHDEP_OBJS) \ + $(THREADOBJ) + + +########################################################################## +# Objects +OBJECT_OBJS= \ + Objects/abstract.o \ + Objects/boolobject.o \ + Objects/bufferobject.o \ + Objects/bytes_methods.o \ + Objects/bytearrayobject.o \ + Objects/capsule.o \ + Objects/cellobject.o \ + Objects/classobject.o \ + Objects/cobject.o \ + Objects/codeobject.o \ + Objects/complexobject.o \ + Objects/descrobject.o \ + Objects/enumobject.o \ + Objects/exceptions.o \ + Objects/genobject.o \ + Objects/fileobject.o \ + Objects/floatobject.o \ + Objects/frameobject.o \ + Objects/funcobject.o \ + Objects/intobject.o \ + Objects/iterobject.o \ + Objects/listobject.o \ + Objects/longobject.o \ + Objects/dictobject.o \ + Objects/memoryobject.o \ + Objects/methodobject.o \ + Objects/moduleobject.o \ + Objects/object.o \ + Objects/obmalloc.o \ + Objects/rangeobject.o \ + Objects/setobject.o \ + Objects/sliceobject.o \ + Objects/stringobject.o \ + Objects/structseq.o \ + Objects/tupleobject.o \ + Objects/typeobject.o \ + Objects/weakrefobject.o \ + $(UNICODE_OBJS) + + +########################################################################## +# objects that get linked into the Python library +LIBRARY_OBJS= \ + Modules/getbuildinfo.o \ + $(PARSER_OBJS) \ + $(OBJECT_OBJS) \ + $(PYTHON_OBJS) \ + $(MODULE_OBJS) \ + $(SIGNAL_OBJS) \ + $(MODOBJS) + +######################################################################### +# Rules + +# Default target +all: build_all +build_all: $(BUILDPYTHON) oldsharedmods sharedmods gdbhooks + +# Compile a binary with gcc profile guided optimization. +profile-opt: + @echo "Building with support for profile generation:" + $(MAKE) clean + $(MAKE) build_all_generate_profile + @echo "Running benchmark to generate profile data:" + $(MAKE) profile-removal + $(MAKE) run_profile_task + @echo "Rebuilding with profile guided optimizations:" + $(MAKE) clean + $(MAKE) build_all_use_profile + +build_all_generate_profile: + $(MAKE) all CFLAGS="$(CFLAGS) -fprofile-generate" LIBS="$(LIBS) -lgcov" + +run_profile_task: + : # FIXME: can't run for a cross build + ./$(BUILDPYTHON) $(PROFILE_TASK) + +build_all_use_profile: + $(MAKE) all CFLAGS="$(CFLAGS) -fprofile-use" + +coverage: + @echo "Building with support for coverage checking:" + $(MAKE) clean + $(MAKE) all CFLAGS="$(CFLAGS) -O0 -pg -fprofile-arcs -ftest-coverage" LIBS="$(LIBS) -lgcov" + + +# Build the interpreter +$(BUILDPYTHON): Modules/python.o $(LIBRARY) $(LDLIBRARY) + $(LINKCC) $(LDFLAGS) $(LINKFORSHARED) -o $@ \ + Modules/python.o \ + $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST) + +platform: $(BUILDPYTHON) pybuilddir.txt + $(RUNSHARED) $(PYTHON_FOR_BUILD) -c 'import sys ; from sysconfig import get_platform ; print get_platform()+"-"+sys.version[0:3]' >platform + +# Create build directory and generate the sysconfig build-time data there. +# pybuilddir.txt contains the name of the build dir and is used for +# sys.path fixup -- see Modules/getpath.c. +pybuilddir.txt: $(BUILDPYTHON) + $(RUNSHARED) $(PYTHON_FOR_BUILD) -S -m sysconfig --generate-posix-vars + +# Build the shared modules +# Under GNU make, MAKEFLAGS are sorted and normalized; the 's' for +# -s, --silent or --quiet is always the first char. +# Under BSD make, MAKEFLAGS might be " -s -v x=y". +sharedmods: $(BUILDPYTHON) pybuilddir.txt + @case "$$MAKEFLAGS" in \ + *\ -s*|s*) quiet="-q";; \ + *) quiet="";; \ + esac; \ + $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ + $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build + +# Build static library +# avoid long command lines, same as LIBRARY_OBJS +$(LIBRARY): $(LIBRARY_OBJS) + -rm -f $@ + $(AR) $(ARFLAGS) $@ Modules/getbuildinfo.o + $(AR) $(ARFLAGS) $@ $(PARSER_OBJS) + $(AR) $(ARFLAGS) $@ $(OBJECT_OBJS) + $(AR) $(ARFLAGS) $@ $(PYTHON_OBJS) + $(AR) $(ARFLAGS) $@ $(MODULE_OBJS) $(SIGNAL_OBJS) + $(AR) $(ARFLAGS) $@ $(MODOBJS) + $(RANLIB) $@ + +libpython$(VERSION).so: $(LIBRARY_OBJS) + if test $(INSTSONAME) != $(LDLIBRARY); then \ + $(BLDSHARED) -Wl,-h$(INSTSONAME) -o $(INSTSONAME) $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \ + $(LN) -f $(INSTSONAME) $@; \ + else \ + $(BLDSHARED) -o $@ $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \ + fi + +libpython$(VERSION).dylib: $(LIBRARY_OBJS) + $(CC) -dynamiclib -Wl,-single_module $(LDFLAGS) -undefined dynamic_lookup -Wl,-install_name,$(prefix)/lib/libpython$(VERSION).dylib -Wl,-compatibility_version,$(VERSION) -Wl,-current_version,$(VERSION) -o $@ $(LIBRARY_OBJS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \ + + +libpython$(VERSION).sl: $(LIBRARY_OBJS) + $(LDSHARED) -o $@ $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST) + +# Copy up the gdb python hooks into a position where they can be automatically +# loaded by gdb during Lib/test/test_gdb.py +# +# Distributors are likely to want to install this somewhere else e.g. relative +# to the stripped DWARF data for the shared library. +gdbhooks: $(BUILDPYTHON)-gdb.py + +SRC_GDB_HOOKS=$(srcdir)/Tools/gdb/libpython.py +$(BUILDPYTHON)-gdb.py: $(SRC_GDB_HOOKS) + $(INSTALL_DATA) $(SRC_GDB_HOOKS) $(BUILDPYTHON)-gdb.py + +# This rule is here for OPENSTEP/Rhapsody/MacOSX. It builds a temporary +# minimal framework (not including the Lib directory and such) in the current +# directory. +RESSRCDIR=Mac/Resources/framework +$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK): \ + $(LIBRARY) \ + $(RESSRCDIR)/Info.plist + $(INSTALL) -d -m $(DIRMODE) $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION) + $(CC) -o $(LDLIBRARY) $(LDFLAGS) -dynamiclib \ + -all_load $(LIBRARY) -Wl,-single_module \ + -install_name $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK) \ + -compatibility_version $(VERSION) \ + -current_version $(VERSION); + $(INSTALL) -d -m $(DIRMODE) \ + $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/Resources/English.lproj + $(INSTALL_DATA) $(RESSRCDIR)/Info.plist \ + $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/Resources/Info.plist + $(LN) -fsn $(VERSION) $(PYTHONFRAMEWORKDIR)/Versions/Current + $(LN) -fsn Versions/Current/$(PYTHONFRAMEWORK) $(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK) + $(LN) -fsn Versions/Current/Headers $(PYTHONFRAMEWORKDIR)/Headers + $(LN) -fsn Versions/Current/Resources $(PYTHONFRAMEWORKDIR)/Resources + +# This rule builds the Cygwin Python DLL and import library if configured +# for a shared core library; otherwise, this rule is a noop. +$(DLLLIBRARY) libpython$(VERSION).dll.a: $(LIBRARY_OBJS) + if test -n "$(DLLLIBRARY)"; then \ + $(LDSHARED) -Wl,--out-implib=$@ -o $(DLLLIBRARY) $^ \ + $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST); \ + else true; \ + fi + + +oldsharedmods: $(SHAREDMODS) + + +Makefile Modules/config.c: Makefile.pre \ + $(srcdir)/Modules/config.c.in \ + $(MAKESETUP) \ + Modules/Setup.config \ + Modules/Setup \ + Modules/Setup.local + $(SHELL) $(MAKESETUP) -c $(srcdir)/Modules/config.c.in \ + -s Modules \ + Modules/Setup.config \ + Modules/Setup.local \ + Modules/Setup + @mv config.c Modules + @echo "The Makefile was updated, you may need to re-run make." + + +Modules/Setup: $(srcdir)/Modules/Setup.dist + @if test -f Modules/Setup; then \ + echo "-----------------------------------------------"; \ + echo "Modules/Setup.dist is newer than Modules/Setup;"; \ + echo "check to make sure you have all the updates you"; \ + echo "need in your Modules/Setup file."; \ + echo "Usually, copying Modules/Setup.dist to Modules/Setup will work."; \ + echo "-----------------------------------------------"; \ + fi + +############################################################################ +# Special rules for object files + +Modules/getbuildinfo.o: $(PARSER_OBJS) \ + $(OBJECT_OBJS) \ + $(PYTHON_OBJS) \ + $(MODULE_OBJS) \ + $(SIGNAL_OBJS) \ + $(MODOBJS) \ + $(srcdir)/Modules/getbuildinfo.c + $(CC) -c $(PY_CFLAGS) \ + -DSVNVERSION="\"`LC_ALL=C $(SVNVERSION)`\"" \ + -DHGVERSION="\"`LC_ALL=C $(HGVERSION)`\"" \ + -DHGTAG="\"`LC_ALL=C $(HGTAG)`\"" \ + -DHGBRANCH="\"`LC_ALL=C $(HGBRANCH)`\"" \ + -o $@ $(srcdir)/Modules/getbuildinfo.c + +Modules/getpath.o: $(srcdir)/Modules/getpath.c Makefile + $(CC) -c $(PY_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \ + -DPREFIX='"$(prefix)"' \ + -DEXEC_PREFIX='"$(exec_prefix)"' \ + -DVERSION='"$(VERSION)"' \ + -DVPATH='"$(VPATH)"' \ + -o $@ $(srcdir)/Modules/getpath.c + +Modules/python.o: $(srcdir)/Modules/python.c + $(MAINCC) -c $(PY_CFLAGS) -o $@ $(srcdir)/Modules/python.c + +Modules/posixmodule.o: $(srcdir)/Modules/posixmodule.c $(srcdir)/Modules/posixmodule.h + +Modules/grpmodule.o: $(srcdir)/Modules/grpmodule.c $(srcdir)/Modules/posixmodule.h + +Modules/pwdmodule.o: $(srcdir)/Modules/pwdmodule.c $(srcdir)/Modules/posixmodule.h + +$(GRAMMAR_H): $(GRAMMAR_INPUT) $(PGENSRCS) + @$(MKDIR_P) Include + $(MAKE) $(PGEN) + $(PGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C) +$(GRAMMAR_C): $(GRAMMAR_H) $(GRAMMAR_INPUT) $(PGENSRCS) + $(MAKE) $(GRAMMAR_H) + touch $(GRAMMAR_C) + +$(PGEN): $(PGENOBJS) + $(CC) $(OPT) $(LDFLAGS) $(PGENOBJS) $(LIBS) -o $(PGEN) + +Parser/grammar.o: $(srcdir)/Parser/grammar.c \ + $(srcdir)/Include/token.h \ + $(srcdir)/Include/grammar.h +Parser/metagrammar.o: $(srcdir)/Parser/metagrammar.c + +Parser/tokenizer_pgen.o: $(srcdir)/Parser/tokenizer.c + +Parser/pgenmain.o: $(srcdir)/Include/parsetok.h + +$(AST_H): $(AST_ASDL) $(ASDLGEN_FILES) + $(MKDIR_P) $(AST_H_DIR) + $(ASDLGEN) -h $(AST_H_DIR) $(AST_ASDL) + +$(AST_C): $(AST_ASDL) $(ASDLGEN_FILES) + $(MKDIR_P) $(AST_C_DIR) + $(ASDLGEN) -c $(AST_C_DIR) $(AST_ASDL) + +Python/compile.o Python/symtable.o Python/ast.o: $(GRAMMAR_H) $(AST_H) + +Python/getplatform.o: $(srcdir)/Python/getplatform.c + $(CC) -c $(PY_CFLAGS) -DPLATFORM='"$(MACHDEP)"' -o $@ $(srcdir)/Python/getplatform.c + +Python/importdl.o: $(srcdir)/Python/importdl.c + $(CC) -c $(PY_CFLAGS) -I$(DLINCLDIR) -o $@ $(srcdir)/Python/importdl.c + +Objects/unicodectype.o: $(srcdir)/Objects/unicodectype.c \ + $(srcdir)/Objects/unicodetype_db.h + +STRINGLIB_HEADERS= \ + $(srcdir)/Include/bytes_methods.h \ + $(srcdir)/Objects/stringlib/count.h \ + $(srcdir)/Objects/stringlib/ctype.h \ + $(srcdir)/Objects/stringlib/fastsearch.h \ + $(srcdir)/Objects/stringlib/find.h \ + $(srcdir)/Objects/stringlib/formatter.h \ + $(srcdir)/Objects/stringlib/partition.h \ + $(srcdir)/Objects/stringlib/split.h \ + $(srcdir)/Objects/stringlib/stringdefs.h \ + $(srcdir)/Objects/stringlib/string_format.h \ + $(srcdir)/Objects/stringlib/transmogrify.h \ + $(srcdir)/Objects/stringlib/unicodedefs.h \ + $(srcdir)/Objects/stringlib/localeutil.h + +Objects/unicodeobject.o: $(srcdir)/Objects/unicodeobject.c \ + $(STRINGLIB_HEADERS) + +Objects/bytearrayobject.o: $(srcdir)/Objects/bytearrayobject.c \ + $(STRINGLIB_HEADERS) + +Objects/stringobject.o: $(srcdir)/Objects/stringobject.c \ + $(STRINGLIB_HEADERS) + +Python/formatter_unicode.o: $(srcdir)/Python/formatter_unicode.c \ + $(STRINGLIB_HEADERS) + +Python/formatter_string.o: $(srcdir)/Python/formatter_string.c \ + $(STRINGLIB_HEADERS) + +############################################################################ +# Header files + +PYTHON_HEADERS= \ + Include/Python-ast.h \ + Include/Python.h \ + Include/abstract.h \ + Include/asdl.h \ + Include/ast.h \ + Include/bitset.h \ + Include/boolobject.h \ + Include/bytearrayobject.h \ + Include/bytes_methods.h \ + Include/bytesobject.h \ + Include/bufferobject.h \ + Include/cellobject.h \ + Include/ceval.h \ + Include/classobject.h \ + Include/cobject.h \ + Include/code.h \ + Include/codecs.h \ + Include/compile.h \ + Include/complexobject.h \ + Include/descrobject.h \ + Include/dictobject.h \ + Include/dtoa.h \ + Include/enumobject.h \ + Include/errcode.h \ + Include/eval.h \ + Include/fileobject.h \ + Include/floatobject.h \ + Include/frameobject.h \ + Include/funcobject.h \ + Include/genobject.h \ + Include/import.h \ + Include/intobject.h \ + Include/intrcheck.h \ + Include/iterobject.h \ + Include/listobject.h \ + Include/longintrepr.h \ + Include/longobject.h \ + Include/marshal.h \ + Include/memoryobject.h \ + Include/metagrammar.h \ + Include/methodobject.h \ + Include/modsupport.h \ + Include/moduleobject.h \ + Include/node.h \ + Include/object.h \ + Include/objimpl.h \ + Include/opcode.h \ + Include/osdefs.h \ + Include/parsetok.h \ + Include/patchlevel.h \ + Include/pgen.h \ + Include/pgenheaders.h \ + Include/pyarena.h \ + Include/pycapsule.h \ + Include/pyctype.h \ + Include/pydebug.h \ + Include/pyerrors.h \ + Include/pyfpe.h \ + Include/pymath.h \ + Include/pygetopt.h \ + Include/pymem.h \ + Include/pyport.h \ + Include/pystate.h \ + Include/pystrcmp.h \ + Include/pystrtod.h \ + Include/pythonrun.h \ + Include/pythread.h \ + Include/rangeobject.h \ + Include/setobject.h \ + Include/sliceobject.h \ + Include/stringobject.h \ + Include/structmember.h \ + Include/structseq.h \ + Include/symtable.h \ + Include/sysmodule.h \ + Include/traceback.h \ + Include/tupleobject.h \ + Include/ucnhash.h \ + Include/unicodeobject.h \ + Include/warnings.h \ + Include/weakrefobject.h \ + pyconfig.h \ + $(PARSER_HEADERS) + +$(LIBRARY_OBJS) $(MODOBJS) Modules/python.o: $(PYTHON_HEADERS) + + +###################################################################### + +# Test the interpreter (twice, once without .pyc files, once with) +# In the past, we've had problems where bugs in the marshalling or +# elsewhere caused bytecode read from .pyc files to behave differently +# than bytecode generated directly from a .py source file. Sometimes +# the bytecode read from a .pyc file had the bug, sometimes the directly +# generated bytecode. This is sometimes a very shy bug needing a lot of +# sample data. + +TESTOPTS= -l $(EXTRATESTOPTS) +TESTPROG= $(srcdir)/Lib/test/regrtest.py +TESTPYTHON= $(RUNSHARED) ./$(BUILDPYTHON) -Wd -3 -E -tt $(TESTPYTHONOPTS) +test: all platform + -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f + -$(TESTPYTHON) $(TESTPROG) $(TESTOPTS) + $(TESTPYTHON) $(TESTPROG) $(TESTOPTS) + +testall: all platform + -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f + $(TESTPYTHON) $(srcdir)/Lib/compileall.py + -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f + -$(TESTPYTHON) $(TESTPROG) -uall $(TESTOPTS) + $(TESTPYTHON) $(TESTPROG) -uall $(TESTOPTS) + +# Run the unitests for both architectures in a Universal build on OSX +# Must be run on an Intel box. +testuniversal: all platform + if [ `arch` != 'i386' ];then \ + echo "This can only be used on OSX/i386" ;\ + exit 1 ;\ + fi + -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f + -$(TESTPYTHON) $(TESTPROG) -uall $(TESTOPTS) + $(TESTPYTHON) $(TESTPROG) -uall $(TESTOPTS) + $(RUNSHARED) /usr/libexec/oah/translate ./$(BUILDPYTHON) -E -tt $(TESTPROG) -uall $(TESTOPTS) + + +# Like testall, but with a single pass only +# run an optional script to include some information about the build environment +buildbottest: all platform + -@if which pybuildbot.identify >/dev/null 2>&1; then \ + pybuildbot.identify "CC='$(CC)'" "CXX='$(CXX)'"; \ + fi + $(TESTPYTHON) -R $(TESTPROG) -uall -rwW $(TESTOPTS) + +QUICKTESTOPTS= $(TESTOPTS) -x test_subprocess test_io test_lib2to3 \ + test_multibytecodec test_urllib2_localnet test_itertools \ + test_multiprocessing test_mailbox test_socket test_poll \ + test_select test_zipfile +quicktest: all platform + -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f + -$(TESTPYTHON) $(TESTPROG) $(QUICKTESTOPTS) + $(TESTPYTHON) $(TESTPROG) $(QUICKTESTOPTS) + +MEMTESTOPTS= $(QUICKTESTOPTS) -x test_dl test___all__ test_fork1 \ + test_longexp +memtest: all platform + -rm -f $(srcdir)/Lib/test/*.py[co] + -$(TESTPYTHON) $(TESTPROG) $(MEMTESTOPTS) + $(TESTPYTHON) $(TESTPROG) $(MEMTESTOPTS) + +# Install everything +install: frameworkinstallstructure altinstall bininstall maninstall frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools + +# Install almost everything without disturbing previous versions +altinstall: frameworkinstallstructure bininstall maninstall altbininstall libinstall inclinstall \ + libainstall altmaninstall \ + sharedinstall oldsharedinstall frameworkinstallmaclib frameworkinstallapps frameworkaltinstallunixtools + +# Install shared libraries enabled by Setup +DESTDIRS= $(exec_prefix) $(LIBDIR) $(BINLIBDEST) $(DESTSHARED) + +oldsharedinstall: $(DESTSHARED) $(SHAREDMODS) + @for i in X $(SHAREDMODS); do \ + if test $$i != X; then \ + echo $(INSTALL_SHARED) $$i $(DESTSHARED)/`basename $$i`; \ + $(INSTALL_SHARED) $$i $(DESTDIR)$(DESTSHARED)/`basename $$i`; \ + fi; \ + done + +$(DESTSHARED): + @for i in $(DESTDIRS); \ + do \ + if test ! -d $(DESTDIR)$$i; then \ + echo "Creating directory $$i"; \ + $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \ + else true; \ + fi; \ + done + + +# Install the interpreter by creating a symlink chain: +# $(PYTHON) -> python2 -> python$(VERSION)) +# Also create equivalent chains for other installed files +bininstall: altbininstall + -if test -f $(DESTDIR)$(BINDIR)/$(PYTHON) -o -h $(DESTDIR)$(BINDIR)/$(PYTHON); \ + then rm -f $(DESTDIR)$(BINDIR)/$(PYTHON); \ + else true; \ + fi + (cd $(DESTDIR)$(BINDIR); $(LN) -s python2$(EXE) $(PYTHON)) + -rm -f $(DESTDIR)$(BINDIR)/python2$(EXE) + (cd $(DESTDIR)$(BINDIR); $(LN) -s python$(VERSION)$(EXE) python2$(EXE)) + -rm -f $(DESTDIR)$(BINDIR)/python2-config + (cd $(DESTDIR)$(BINDIR); $(LN) -s python$(VERSION)-config python2-config) + -rm -f $(DESTDIR)$(BINDIR)/python-config + (cd $(DESTDIR)$(BINDIR); $(LN) -s python2-config python-config) + -test -d $(DESTDIR)$(LIBPC) || $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$(LIBPC) + -rm -f $(DESTDIR)$(LIBPC)/python2.pc + (cd $(DESTDIR)$(LIBPC); $(LN) -s python-$(VERSION).pc python2.pc) + -rm -f $(DESTDIR)$(LIBPC)/python.pc + (cd $(DESTDIR)$(LIBPC); $(LN) -s python2.pc python.pc) + +# Install the interpreter with $(VERSION) affixed +# This goes into $(exec_prefix) +altbininstall: $(BUILDPYTHON) + @for i in $(BINDIR) $(LIBDIR); \ + do \ + if test ! -d $(DESTDIR)$$i; then \ + echo "Creating directory $$i"; \ + $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \ + else true; \ + fi; \ + done + $(INSTALL_PROGRAM) $(BUILDPYTHON) $(DESTDIR)$(BINDIR)/python$(VERSION)$(EXE) + if test -f $(LDLIBRARY); then \ + if test -n "$(DLLLIBRARY)" ; then \ + $(INSTALL_SHARED) $(DLLLIBRARY) $(DESTDIR)$(BINDIR); \ + else \ + $(INSTALL_SHARED) $(LDLIBRARY) $(DESTDIR)$(LIBDIR)/$(INSTSONAME); \ + if test $(LDLIBRARY) != $(INSTSONAME); then \ + (cd $(DESTDIR)$(LIBDIR); $(LN) -sf $(INSTSONAME) $(LDLIBRARY)) \ + fi \ + fi; \ + else true; \ + fi + +# Install the versioned manual page +altmaninstall: + @for i in $(MANDIR) $(MANDIR)/man1; \ + do \ + if test ! -d $(DESTDIR)$$i; then \ + echo "Creating directory $$i"; \ + $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \ + else true; \ + fi; \ + done + $(INSTALL_DATA) $(srcdir)/Misc/python.man \ + $(DESTDIR)$(MANDIR)/man1/python$(VERSION).1 + +# Install the unversioned manual pages +maninstall: altmaninstall + -rm -f $(DESTDIR)$(MANDIR)/man1/python2.1 + (cd $(DESTDIR)$(MANDIR)/man1; $(LN) -s python$(VERSION).1 python2.1) + -rm -f $(DESTDIR)$(MANDIR)/man1/python.1 + (cd $(DESTDIR)$(MANDIR)/man1; $(LN) -s python2.1 python.1) + +# Install the library +PLATDIR= plat-$(MACHDEP) +EXTRAPLATDIR= $(PLATMACDIRS) +EXTRAMACHDEPPATH=$(PLATMACPATH) +MACHDEPS= $(PLATDIR) $(EXTRAPLATDIR) +XMLLIBSUBDIRS= xml xml/dom xml/etree xml/parsers xml/sax +PLATMACDIRS= plat-mac plat-mac/Carbon plat-mac/lib-scriptpackages \ + plat-mac/lib-scriptpackages/_builtinSuites \ + plat-mac/lib-scriptpackages/CodeWarrior \ + plat-mac/lib-scriptpackages/Explorer \ + plat-mac/lib-scriptpackages/Finder \ + plat-mac/lib-scriptpackages/Netscape \ + plat-mac/lib-scriptpackages/StdSuites \ + plat-mac/lib-scriptpackages/SystemEvents \ + plat-mac/lib-scriptpackages/Terminal +PLATMACPATH=:plat-mac:plat-mac/lib-scriptpackages +LIBSUBDIRS= lib-tk lib-tk/test lib-tk/test/test_tkinter \ + lib-tk/test/test_ttk site-packages test test/data \ + test/cjkencodings test/decimaltestdata test/xmltestdata test/subprocessdata \ + test/tracedmodules \ + encodings compiler hotshot \ + email email/mime email/test email/test/data \ + json json/tests \ + sqlite3 sqlite3/test \ + logging bsddb bsddb/test csv importlib wsgiref \ + lib2to3 lib2to3/fixes lib2to3/pgen2 lib2to3/tests \ + lib2to3/tests/data lib2to3/tests/data/fixers lib2to3/tests/data/fixers/myfixes \ + ctypes ctypes/test ctypes/macholib idlelib idlelib/Icons \ + distutils distutils/command distutils/tests $(XMLLIBSUBDIRS) \ + multiprocessing multiprocessing/dummy \ + unittest unittest/test \ + lib-old \ + curses pydoc_data $(MACHDEPS) +libinstall: build_all $(srcdir)/Lib/$(PLATDIR) $(srcdir)/Modules/xxmodule.c + @for i in $(SCRIPTDIR) $(LIBDEST); \ + do \ + if test ! -d $(DESTDIR)$$i; then \ + echo "Creating directory $$i"; \ + $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \ + else true; \ + fi; \ + done + @for d in $(LIBSUBDIRS); \ + do \ + a=$(srcdir)/Lib/$$d; \ + if test ! -d $$a; then continue; else true; fi; \ + b=$(LIBDEST)/$$d; \ + if test ! -d $(DESTDIR)$$b; then \ + echo "Creating directory $$b"; \ + $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$b; \ + else true; \ + fi; \ + done + @for i in $(srcdir)/Lib/*.py `cat pybuilddir.txt`/_sysconfigdata.py $(srcdir)/Lib/*.doc $(srcdir)/Lib/*.egg-info ; \ + do \ + if test -x $$i; then \ + $(INSTALL_SCRIPT) $$i $(DESTDIR)$(LIBDEST); \ + echo $(INSTALL_SCRIPT) $$i $(LIBDEST); \ + else \ + $(INSTALL_DATA) $$i $(DESTDIR)$(LIBDEST); \ + echo $(INSTALL_DATA) $$i $(LIBDEST); \ + fi; \ + done + @for d in $(LIBSUBDIRS); \ + do \ + a=$(srcdir)/Lib/$$d; \ + if test ! -d $$a; then continue; else true; fi; \ + if test `ls $$a | wc -l` -lt 1; then continue; fi; \ + b=$(LIBDEST)/$$d; \ + for i in $$a/*; \ + do \ + case $$i in \ + *CVS) ;; \ + *.py[co]) ;; \ + *.orig) ;; \ + *~) ;; \ + *) \ + if test -d $$i; then continue; fi; \ + if test -x $$i; then \ + echo $(INSTALL_SCRIPT) $$i $$b; \ + $(INSTALL_SCRIPT) $$i $(DESTDIR)$$b; \ + else \ + echo $(INSTALL_DATA) $$i $$b; \ + $(INSTALL_DATA) $$i $(DESTDIR)$$b; \ + fi;; \ + esac; \ + done; \ + done + $(INSTALL_DATA) $(srcdir)/LICENSE $(DESTDIR)$(LIBDEST)/LICENSE.txt + if test -d $(DESTDIR)$(LIBDEST)/distutils/tests; then \ + $(INSTALL_DATA) $(srcdir)/Modules/xxmodule.c \ + $(DESTDIR)$(LIBDEST)/distutils/tests ; \ + fi + PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -Wi -tt $(DESTDIR)$(LIBDEST)/compileall.py \ + -d $(LIBDEST) -f \ + -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ + $(DESTDIR)$(LIBDEST) + PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -Wi -tt -O $(DESTDIR)$(LIBDEST)/compileall.py \ + -d $(LIBDEST) -f \ + -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ + $(DESTDIR)$(LIBDEST) + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -Wi -t $(DESTDIR)$(LIBDEST)/compileall.py \ + -d $(LIBDEST)/site-packages -f \ + -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -Wi -t -O $(DESTDIR)$(LIBDEST)/compileall.py \ + -d $(LIBDEST)/site-packages -f \ + -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/Grammar.txt + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/PatternGrammar.txt + +# Create the PLATDIR source directory, if one wasn't distributed.. +$(srcdir)/Lib/$(PLATDIR): + mkdir $(srcdir)/Lib/$(PLATDIR) + cp $(srcdir)/Lib/plat-generic/regen $(srcdir)/Lib/$(PLATDIR)/regen + export PATH; PATH="`pwd`:$$PATH"; \ + export PYTHONPATH; PYTHONPATH="$(srcdir)/Lib:$(abs_builddir)/`cat pybuilddir.txt`"; \ + export DYLD_FRAMEWORK_PATH; DYLD_FRAMEWORK_PATH="`pwd`"; \ + export EXE; EXE="$(BUILDEXE)"; \ + if [ -n "$(MULTIARCH)" ]; then export MULTIARCH; MULTIARCH=$(MULTIARCH); fi; \ + export PYTHON_FOR_BUILD; \ + if [ "$(build)" = "$(host)" ]; then \ + PYTHON_FOR_BUILD="$(BUILDPYTHON)"; \ + else \ + PYTHON_FOR_BUILD="$(PYTHON_FOR_BUILD)"; \ + fi; \ + cd $(srcdir)/Lib/$(PLATDIR); $(RUNSHARED) ./regen + +python-config: $(srcdir)/Misc/python-config.in + # Substitution happens here, as the completely-expanded BINDIR + # is not available in configure + sed -e "s,@EXENAME@,$(BINDIR)/python$(VERSION)$(EXE)," < $(srcdir)/Misc/python-config.in >python-config + +# Install the include files +INCLDIRSTOMAKE=$(INCLUDEDIR) $(CONFINCLUDEDIR) $(INCLUDEPY) $(CONFINCLUDEPY) +inclinstall: + @for i in $(INCLDIRSTOMAKE); \ + do \ + if test ! -d $(DESTDIR)$$i; then \ + echo "Creating directory $$i"; \ + $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \ + else true; \ + fi; \ + done + @for i in $(srcdir)/Include/*.h; \ + do \ + echo $(INSTALL_DATA) $$i $(INCLUDEPY); \ + $(INSTALL_DATA) $$i $(DESTDIR)$(INCLUDEPY); \ + done + $(INSTALL_DATA) pyconfig.h $(DESTDIR)$(CONFINCLUDEPY)/pyconfig.h + +# Install the library and miscellaneous stuff needed for extending/embedding +# This goes into $(exec_prefix) +LIBPL= $(LIBP)/config + +# pkgconfig directory +LIBPC= $(LIBDIR)/pkgconfig + +libainstall: all python-config + @for i in $(LIBDIR) $(LIBP) $(LIBPL) $(LIBPC); \ + do \ + if test ! -d $(DESTDIR)$$i; then \ + echo "Creating directory $$i"; \ + $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \ + else true; \ + fi; \ + done + @if test -d $(LIBRARY); then :; else \ + if test "$(PYTHONFRAMEWORKDIR)" = no-framework; then \ + if test "$(SO)" = .dll; then \ + $(INSTALL_DATA) $(LDLIBRARY) $(DESTDIR)$(LIBPL) ; \ + else \ + $(INSTALL_DATA) $(LIBRARY) $(DESTDIR)$(LIBPL)/$(LIBRARY) ; \ + $(RANLIB) $(DESTDIR)$(LIBPL)/$(LIBRARY) ; \ + fi; \ + else \ + echo Skip install of $(LIBRARY) - use make frameworkinstall; \ + fi; \ + fi + $(INSTALL_DATA) Modules/config.c $(DESTDIR)$(LIBPL)/config.c + $(INSTALL_DATA) Modules/python.o $(DESTDIR)$(LIBPL)/python.o + $(INSTALL_DATA) $(srcdir)/Modules/config.c.in $(DESTDIR)$(LIBPL)/config.c.in + $(INSTALL_DATA) Makefile $(DESTDIR)$(LIBPL)/Makefile + $(INSTALL_DATA) Modules/Setup $(DESTDIR)$(LIBPL)/Setup + $(INSTALL_DATA) Modules/Setup.local $(DESTDIR)$(LIBPL)/Setup.local + $(INSTALL_DATA) Modules/Setup.config $(DESTDIR)$(LIBPL)/Setup.config + $(INSTALL_DATA) Misc/python.pc $(DESTDIR)$(LIBPC)/python-$(VERSION).pc + $(INSTALL_SCRIPT) $(srcdir)/Modules/makesetup $(DESTDIR)$(LIBPL)/makesetup + $(INSTALL_SCRIPT) $(srcdir)/install-sh $(DESTDIR)$(LIBPL)/install-sh + $(INSTALL_SCRIPT) python-config $(DESTDIR)$(BINDIR)/python$(VERSION)-config + rm python-config + @if [ -s Modules/python.exp -a \ + "`echo $(MACHDEP) | sed 's/^\(...\).*/\1/'`" = "aix" ]; then \ + echo; echo "Installing support files for building shared extension modules on AIX:"; \ + $(INSTALL_DATA) Modules/python.exp \ + $(DESTDIR)$(LIBPL)/python.exp; \ + echo; echo "$(LIBPL)/python.exp"; \ + $(INSTALL_SCRIPT) $(srcdir)/Modules/makexp_aix \ + $(DESTDIR)$(LIBPL)/makexp_aix; \ + echo "$(LIBPL)/makexp_aix"; \ + $(INSTALL_SCRIPT) $(srcdir)/Modules/ld_so_aix \ + $(DESTDIR)$(LIBPL)/ld_so_aix; \ + echo "$(LIBPL)/ld_so_aix"; \ + echo; echo "See Misc/AIX-NOTES for details."; \ + else true; \ + fi + @case "$(MACHDEP)" in beos*) \ + echo; echo "Installing support files for building shared extension modules on BeOS:"; \ + $(INSTALL_DATA) Misc/BeOS-NOTES $(DESTDIR)$(LIBPL)/README; \ + echo; echo "$(LIBPL)/README"; \ + $(INSTALL_SCRIPT) Modules/ar_beos $(DESTDIR)$(LIBPL)/ar_beos; \ + echo "$(LIBPL)/ar_beos"; \ + $(INSTALL_SCRIPT) Modules/ld_so_beos $(DESTDIR)$(LIBPL)/ld_so_beos; \ + echo "$(LIBPL)/ld_so_beos"; \ + echo; echo "See Misc/BeOS-NOTES for details."; \ + ;; \ + esac + +# Install the dynamically loadable modules +# This goes into $(exec_prefix) +sharedinstall: sharedmods + $(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/setup.py install \ + --prefix=$(prefix) \ + --install-scripts=$(BINDIR) \ + --install-platlib=$(DESTSHARED) \ + --root=$(DESTDIR)/ + -rm $(DESTDIR)$(DESTSHARED)/_sysconfigdata.py* + +# Here are a couple of targets for MacOSX again, to install a full +# framework-based Python. frameworkinstall installs everything, the +# subtargets install specific parts. Much of the actual work is offloaded to +# the Makefile in Mac +# +# +# This target is here for backward compatiblity, previous versions of Python +# hadn't integrated framework installation in the normal install process. +frameworkinstall: install + +# On install, we re-make the framework +# structure in the install location, /Library/Frameworks/ or the argument to +# --enable-framework. If --enable-framework has been specified then we have +# automatically set prefix to the location deep down in the framework, so we +# only have to cater for the structural bits of the framework. + +frameworkinstallframework: frameworkinstallstructure install frameworkinstallmaclib + +frameworkinstallstructure: $(LDLIBRARY) + @if test "$(PYTHONFRAMEWORKDIR)" = no-framework; then \ + echo Not configured with --enable-framework; \ + exit 1; \ + else true; \ + fi + @for i in $(prefix)/Resources/English.lproj $(prefix)/lib; do\ + if test ! -d $(DESTDIR)$$i; then \ + echo "Creating directory $(DESTDIR)$$i"; \ + $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \ + else true; \ + fi; \ + done + $(LN) -fsn include/python$(VERSION) $(DESTDIR)$(prefix)/Headers + sed 's/%VERSION%/'"`$(RUNSHARED) ./$(BUILDPYTHON) -c 'import platform; print platform.python_version()'`"'/g' < $(RESSRCDIR)/Info.plist > $(DESTDIR)$(prefix)/Resources/Info.plist + $(LN) -fsn $(VERSION) $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Versions/Current + $(LN) -fsn Versions/Current/$(PYTHONFRAMEWORK) $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/$(PYTHONFRAMEWORK) + $(LN) -fsn Versions/Current/Headers $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Headers + $(LN) -fsn Versions/Current/Resources $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Resources + $(INSTALL_SHARED) $(LDLIBRARY) $(DESTDIR)$(PYTHONFRAMEWORKPREFIX)/$(LDLIBRARY) + +# This installs Mac/Lib into the framework +# Install a number of symlinks to keep software that expects a normal unix +# install (which includes python-config) happy. +frameworkinstallmaclib: + ln -fs "../../../$(PYTHONFRAMEWORK)" "$(DESTDIR)$(prefix)/lib/python$(VERSION)/config/libpython$(VERSION).a" + ln -fs "../../../$(PYTHONFRAMEWORK)" "$(DESTDIR)$(prefix)/lib/python$(VERSION)/config/libpython$(VERSION).dylib" + ln -fs "../$(PYTHONFRAMEWORK)" "$(DESTDIR)$(prefix)/lib/libpython$(VERSION).dylib" + cd Mac && $(MAKE) installmacsubtree DESTDIR="$(DESTDIR)" + +# This installs the IDE, the Launcher and other apps into /Applications +frameworkinstallapps: + cd Mac && $(MAKE) installapps DESTDIR="$(DESTDIR)" + +# This install the unix python and pythonw tools in /usr/local/bin +frameworkinstallunixtools: + cd Mac && $(MAKE) installunixtools DESTDIR="$(DESTDIR)" + +frameworkaltinstallunixtools: + cd Mac && $(MAKE) altinstallunixtools DESTDIR="$(DESTDIR)" + +# This installs the Demos and Tools into the applications directory. +# It is not part of a normal frameworkinstall +frameworkinstallextras: + cd Mac && $(MAKE) installextras DESTDIR="$(DESTDIR)" + +# This installs a few of the useful scripts in Tools/scripts +scriptsinstall: + SRCDIR=$(srcdir) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) $(srcdir)/Tools/scripts/setup.py install \ + --prefix=$(prefix) \ + --install-scripts=$(BINDIR) \ + --root=$(DESTDIR)/ + +# Build the toplevel Makefile +Makefile.pre: Makefile.pre.in config.status + CONFIG_FILES=Makefile.pre CONFIG_HEADERS= $(SHELL) config.status + $(MAKE) -f Makefile.pre Makefile + +# Run the configure script. +config.status: $(srcdir)/configure + $(SHELL) $(srcdir)/configure $(CONFIG_ARGS) + +.PRECIOUS: config.status $(BUILDPYTHON) Makefile Makefile.pre + +# Some make's put the object file in the current directory +.c.o: + $(CC) -c $(PY_CFLAGS) -o $@ $< + +# Run reindent on the library +reindent: + ./$(BUILDPYTHON) $(srcdir)/Tools/scripts/reindent.py -r $(srcdir)/Lib + +# Rerun configure with the same options as it was run last time, +# provided the config.status script exists +recheck: + $(SHELL) config.status --recheck + $(SHELL) config.status + +# Rebuild the configure script from configure.ac; also rebuild pyconfig.h.in +autoconf: + (cd $(srcdir); autoconf) + (cd $(srcdir); autoheader) + +# Create a tags file for vi +tags:: + cd $(srcdir); \ + ctags -w -t Include/*.h; \ + for i in $(SRCDIRS); do ctags -w -t -a $$i/*.[ch]; \ + done; \ + sort -o tags tags + +# Create a tags file for GNU Emacs +TAGS:: + cd $(srcdir); \ + etags Include/*.h; \ + for i in $(SRCDIRS); do etags -a $$i/*.[ch]; done + +# Touch generated files +touch: + touch Include/Python-ast.h Python/Python-ast.c + +# Sanitation targets -- clean leaves libraries, executables and tags +# files, which clobber removes as well +pycremoval: + find $(srcdir) -name '*.py[co]' -exec rm -f {} ';' + +clean: pycremoval + find . -name '*.[oa]' -exec rm -f {} ';' + find . -name '*.s[ol]' -exec rm -f {} ';' + find . -name '*.so.[0-9]*.[0-9]*' -exec rm -f {} ';' + find build -name 'fficonfig.h' -exec rm -f {} ';' || true + find build -name 'fficonfig.py' -exec rm -f {} ';' || true + -rm -f Lib/lib2to3/*Grammar*.pickle + +profile-removal: + find . -name '*.gc??' -exec rm -f {} ';' + +clobber: clean profile-removal + -rm -f $(BUILDPYTHON) $(PGEN) $(LIBRARY) $(LDLIBRARY) $(DLLLIBRARY) \ + tags TAGS \ + config.cache config.log pyconfig.h Modules/config.c + -rm -rf build platform + -rm -rf $(PYTHONFRAMEWORKDIR) + +# Make things extra clean, before making a distribution: +# remove all generated files, even Makefile[.pre] +# Keep configure and Python-ast.[ch], it's possible they can't be generated +distclean: clobber + for file in Lib/test/data/* ; do \ + if test "$$file" != "Lib/test/data/README"; then rm "$$file"; fi; \ + done + -rm -f core Makefile Makefile.pre config.status \ + Modules/Setup Modules/Setup.local Modules/Setup.config \ + Modules/ld_so_aix Modules/python.exp Misc/python.pc + -rm -f python*-gdb.py + -rm -f pybuilddir.txt + find $(srcdir) '(' -name '*.fdc' -o -name '*~' \ + -o -name '[@,#]*' -o -name '*.old' \ + -o -name '*.orig' -o -name '*.rej' \ + -o -name '*.bak' ')' \ + -exec rm -f {} ';' + +# Check for smelly exported symbols (not starting with Py/_Py) +smelly: all + nm -p $(LIBRARY) | \ + sed -n "/ [TDB] /s/.* //p" | grep -v "^_*Py" | sort -u; \ + +# Find files with funny names +funny: + find $(SUBDIRS) $(SUBDIRSTOO) -type d \ + -o -name '*.[chs]' \ + -o -name '*.py' \ + -o -name '*.doc' \ + -o -name '*.sty' \ + -o -name '*.bib' \ + -o -name '*.dat' \ + -o -name '*.el' \ + -o -name '*.fd' \ + -o -name '*.in' \ + -o -name '*.tex' \ + -o -name '*,[vpt]' \ + -o -name 'Setup' \ + -o -name 'Setup.*' \ + -o -name README \ + -o -name Makefile \ + -o -name ChangeLog \ + -o -name Repository \ + -o -name Root \ + -o -name Entries \ + -o -name Tag \ + -o -name tags \ + -o -name TAGS \ + -o -name .cvsignore \ + -o -name MANIFEST \ + -o -print + +# Perform some verification checks on any modified files. +patchcheck: + $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/scripts/patchcheck.py + +# Dependencies + +Python/thread.o: $(srcdir)/Python/thread_atheos.h $(srcdir)/Python/thread_beos.h $(srcdir)/Python/thread_cthread.h $(srcdir)/Python/thread_foobar.h $(srcdir)/Python/thread_lwp.h $(srcdir)/Python/thread_nt.h $(srcdir)/Python/thread_os2.h $(srcdir)/Python/thread_pth.h $(srcdir)/Python/thread_pthread.h $(srcdir)/Python/thread_sgi.h $(srcdir)/Python/thread_solaris.h $(srcdir)/Python/thread_wince.h + +# Declare targets that aren't real files +.PHONY: all build_all sharedmods oldsharedmods test quicktest memtest +.PHONY: install altinstall oldsharedinstall bininstall altbininstall +.PHONY: maninstall libinstall inclinstall libainstall sharedinstall +.PHONY: frameworkinstall frameworkinstallframework frameworkinstallstructure +.PHONY: frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools +.PHONY: frameworkaltinstallunixtools recheck autoconf clean clobber distclean +.PHONY: smelly funny patchcheck touch altmaninstall +.PHONY: gdbhooks + +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY + +# Rules appended by makedepend + +Modules/threadmodule.o: $(srcdir)/Modules/threadmodule.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/threadmodule.c -o Modules/threadmodule.o +Modules/threadmodule$(SO): Modules/threadmodule.o; $(BLDSHARED) Modules/threadmodule.o -o Modules/threadmodule$(SO) +Modules/signalmodule.o: $(srcdir)/Modules/signalmodule.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/signalmodule.c -o Modules/signalmodule.o +Modules/signalmodule$(SO): Modules/signalmodule.o; $(BLDSHARED) Modules/signalmodule.o -o Modules/signalmodule$(SO) +Modules/posixmodule.o: $(srcdir)/Modules/posixmodule.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/posixmodule.c -o Modules/posixmodule.o +Modules/posixmodule$(SO): Modules/posixmodule.o; $(BLDSHARED) Modules/posixmodule.o -o Modules/posixmodule$(SO) +Modules/errnomodule.o: $(srcdir)/Modules/errnomodule.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/errnomodule.c -o Modules/errnomodule.o +Modules/errnomodule$(SO): Modules/errnomodule.o; $(BLDSHARED) Modules/errnomodule.o -o Modules/errnomodule$(SO) +Modules/pwdmodule.o: $(srcdir)/Modules/pwdmodule.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/pwdmodule.c -o Modules/pwdmodule.o +Modules/pwdmodule$(SO): Modules/pwdmodule.o; $(BLDSHARED) Modules/pwdmodule.o -o Modules/pwdmodule$(SO) +Modules/_sre.o: $(srcdir)/Modules/_sre.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/_sre.c -o Modules/_sre.o +Modules/_sre$(SO): Modules/_sre.o; $(BLDSHARED) Modules/_sre.o -o Modules/_sre$(SO) +Modules/_codecsmodule.o: $(srcdir)/Modules/_codecsmodule.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/_codecsmodule.c -o Modules/_codecsmodule.o +Modules/_codecsmodule$(SO): Modules/_codecsmodule.o; $(BLDSHARED) Modules/_codecsmodule.o -o Modules/_codecsmodule$(SO) +Modules/_weakref.o: $(srcdir)/Modules/_weakref.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/_weakref.c -o Modules/_weakref.o +Modules/_weakref$(SO): Modules/_weakref.o; $(BLDSHARED) Modules/_weakref.o -o Modules/_weakref$(SO) +Modules/zipimport.o: $(srcdir)/Modules/zipimport.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/zipimport.c -o Modules/zipimport.o +Modules/zipimport$(SO): Modules/zipimport.o; $(BLDSHARED) Modules/zipimport.o -o Modules/zipimport$(SO) +Modules/symtablemodule.o: $(srcdir)/Modules/symtablemodule.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/symtablemodule.c -o Modules/symtablemodule.o +Modules/_symtablemodule$(SO): Modules/symtablemodule.o; $(BLDSHARED) Modules/symtablemodule.o -o Modules/_symtablemodule$(SO) +Modules/xxsubtype.o: $(srcdir)/Modules/xxsubtype.c; $(CC) $(PY_CFLAGS) -c $(srcdir)/Modules/xxsubtype.c -o Modules/xxsubtype.o +Modules/xxsubtype$(SO): Modules/xxsubtype.o; $(BLDSHARED) Modules/xxsubtype.o -o Modules/xxsubtype$(SO) diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/config/Setup b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/config/Setup new file mode 100644 index 0000000..2ad1aa3 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/config/Setup @@ -0,0 +1,499 @@ +# -*- makefile -*- +# The file Setup is used by the makesetup script to construct the files +# Makefile and config.c, from Makefile.pre and config.c.in, +# respectively. The file Setup itself is initially copied from +# Setup.dist; once it exists it will not be overwritten, so you can edit +# Setup to your heart's content. Note that Makefile.pre is created +# from Makefile.pre.in by the toplevel configure script. + +# (VPATH notes: Setup and Makefile.pre are in the build directory, as +# are Makefile and config.c; the *.in and *.dist files are in the source +# directory.) + +# Each line in this file describes one or more optional modules. +# Modules enabled here will not be compiled by the setup.py script, +# so the file can be used to override setup.py's behavior. + +# Lines have the following structure: +# +# ... [ ...] [ ...] [ ...] +# +# is anything ending in .c (.C, .cc, .c++ are C++ files) +# is anything starting with -I, -D, -U or -C +# is anything ending in .a or beginning with -l or -L +# is anything else but should be a valid Python +# identifier (letters, digits, underscores, beginning with non-digit) +# +# (As the makesetup script changes, it may recognize some other +# arguments as well, e.g. *.so and *.sl as libraries. See the big +# case statement in the makesetup script.) +# +# Lines can also have the form +# +# = +# +# which defines a Make variable definition inserted into Makefile.in +# +# Finally, if a line contains just the word "*shared*" (without the +# quotes but with the stars), then the following modules will not be +# built statically. The build process works like this: +# +# 1. Build all modules that are declared as static in Modules/Setup, +# combine them into libpythonxy.a, combine that into python. +# 2. Build all modules that are listed as shared in Modules/Setup. +# 3. Invoke setup.py. That builds all modules that +# a) are not builtin, and +# b) are not listed in Modules/Setup, and +# c) can be build on the target +# +# Therefore, modules declared to be shared will not be +# included in the config.c file, nor in the list of objects to be +# added to the library archive, and their linker options won't be +# added to the linker options. Rules to create their .o files and +# their shared libraries will still be added to the Makefile, and +# their names will be collected in the Make variable SHAREDMODS. This +# is used to build modules as shared libraries. (They can be +# installed using "make sharedinstall", which is implied by the +# toplevel "make install" target.) (For compatibility, +# *noconfig* has the same effect as *shared*.) +# +# In addition, *static* explicitly declares the following modules to +# be static. Lines containing "*static*" and "*shared*" may thus +# alternate throughout this file. + +# NOTE: As a standard policy, as many modules as can be supported by a +# platform should be present. The distribution comes with all modules +# enabled that are supported by most platforms and don't require you +# to ftp sources from elsewhere. + + +# Some special rules to define PYTHONPATH. +# Edit the definitions below to indicate which options you are using. +# Don't add any whitespace or comments! + +# Directories where library files get installed. +# DESTLIB is for Python modules; MACHDESTLIB for shared libraries. +DESTLIB=$(LIBDEST) +MACHDESTLIB=$(BINLIBDEST) + +# NOTE: all the paths are now relative to the prefix that is computed +# at run time! + +# Standard path -- don't edit. +# No leading colon since this is the first entry. +# Empty since this is now just the runtime prefix. +DESTPATH= + +# Site specific path components -- should begin with : if non-empty +SITEPATH= + +# Standard path components for test modules +TESTPATH= + +# Path components for machine- or system-dependent modules and shared libraries +MACHDEPPATH=:plat-$(MACHDEP) +EXTRAMACHDEPPATH= + +# Path component for the Tkinter-related modules +# The TKPATH variable is always enabled, to save you the effort. +TKPATH=:lib-tk + +# Path component for old modules. +OLDPATH=:lib-old + +COREPYTHONPATH=$(DESTPATH)$(SITEPATH)$(TESTPATH)$(MACHDEPPATH)$(EXTRAMACHDEPPATH)$(TKPATH)$(OLDPATH) +PYTHONPATH=$(COREPYTHONPATH) + + +# The modules listed here can't be built as shared libraries for +# various reasons; therefore they are listed here instead of in the +# normal order. + +# This only contains the minimal set of modules required to run the +# setup.py script in the root of the Python source tree. + +posix posixmodule.c # posix (UNIX) system calls +errno errnomodule.c # posix (UNIX) errno values +pwd pwdmodule.c # this is needed to find out the user's home dir + # if $HOME is not set +_sre _sre.c # Fredrik Lundh's new regular expressions +_codecs _codecsmodule.c # access to the builtin codecs and codec registry +_weakref _weakref.c # weak references + +# The zipimport module is always imported at startup. Having it as a +# builtin module avoids some bootstrapping problems and reduces overhead. +zipimport zipimport.c + +# The rest of the modules listed in this file are all commented out by +# default. Usually they can be detected and built as dynamically +# loaded modules by the new setup.py script added in Python 2.1. If +# you're on a platform that doesn't support dynamic loading, want to +# compile modules statically into the Python binary, or need to +# specify some odd set of compiler switches, you can uncomment the +# appropriate lines below. + +# ====================================================================== + +# The Python symtable module depends on .h files that setup.py doesn't track +_symtable symtablemodule.c + +# The SGI specific GL module: + +GLHACK=-Dclear=__GLclear +#gl glmodule.c cgensupport.c -I$(srcdir) $(GLHACK) -lgl -lX11 + +# Pure module. Cannot be linked dynamically. +# -DWITH_QUANTIFY, -DWITH_PURIFY, or -DWITH_ALL_PURE +#WHICH_PURE_PRODUCTS=-DWITH_ALL_PURE +#PURE_INCLS=-I/usr/local/include +#PURE_STUBLIBS=-L/usr/local/lib -lpurify_stubs -lquantify_stubs +#pure puremodule.c $(WHICH_PURE_PRODUCTS) $(PURE_INCLS) $(PURE_STUBLIBS) + +# Uncommenting the following line tells makesetup that all following +# modules are to be built as shared libraries (see above for more +# detail; also note that *static* reverses this effect): + +#*shared* + +# GNU readline. Unlike previous Python incarnations, GNU readline is +# now incorporated in an optional module, configured in the Setup file +# instead of by a configure script switch. You may have to insert a +# -L option pointing to the directory where libreadline.* lives, +# and you may have to change -ltermcap to -ltermlib or perhaps remove +# it, depending on your system -- see the GNU readline instructions. +# It's okay for this to be a shared library, too. + +#readline readline.c -lreadline -ltermcap + + +# Modules that should always be present (non UNIX dependent): + +#array arraymodule.c # array objects +#cmath cmathmodule.c _math.c # -lm # complex math library functions +#math mathmodule.c _math.c # -lm # math library functions, e.g. sin() +#_struct _struct.c # binary structure packing/unpacking +#time timemodule.c # -lm # time operations and variables +#operator operator.c # operator.add() and similar goodies +#_testcapi _testcapimodule.c # Python C API test module +#_random _randommodule.c # Random number generator +#_collections _collectionsmodule.c # Container types +#_heapq _heapqmodule.c # Heapq type +#itertools itertoolsmodule.c # Functions creating iterators for efficient looping +#strop stropmodule.c # String manipulations +#_functools _functoolsmodule.c # Tools for working with functions and callable objects +#_elementtree -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI _elementtree.c # elementtree accelerator +#_pickle _pickle.c # pickle accelerator +#datetime datetimemodule.c # date/time type +#_bisect _bisectmodule.c # Bisection algorithms + +#unicodedata unicodedata.c # static Unicode character database + +# access to ISO C locale support +#_locale _localemodule.c # -lintl + +# Standard I/O baseline +#_io -I$(srcdir)/Modules/_io _io/bufferedio.c _io/bytesio.c _io/fileio.c _io/iobase.c _io/_iomodule.c _io/stringio.c _io/textio.c + + +# Modules with some UNIX dependencies -- on by default: +# (If you have a really backward UNIX, select and socket may not be +# supported...) + +#fcntl fcntlmodule.c # fcntl(2) and ioctl(2) +#spwd spwdmodule.c # spwd(3) +#grp grpmodule.c # grp(3) +#select selectmodule.c # select(2); not on ancient System V + +# Memory-mapped files (also works on Win32). +#mmap mmapmodule.c + +# CSV file helper +#_csv _csv.c + +# Socket module helper for socket(2) +#_socket socketmodule.c timemodule.c + +# Socket module helper for SSL support; you must comment out the other +# socket line above, and possibly edit the SSL variable: +#SSL=/usr/local/ssl +#_ssl _ssl.c \ +# -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \ +# -L$(SSL)/lib -lssl -lcrypto + +# The crypt module is now disabled by default because it breaks builds +# on many systems (where -lcrypt is needed), e.g. Linux (I believe). +# +# First, look at Setup.config; configure may have set this for you. + +#crypt cryptmodule.c # -lcrypt # crypt(3); needs -lcrypt on some systems + + +# Some more UNIX dependent modules -- off by default, since these +# are not supported by all UNIX systems: + +#nis nismodule.c -lnsl # Sun yellow pages -- not everywhere +#termios termios.c # Steen Lumholt's termios module +#resource resource.c # Jeremy Hylton's rlimit interface + + +# Multimedia modules -- off by default. +# These don't work for 64-bit platforms!!! +# #993173 says audioop works on 64-bit platforms, though. +# These represent audio samples or images as strings: + +#audioop audioop.c # Operations on audio samples +#imageop imageop.c # Operations on images + + +# Note that the _md5 and _sha modules are normally only built if the +# system does not have the OpenSSL libs containing an optimized version. + +# The _md5 module implements the RSA Data Security, Inc. MD5 +# Message-Digest Algorithm, described in RFC 1321. The necessary files +# md5.c and md5.h are included here. + +#_md5 md5module.c md5.c + + +# The _sha module implements the SHA checksum algorithms. +# (NIST's Secure Hash Algorithms.) +#_sha shamodule.c +#_sha256 sha256module.c +#_sha512 sha512module.c + + +# SGI IRIX specific modules -- off by default. + +# These module work on any SGI machine: + +# *** gl must be enabled higher up in this file *** +#fm fmmodule.c $(GLHACK) -lfm -lgl # Font Manager +#sgi sgimodule.c # sgi.nap() and a few more + +# This module requires the header file +# /usr/people/4Dgifts/iristools/include/izoom.h: +#imgfile imgfile.c -limage -lgutil -lgl -lm # Image Processing Utilities + + +# These modules require the Multimedia Development Option (I think): + +#al almodule.c -laudio # Audio Library +#cd cdmodule.c -lcdaudio -lds -lmediad # CD Audio Library +#cl clmodule.c -lcl -lawareaudio # Compression Library +#sv svmodule.c yuvconvert.c -lsvideo -lXext -lX11 # Starter Video + + +# The FORMS library, by Mark Overmars, implements user interface +# components such as dialogs and buttons using SGI's GL and FM +# libraries. You must ftp the FORMS library separately from +# ftp://ftp.cs.ruu.nl/pub/SGI/FORMS. It was tested with FORMS 2.2a. +# NOTE: if you want to be able to use FORMS and curses simultaneously +# (or both link them statically into the same binary), you must +# compile all of FORMS with the cc option "-Dclear=__GLclear". + +# The FORMS variable must point to the FORMS subdirectory of the forms +# toplevel directory: + +#FORMS=/ufs/guido/src/forms/FORMS +#fl flmodule.c -I$(FORMS) $(GLHACK) $(FORMS)/libforms.a -lfm -lgl + + +# SunOS specific modules -- off by default: + +#sunaudiodev sunaudiodev.c + + +# A Linux specific module -- off by default; this may also work on +# some *BSDs. + +#linuxaudiodev linuxaudiodev.c + + +# George Neville-Neil's timing module: + +#timing timingmodule.c + + +# The _tkinter module. +# +# The command for _tkinter is long and site specific. Please +# uncomment and/or edit those parts as indicated. If you don't have a +# specific extension (e.g. Tix or BLT), leave the corresponding line +# commented out. (Leave the trailing backslashes in! If you +# experience strange errors, you may want to join all uncommented +# lines and remove the backslashes -- the backslash interpretation is +# done by the shell's "read" command and it may not be implemented on +# every system. + +# *** Always uncomment this (leave the leading underscore in!): +# _tkinter _tkinter.c tkappinit.c -DWITH_APPINIT \ +# *** Uncomment and edit to reflect where your Tcl/Tk libraries are: +# -L/usr/local/lib \ +# *** Uncomment and edit to reflect where your Tcl/Tk headers are: +# -I/usr/local/include \ +# *** Uncomment and edit to reflect where your X11 header files are: +# -I/usr/X11R6/include \ +# *** Or uncomment this for Solaris: +# -I/usr/openwin/include \ +# *** Uncomment and edit for Tix extension only: +# -DWITH_TIX -ltix8.1.8.2 \ +# *** Uncomment and edit for BLT extension only: +# -DWITH_BLT -I/usr/local/blt/blt8.0-unoff/include -lBLT8.0 \ +# *** Uncomment and edit for PIL (TkImaging) extension only: +# (See http://www.pythonware.com/products/pil/ for more info) +# -DWITH_PIL -I../Extensions/Imaging/libImaging tkImaging.c \ +# *** Uncomment and edit for TOGL extension only: +# -DWITH_TOGL togl.c \ +# *** Uncomment and edit to reflect your Tcl/Tk versions: +# -ltk8.2 -ltcl8.2 \ +# *** Uncomment and edit to reflect where your X11 libraries are: +# -L/usr/X11R6/lib \ +# *** Or uncomment this for Solaris: +# -L/usr/openwin/lib \ +# *** Uncomment these for TOGL extension only: +# -lGL -lGLU -lXext -lXmu \ +# *** Uncomment for AIX: +# -lld \ +# *** Always uncomment this; X11 libraries to link with: +# -lX11 + +# Lance Ellinghaus's syslog module +#syslog syslogmodule.c # syslog daemon interface + + +# Curses support, requring the System V version of curses, often +# provided by the ncurses library. e.g. on Linux, link with -lncurses +# instead of -lcurses). +# +# First, look at Setup.config; configure may have set this for you. + +#_curses _cursesmodule.c -lcurses -ltermcap +# Wrapper for the panel library that's part of ncurses and SYSV curses. +#_curses_panel _curses_panel.c -lpanel -lncurses + + +# Generic (SunOS / SVR4) dynamic loading module. +# This is not needed for dynamic loading of Python modules -- +# it is a highly experimental and dangerous device for calling +# *arbitrary* C functions in *arbitrary* shared libraries: + +#dl dlmodule.c + + +# Modules that provide persistent dictionary-like semantics. You will +# probably want to arrange for at least one of them to be available on +# your machine, though none are defined by default because of library +# dependencies. The Python module anydbm.py provides an +# implementation independent wrapper for these; dumbdbm.py provides +# similar functionality (but slower of course) implemented in Python. + +# The standard Unix dbm module has been moved to Setup.config so that +# it will be compiled as a shared library by default. Compiling it as +# a built-in module causes conflicts with the pybsddb3 module since it +# creates a static dependency on an out-of-date version of db.so. +# +# First, look at Setup.config; configure may have set this for you. + +#dbm dbmmodule.c # dbm(3) may require -lndbm or similar + +# Anthony Baxter's gdbm module. GNU dbm(3) will require -lgdbm: +# +# First, look at Setup.config; configure may have set this for you. + +#gdbm gdbmmodule.c -I/usr/local/include -L/usr/local/lib -lgdbm + + +# Sleepycat Berkeley DB interface. +# +# This requires the Sleepycat DB code, see http://www.sleepycat.com/ +# The earliest supported version of that library is 3.0, the latest +# supported version is 4.0 (4.1 is specifically not supported, as that +# changes the semantics of transactional databases). A list of available +# releases can be found at +# +# http://www.sleepycat.com/update/index.html +# +# Edit the variables DB and DBLIBVERto point to the db top directory +# and the subdirectory of PORT where you built it. +#DB=/usr/local/BerkeleyDB.4.0 +#DBLIBVER=4.0 +#DBINC=$(DB)/include +#DBLIB=$(DB)/lib +#_bsddb _bsddb.c -I$(DBINC) -L$(DBLIB) -ldb-$(DBLIBVER) + +# Historical Berkeley DB 1.85 +# +# This module is deprecated; the 1.85 version of the Berkeley DB library has +# bugs that can cause data corruption. If you can, use later versions of the +# library instead, available from . + +#DB=/depot/sundry/src/berkeley-db/db.1.85 +#DBPORT=$(DB)/PORT/irix.5.3 +#bsddb185 bsddbmodule.c -I$(DBPORT)/include -I$(DBPORT) $(DBPORT)/libdb.a + + + +# Helper module for various ascii-encoders +#binascii binascii.c + +# Fred Drake's interface to the Python parser +#parser parsermodule.c + +# cStringIO and cPickle +#cStringIO cStringIO.c +#cPickle cPickle.c + + +# Lee Busby's SIGFPE modules. +# The library to link fpectl with is platform specific. +# Choose *one* of the options below for fpectl: + +# For SGI IRIX (tested on 5.3): +#fpectl fpectlmodule.c -lfpe + +# For Solaris with SunPro compiler (tested on Solaris 2.5 with SunPro C 4.2): +# (Without the compiler you don't have -lsunmath.) +#fpectl fpectlmodule.c -R/opt/SUNWspro/lib -lsunmath -lm + +# For other systems: see instructions in fpectlmodule.c. +#fpectl fpectlmodule.c ... + +# Test module for fpectl. No extra libraries needed. +#fpetest fpetestmodule.c + +# Andrew Kuchling's zlib module. +# This require zlib 1.1.3 (or later). +# See http://www.gzip.org/zlib/ +#zlib zlibmodule.c -I$(prefix)/include -L$(exec_prefix)/lib -lz + +# Interface to the Expat XML parser +# +# Expat was written by James Clark and is now maintained by a group of +# developers on SourceForge; see www.libexpat.org for more +# information. The pyexpat module was written by Paul Prescod after a +# prototype by Jack Jansen. Source of Expat 1.95.2 is included in +# Modules/expat/. Usage of a system shared libexpat.so/expat.dll is +# not advised. +# +# More information on Expat can be found at www.libexpat.org. +# +#pyexpat expat/xmlparse.c expat/xmlrole.c expat/xmltok.c pyexpat.c -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI + + +# Hye-Shik Chang's CJKCodecs + +# multibytecodec is required for all the other CJK codec modules +#_multibytecodec cjkcodecs/multibytecodec.c + +#_codecs_cn cjkcodecs/_codecs_cn.c +#_codecs_hk cjkcodecs/_codecs_hk.c +#_codecs_iso2022 cjkcodecs/_codecs_iso2022.c +#_codecs_jp cjkcodecs/_codecs_jp.c +#_codecs_kr cjkcodecs/_codecs_kr.c +#_codecs_tw cjkcodecs/_codecs_tw.c + +# Example -- included for reference only: +# xx xxmodule.c + +# Another example -- the 'xxsubtype' module shows C-level subtyping in action +xxsubtype xxsubtype.c diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/config/Setup.config b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/config/Setup.config new file mode 100644 index 0000000..807ab6b --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/config/Setup.config @@ -0,0 +1,13 @@ +# This file is transmogrified into Setup.config by config.status. + +# The purpose of this file is to conditionally enable certain modules +# based on configure-time options. + +# Threading +thread threadmodule.c + +# The signal module +signal signalmodule.c + +# The rest of the modules previously listed in this file are built +# by the setup.py script in Python 2.1 and later. diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/config/Setup.local b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/config/Setup.local new file mode 100644 index 0000000..ca2983e --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/config/Setup.local @@ -0,0 +1 @@ +# Edit this file for local setup changes diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/__init__.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/__init__.py new file mode 100644 index 0000000..a780ebe --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/__init__.py @@ -0,0 +1,123 @@ +# Copyright (C) 2001-2006 Python Software Foundation +# Author: Barry Warsaw +# Contact: email-sig@python.org + +"""A package for parsing, handling, and generating email messages.""" + +__version__ = '4.0.3' + +__all__ = [ + # Old names + 'base64MIME', + 'Charset', + 'Encoders', + 'Errors', + 'Generator', + 'Header', + 'Iterators', + 'Message', + 'MIMEAudio', + 'MIMEBase', + 'MIMEImage', + 'MIMEMessage', + 'MIMEMultipart', + 'MIMENonMultipart', + 'MIMEText', + 'Parser', + 'quopriMIME', + 'Utils', + 'message_from_string', + 'message_from_file', + # new names + 'base64mime', + 'charset', + 'encoders', + 'errors', + 'generator', + 'header', + 'iterators', + 'message', + 'mime', + 'parser', + 'quoprimime', + 'utils', + ] + + + +# Some convenience routines. Don't import Parser and Message as side-effects +# of importing email since those cascadingly import most of the rest of the +# email package. +def message_from_string(s, *args, **kws): + """Parse a string into a Message object model. + + Optional _class and strict are passed to the Parser constructor. + """ + from email.parser import Parser + return Parser(*args, **kws).parsestr(s) + + +def message_from_file(fp, *args, **kws): + """Read a file and parse its contents into a Message object model. + + Optional _class and strict are passed to the Parser constructor. + """ + from email.parser import Parser + return Parser(*args, **kws).parse(fp) + + + +# Lazy loading to provide name mapping from new-style names (PEP 8 compatible +# email 4.0 module names), to old-style names (email 3.0 module names). +import sys + +class LazyImporter(object): + def __init__(self, module_name): + self.__name__ = 'email.' + module_name + + def __getattr__(self, name): + __import__(self.__name__) + mod = sys.modules[self.__name__] + self.__dict__.update(mod.__dict__) + return getattr(mod, name) + + +_LOWERNAMES = [ + # email. -> email. + 'Charset', + 'Encoders', + 'Errors', + 'FeedParser', + 'Generator', + 'Header', + 'Iterators', + 'Message', + 'Parser', + 'Utils', + 'base64MIME', + 'quopriMIME', + ] + +_MIMENAMES = [ + # email.MIME -> email.mime. + 'Audio', + 'Base', + 'Image', + 'Message', + 'Multipart', + 'NonMultipart', + 'Text', + ] + +for _name in _LOWERNAMES: + importer = LazyImporter(_name.lower()) + sys.modules['email.' + _name] = importer + setattr(sys.modules['email'], _name, importer) + + +import email.mime +for _name in _MIMENAMES: + importer = LazyImporter('mime.' + _name.lower()) + sys.modules['email.MIME' + _name] = importer + setattr(sys.modules['email'], 'MIME' + _name, importer) + setattr(sys.modules['email.mime'], _name, importer) diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/__init__.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/__init__.pyc new file mode 100644 index 0000000..7610fc8 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/__init__.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/__init__.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/__init__.pyo new file mode 100644 index 0000000..7610fc8 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/__init__.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/_parseaddr.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/_parseaddr.py new file mode 100644 index 0000000..690db2c --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/_parseaddr.py @@ -0,0 +1,497 @@ +# Copyright (C) 2002-2007 Python Software Foundation +# Contact: email-sig@python.org + +"""Email address parsing code. + +Lifted directly from rfc822.py. This should eventually be rewritten. +""" + +__all__ = [ + 'mktime_tz', + 'parsedate', + 'parsedate_tz', + 'quote', + ] + +import time, calendar + +SPACE = ' ' +EMPTYSTRING = '' +COMMASPACE = ', ' + +# Parse a date field +_monthnames = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', + 'aug', 'sep', 'oct', 'nov', 'dec', + 'january', 'february', 'march', 'april', 'may', 'june', 'july', + 'august', 'september', 'october', 'november', 'december'] + +_daynames = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'] + +# The timezone table does not include the military time zones defined +# in RFC822, other than Z. According to RFC1123, the description in +# RFC822 gets the signs wrong, so we can't rely on any such time +# zones. RFC1123 recommends that numeric timezone indicators be used +# instead of timezone names. + +_timezones = {'UT':0, 'UTC':0, 'GMT':0, 'Z':0, + 'AST': -400, 'ADT': -300, # Atlantic (used in Canada) + 'EST': -500, 'EDT': -400, # Eastern + 'CST': -600, 'CDT': -500, # Central + 'MST': -700, 'MDT': -600, # Mountain + 'PST': -800, 'PDT': -700 # Pacific + } + + +def parsedate_tz(data): + """Convert a date string to a time tuple. + + Accounts for military timezones. + """ + data = data.split() + # The FWS after the comma after the day-of-week is optional, so search and + # adjust for this. + if data[0].endswith(',') or data[0].lower() in _daynames: + # There's a dayname here. Skip it + del data[0] + else: + i = data[0].rfind(',') + if i >= 0: + data[0] = data[0][i+1:] + if len(data) == 3: # RFC 850 date, deprecated + stuff = data[0].split('-') + if len(stuff) == 3: + data = stuff + data[1:] + if len(data) == 4: + s = data[3] + i = s.find('+') + if i > 0: + data[3:] = [s[:i], s[i+1:]] + else: + data.append('') # Dummy tz + if len(data) < 5: + return None + data = data[:5] + [dd, mm, yy, tm, tz] = data + mm = mm.lower() + if mm not in _monthnames: + dd, mm = mm, dd.lower() + if mm not in _monthnames: + return None + mm = _monthnames.index(mm) + 1 + if mm > 12: + mm -= 12 + if dd[-1] == ',': + dd = dd[:-1] + i = yy.find(':') + if i > 0: + yy, tm = tm, yy + if yy[-1] == ',': + yy = yy[:-1] + if not yy[0].isdigit(): + yy, tz = tz, yy + if tm[-1] == ',': + tm = tm[:-1] + tm = tm.split(':') + if len(tm) == 2: + [thh, tmm] = tm + tss = '0' + elif len(tm) == 3: + [thh, tmm, tss] = tm + else: + return None + try: + yy = int(yy) + dd = int(dd) + thh = int(thh) + tmm = int(tmm) + tss = int(tss) + except ValueError: + return None + # Check for a yy specified in two-digit format, then convert it to the + # appropriate four-digit format, according to the POSIX standard. RFC 822 + # calls for a two-digit yy, but RFC 2822 (which obsoletes RFC 822) + # mandates a 4-digit yy. For more information, see the documentation for + # the time module. + if yy < 100: + # The year is between 1969 and 1999 (inclusive). + if yy > 68: + yy += 1900 + # The year is between 2000 and 2068 (inclusive). + else: + yy += 2000 + tzoffset = None + tz = tz.upper() + if tz in _timezones: + tzoffset = _timezones[tz] + else: + try: + tzoffset = int(tz) + except ValueError: + pass + # Convert a timezone offset into seconds ; -0500 -> -18000 + if tzoffset: + if tzoffset < 0: + tzsign = -1 + tzoffset = -tzoffset + else: + tzsign = 1 + tzoffset = tzsign * ( (tzoffset//100)*3600 + (tzoffset % 100)*60) + # Daylight Saving Time flag is set to -1, since DST is unknown. + return yy, mm, dd, thh, tmm, tss, 0, 1, -1, tzoffset + + +def parsedate(data): + """Convert a time string to a time tuple.""" + t = parsedate_tz(data) + if isinstance(t, tuple): + return t[:9] + else: + return t + + +def mktime_tz(data): + """Turn a 10-tuple as returned by parsedate_tz() into a POSIX timestamp.""" + if data[9] is None: + # No zone info, so localtime is better assumption than GMT + return time.mktime(data[:8] + (-1,)) + else: + t = calendar.timegm(data) + return t - data[9] + + +def quote(str): + """Prepare string to be used in a quoted string. + + Turns backslash and double quote characters into quoted pairs. These + are the only characters that need to be quoted inside a quoted string. + Does not add the surrounding double quotes. + """ + return str.replace('\\', '\\\\').replace('"', '\\"') + + +class AddrlistClass: + """Address parser class by Ben Escoto. + + To understand what this class does, it helps to have a copy of RFC 2822 in + front of you. + + Note: this class interface is deprecated and may be removed in the future. + Use rfc822.AddressList instead. + """ + + def __init__(self, field): + """Initialize a new instance. + + `field' is an unparsed address header field, containing + one or more addresses. + """ + self.specials = '()<>@,:;.\"[]' + self.pos = 0 + self.LWS = ' \t' + self.CR = '\r\n' + self.FWS = self.LWS + self.CR + self.atomends = self.specials + self.LWS + self.CR + # Note that RFC 2822 now specifies `.' as obs-phrase, meaning that it + # is obsolete syntax. RFC 2822 requires that we recognize obsolete + # syntax, so allow dots in phrases. + self.phraseends = self.atomends.replace('.', '') + self.field = field + self.commentlist = [] + + def gotonext(self): + """Parse up to the start of the next address.""" + while self.pos < len(self.field): + if self.field[self.pos] in self.LWS + '\n\r': + self.pos += 1 + elif self.field[self.pos] == '(': + self.commentlist.append(self.getcomment()) + else: + break + + def getaddrlist(self): + """Parse all addresses. + + Returns a list containing all of the addresses. + """ + result = [] + while self.pos < len(self.field): + ad = self.getaddress() + if ad: + result += ad + else: + result.append(('', '')) + return result + + def getaddress(self): + """Parse the next address.""" + self.commentlist = [] + self.gotonext() + + oldpos = self.pos + oldcl = self.commentlist + plist = self.getphraselist() + + self.gotonext() + returnlist = [] + + if self.pos >= len(self.field): + # Bad email address technically, no domain. + if plist: + returnlist = [(SPACE.join(self.commentlist), plist[0])] + + elif self.field[self.pos] in '.@': + # email address is just an addrspec + # this isn't very efficient since we start over + self.pos = oldpos + self.commentlist = oldcl + addrspec = self.getaddrspec() + returnlist = [(SPACE.join(self.commentlist), addrspec)] + + elif self.field[self.pos] == ':': + # address is a group + returnlist = [] + + fieldlen = len(self.field) + self.pos += 1 + while self.pos < len(self.field): + self.gotonext() + if self.pos < fieldlen and self.field[self.pos] == ';': + self.pos += 1 + break + returnlist = returnlist + self.getaddress() + + elif self.field[self.pos] == '<': + # Address is a phrase then a route addr + routeaddr = self.getrouteaddr() + + if self.commentlist: + returnlist = [(SPACE.join(plist) + ' (' + + ' '.join(self.commentlist) + ')', routeaddr)] + else: + returnlist = [(SPACE.join(plist), routeaddr)] + + else: + if plist: + returnlist = [(SPACE.join(self.commentlist), plist[0])] + elif self.field[self.pos] in self.specials: + self.pos += 1 + + self.gotonext() + if self.pos < len(self.field) and self.field[self.pos] == ',': + self.pos += 1 + return returnlist + + def getrouteaddr(self): + """Parse a route address (Return-path value). + + This method just skips all the route stuff and returns the addrspec. + """ + if self.field[self.pos] != '<': + return + + expectroute = False + self.pos += 1 + self.gotonext() + adlist = '' + while self.pos < len(self.field): + if expectroute: + self.getdomain() + expectroute = False + elif self.field[self.pos] == '>': + self.pos += 1 + break + elif self.field[self.pos] == '@': + self.pos += 1 + expectroute = True + elif self.field[self.pos] == ':': + self.pos += 1 + else: + adlist = self.getaddrspec() + self.pos += 1 + break + self.gotonext() + + return adlist + + def getaddrspec(self): + """Parse an RFC 2822 addr-spec.""" + aslist = [] + + self.gotonext() + while self.pos < len(self.field): + if self.field[self.pos] == '.': + aslist.append('.') + self.pos += 1 + elif self.field[self.pos] == '"': + aslist.append('"%s"' % quote(self.getquote())) + elif self.field[self.pos] in self.atomends: + break + else: + aslist.append(self.getatom()) + self.gotonext() + + if self.pos >= len(self.field) or self.field[self.pos] != '@': + return EMPTYSTRING.join(aslist) + + aslist.append('@') + self.pos += 1 + self.gotonext() + return EMPTYSTRING.join(aslist) + self.getdomain() + + def getdomain(self): + """Get the complete domain name from an address.""" + sdlist = [] + while self.pos < len(self.field): + if self.field[self.pos] in self.LWS: + self.pos += 1 + elif self.field[self.pos] == '(': + self.commentlist.append(self.getcomment()) + elif self.field[self.pos] == '[': + sdlist.append(self.getdomainliteral()) + elif self.field[self.pos] == '.': + self.pos += 1 + sdlist.append('.') + elif self.field[self.pos] in self.atomends: + break + else: + sdlist.append(self.getatom()) + return EMPTYSTRING.join(sdlist) + + def getdelimited(self, beginchar, endchars, allowcomments=True): + """Parse a header fragment delimited by special characters. + + `beginchar' is the start character for the fragment. + If self is not looking at an instance of `beginchar' then + getdelimited returns the empty string. + + `endchars' is a sequence of allowable end-delimiting characters. + Parsing stops when one of these is encountered. + + If `allowcomments' is non-zero, embedded RFC 2822 comments are allowed + within the parsed fragment. + """ + if self.field[self.pos] != beginchar: + return '' + + slist = [''] + quote = False + self.pos += 1 + while self.pos < len(self.field): + if quote: + slist.append(self.field[self.pos]) + quote = False + elif self.field[self.pos] in endchars: + self.pos += 1 + break + elif allowcomments and self.field[self.pos] == '(': + slist.append(self.getcomment()) + continue # have already advanced pos from getcomment + elif self.field[self.pos] == '\\': + quote = True + else: + slist.append(self.field[self.pos]) + self.pos += 1 + + return EMPTYSTRING.join(slist) + + def getquote(self): + """Get a quote-delimited fragment from self's field.""" + return self.getdelimited('"', '"\r', False) + + def getcomment(self): + """Get a parenthesis-delimited fragment from self's field.""" + return self.getdelimited('(', ')\r', True) + + def getdomainliteral(self): + """Parse an RFC 2822 domain-literal.""" + return '[%s]' % self.getdelimited('[', ']\r', False) + + def getatom(self, atomends=None): + """Parse an RFC 2822 atom. + + Optional atomends specifies a different set of end token delimiters + (the default is to use self.atomends). This is used e.g. in + getphraselist() since phrase endings must not include the `.' (which + is legal in phrases).""" + atomlist = [''] + if atomends is None: + atomends = self.atomends + + while self.pos < len(self.field): + if self.field[self.pos] in atomends: + break + else: + atomlist.append(self.field[self.pos]) + self.pos += 1 + + return EMPTYSTRING.join(atomlist) + + def getphraselist(self): + """Parse a sequence of RFC 2822 phrases. + + A phrase is a sequence of words, which are in turn either RFC 2822 + atoms or quoted-strings. Phrases are canonicalized by squeezing all + runs of continuous whitespace into one space. + """ + plist = [] + + while self.pos < len(self.field): + if self.field[self.pos] in self.FWS: + self.pos += 1 + elif self.field[self.pos] == '"': + plist.append(self.getquote()) + elif self.field[self.pos] == '(': + self.commentlist.append(self.getcomment()) + elif self.field[self.pos] in self.phraseends: + break + else: + plist.append(self.getatom(self.phraseends)) + + return plist + +class AddressList(AddrlistClass): + """An AddressList encapsulates a list of parsed RFC 2822 addresses.""" + def __init__(self, field): + AddrlistClass.__init__(self, field) + if field: + self.addresslist = self.getaddrlist() + else: + self.addresslist = [] + + def __len__(self): + return len(self.addresslist) + + def __add__(self, other): + # Set union + newaddr = AddressList(None) + newaddr.addresslist = self.addresslist[:] + for x in other.addresslist: + if not x in self.addresslist: + newaddr.addresslist.append(x) + return newaddr + + def __iadd__(self, other): + # Set union, in-place + for x in other.addresslist: + if not x in self.addresslist: + self.addresslist.append(x) + return self + + def __sub__(self, other): + # Set difference + newaddr = AddressList(None) + for x in self.addresslist: + if not x in other.addresslist: + newaddr.addresslist.append(x) + return newaddr + + def __isub__(self, other): + # Set difference, in-place + for x in other.addresslist: + if x in self.addresslist: + self.addresslist.remove(x) + return self + + def __getitem__(self, index): + # Make indexing, slices, and 'in' work + return self.addresslist[index] diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/_parseaddr.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/_parseaddr.pyc new file mode 100644 index 0000000..e6851cb Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/_parseaddr.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/_parseaddr.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/_parseaddr.pyo new file mode 100644 index 0000000..e6851cb Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/_parseaddr.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/base64mime.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/base64mime.py new file mode 100644 index 0000000..4aa8000 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/base64mime.py @@ -0,0 +1,183 @@ +# Copyright (C) 2002-2006 Python Software Foundation +# Author: Ben Gertzfield +# Contact: email-sig@python.org + +"""Base64 content transfer encoding per RFCs 2045-2047. + +This module handles the content transfer encoding method defined in RFC 2045 +to encode arbitrary 8-bit data using the three 8-bit bytes in four 7-bit +characters encoding known as Base64. + +It is used in the MIME standards for email to attach images, audio, and text +using some 8-bit character sets to messages. + +This module provides an interface to encode and decode both headers and bodies +with Base64 encoding. + +RFC 2045 defines a method for including character set information in an +`encoded-word' in a header. This method is commonly used for 8-bit real names +in To:, From:, Cc:, etc. fields, as well as Subject: lines. + +This module does not do the line wrapping or end-of-line character conversion +necessary for proper internationalized headers; it only does dumb encoding and +decoding. To deal with the various line wrapping issues, use the email.header +module. +""" + +__all__ = [ + 'base64_len', + 'body_decode', + 'body_encode', + 'decode', + 'decodestring', + 'encode', + 'encodestring', + 'header_encode', + ] + + +from binascii import b2a_base64, a2b_base64 +from email.utils import fix_eols + +CRLF = '\r\n' +NL = '\n' +EMPTYSTRING = '' + +# See also Charset.py +MISC_LEN = 7 + + + +# Helpers +def base64_len(s): + """Return the length of s when it is encoded with base64.""" + groups_of_3, leftover = divmod(len(s), 3) + # 4 bytes out for each 3 bytes (or nonzero fraction thereof) in. + # Thanks, Tim! + n = groups_of_3 * 4 + if leftover: + n += 4 + return n + + + +def header_encode(header, charset='iso-8859-1', keep_eols=False, + maxlinelen=76, eol=NL): + """Encode a single header line with Base64 encoding in a given charset. + + Defined in RFC 2045, this Base64 encoding is identical to normal Base64 + encoding, except that each line must be intelligently wrapped (respecting + the Base64 encoding), and subsequent lines must start with a space. + + charset names the character set to use to encode the header. It defaults + to iso-8859-1. + + End-of-line characters (\\r, \\n, \\r\\n) will be automatically converted + to the canonical email line separator \\r\\n unless the keep_eols + parameter is True (the default is False). + + Each line of the header will be terminated in the value of eol, which + defaults to "\\n". Set this to "\\r\\n" if you are using the result of + this function directly in email. + + The resulting string will be in the form: + + "=?charset?b?WW/5ciBtYXp66XLrIHf8eiBhIGhhbXBzdGHuciBBIFlv+XIgbWF6euly?=\\n + =?charset?b?6yB3/HogYSBoYW1wc3Rh7nIgQkMgWW/5ciBtYXp66XLrIHf8eiBhIGhh?=" + + with each line wrapped at, at most, maxlinelen characters (defaults to 76 + characters). + """ + # Return empty headers unchanged + if not header: + return header + + if not keep_eols: + header = fix_eols(header) + + # Base64 encode each line, in encoded chunks no greater than maxlinelen in + # length, after the RFC chrome is added in. + base64ed = [] + max_encoded = maxlinelen - len(charset) - MISC_LEN + max_unencoded = max_encoded * 3 // 4 + + for i in range(0, len(header), max_unencoded): + base64ed.append(b2a_base64(header[i:i+max_unencoded])) + + # Now add the RFC chrome to each encoded chunk + lines = [] + for line in base64ed: + # Ignore the last character of each line if it is a newline + if line.endswith(NL): + line = line[:-1] + # Add the chrome + lines.append('=?%s?b?%s?=' % (charset, line)) + # Glue the lines together and return it. BAW: should we be able to + # specify the leading whitespace in the joiner? + joiner = eol + ' ' + return joiner.join(lines) + + + +def encode(s, binary=True, maxlinelen=76, eol=NL): + """Encode a string with base64. + + Each line will be wrapped at, at most, maxlinelen characters (defaults to + 76 characters). + + If binary is False, end-of-line characters will be converted to the + canonical email end-of-line sequence \\r\\n. Otherwise they will be left + verbatim (this is the default). + + Each line of encoded text will end with eol, which defaults to "\\n". Set + this to "\\r\\n" if you will be using the result of this function directly + in an email. + """ + if not s: + return s + + if not binary: + s = fix_eols(s) + + encvec = [] + max_unencoded = maxlinelen * 3 // 4 + for i in range(0, len(s), max_unencoded): + # BAW: should encode() inherit b2a_base64()'s dubious behavior in + # adding a newline to the encoded string? + enc = b2a_base64(s[i:i + max_unencoded]) + if enc.endswith(NL) and eol != NL: + enc = enc[:-1] + eol + encvec.append(enc) + return EMPTYSTRING.join(encvec) + + +# For convenience and backwards compatibility w/ standard base64 module +body_encode = encode +encodestring = encode + + + +def decode(s, convert_eols=None): + """Decode a raw base64 string. + + If convert_eols is set to a string value, all canonical email linefeeds, + e.g. "\\r\\n", in the decoded text will be converted to the value of + convert_eols. os.linesep is a good choice for convert_eols if you are + decoding a text attachment. + + This function does not parse a full MIME header value encoded with + base64 (like =?iso-8895-1?b?bmloISBuaWgh?=) -- please use the high + level email.header class for that functionality. + """ + if not s: + return s + + dec = a2b_base64(s) + if convert_eols: + return dec.replace(CRLF, convert_eols) + return dec + + +# For convenience and backwards compatibility w/ standard base64 module +body_decode = decode +decodestring = decode diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/base64mime.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/base64mime.pyc new file mode 100644 index 0000000..d985cef Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/base64mime.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/base64mime.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/base64mime.pyo new file mode 100644 index 0000000..d985cef Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/base64mime.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/charset.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/charset.py new file mode 100644 index 0000000..dddaa76 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/charset.py @@ -0,0 +1,397 @@ +# Copyright (C) 2001-2006 Python Software Foundation +# Author: Ben Gertzfield, Barry Warsaw +# Contact: email-sig@python.org + +__all__ = [ + 'Charset', + 'add_alias', + 'add_charset', + 'add_codec', + ] + +import codecs +import email.base64mime +import email.quoprimime + +from email import errors +from email.encoders import encode_7or8bit + + + +# Flags for types of header encodings +QP = 1 # Quoted-Printable +BASE64 = 2 # Base64 +SHORTEST = 3 # the shorter of QP and base64, but only for headers + +# In "=?charset?q?hello_world?=", the =?, ?q?, and ?= add up to 7 +MISC_LEN = 7 + +DEFAULT_CHARSET = 'us-ascii' + + + +# Defaults +CHARSETS = { + # input header enc body enc output conv + 'iso-8859-1': (QP, QP, None), + 'iso-8859-2': (QP, QP, None), + 'iso-8859-3': (QP, QP, None), + 'iso-8859-4': (QP, QP, None), + # iso-8859-5 is Cyrillic, and not especially used + # iso-8859-6 is Arabic, also not particularly used + # iso-8859-7 is Greek, QP will not make it readable + # iso-8859-8 is Hebrew, QP will not make it readable + 'iso-8859-9': (QP, QP, None), + 'iso-8859-10': (QP, QP, None), + # iso-8859-11 is Thai, QP will not make it readable + 'iso-8859-13': (QP, QP, None), + 'iso-8859-14': (QP, QP, None), + 'iso-8859-15': (QP, QP, None), + 'iso-8859-16': (QP, QP, None), + 'windows-1252':(QP, QP, None), + 'viscii': (QP, QP, None), + 'us-ascii': (None, None, None), + 'big5': (BASE64, BASE64, None), + 'gb2312': (BASE64, BASE64, None), + 'euc-jp': (BASE64, None, 'iso-2022-jp'), + 'shift_jis': (BASE64, None, 'iso-2022-jp'), + 'iso-2022-jp': (BASE64, None, None), + 'koi8-r': (BASE64, BASE64, None), + 'utf-8': (SHORTEST, BASE64, 'utf-8'), + # We're making this one up to represent raw unencoded 8-bit + '8bit': (None, BASE64, 'utf-8'), + } + +# Aliases for other commonly-used names for character sets. Map +# them to the real ones used in email. +ALIASES = { + 'latin_1': 'iso-8859-1', + 'latin-1': 'iso-8859-1', + 'latin_2': 'iso-8859-2', + 'latin-2': 'iso-8859-2', + 'latin_3': 'iso-8859-3', + 'latin-3': 'iso-8859-3', + 'latin_4': 'iso-8859-4', + 'latin-4': 'iso-8859-4', + 'latin_5': 'iso-8859-9', + 'latin-5': 'iso-8859-9', + 'latin_6': 'iso-8859-10', + 'latin-6': 'iso-8859-10', + 'latin_7': 'iso-8859-13', + 'latin-7': 'iso-8859-13', + 'latin_8': 'iso-8859-14', + 'latin-8': 'iso-8859-14', + 'latin_9': 'iso-8859-15', + 'latin-9': 'iso-8859-15', + 'latin_10':'iso-8859-16', + 'latin-10':'iso-8859-16', + 'cp949': 'ks_c_5601-1987', + 'euc_jp': 'euc-jp', + 'euc_kr': 'euc-kr', + 'ascii': 'us-ascii', + } + + +# Map charsets to their Unicode codec strings. +CODEC_MAP = { + 'gb2312': 'eucgb2312_cn', + 'big5': 'big5_tw', + # Hack: We don't want *any* conversion for stuff marked us-ascii, as all + # sorts of garbage might be sent to us in the guise of 7-bit us-ascii. + # Let that stuff pass through without conversion to/from Unicode. + 'us-ascii': None, + } + + + +# Convenience functions for extending the above mappings +def add_charset(charset, header_enc=None, body_enc=None, output_charset=None): + """Add character set properties to the global registry. + + charset is the input character set, and must be the canonical name of a + character set. + + Optional header_enc and body_enc is either Charset.QP for + quoted-printable, Charset.BASE64 for base64 encoding, Charset.SHORTEST for + the shortest of qp or base64 encoding, or None for no encoding. SHORTEST + is only valid for header_enc. It describes how message headers and + message bodies in the input charset are to be encoded. Default is no + encoding. + + Optional output_charset is the character set that the output should be + in. Conversions will proceed from input charset, to Unicode, to the + output charset when the method Charset.convert() is called. The default + is to output in the same character set as the input. + + Both input_charset and output_charset must have Unicode codec entries in + the module's charset-to-codec mapping; use add_codec(charset, codecname) + to add codecs the module does not know about. See the codecs module's + documentation for more information. + """ + if body_enc == SHORTEST: + raise ValueError('SHORTEST not allowed for body_enc') + CHARSETS[charset] = (header_enc, body_enc, output_charset) + + +def add_alias(alias, canonical): + """Add a character set alias. + + alias is the alias name, e.g. latin-1 + canonical is the character set's canonical name, e.g. iso-8859-1 + """ + ALIASES[alias] = canonical + + +def add_codec(charset, codecname): + """Add a codec that map characters in the given charset to/from Unicode. + + charset is the canonical name of a character set. codecname is the name + of a Python codec, as appropriate for the second argument to the unicode() + built-in, or to the encode() method of a Unicode string. + """ + CODEC_MAP[charset] = codecname + + + +class Charset: + """Map character sets to their email properties. + + This class provides information about the requirements imposed on email + for a specific character set. It also provides convenience routines for + converting between character sets, given the availability of the + applicable codecs. Given a character set, it will do its best to provide + information on how to use that character set in an email in an + RFC-compliant way. + + Certain character sets must be encoded with quoted-printable or base64 + when used in email headers or bodies. Certain character sets must be + converted outright, and are not allowed in email. Instances of this + module expose the following information about a character set: + + input_charset: The initial character set specified. Common aliases + are converted to their `official' email names (e.g. latin_1 + is converted to iso-8859-1). Defaults to 7-bit us-ascii. + + header_encoding: If the character set must be encoded before it can be + used in an email header, this attribute will be set to + Charset.QP (for quoted-printable), Charset.BASE64 (for + base64 encoding), or Charset.SHORTEST for the shortest of + QP or BASE64 encoding. Otherwise, it will be None. + + body_encoding: Same as header_encoding, but describes the encoding for the + mail message's body, which indeed may be different than the + header encoding. Charset.SHORTEST is not allowed for + body_encoding. + + output_charset: Some character sets must be converted before the can be + used in email headers or bodies. If the input_charset is + one of them, this attribute will contain the name of the + charset output will be converted to. Otherwise, it will + be None. + + input_codec: The name of the Python codec used to convert the + input_charset to Unicode. If no conversion codec is + necessary, this attribute will be None. + + output_codec: The name of the Python codec used to convert Unicode + to the output_charset. If no conversion codec is necessary, + this attribute will have the same value as the input_codec. + """ + def __init__(self, input_charset=DEFAULT_CHARSET): + # RFC 2046, $4.1.2 says charsets are not case sensitive. We coerce to + # unicode because its .lower() is locale insensitive. If the argument + # is already a unicode, we leave it at that, but ensure that the + # charset is ASCII, as the standard (RFC XXX) requires. + try: + if isinstance(input_charset, unicode): + input_charset.encode('ascii') + else: + input_charset = unicode(input_charset, 'ascii') + except UnicodeError: + raise errors.CharsetError(input_charset) + input_charset = input_charset.lower().encode('ascii') + # Set the input charset after filtering through the aliases and/or codecs + if not (input_charset in ALIASES or input_charset in CHARSETS): + try: + input_charset = codecs.lookup(input_charset).name + except LookupError: + pass + self.input_charset = ALIASES.get(input_charset, input_charset) + # We can try to guess which encoding and conversion to use by the + # charset_map dictionary. Try that first, but let the user override + # it. + henc, benc, conv = CHARSETS.get(self.input_charset, + (SHORTEST, BASE64, None)) + if not conv: + conv = self.input_charset + # Set the attributes, allowing the arguments to override the default. + self.header_encoding = henc + self.body_encoding = benc + self.output_charset = ALIASES.get(conv, conv) + # Now set the codecs. If one isn't defined for input_charset, + # guess and try a Unicode codec with the same name as input_codec. + self.input_codec = CODEC_MAP.get(self.input_charset, + self.input_charset) + self.output_codec = CODEC_MAP.get(self.output_charset, + self.output_charset) + + def __str__(self): + return self.input_charset.lower() + + __repr__ = __str__ + + def __eq__(self, other): + return str(self) == str(other).lower() + + def __ne__(self, other): + return not self.__eq__(other) + + def get_body_encoding(self): + """Return the content-transfer-encoding used for body encoding. + + This is either the string `quoted-printable' or `base64' depending on + the encoding used, or it is a function in which case you should call + the function with a single argument, the Message object being + encoded. The function should then set the Content-Transfer-Encoding + header itself to whatever is appropriate. + + Returns "quoted-printable" if self.body_encoding is QP. + Returns "base64" if self.body_encoding is BASE64. + Returns "7bit" otherwise. + """ + assert self.body_encoding != SHORTEST + if self.body_encoding == QP: + return 'quoted-printable' + elif self.body_encoding == BASE64: + return 'base64' + else: + return encode_7or8bit + + def convert(self, s): + """Convert a string from the input_codec to the output_codec.""" + if self.input_codec != self.output_codec: + return unicode(s, self.input_codec).encode(self.output_codec) + else: + return s + + def to_splittable(self, s): + """Convert a possibly multibyte string to a safely splittable format. + + Uses the input_codec to try and convert the string to Unicode, so it + can be safely split on character boundaries (even for multibyte + characters). + + Returns the string as-is if it isn't known how to convert it to + Unicode with the input_charset. + + Characters that could not be converted to Unicode will be replaced + with the Unicode replacement character U+FFFD. + """ + if isinstance(s, unicode) or self.input_codec is None: + return s + try: + return unicode(s, self.input_codec, 'replace') + except LookupError: + # Input codec not installed on system, so return the original + # string unchanged. + return s + + def from_splittable(self, ustr, to_output=True): + """Convert a splittable string back into an encoded string. + + Uses the proper codec to try and convert the string from Unicode back + into an encoded format. Return the string as-is if it is not Unicode, + or if it could not be converted from Unicode. + + Characters that could not be converted from Unicode will be replaced + with an appropriate character (usually '?'). + + If to_output is True (the default), uses output_codec to convert to an + encoded format. If to_output is False, uses input_codec. + """ + if to_output: + codec = self.output_codec + else: + codec = self.input_codec + if not isinstance(ustr, unicode) or codec is None: + return ustr + try: + return ustr.encode(codec, 'replace') + except LookupError: + # Output codec not installed + return ustr + + def get_output_charset(self): + """Return the output character set. + + This is self.output_charset if that is not None, otherwise it is + self.input_charset. + """ + return self.output_charset or self.input_charset + + def encoded_header_len(self, s): + """Return the length of the encoded header string.""" + cset = self.get_output_charset() + # The len(s) of a 7bit encoding is len(s) + if self.header_encoding == BASE64: + return email.base64mime.base64_len(s) + len(cset) + MISC_LEN + elif self.header_encoding == QP: + return email.quoprimime.header_quopri_len(s) + len(cset) + MISC_LEN + elif self.header_encoding == SHORTEST: + lenb64 = email.base64mime.base64_len(s) + lenqp = email.quoprimime.header_quopri_len(s) + return min(lenb64, lenqp) + len(cset) + MISC_LEN + else: + return len(s) + + def header_encode(self, s, convert=False): + """Header-encode a string, optionally converting it to output_charset. + + If convert is True, the string will be converted from the input + charset to the output charset automatically. This is not useful for + multibyte character sets, which have line length issues (multibyte + characters must be split on a character, not a byte boundary); use the + high-level Header class to deal with these issues. convert defaults + to False. + + The type of encoding (base64 or quoted-printable) will be based on + self.header_encoding. + """ + cset = self.get_output_charset() + if convert: + s = self.convert(s) + # 7bit/8bit encodings return the string unchanged (modulo conversions) + if self.header_encoding == BASE64: + return email.base64mime.header_encode(s, cset) + elif self.header_encoding == QP: + return email.quoprimime.header_encode(s, cset, maxlinelen=None) + elif self.header_encoding == SHORTEST: + lenb64 = email.base64mime.base64_len(s) + lenqp = email.quoprimime.header_quopri_len(s) + if lenb64 < lenqp: + return email.base64mime.header_encode(s, cset) + else: + return email.quoprimime.header_encode(s, cset, maxlinelen=None) + else: + return s + + def body_encode(self, s, convert=True): + """Body-encode a string and convert it to output_charset. + + If convert is True (the default), the string will be converted from + the input charset to output charset automatically. Unlike + header_encode(), there are no issues with byte boundaries and + multibyte charsets in email bodies, so this is usually pretty safe. + + The type of encoding (base64 or quoted-printable) will be based on + self.body_encoding. + """ + if convert: + s = self.convert(s) + # 7bit/8bit encodings return the string unchanged (module conversions) + if self.body_encoding is BASE64: + return email.base64mime.body_encode(s) + elif self.body_encoding is QP: + return email.quoprimime.body_encode(s) + else: + return s diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/charset.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/charset.pyc new file mode 100644 index 0000000..8fb22c1 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/charset.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/charset.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/charset.pyo new file mode 100644 index 0000000..d929de8 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/charset.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/encoders.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/encoders.py new file mode 100644 index 0000000..af45e62 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/encoders.py @@ -0,0 +1,82 @@ +# Copyright (C) 2001-2006 Python Software Foundation +# Author: Barry Warsaw +# Contact: email-sig@python.org + +"""Encodings and related functions.""" + +__all__ = [ + 'encode_7or8bit', + 'encode_base64', + 'encode_noop', + 'encode_quopri', + ] + +import base64 + +from quopri import encodestring as _encodestring + + + +def _qencode(s): + enc = _encodestring(s, quotetabs=True) + # Must encode spaces, which quopri.encodestring() doesn't do + return enc.replace(' ', '=20') + + +def _bencode(s): + # We can't quite use base64.encodestring() since it tacks on a "courtesy + # newline". Blech! + if not s: + return s + hasnewline = (s[-1] == '\n') + value = base64.encodestring(s) + if not hasnewline and value[-1] == '\n': + return value[:-1] + return value + + + +def encode_base64(msg): + """Encode the message's payload in Base64. + + Also, add an appropriate Content-Transfer-Encoding header. + """ + orig = msg.get_payload() + encdata = _bencode(orig) + msg.set_payload(encdata) + msg['Content-Transfer-Encoding'] = 'base64' + + + +def encode_quopri(msg): + """Encode the message's payload in quoted-printable. + + Also, add an appropriate Content-Transfer-Encoding header. + """ + orig = msg.get_payload() + encdata = _qencode(orig) + msg.set_payload(encdata) + msg['Content-Transfer-Encoding'] = 'quoted-printable' + + + +def encode_7or8bit(msg): + """Set the Content-Transfer-Encoding header to 7bit or 8bit.""" + orig = msg.get_payload() + if orig is None: + # There's no payload. For backwards compatibility we use 7bit + msg['Content-Transfer-Encoding'] = '7bit' + return + # We play a trick to make this go fast. If encoding to ASCII succeeds, we + # know the data must be 7bit, otherwise treat it as 8bit. + try: + orig.encode('ascii') + except UnicodeError: + msg['Content-Transfer-Encoding'] = '8bit' + else: + msg['Content-Transfer-Encoding'] = '7bit' + + + +def encode_noop(msg): + """Do nothing.""" diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/encoders.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/encoders.pyc new file mode 100644 index 0000000..e6ec4dd Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/encoders.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/encoders.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/encoders.pyo new file mode 100644 index 0000000..e6ec4dd Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/encoders.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/errors.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/errors.py new file mode 100644 index 0000000..d52a624 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/errors.py @@ -0,0 +1,57 @@ +# Copyright (C) 2001-2006 Python Software Foundation +# Author: Barry Warsaw +# Contact: email-sig@python.org + +"""email package exception classes.""" + + + +class MessageError(Exception): + """Base class for errors in the email package.""" + + +class MessageParseError(MessageError): + """Base class for message parsing errors.""" + + +class HeaderParseError(MessageParseError): + """Error while parsing headers.""" + + +class BoundaryError(MessageParseError): + """Couldn't find terminating boundary.""" + + +class MultipartConversionError(MessageError, TypeError): + """Conversion to a multipart is prohibited.""" + + +class CharsetError(MessageError): + """An illegal charset was given.""" + + + +# These are parsing defects which the parser was able to work around. +class MessageDefect: + """Base class for a message defect.""" + + def __init__(self, line=None): + self.line = line + +class NoBoundaryInMultipartDefect(MessageDefect): + """A message claimed to be a multipart but had no boundary parameter.""" + +class StartBoundaryNotFoundDefect(MessageDefect): + """The claimed start boundary was never found.""" + +class FirstHeaderLineIsContinuationDefect(MessageDefect): + """A message had a continuation line as its first header line.""" + +class MisplacedEnvelopeHeaderDefect(MessageDefect): + """A 'Unix-from' header was found in the middle of a header block.""" + +class MalformedHeaderDefect(MessageDefect): + """Found a header that was missing a colon, or was otherwise malformed.""" + +class MultipartInvariantViolationDefect(MessageDefect): + """A message claimed to be a multipart but no subparts were found.""" diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/errors.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/errors.pyc new file mode 100644 index 0000000..6d245f6 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/errors.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/errors.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/errors.pyo new file mode 100644 index 0000000..6d245f6 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/errors.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/feedparser.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/feedparser.py new file mode 100644 index 0000000..15db26d --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/feedparser.py @@ -0,0 +1,484 @@ +# Copyright (C) 2004-2006 Python Software Foundation +# Authors: Baxter, Wouters and Warsaw +# Contact: email-sig@python.org + +"""FeedParser - An email feed parser. + +The feed parser implements an interface for incrementally parsing an email +message, line by line. This has advantages for certain applications, such as +those reading email messages off a socket. + +FeedParser.feed() is the primary interface for pushing new data into the +parser. It returns when there's nothing more it can do with the available +data. When you have no more data to push into the parser, call .close(). +This completes the parsing and returns the root message object. + +The other advantage of this parser is that it will never raise a parsing +exception. Instead, when it finds something unexpected, it adds a 'defect' to +the current message. Defects are just instances that live on the message +object's .defects attribute. +""" + +__all__ = ['FeedParser'] + +import re + +from email import errors +from email import message + +NLCRE = re.compile('\r\n|\r|\n') +NLCRE_bol = re.compile('(\r\n|\r|\n)') +NLCRE_eol = re.compile('(\r\n|\r|\n)\Z') +NLCRE_crack = re.compile('(\r\n|\r|\n)') +# RFC 2822 $3.6.8 Optional fields. ftext is %d33-57 / %d59-126, Any character +# except controls, SP, and ":". +headerRE = re.compile(r'^(From |[\041-\071\073-\176]{1,}:|[\t ])') +EMPTYSTRING = '' +NL = '\n' + +NeedMoreData = object() + + + +class BufferedSubFile(object): + """A file-ish object that can have new data loaded into it. + + You can also push and pop line-matching predicates onto a stack. When the + current predicate matches the current line, a false EOF response + (i.e. empty string) is returned instead. This lets the parser adhere to a + simple abstraction -- it parses until EOF closes the current message. + """ + def __init__(self): + # The last partial line pushed into this object. + self._partial = '' + # The list of full, pushed lines, in reverse order + self._lines = [] + # The stack of false-EOF checking predicates. + self._eofstack = [] + # A flag indicating whether the file has been closed or not. + self._closed = False + + def push_eof_matcher(self, pred): + self._eofstack.append(pred) + + def pop_eof_matcher(self): + return self._eofstack.pop() + + def close(self): + # Don't forget any trailing partial line. + self._lines.append(self._partial) + self._partial = '' + self._closed = True + + def readline(self): + if not self._lines: + if self._closed: + return '' + return NeedMoreData + # Pop the line off the stack and see if it matches the current + # false-EOF predicate. + line = self._lines.pop() + # RFC 2046, section 5.1.2 requires us to recognize outer level + # boundaries at any level of inner nesting. Do this, but be sure it's + # in the order of most to least nested. + for ateof in self._eofstack[::-1]: + if ateof(line): + # We're at the false EOF. But push the last line back first. + self._lines.append(line) + return '' + return line + + def unreadline(self, line): + # Let the consumer push a line back into the buffer. + assert line is not NeedMoreData + self._lines.append(line) + + def push(self, data): + """Push some new data into this object.""" + # Handle any previous leftovers + data, self._partial = self._partial + data, '' + # Crack into lines, but preserve the newlines on the end of each + parts = NLCRE_crack.split(data) + # The *ahem* interesting behaviour of re.split when supplied grouping + # parentheses is that the last element of the resulting list is the + # data after the final RE. In the case of a NL/CR terminated string, + # this is the empty string. + self._partial = parts.pop() + #GAN 29Mar09 bugs 1555570, 1721862 Confusion at 8K boundary ending with \r: + # is there a \n to follow later? + if not self._partial and parts and parts[-1].endswith('\r'): + self._partial = parts.pop(-2)+parts.pop() + # parts is a list of strings, alternating between the line contents + # and the eol character(s). Gather up a list of lines after + # re-attaching the newlines. + lines = [] + for i in range(len(parts) // 2): + lines.append(parts[i*2] + parts[i*2+1]) + self.pushlines(lines) + + def pushlines(self, lines): + # Reverse and insert at the front of the lines. + self._lines[:0] = lines[::-1] + + def is_closed(self): + return self._closed + + def __iter__(self): + return self + + def next(self): + line = self.readline() + if line == '': + raise StopIteration + return line + + + +class FeedParser: + """A feed-style parser of email.""" + + def __init__(self, _factory=message.Message): + """_factory is called with no arguments to create a new message obj""" + self._factory = _factory + self._input = BufferedSubFile() + self._msgstack = [] + self._parse = self._parsegen().next + self._cur = None + self._last = None + self._headersonly = False + + # Non-public interface for supporting Parser's headersonly flag + def _set_headersonly(self): + self._headersonly = True + + def feed(self, data): + """Push more data into the parser.""" + self._input.push(data) + self._call_parse() + + def _call_parse(self): + try: + self._parse() + except StopIteration: + pass + + def close(self): + """Parse all remaining data and return the root message object.""" + self._input.close() + self._call_parse() + root = self._pop_message() + assert not self._msgstack + # Look for final set of defects + if root.get_content_maintype() == 'multipart' \ + and not root.is_multipart(): + root.defects.append(errors.MultipartInvariantViolationDefect()) + return root + + def _new_message(self): + msg = self._factory() + if self._cur and self._cur.get_content_type() == 'multipart/digest': + msg.set_default_type('message/rfc822') + if self._msgstack: + self._msgstack[-1].attach(msg) + self._msgstack.append(msg) + self._cur = msg + self._last = msg + + def _pop_message(self): + retval = self._msgstack.pop() + if self._msgstack: + self._cur = self._msgstack[-1] + else: + self._cur = None + return retval + + def _parsegen(self): + # Create a new message and start by parsing headers. + self._new_message() + headers = [] + # Collect the headers, searching for a line that doesn't match the RFC + # 2822 header or continuation pattern (including an empty line). + for line in self._input: + if line is NeedMoreData: + yield NeedMoreData + continue + if not headerRE.match(line): + # If we saw the RFC defined header/body separator + # (i.e. newline), just throw it away. Otherwise the line is + # part of the body so push it back. + if not NLCRE.match(line): + self._input.unreadline(line) + break + headers.append(line) + # Done with the headers, so parse them and figure out what we're + # supposed to see in the body of the message. + self._parse_headers(headers) + # Headers-only parsing is a backwards compatibility hack, which was + # necessary in the older parser, which could raise errors. All + # remaining lines in the input are thrown into the message body. + if self._headersonly: + lines = [] + while True: + line = self._input.readline() + if line is NeedMoreData: + yield NeedMoreData + continue + if line == '': + break + lines.append(line) + self._cur.set_payload(EMPTYSTRING.join(lines)) + return + if self._cur.get_content_type() == 'message/delivery-status': + # message/delivery-status contains blocks of headers separated by + # a blank line. We'll represent each header block as a separate + # nested message object, but the processing is a bit different + # than standard message/* types because there is no body for the + # nested messages. A blank line separates the subparts. + while True: + self._input.push_eof_matcher(NLCRE.match) + for retval in self._parsegen(): + if retval is NeedMoreData: + yield NeedMoreData + continue + break + msg = self._pop_message() + # We need to pop the EOF matcher in order to tell if we're at + # the end of the current file, not the end of the last block + # of message headers. + self._input.pop_eof_matcher() + # The input stream must be sitting at the newline or at the + # EOF. We want to see if we're at the end of this subpart, so + # first consume the blank line, then test the next line to see + # if we're at this subpart's EOF. + while True: + line = self._input.readline() + if line is NeedMoreData: + yield NeedMoreData + continue + break + while True: + line = self._input.readline() + if line is NeedMoreData: + yield NeedMoreData + continue + break + if line == '': + break + # Not at EOF so this is a line we're going to need. + self._input.unreadline(line) + return + if self._cur.get_content_maintype() == 'message': + # The message claims to be a message/* type, then what follows is + # another RFC 2822 message. + for retval in self._parsegen(): + if retval is NeedMoreData: + yield NeedMoreData + continue + break + self._pop_message() + return + if self._cur.get_content_maintype() == 'multipart': + boundary = self._cur.get_boundary() + if boundary is None: + # The message /claims/ to be a multipart but it has not + # defined a boundary. That's a problem which we'll handle by + # reading everything until the EOF and marking the message as + # defective. + self._cur.defects.append(errors.NoBoundaryInMultipartDefect()) + lines = [] + for line in self._input: + if line is NeedMoreData: + yield NeedMoreData + continue + lines.append(line) + self._cur.set_payload(EMPTYSTRING.join(lines)) + return + # Create a line match predicate which matches the inter-part + # boundary as well as the end-of-multipart boundary. Don't push + # this onto the input stream until we've scanned past the + # preamble. + separator = '--' + boundary + boundaryre = re.compile( + '(?P' + re.escape(separator) + + r')(?P--)?(?P[ \t]*)(?P\r\n|\r|\n)?$') + capturing_preamble = True + preamble = [] + linesep = False + while True: + line = self._input.readline() + if line is NeedMoreData: + yield NeedMoreData + continue + if line == '': + break + mo = boundaryre.match(line) + if mo: + # If we're looking at the end boundary, we're done with + # this multipart. If there was a newline at the end of + # the closing boundary, then we need to initialize the + # epilogue with the empty string (see below). + if mo.group('end'): + linesep = mo.group('linesep') + break + # We saw an inter-part boundary. Were we in the preamble? + if capturing_preamble: + if preamble: + # According to RFC 2046, the last newline belongs + # to the boundary. + lastline = preamble[-1] + eolmo = NLCRE_eol.search(lastline) + if eolmo: + preamble[-1] = lastline[:-len(eolmo.group(0))] + self._cur.preamble = EMPTYSTRING.join(preamble) + capturing_preamble = False + self._input.unreadline(line) + continue + # We saw a boundary separating two parts. Consume any + # multiple boundary lines that may be following. Our + # interpretation of RFC 2046 BNF grammar does not produce + # body parts within such double boundaries. + while True: + line = self._input.readline() + if line is NeedMoreData: + yield NeedMoreData + continue + mo = boundaryre.match(line) + if not mo: + self._input.unreadline(line) + break + # Recurse to parse this subpart; the input stream points + # at the subpart's first line. + self._input.push_eof_matcher(boundaryre.match) + for retval in self._parsegen(): + if retval is NeedMoreData: + yield NeedMoreData + continue + break + # Because of RFC 2046, the newline preceding the boundary + # separator actually belongs to the boundary, not the + # previous subpart's payload (or epilogue if the previous + # part is a multipart). + if self._last.get_content_maintype() == 'multipart': + epilogue = self._last.epilogue + if epilogue == '': + self._last.epilogue = None + elif epilogue is not None: + mo = NLCRE_eol.search(epilogue) + if mo: + end = len(mo.group(0)) + self._last.epilogue = epilogue[:-end] + else: + payload = self._last.get_payload() + if isinstance(payload, basestring): + mo = NLCRE_eol.search(payload) + if mo: + payload = payload[:-len(mo.group(0))] + self._last.set_payload(payload) + self._input.pop_eof_matcher() + self._pop_message() + # Set the multipart up for newline cleansing, which will + # happen if we're in a nested multipart. + self._last = self._cur + else: + # I think we must be in the preamble + assert capturing_preamble + preamble.append(line) + # We've seen either the EOF or the end boundary. If we're still + # capturing the preamble, we never saw the start boundary. Note + # that as a defect and store the captured text as the payload. + # Everything from here to the EOF is epilogue. + if capturing_preamble: + self._cur.defects.append(errors.StartBoundaryNotFoundDefect()) + self._cur.set_payload(EMPTYSTRING.join(preamble)) + epilogue = [] + for line in self._input: + if line is NeedMoreData: + yield NeedMoreData + continue + self._cur.epilogue = EMPTYSTRING.join(epilogue) + return + # If the end boundary ended in a newline, we'll need to make sure + # the epilogue isn't None + if linesep: + epilogue = [''] + else: + epilogue = [] + for line in self._input: + if line is NeedMoreData: + yield NeedMoreData + continue + epilogue.append(line) + # Any CRLF at the front of the epilogue is not technically part of + # the epilogue. Also, watch out for an empty string epilogue, + # which means a single newline. + if epilogue: + firstline = epilogue[0] + bolmo = NLCRE_bol.match(firstline) + if bolmo: + epilogue[0] = firstline[len(bolmo.group(0)):] + self._cur.epilogue = EMPTYSTRING.join(epilogue) + return + # Otherwise, it's some non-multipart type, so the entire rest of the + # file contents becomes the payload. + lines = [] + for line in self._input: + if line is NeedMoreData: + yield NeedMoreData + continue + lines.append(line) + self._cur.set_payload(EMPTYSTRING.join(lines)) + + def _parse_headers(self, lines): + # Passed a list of lines that make up the headers for the current msg + lastheader = '' + lastvalue = [] + for lineno, line in enumerate(lines): + # Check for continuation + if line[0] in ' \t': + if not lastheader: + # The first line of the headers was a continuation. This + # is illegal, so let's note the defect, store the illegal + # line, and ignore it for purposes of headers. + defect = errors.FirstHeaderLineIsContinuationDefect(line) + self._cur.defects.append(defect) + continue + lastvalue.append(line) + continue + if lastheader: + # XXX reconsider the joining of folded lines + lhdr = EMPTYSTRING.join(lastvalue)[:-1].rstrip('\r\n') + self._cur[lastheader] = lhdr + lastheader, lastvalue = '', [] + # Check for envelope header, i.e. unix-from + if line.startswith('From '): + if lineno == 0: + # Strip off the trailing newline + mo = NLCRE_eol.search(line) + if mo: + line = line[:-len(mo.group(0))] + self._cur.set_unixfrom(line) + continue + elif lineno == len(lines) - 1: + # Something looking like a unix-from at the end - it's + # probably the first line of the body, so push back the + # line and stop. + self._input.unreadline(line) + return + else: + # Weirdly placed unix-from line. Note this as a defect + # and ignore it. + defect = errors.MisplacedEnvelopeHeaderDefect(line) + self._cur.defects.append(defect) + continue + # Split the line on the colon separating field name from value. + i = line.find(':') + if i < 0: + defect = errors.MalformedHeaderDefect(line) + self._cur.defects.append(defect) + continue + lastheader = line[:i] + lastvalue = [line[i+1:].lstrip()] + # Done with all the lines, so handle the last header. + if lastheader: + # XXX reconsider the joining of folded lines + self._cur[lastheader] = EMPTYSTRING.join(lastvalue).rstrip('\r\n') diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/feedparser.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/feedparser.pyc new file mode 100644 index 0000000..abe5cc1 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/feedparser.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/feedparser.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/feedparser.pyo new file mode 100644 index 0000000..1426e8e Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/feedparser.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/generator.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/generator.py new file mode 100644 index 0000000..5626ab9 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/generator.py @@ -0,0 +1,372 @@ +# Copyright (C) 2001-2010 Python Software Foundation +# Contact: email-sig@python.org + +"""Classes to generate plain text from a message object tree.""" + +__all__ = ['Generator', 'DecodedGenerator'] + +import re +import sys +import time +import random +import warnings + +from cStringIO import StringIO +from email.header import Header + +UNDERSCORE = '_' +NL = '\n' + +fcre = re.compile(r'^From ', re.MULTILINE) + +def _is8bitstring(s): + if isinstance(s, str): + try: + unicode(s, 'us-ascii') + except UnicodeError: + return True + return False + + + +class Generator: + """Generates output from a Message object tree. + + This basic generator writes the message to the given file object as plain + text. + """ + # + # Public interface + # + + def __init__(self, outfp, mangle_from_=True, maxheaderlen=78): + """Create the generator for message flattening. + + outfp is the output file-like object for writing the message to. It + must have a write() method. + + Optional mangle_from_ is a flag that, when True (the default), escapes + From_ lines in the body of the message by putting a `>' in front of + them. + + Optional maxheaderlen specifies the longest length for a non-continued + header. When a header line is longer (in characters, with tabs + expanded to 8 spaces) than maxheaderlen, the header will split as + defined in the Header class. Set maxheaderlen to zero to disable + header wrapping. The default is 78, as recommended (but not required) + by RFC 2822. + """ + self._fp = outfp + self._mangle_from_ = mangle_from_ + self._maxheaderlen = maxheaderlen + + def write(self, s): + # Just delegate to the file object + self._fp.write(s) + + def flatten(self, msg, unixfrom=False): + """Print the message object tree rooted at msg to the output file + specified when the Generator instance was created. + + unixfrom is a flag that forces the printing of a Unix From_ delimiter + before the first object in the message tree. If the original message + has no From_ delimiter, a `standard' one is crafted. By default, this + is False to inhibit the printing of any From_ delimiter. + + Note that for subobjects, no From_ line is printed. + """ + if unixfrom: + ufrom = msg.get_unixfrom() + if not ufrom: + ufrom = 'From nobody ' + time.ctime(time.time()) + print >> self._fp, ufrom + self._write(msg) + + def clone(self, fp): + """Clone this generator with the exact same options.""" + return self.__class__(fp, self._mangle_from_, self._maxheaderlen) + + # + # Protected interface - undocumented ;/ + # + + def _write(self, msg): + # We can't write the headers yet because of the following scenario: + # say a multipart message includes the boundary string somewhere in + # its body. We'd have to calculate the new boundary /before/ we write + # the headers so that we can write the correct Content-Type: + # parameter. + # + # The way we do this, so as to make the _handle_*() methods simpler, + # is to cache any subpart writes into a StringIO. The we write the + # headers and the StringIO contents. That way, subpart handlers can + # Do The Right Thing, and can still modify the Content-Type: header if + # necessary. + oldfp = self._fp + try: + self._fp = sfp = StringIO() + self._dispatch(msg) + finally: + self._fp = oldfp + # Write the headers. First we see if the message object wants to + # handle that itself. If not, we'll do it generically. + meth = getattr(msg, '_write_headers', None) + if meth is None: + self._write_headers(msg) + else: + meth(self) + self._fp.write(sfp.getvalue()) + + def _dispatch(self, msg): + # Get the Content-Type: for the message, then try to dispatch to + # self._handle__(). If there's no handler for the + # full MIME type, then dispatch to self._handle_(). If + # that's missing too, then dispatch to self._writeBody(). + main = msg.get_content_maintype() + sub = msg.get_content_subtype() + specific = UNDERSCORE.join((main, sub)).replace('-', '_') + meth = getattr(self, '_handle_' + specific, None) + if meth is None: + generic = main.replace('-', '_') + meth = getattr(self, '_handle_' + generic, None) + if meth is None: + meth = self._writeBody + meth(msg) + + # + # Default handlers + # + + def _write_headers(self, msg): + for h, v in msg.items(): + print >> self._fp, '%s:' % h, + if self._maxheaderlen == 0: + # Explicit no-wrapping + print >> self._fp, v + elif isinstance(v, Header): + # Header instances know what to do + print >> self._fp, v.encode() + elif _is8bitstring(v): + # If we have raw 8bit data in a byte string, we have no idea + # what the encoding is. There is no safe way to split this + # string. If it's ascii-subset, then we could do a normal + # ascii split, but if it's multibyte then we could break the + # string. There's no way to know so the least harm seems to + # be to not split the string and risk it being too long. + print >> self._fp, v + else: + # Header's got lots of smarts, so use it. Note that this is + # fundamentally broken though because we lose idempotency when + # the header string is continued with tabs. It will now be + # continued with spaces. This was reversedly broken before we + # fixed bug 1974. Either way, we lose. + print >> self._fp, Header( + v, maxlinelen=self._maxheaderlen, header_name=h).encode() + # A blank line always separates headers from body + print >> self._fp + + # + # Handlers for writing types and subtypes + # + + def _handle_text(self, msg): + payload = msg.get_payload() + if payload is None: + return + if not isinstance(payload, basestring): + raise TypeError('string payload expected: %s' % type(payload)) + if self._mangle_from_: + payload = fcre.sub('>From ', payload) + self._fp.write(payload) + + # Default body handler + _writeBody = _handle_text + + def _handle_multipart(self, msg): + # The trick here is to write out each part separately, merge them all + # together, and then make sure that the boundary we've chosen isn't + # present in the payload. + msgtexts = [] + subparts = msg.get_payload() + if subparts is None: + subparts = [] + elif isinstance(subparts, basestring): + # e.g. a non-strict parse of a message with no starting boundary. + self._fp.write(subparts) + return + elif not isinstance(subparts, list): + # Scalar payload + subparts = [subparts] + for part in subparts: + s = StringIO() + g = self.clone(s) + g.flatten(part, unixfrom=False) + msgtexts.append(s.getvalue()) + # BAW: What about boundaries that are wrapped in double-quotes? + boundary = msg.get_boundary() + if not boundary: + # Create a boundary that doesn't appear in any of the + # message texts. + alltext = NL.join(msgtexts) + boundary = _make_boundary(alltext) + msg.set_boundary(boundary) + # If there's a preamble, write it out, with a trailing CRLF + if msg.preamble is not None: + if self._mangle_from_: + preamble = fcre.sub('>From ', msg.preamble) + else: + preamble = msg.preamble + print >> self._fp, preamble + # dash-boundary transport-padding CRLF + print >> self._fp, '--' + boundary + # body-part + if msgtexts: + self._fp.write(msgtexts.pop(0)) + # *encapsulation + # --> delimiter transport-padding + # --> CRLF body-part + for body_part in msgtexts: + # delimiter transport-padding CRLF + print >> self._fp, '\n--' + boundary + # body-part + self._fp.write(body_part) + # close-delimiter transport-padding + self._fp.write('\n--' + boundary + '--') + if msg.epilogue is not None: + print >> self._fp + if self._mangle_from_: + epilogue = fcre.sub('>From ', msg.epilogue) + else: + epilogue = msg.epilogue + self._fp.write(epilogue) + + def _handle_multipart_signed(self, msg): + # The contents of signed parts has to stay unmodified in order to keep + # the signature intact per RFC1847 2.1, so we disable header wrapping. + # RDM: This isn't enough to completely preserve the part, but it helps. + old_maxheaderlen = self._maxheaderlen + try: + self._maxheaderlen = 0 + self._handle_multipart(msg) + finally: + self._maxheaderlen = old_maxheaderlen + + def _handle_message_delivery_status(self, msg): + # We can't just write the headers directly to self's file object + # because this will leave an extra newline between the last header + # block and the boundary. Sigh. + blocks = [] + for part in msg.get_payload(): + s = StringIO() + g = self.clone(s) + g.flatten(part, unixfrom=False) + text = s.getvalue() + lines = text.split('\n') + # Strip off the unnecessary trailing empty line + if lines and lines[-1] == '': + blocks.append(NL.join(lines[:-1])) + else: + blocks.append(text) + # Now join all the blocks with an empty line. This has the lovely + # effect of separating each block with an empty line, but not adding + # an extra one after the last one. + self._fp.write(NL.join(blocks)) + + def _handle_message(self, msg): + s = StringIO() + g = self.clone(s) + # The payload of a message/rfc822 part should be a multipart sequence + # of length 1. The zeroth element of the list should be the Message + # object for the subpart. Extract that object, stringify it, and + # write it out. + # Except, it turns out, when it's a string instead, which happens when + # and only when HeaderParser is used on a message of mime type + # message/rfc822. Such messages are generated by, for example, + # Groupwise when forwarding unadorned messages. (Issue 7970.) So + # in that case we just emit the string body. + payload = msg.get_payload() + if isinstance(payload, list): + g.flatten(msg.get_payload(0), unixfrom=False) + payload = s.getvalue() + self._fp.write(payload) + + + +_FMT = '[Non-text (%(type)s) part of message omitted, filename %(filename)s]' + +class DecodedGenerator(Generator): + """Generates a text representation of a message. + + Like the Generator base class, except that non-text parts are substituted + with a format string representing the part. + """ + def __init__(self, outfp, mangle_from_=True, maxheaderlen=78, fmt=None): + """Like Generator.__init__() except that an additional optional + argument is allowed. + + Walks through all subparts of a message. If the subpart is of main + type `text', then it prints the decoded payload of the subpart. + + Otherwise, fmt is a format string that is used instead of the message + payload. fmt is expanded with the following keywords (in + %(keyword)s format): + + type : Full MIME type of the non-text part + maintype : Main MIME type of the non-text part + subtype : Sub-MIME type of the non-text part + filename : Filename of the non-text part + description: Description associated with the non-text part + encoding : Content transfer encoding of the non-text part + + The default value for fmt is None, meaning + + [Non-text (%(type)s) part of message omitted, filename %(filename)s] + """ + Generator.__init__(self, outfp, mangle_from_, maxheaderlen) + if fmt is None: + self._fmt = _FMT + else: + self._fmt = fmt + + def _dispatch(self, msg): + for part in msg.walk(): + maintype = part.get_content_maintype() + if maintype == 'text': + print >> self, part.get_payload(decode=True) + elif maintype == 'multipart': + # Just skip this + pass + else: + print >> self, self._fmt % { + 'type' : part.get_content_type(), + 'maintype' : part.get_content_maintype(), + 'subtype' : part.get_content_subtype(), + 'filename' : part.get_filename('[no filename]'), + 'description': part.get('Content-Description', + '[no description]'), + 'encoding' : part.get('Content-Transfer-Encoding', + '[no encoding]'), + } + + + +# Helper +_width = len(repr(sys.maxint-1)) +_fmt = '%%0%dd' % _width + +def _make_boundary(text=None): + # Craft a random boundary. If text is given, ensure that the chosen + # boundary doesn't appear in the text. + token = random.randrange(sys.maxint) + boundary = ('=' * 15) + (_fmt % token) + '==' + if text is None: + return boundary + b = boundary + counter = 0 + while True: + cre = re.compile('^--' + re.escape(b) + '(--)?$', re.MULTILINE) + if not cre.search(text): + break + b = boundary + '.' + str(counter) + counter += 1 + return b diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/generator.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/generator.pyc new file mode 100644 index 0000000..30a5904 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/generator.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/generator.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/generator.pyo new file mode 100644 index 0000000..30a5904 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/generator.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/header.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/header.py new file mode 100644 index 0000000..2cf870f --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/header.py @@ -0,0 +1,514 @@ +# Copyright (C) 2002-2006 Python Software Foundation +# Author: Ben Gertzfield, Barry Warsaw +# Contact: email-sig@python.org + +"""Header encoding and decoding functionality.""" + +__all__ = [ + 'Header', + 'decode_header', + 'make_header', + ] + +import re +import binascii + +import email.quoprimime +import email.base64mime + +from email.errors import HeaderParseError +from email.charset import Charset + +NL = '\n' +SPACE = ' ' +USPACE = u' ' +SPACE8 = ' ' * 8 +UEMPTYSTRING = u'' + +MAXLINELEN = 76 + +USASCII = Charset('us-ascii') +UTF8 = Charset('utf-8') + +# Match encoded-word strings in the form =?charset?q?Hello_World?= +ecre = re.compile(r''' + =\? # literal =? + (?P[^?]*?) # non-greedy up to the next ? is the charset + \? # literal ? + (?P[qb]) # either a "q" or a "b", case insensitive + \? # literal ? + (?P.*?) # non-greedy up to the next ?= is the encoded string + \?= # literal ?= + (?=[ \t]|$) # whitespace or the end of the string + ''', re.VERBOSE | re.IGNORECASE | re.MULTILINE) + +# Field name regexp, including trailing colon, but not separating whitespace, +# according to RFC 2822. Character range is from tilde to exclamation mark. +# For use with .match() +fcre = re.compile(r'[\041-\176]+:$') + +# Find a header embedded in a putative header value. Used to check for +# header injection attack. +_embeded_header = re.compile(r'\n[^ \t]+:') + + + +# Helpers +_max_append = email.quoprimime._max_append + + + +def decode_header(header): + """Decode a message header value without converting charset. + + Returns a list of (decoded_string, charset) pairs containing each of the + decoded parts of the header. Charset is None for non-encoded parts of the + header, otherwise a lower-case string containing the name of the character + set specified in the encoded string. + + An email.errors.HeaderParseError may be raised when certain decoding error + occurs (e.g. a base64 decoding exception). + """ + # If no encoding, just return the header + header = str(header) + if not ecre.search(header): + return [(header, None)] + decoded = [] + dec = '' + for line in header.splitlines(): + # This line might not have an encoding in it + if not ecre.search(line): + decoded.append((line, None)) + continue + parts = ecre.split(line) + while parts: + unenc = parts.pop(0).strip() + if unenc: + # Should we continue a long line? + if decoded and decoded[-1][1] is None: + decoded[-1] = (decoded[-1][0] + SPACE + unenc, None) + else: + decoded.append((unenc, None)) + if parts: + charset, encoding = [s.lower() for s in parts[0:2]] + encoded = parts[2] + dec = None + if encoding == 'q': + dec = email.quoprimime.header_decode(encoded) + elif encoding == 'b': + paderr = len(encoded) % 4 # Postel's law: add missing padding + if paderr: + encoded += '==='[:4 - paderr] + try: + dec = email.base64mime.decode(encoded) + except binascii.Error: + # Turn this into a higher level exception. BAW: Right + # now we throw the lower level exception away but + # when/if we get exception chaining, we'll preserve it. + raise HeaderParseError + if dec is None: + dec = encoded + + if decoded and decoded[-1][1] == charset: + decoded[-1] = (decoded[-1][0] + dec, decoded[-1][1]) + else: + decoded.append((dec, charset)) + del parts[0:3] + return decoded + + + +def make_header(decoded_seq, maxlinelen=None, header_name=None, + continuation_ws=' '): + """Create a Header from a sequence of pairs as returned by decode_header() + + decode_header() takes a header value string and returns a sequence of + pairs of the format (decoded_string, charset) where charset is the string + name of the character set. + + This function takes one of those sequence of pairs and returns a Header + instance. Optional maxlinelen, header_name, and continuation_ws are as in + the Header constructor. + """ + h = Header(maxlinelen=maxlinelen, header_name=header_name, + continuation_ws=continuation_ws) + for s, charset in decoded_seq: + # None means us-ascii but we can simply pass it on to h.append() + if charset is not None and not isinstance(charset, Charset): + charset = Charset(charset) + h.append(s, charset) + return h + + + +class Header: + def __init__(self, s=None, charset=None, + maxlinelen=None, header_name=None, + continuation_ws=' ', errors='strict'): + """Create a MIME-compliant header that can contain many character sets. + + Optional s is the initial header value. If None, the initial header + value is not set. You can later append to the header with .append() + method calls. s may be a byte string or a Unicode string, but see the + .append() documentation for semantics. + + Optional charset serves two purposes: it has the same meaning as the + charset argument to the .append() method. It also sets the default + character set for all subsequent .append() calls that omit the charset + argument. If charset is not provided in the constructor, the us-ascii + charset is used both as s's initial charset and as the default for + subsequent .append() calls. + + The maximum line length can be specified explicit via maxlinelen. For + splitting the first line to a shorter value (to account for the field + header which isn't included in s, e.g. `Subject') pass in the name of + the field in header_name. The default maxlinelen is 76. + + continuation_ws must be RFC 2822 compliant folding whitespace (usually + either a space or a hard tab) which will be prepended to continuation + lines. + + errors is passed through to the .append() call. + """ + if charset is None: + charset = USASCII + if not isinstance(charset, Charset): + charset = Charset(charset) + self._charset = charset + self._continuation_ws = continuation_ws + cws_expanded_len = len(continuation_ws.replace('\t', SPACE8)) + # BAW: I believe `chunks' and `maxlinelen' should be non-public. + self._chunks = [] + if s is not None: + self.append(s, charset, errors) + if maxlinelen is None: + maxlinelen = MAXLINELEN + if header_name is None: + # We don't know anything about the field header so the first line + # is the same length as subsequent lines. + self._firstlinelen = maxlinelen + else: + # The first line should be shorter to take into account the field + # header. Also subtract off 2 extra for the colon and space. + self._firstlinelen = maxlinelen - len(header_name) - 2 + # Second and subsequent lines should subtract off the length in + # columns of the continuation whitespace prefix. + self._maxlinelen = maxlinelen - cws_expanded_len + + def __str__(self): + """A synonym for self.encode().""" + return self.encode() + + def __unicode__(self): + """Helper for the built-in unicode function.""" + uchunks = [] + lastcs = None + for s, charset in self._chunks: + # We must preserve spaces between encoded and non-encoded word + # boundaries, which means for us we need to add a space when we go + # from a charset to None/us-ascii, or from None/us-ascii to a + # charset. Only do this for the second and subsequent chunks. + nextcs = charset + if uchunks: + if lastcs not in (None, 'us-ascii'): + if nextcs in (None, 'us-ascii'): + uchunks.append(USPACE) + nextcs = None + elif nextcs not in (None, 'us-ascii'): + uchunks.append(USPACE) + lastcs = nextcs + uchunks.append(unicode(s, str(charset))) + return UEMPTYSTRING.join(uchunks) + + # Rich comparison operators for equality only. BAW: does it make sense to + # have or explicitly disable <, <=, >, >= operators? + def __eq__(self, other): + # other may be a Header or a string. Both are fine so coerce + # ourselves to a string, swap the args and do another comparison. + return other == self.encode() + + def __ne__(self, other): + return not self == other + + def append(self, s, charset=None, errors='strict'): + """Append a string to the MIME header. + + Optional charset, if given, should be a Charset instance or the name + of a character set (which will be converted to a Charset instance). A + value of None (the default) means that the charset given in the + constructor is used. + + s may be a byte string or a Unicode string. If it is a byte string + (i.e. isinstance(s, str) is true), then charset is the encoding of + that byte string, and a UnicodeError will be raised if the string + cannot be decoded with that charset. If s is a Unicode string, then + charset is a hint specifying the character set of the characters in + the string. In this case, when producing an RFC 2822 compliant header + using RFC 2047 rules, the Unicode string will be encoded using the + following charsets in order: us-ascii, the charset hint, utf-8. The + first character set not to provoke a UnicodeError is used. + + Optional `errors' is passed as the third argument to any unicode() or + ustr.encode() call. + """ + if charset is None: + charset = self._charset + elif not isinstance(charset, Charset): + charset = Charset(charset) + # If the charset is our faux 8bit charset, leave the string unchanged + if charset != '8bit': + # We need to test that the string can be converted to unicode and + # back to a byte string, given the input and output codecs of the + # charset. + if isinstance(s, str): + # Possibly raise UnicodeError if the byte string can't be + # converted to a unicode with the input codec of the charset. + incodec = charset.input_codec or 'us-ascii' + ustr = unicode(s, incodec, errors) + # Now make sure that the unicode could be converted back to a + # byte string with the output codec, which may be different + # than the iput coded. Still, use the original byte string. + outcodec = charset.output_codec or 'us-ascii' + ustr.encode(outcodec, errors) + elif isinstance(s, unicode): + # Now we have to be sure the unicode string can be converted + # to a byte string with a reasonable output codec. We want to + # use the byte string in the chunk. + for charset in USASCII, charset, UTF8: + try: + outcodec = charset.output_codec or 'us-ascii' + s = s.encode(outcodec, errors) + break + except UnicodeError: + pass + else: + assert False, 'utf-8 conversion failed' + self._chunks.append((s, charset)) + + def _split(self, s, charset, maxlinelen, splitchars): + # Split up a header safely for use with encode_chunks. + splittable = charset.to_splittable(s) + encoded = charset.from_splittable(splittable, True) + elen = charset.encoded_header_len(encoded) + # If the line's encoded length first, just return it + if elen <= maxlinelen: + return [(encoded, charset)] + # If we have undetermined raw 8bit characters sitting in a byte + # string, we really don't know what the right thing to do is. We + # can't really split it because it might be multibyte data which we + # could break if we split it between pairs. The least harm seems to + # be to not split the header at all, but that means they could go out + # longer than maxlinelen. + if charset == '8bit': + return [(s, charset)] + # BAW: I'm not sure what the right test here is. What we're trying to + # do is be faithful to RFC 2822's recommendation that ($2.2.3): + # + # "Note: Though structured field bodies are defined in such a way that + # folding can take place between many of the lexical tokens (and even + # within some of the lexical tokens), folding SHOULD be limited to + # placing the CRLF at higher-level syntactic breaks." + # + # For now, I can only imagine doing this when the charset is us-ascii, + # although it's possible that other charsets may also benefit from the + # higher-level syntactic breaks. + elif charset == 'us-ascii': + return self._split_ascii(s, charset, maxlinelen, splitchars) + # BAW: should we use encoded? + elif elen == len(s): + # We can split on _maxlinelen boundaries because we know that the + # encoding won't change the size of the string + splitpnt = maxlinelen + first = charset.from_splittable(splittable[:splitpnt], False) + last = charset.from_splittable(splittable[splitpnt:], False) + else: + # Binary search for split point + first, last = _binsplit(splittable, charset, maxlinelen) + # first is of the proper length so just wrap it in the appropriate + # chrome. last must be recursively split. + fsplittable = charset.to_splittable(first) + fencoded = charset.from_splittable(fsplittable, True) + chunk = [(fencoded, charset)] + return chunk + self._split(last, charset, self._maxlinelen, splitchars) + + def _split_ascii(self, s, charset, firstlen, splitchars): + chunks = _split_ascii(s, firstlen, self._maxlinelen, + self._continuation_ws, splitchars) + return zip(chunks, [charset]*len(chunks)) + + def _encode_chunks(self, newchunks, maxlinelen): + # MIME-encode a header with many different charsets and/or encodings. + # + # Given a list of pairs (string, charset), return a MIME-encoded + # string suitable for use in a header field. Each pair may have + # different charsets and/or encodings, and the resulting header will + # accurately reflect each setting. + # + # Each encoding can be email.utils.QP (quoted-printable, for + # ASCII-like character sets like iso-8859-1), email.utils.BASE64 + # (Base64, for non-ASCII like character sets like KOI8-R and + # iso-2022-jp), or None (no encoding). + # + # Each pair will be represented on a separate line; the resulting + # string will be in the format: + # + # =?charset1?q?Mar=EDa_Gonz=E1lez_Alonso?=\n + # =?charset2?b?SvxyZ2VuIEL2aW5n?=" + chunks = [] + for header, charset in newchunks: + if not header: + continue + if charset is None or charset.header_encoding is None: + s = header + else: + s = charset.header_encode(header) + # Don't add more folding whitespace than necessary + if chunks and chunks[-1].endswith(' '): + extra = '' + else: + extra = ' ' + _max_append(chunks, s, maxlinelen, extra) + joiner = NL + self._continuation_ws + return joiner.join(chunks) + + def encode(self, splitchars=';, '): + """Encode a message header into an RFC-compliant format. + + There are many issues involved in converting a given string for use in + an email header. Only certain character sets are readable in most + email clients, and as header strings can only contain a subset of + 7-bit ASCII, care must be taken to properly convert and encode (with + Base64 or quoted-printable) header strings. In addition, there is a + 75-character length limit on any given encoded header field, so + line-wrapping must be performed, even with double-byte character sets. + + This method will do its best to convert the string to the correct + character set used in email, and encode and line wrap it safely with + the appropriate scheme for that character set. + + If the given charset is not known or an error occurs during + conversion, this function will return the header untouched. + + Optional splitchars is a string containing characters to split long + ASCII lines on, in rough support of RFC 2822's `highest level + syntactic breaks'. This doesn't affect RFC 2047 encoded lines. + """ + newchunks = [] + maxlinelen = self._firstlinelen + lastlen = 0 + for s, charset in self._chunks: + # The first bit of the next chunk should be just long enough to + # fill the next line. Don't forget the space separating the + # encoded words. + targetlen = maxlinelen - lastlen - 1 + if targetlen < charset.encoded_header_len(''): + # Stick it on the next line + targetlen = maxlinelen + newchunks += self._split(s, charset, targetlen, splitchars) + lastchunk, lastcharset = newchunks[-1] + lastlen = lastcharset.encoded_header_len(lastchunk) + value = self._encode_chunks(newchunks, maxlinelen) + if _embeded_header.search(value): + raise HeaderParseError("header value appears to contain " + "an embedded header: {!r}".format(value)) + return value + + + +def _split_ascii(s, firstlen, restlen, continuation_ws, splitchars): + lines = [] + maxlen = firstlen + for line in s.splitlines(): + # Ignore any leading whitespace (i.e. continuation whitespace) already + # on the line, since we'll be adding our own. + line = line.lstrip() + if len(line) < maxlen: + lines.append(line) + maxlen = restlen + continue + # Attempt to split the line at the highest-level syntactic break + # possible. Note that we don't have a lot of smarts about field + # syntax; we just try to break on semi-colons, then commas, then + # whitespace. + for ch in splitchars: + if ch in line: + break + else: + # There's nothing useful to split the line on, not even spaces, so + # just append this line unchanged + lines.append(line) + maxlen = restlen + continue + # Now split the line on the character plus trailing whitespace + cre = re.compile(r'%s\s*' % ch) + if ch in ';,': + eol = ch + else: + eol = '' + joiner = eol + ' ' + joinlen = len(joiner) + wslen = len(continuation_ws.replace('\t', SPACE8)) + this = [] + linelen = 0 + for part in cre.split(line): + curlen = linelen + max(0, len(this)-1) * joinlen + partlen = len(part) + onfirstline = not lines + # We don't want to split after the field name, if we're on the + # first line and the field name is present in the header string. + if ch == ' ' and onfirstline and \ + len(this) == 1 and fcre.match(this[0]): + this.append(part) + linelen += partlen + elif curlen + partlen > maxlen: + if this: + lines.append(joiner.join(this) + eol) + # If this part is longer than maxlen and we aren't already + # splitting on whitespace, try to recursively split this line + # on whitespace. + if partlen > maxlen and ch != ' ': + subl = _split_ascii(part, maxlen, restlen, + continuation_ws, ' ') + lines.extend(subl[:-1]) + this = [subl[-1]] + else: + this = [part] + linelen = wslen + len(this[-1]) + maxlen = restlen + else: + this.append(part) + linelen += partlen + # Put any left over parts on a line by themselves + if this: + lines.append(joiner.join(this)) + return lines + + + +def _binsplit(splittable, charset, maxlinelen): + i = 0 + j = len(splittable) + while i < j: + # Invariants: + # 1. splittable[:k] fits for all k <= i (note that we *assume*, + # at the start, that splittable[:0] fits). + # 2. splittable[:k] does not fit for any k > j (at the start, + # this means we shouldn't look at any k > len(splittable)). + # 3. We don't know about splittable[:k] for k in i+1..j. + # 4. We want to set i to the largest k that fits, with i <= k <= j. + # + m = (i+j+1) >> 1 # ceiling((i+j)/2); i < m <= j + chunk = charset.from_splittable(splittable[:m], True) + chunklen = charset.encoded_header_len(chunk) + if chunklen <= maxlinelen: + # m is acceptable, so is a new lower bound. + i = m + else: + # m is not acceptable, so final i must be < m. + j = m - 1 + # i == j. Invariant #1 implies that splittable[:i] fits, and + # invariant #2 implies that splittable[:i+1] does not fit, so i + # is what we're looking for. + first = charset.from_splittable(splittable[:i], False) + last = charset.from_splittable(splittable[i:], False) + return first, last diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/header.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/header.pyc new file mode 100644 index 0000000..a6f1934 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/header.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/header.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/header.pyo new file mode 100644 index 0000000..c5147dd Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/header.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/iterators.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/iterators.py new file mode 100644 index 0000000..e99f228 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/iterators.py @@ -0,0 +1,73 @@ +# Copyright (C) 2001-2006 Python Software Foundation +# Author: Barry Warsaw +# Contact: email-sig@python.org + +"""Various types of useful iterators and generators.""" + +__all__ = [ + 'body_line_iterator', + 'typed_subpart_iterator', + 'walk', + # Do not include _structure() since it's part of the debugging API. + ] + +import sys +from cStringIO import StringIO + + + +# This function will become a method of the Message class +def walk(self): + """Walk over the message tree, yielding each subpart. + + The walk is performed in depth-first order. This method is a + generator. + """ + yield self + if self.is_multipart(): + for subpart in self.get_payload(): + for subsubpart in subpart.walk(): + yield subsubpart + + + +# These two functions are imported into the Iterators.py interface module. +def body_line_iterator(msg, decode=False): + """Iterate over the parts, returning string payloads line-by-line. + + Optional decode (default False) is passed through to .get_payload(). + """ + for subpart in msg.walk(): + payload = subpart.get_payload(decode=decode) + if isinstance(payload, basestring): + for line in StringIO(payload): + yield line + + +def typed_subpart_iterator(msg, maintype='text', subtype=None): + """Iterate over the subparts with a given MIME type. + + Use `maintype' as the main MIME type to match against; this defaults to + "text". Optional `subtype' is the MIME subtype to match against; if + omitted, only the main type is matched. + """ + for subpart in msg.walk(): + if subpart.get_content_maintype() == maintype: + if subtype is None or subpart.get_content_subtype() == subtype: + yield subpart + + + +def _structure(msg, fp=None, level=0, include_default=False): + """A handy debugging aid""" + if fp is None: + fp = sys.stdout + tab = ' ' * (level * 4) + print >> fp, tab + msg.get_content_type(), + if include_default: + print >> fp, '[%s]' % msg.get_default_type() + else: + print >> fp + if msg.is_multipart(): + for subpart in msg.get_payload(): + _structure(subpart, fp, level+1, include_default) diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/iterators.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/iterators.pyc new file mode 100644 index 0000000..a58142d Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/iterators.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/iterators.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/iterators.pyo new file mode 100644 index 0000000..a58142d Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/iterators.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/message.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/message.py new file mode 100644 index 0000000..7c93370 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/message.py @@ -0,0 +1,797 @@ +# Copyright (C) 2001-2006 Python Software Foundation +# Author: Barry Warsaw +# Contact: email-sig@python.org + +"""Basic message object for the email package object model.""" + +__all__ = ['Message'] + +import re +import uu +import binascii +import warnings +from cStringIO import StringIO + +# Intrapackage imports +import email.charset +from email import utils +from email import errors + +SEMISPACE = '; ' + +# Regular expression that matches `special' characters in parameters, the +# existence of which force quoting of the parameter value. +tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]') + + +# Helper functions +def _splitparam(param): + # Split header parameters. BAW: this may be too simple. It isn't + # strictly RFC 2045 (section 5.1) compliant, but it catches most headers + # found in the wild. We may eventually need a full fledged parser + # eventually. + a, sep, b = param.partition(';') + if not sep: + return a.strip(), None + return a.strip(), b.strip() + +def _formatparam(param, value=None, quote=True): + """Convenience function to format and return a key=value pair. + + This will quote the value if needed or if quote is true. If value is a + three tuple (charset, language, value), it will be encoded according + to RFC2231 rules. + """ + if value is not None and len(value) > 0: + # A tuple is used for RFC 2231 encoded parameter values where items + # are (charset, language, value). charset is a string, not a Charset + # instance. + if isinstance(value, tuple): + # Encode as per RFC 2231 + param += '*' + value = utils.encode_rfc2231(value[2], value[0], value[1]) + # BAW: Please check this. I think that if quote is set it should + # force quoting even if not necessary. + if quote or tspecials.search(value): + return '%s="%s"' % (param, utils.quote(value)) + else: + return '%s=%s' % (param, value) + else: + return param + +def _parseparam(s): + plist = [] + while s[:1] == ';': + s = s[1:] + end = s.find(';') + while end > 0 and (s.count('"', 0, end) - s.count('\\"', 0, end)) % 2: + end = s.find(';', end + 1) + if end < 0: + end = len(s) + f = s[:end] + if '=' in f: + i = f.index('=') + f = f[:i].strip().lower() + '=' + f[i+1:].strip() + plist.append(f.strip()) + s = s[end:] + return plist + + +def _unquotevalue(value): + # This is different than utils.collapse_rfc2231_value() because it doesn't + # try to convert the value to a unicode. Message.get_param() and + # Message.get_params() are both currently defined to return the tuple in + # the face of RFC 2231 parameters. + if isinstance(value, tuple): + return value[0], value[1], utils.unquote(value[2]) + else: + return utils.unquote(value) + + + +class Message: + """Basic message object. + + A message object is defined as something that has a bunch of RFC 2822 + headers and a payload. It may optionally have an envelope header + (a.k.a. Unix-From or From_ header). If the message is a container (i.e. a + multipart or a message/rfc822), then the payload is a list of Message + objects, otherwise it is a string. + + Message objects implement part of the `mapping' interface, which assumes + there is exactly one occurrence of the header per message. Some headers + do in fact appear multiple times (e.g. Received) and for those headers, + you must use the explicit API to set or get all the headers. Not all of + the mapping methods are implemented. + """ + def __init__(self): + self._headers = [] + self._unixfrom = None + self._payload = None + self._charset = None + # Defaults for multipart messages + self.preamble = self.epilogue = None + self.defects = [] + # Default content type + self._default_type = 'text/plain' + + def __str__(self): + """Return the entire formatted message as a string. + This includes the headers, body, and envelope header. + """ + return self.as_string(unixfrom=True) + + def as_string(self, unixfrom=False): + """Return the entire formatted message as a string. + Optional `unixfrom' when True, means include the Unix From_ envelope + header. + + This is a convenience method and may not generate the message exactly + as you intend because by default it mangles lines that begin with + "From ". For more flexibility, use the flatten() method of a + Generator instance. + """ + from email.generator import Generator + fp = StringIO() + g = Generator(fp) + g.flatten(self, unixfrom=unixfrom) + return fp.getvalue() + + def is_multipart(self): + """Return True if the message consists of multiple parts.""" + return isinstance(self._payload, list) + + # + # Unix From_ line + # + def set_unixfrom(self, unixfrom): + self._unixfrom = unixfrom + + def get_unixfrom(self): + return self._unixfrom + + # + # Payload manipulation. + # + def attach(self, payload): + """Add the given payload to the current payload. + + The current payload will always be a list of objects after this method + is called. If you want to set the payload to a scalar object, use + set_payload() instead. + """ + if self._payload is None: + self._payload = [payload] + else: + self._payload.append(payload) + + def get_payload(self, i=None, decode=False): + """Return a reference to the payload. + + The payload will either be a list object or a string. If you mutate + the list object, you modify the message's payload in place. Optional + i returns that index into the payload. + + Optional decode is a flag indicating whether the payload should be + decoded or not, according to the Content-Transfer-Encoding header + (default is False). + + When True and the message is not a multipart, the payload will be + decoded if this header's value is `quoted-printable' or `base64'. If + some other encoding is used, or the header is missing, or if the + payload has bogus data (i.e. bogus base64 or uuencoded data), the + payload is returned as-is. + + If the message is a multipart and the decode flag is True, then None + is returned. + """ + if i is None: + payload = self._payload + elif not isinstance(self._payload, list): + raise TypeError('Expected list, got %s' % type(self._payload)) + else: + payload = self._payload[i] + if decode: + if self.is_multipart(): + return None + cte = self.get('content-transfer-encoding', '').lower() + if cte == 'quoted-printable': + return utils._qdecode(payload) + elif cte == 'base64': + try: + return utils._bdecode(payload) + except binascii.Error: + # Incorrect padding + return payload + elif cte in ('x-uuencode', 'uuencode', 'uue', 'x-uue'): + sfp = StringIO() + try: + uu.decode(StringIO(payload+'\n'), sfp, quiet=True) + payload = sfp.getvalue() + except uu.Error: + # Some decoding problem + return payload + # Everything else, including encodings with 8bit or 7bit are returned + # unchanged. + return payload + + def set_payload(self, payload, charset=None): + """Set the payload to the given value. + + Optional charset sets the message's default character set. See + set_charset() for details. + """ + self._payload = payload + if charset is not None: + self.set_charset(charset) + + def set_charset(self, charset): + """Set the charset of the payload to a given character set. + + charset can be a Charset instance, a string naming a character set, or + None. If it is a string it will be converted to a Charset instance. + If charset is None, the charset parameter will be removed from the + Content-Type field. Anything else will generate a TypeError. + + The message will be assumed to be of type text/* encoded with + charset.input_charset. It will be converted to charset.output_charset + and encoded properly, if needed, when generating the plain text + representation of the message. MIME headers (MIME-Version, + Content-Type, Content-Transfer-Encoding) will be added as needed. + + """ + if charset is None: + self.del_param('charset') + self._charset = None + return + if isinstance(charset, basestring): + charset = email.charset.Charset(charset) + if not isinstance(charset, email.charset.Charset): + raise TypeError(charset) + # BAW: should we accept strings that can serve as arguments to the + # Charset constructor? + self._charset = charset + if 'MIME-Version' not in self: + self.add_header('MIME-Version', '1.0') + if 'Content-Type' not in self: + self.add_header('Content-Type', 'text/plain', + charset=charset.get_output_charset()) + else: + self.set_param('charset', charset.get_output_charset()) + if isinstance(self._payload, unicode): + self._payload = self._payload.encode(charset.output_charset) + if str(charset) != charset.get_output_charset(): + self._payload = charset.body_encode(self._payload) + if 'Content-Transfer-Encoding' not in self: + cte = charset.get_body_encoding() + try: + cte(self) + except TypeError: + self._payload = charset.body_encode(self._payload) + self.add_header('Content-Transfer-Encoding', cte) + + def get_charset(self): + """Return the Charset instance associated with the message's payload. + """ + return self._charset + + # + # MAPPING INTERFACE (partial) + # + def __len__(self): + """Return the total number of headers, including duplicates.""" + return len(self._headers) + + def __getitem__(self, name): + """Get a header value. + + Return None if the header is missing instead of raising an exception. + + Note that if the header appeared multiple times, exactly which + occurrence gets returned is undefined. Use get_all() to get all + the values matching a header field name. + """ + return self.get(name) + + def __setitem__(self, name, val): + """Set the value of a header. + + Note: this does not overwrite an existing header with the same field + name. Use __delitem__() first to delete any existing headers. + """ + self._headers.append((name, val)) + + def __delitem__(self, name): + """Delete all occurrences of a header, if present. + + Does not raise an exception if the header is missing. + """ + name = name.lower() + newheaders = [] + for k, v in self._headers: + if k.lower() != name: + newheaders.append((k, v)) + self._headers = newheaders + + def __contains__(self, name): + return name.lower() in [k.lower() for k, v in self._headers] + + def has_key(self, name): + """Return true if the message contains the header.""" + missing = object() + return self.get(name, missing) is not missing + + def keys(self): + """Return a list of all the message's header field names. + + These will be sorted in the order they appeared in the original + message, or were added to the message, and may contain duplicates. + Any fields deleted and re-inserted are always appended to the header + list. + """ + return [k for k, v in self._headers] + + def values(self): + """Return a list of all the message's header values. + + These will be sorted in the order they appeared in the original + message, or were added to the message, and may contain duplicates. + Any fields deleted and re-inserted are always appended to the header + list. + """ + return [v for k, v in self._headers] + + def items(self): + """Get all the message's header fields and values. + + These will be sorted in the order they appeared in the original + message, or were added to the message, and may contain duplicates. + Any fields deleted and re-inserted are always appended to the header + list. + """ + return self._headers[:] + + def get(self, name, failobj=None): + """Get a header value. + + Like __getitem__() but return failobj instead of None when the field + is missing. + """ + name = name.lower() + for k, v in self._headers: + if k.lower() == name: + return v + return failobj + + # + # Additional useful stuff + # + + def get_all(self, name, failobj=None): + """Return a list of all the values for the named field. + + These will be sorted in the order they appeared in the original + message, and may contain duplicates. Any fields deleted and + re-inserted are always appended to the header list. + + If no such fields exist, failobj is returned (defaults to None). + """ + values = [] + name = name.lower() + for k, v in self._headers: + if k.lower() == name: + values.append(v) + if not values: + return failobj + return values + + def add_header(self, _name, _value, **_params): + """Extended header setting. + + name is the header field to add. keyword arguments can be used to set + additional parameters for the header field, with underscores converted + to dashes. Normally the parameter will be added as key="value" unless + value is None, in which case only the key will be added. If a + parameter value contains non-ASCII characters it must be specified as a + three-tuple of (charset, language, value), in which case it will be + encoded according to RFC2231 rules. + + Example: + + msg.add_header('content-disposition', 'attachment', filename='bud.gif') + """ + parts = [] + for k, v in _params.items(): + if v is None: + parts.append(k.replace('_', '-')) + else: + parts.append(_formatparam(k.replace('_', '-'), v)) + if _value is not None: + parts.insert(0, _value) + self._headers.append((_name, SEMISPACE.join(parts))) + + def replace_header(self, _name, _value): + """Replace a header. + + Replace the first matching header found in the message, retaining + header order and case. If no matching header was found, a KeyError is + raised. + """ + _name = _name.lower() + for i, (k, v) in zip(range(len(self._headers)), self._headers): + if k.lower() == _name: + self._headers[i] = (k, _value) + break + else: + raise KeyError(_name) + + # + # Use these three methods instead of the three above. + # + + def get_content_type(self): + """Return the message's content type. + + The returned string is coerced to lower case of the form + `maintype/subtype'. If there was no Content-Type header in the + message, the default type as given by get_default_type() will be + returned. Since according to RFC 2045, messages always have a default + type this will always return a value. + + RFC 2045 defines a message's default type to be text/plain unless it + appears inside a multipart/digest container, in which case it would be + message/rfc822. + """ + missing = object() + value = self.get('content-type', missing) + if value is missing: + # This should have no parameters + return self.get_default_type() + ctype = _splitparam(value)[0].lower() + # RFC 2045, section 5.2 says if its invalid, use text/plain + if ctype.count('/') != 1: + return 'text/plain' + return ctype + + def get_content_maintype(self): + """Return the message's main content type. + + This is the `maintype' part of the string returned by + get_content_type(). + """ + ctype = self.get_content_type() + return ctype.split('/')[0] + + def get_content_subtype(self): + """Returns the message's sub-content type. + + This is the `subtype' part of the string returned by + get_content_type(). + """ + ctype = self.get_content_type() + return ctype.split('/')[1] + + def get_default_type(self): + """Return the `default' content type. + + Most messages have a default content type of text/plain, except for + messages that are subparts of multipart/digest containers. Such + subparts have a default content type of message/rfc822. + """ + return self._default_type + + def set_default_type(self, ctype): + """Set the `default' content type. + + ctype should be either "text/plain" or "message/rfc822", although this + is not enforced. The default content type is not stored in the + Content-Type header. + """ + self._default_type = ctype + + def _get_params_preserve(self, failobj, header): + # Like get_params() but preserves the quoting of values. BAW: + # should this be part of the public interface? + missing = object() + value = self.get(header, missing) + if value is missing: + return failobj + params = [] + for p in _parseparam(';' + value): + try: + name, val = p.split('=', 1) + name = name.strip() + val = val.strip() + except ValueError: + # Must have been a bare attribute + name = p.strip() + val = '' + params.append((name, val)) + params = utils.decode_params(params) + return params + + def get_params(self, failobj=None, header='content-type', unquote=True): + """Return the message's Content-Type parameters, as a list. + + The elements of the returned list are 2-tuples of key/value pairs, as + split on the `=' sign. The left hand side of the `=' is the key, + while the right hand side is the value. If there is no `=' sign in + the parameter the value is the empty string. The value is as + described in the get_param() method. + + Optional failobj is the object to return if there is no Content-Type + header. Optional header is the header to search instead of + Content-Type. If unquote is True, the value is unquoted. + """ + missing = object() + params = self._get_params_preserve(missing, header) + if params is missing: + return failobj + if unquote: + return [(k, _unquotevalue(v)) for k, v in params] + else: + return params + + def get_param(self, param, failobj=None, header='content-type', + unquote=True): + """Return the parameter value if found in the Content-Type header. + + Optional failobj is the object to return if there is no Content-Type + header, or the Content-Type header has no such parameter. Optional + header is the header to search instead of Content-Type. + + Parameter keys are always compared case insensitively. The return + value can either be a string, or a 3-tuple if the parameter was RFC + 2231 encoded. When it's a 3-tuple, the elements of the value are of + the form (CHARSET, LANGUAGE, VALUE). Note that both CHARSET and + LANGUAGE can be None, in which case you should consider VALUE to be + encoded in the us-ascii charset. You can usually ignore LANGUAGE. + + Your application should be prepared to deal with 3-tuple return + values, and can convert the parameter to a Unicode string like so: + + param = msg.get_param('foo') + if isinstance(param, tuple): + param = unicode(param[2], param[0] or 'us-ascii') + + In any case, the parameter value (either the returned string, or the + VALUE item in the 3-tuple) is always unquoted, unless unquote is set + to False. + """ + if header not in self: + return failobj + for k, v in self._get_params_preserve(failobj, header): + if k.lower() == param.lower(): + if unquote: + return _unquotevalue(v) + else: + return v + return failobj + + def set_param(self, param, value, header='Content-Type', requote=True, + charset=None, language=''): + """Set a parameter in the Content-Type header. + + If the parameter already exists in the header, its value will be + replaced with the new value. + + If header is Content-Type and has not yet been defined for this + message, it will be set to "text/plain" and the new parameter and + value will be appended as per RFC 2045. + + An alternate header can specified in the header argument, and all + parameters will be quoted as necessary unless requote is False. + + If charset is specified, the parameter will be encoded according to RFC + 2231. Optional language specifies the RFC 2231 language, defaulting + to the empty string. Both charset and language should be strings. + """ + if not isinstance(value, tuple) and charset: + value = (charset, language, value) + + if header not in self and header.lower() == 'content-type': + ctype = 'text/plain' + else: + ctype = self.get(header) + if not self.get_param(param, header=header): + if not ctype: + ctype = _formatparam(param, value, requote) + else: + ctype = SEMISPACE.join( + [ctype, _formatparam(param, value, requote)]) + else: + ctype = '' + for old_param, old_value in self.get_params(header=header, + unquote=requote): + append_param = '' + if old_param.lower() == param.lower(): + append_param = _formatparam(param, value, requote) + else: + append_param = _formatparam(old_param, old_value, requote) + if not ctype: + ctype = append_param + else: + ctype = SEMISPACE.join([ctype, append_param]) + if ctype != self.get(header): + del self[header] + self[header] = ctype + + def del_param(self, param, header='content-type', requote=True): + """Remove the given parameter completely from the Content-Type header. + + The header will be re-written in place without the parameter or its + value. All values will be quoted as necessary unless requote is + False. Optional header specifies an alternative to the Content-Type + header. + """ + if header not in self: + return + new_ctype = '' + for p, v in self.get_params(header=header, unquote=requote): + if p.lower() != param.lower(): + if not new_ctype: + new_ctype = _formatparam(p, v, requote) + else: + new_ctype = SEMISPACE.join([new_ctype, + _formatparam(p, v, requote)]) + if new_ctype != self.get(header): + del self[header] + self[header] = new_ctype + + def set_type(self, type, header='Content-Type', requote=True): + """Set the main type and subtype for the Content-Type header. + + type must be a string in the form "maintype/subtype", otherwise a + ValueError is raised. + + This method replaces the Content-Type header, keeping all the + parameters in place. If requote is False, this leaves the existing + header's quoting as is. Otherwise, the parameters will be quoted (the + default). + + An alternative header can be specified in the header argument. When + the Content-Type header is set, we'll always also add a MIME-Version + header. + """ + # BAW: should we be strict? + if not type.count('/') == 1: + raise ValueError + # Set the Content-Type, you get a MIME-Version + if header.lower() == 'content-type': + del self['mime-version'] + self['MIME-Version'] = '1.0' + if header not in self: + self[header] = type + return + params = self.get_params(header=header, unquote=requote) + del self[header] + self[header] = type + # Skip the first param; it's the old type. + for p, v in params[1:]: + self.set_param(p, v, header, requote) + + def get_filename(self, failobj=None): + """Return the filename associated with the payload if present. + + The filename is extracted from the Content-Disposition header's + `filename' parameter, and it is unquoted. If that header is missing + the `filename' parameter, this method falls back to looking for the + `name' parameter. + """ + missing = object() + filename = self.get_param('filename', missing, 'content-disposition') + if filename is missing: + filename = self.get_param('name', missing, 'content-type') + if filename is missing: + return failobj + return utils.collapse_rfc2231_value(filename).strip() + + def get_boundary(self, failobj=None): + """Return the boundary associated with the payload if present. + + The boundary is extracted from the Content-Type header's `boundary' + parameter, and it is unquoted. + """ + missing = object() + boundary = self.get_param('boundary', missing) + if boundary is missing: + return failobj + # RFC 2046 says that boundaries may begin but not end in w/s + return utils.collapse_rfc2231_value(boundary).rstrip() + + def set_boundary(self, boundary): + """Set the boundary parameter in Content-Type to 'boundary'. + + This is subtly different than deleting the Content-Type header and + adding a new one with a new boundary parameter via add_header(). The + main difference is that using the set_boundary() method preserves the + order of the Content-Type header in the original message. + + HeaderParseError is raised if the message has no Content-Type header. + """ + missing = object() + params = self._get_params_preserve(missing, 'content-type') + if params is missing: + # There was no Content-Type header, and we don't know what type + # to set it to, so raise an exception. + raise errors.HeaderParseError('No Content-Type header found') + newparams = [] + foundp = False + for pk, pv in params: + if pk.lower() == 'boundary': + newparams.append(('boundary', '"%s"' % boundary)) + foundp = True + else: + newparams.append((pk, pv)) + if not foundp: + # The original Content-Type header had no boundary attribute. + # Tack one on the end. BAW: should we raise an exception + # instead??? + newparams.append(('boundary', '"%s"' % boundary)) + # Replace the existing Content-Type header with the new value + newheaders = [] + for h, v in self._headers: + if h.lower() == 'content-type': + parts = [] + for k, v in newparams: + if v == '': + parts.append(k) + else: + parts.append('%s=%s' % (k, v)) + newheaders.append((h, SEMISPACE.join(parts))) + + else: + newheaders.append((h, v)) + self._headers = newheaders + + def get_content_charset(self, failobj=None): + """Return the charset parameter of the Content-Type header. + + The returned string is always coerced to lower case. If there is no + Content-Type header, or if that header has no charset parameter, + failobj is returned. + """ + missing = object() + charset = self.get_param('charset', missing) + if charset is missing: + return failobj + if isinstance(charset, tuple): + # RFC 2231 encoded, so decode it, and it better end up as ascii. + pcharset = charset[0] or 'us-ascii' + try: + # LookupError will be raised if the charset isn't known to + # Python. UnicodeError will be raised if the encoded text + # contains a character not in the charset. + charset = unicode(charset[2], pcharset).encode('us-ascii') + except (LookupError, UnicodeError): + charset = charset[2] + # charset character must be in us-ascii range + try: + if isinstance(charset, str): + charset = unicode(charset, 'us-ascii') + charset = charset.encode('us-ascii') + except UnicodeError: + return failobj + # RFC 2046, $4.1.2 says charsets are not case sensitive + return charset.lower() + + def get_charsets(self, failobj=None): + """Return a list containing the charset(s) used in this message. + + The returned list of items describes the Content-Type headers' + charset parameter for this message and all the subparts in its + payload. + + Each item will either be a string (the value of the charset parameter + in the Content-Type header of that part) or the value of the + 'failobj' parameter (defaults to None), if the part does not have a + main MIME type of "text", or the charset is not defined. + + The list will contain one string for each part of the message, plus + one for the container message (i.e. self), so that a non-multipart + message will still return a list of length 1. + """ + return [part.get_content_charset(failobj) for part in self.walk()] + + # I.e. def walk(self): ... + from email.iterators import walk diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/message.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/message.pyc new file mode 100644 index 0000000..9cf7cb8 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/message.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/message.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/message.pyo new file mode 100644 index 0000000..9cf7cb8 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/message.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/__init__.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/__init__.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/__init__.pyc new file mode 100644 index 0000000..ee7fc49 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/__init__.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/__init__.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/__init__.pyo new file mode 100644 index 0000000..ee7fc49 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/__init__.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/application.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/application.py new file mode 100644 index 0000000..f5c5905 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/application.py @@ -0,0 +1,36 @@ +# Copyright (C) 2001-2006 Python Software Foundation +# Author: Keith Dart +# Contact: email-sig@python.org + +"""Class representing application/* type MIME documents.""" + +__all__ = ["MIMEApplication"] + +from email import encoders +from email.mime.nonmultipart import MIMENonMultipart + + +class MIMEApplication(MIMENonMultipart): + """Class for generating application/* MIME documents.""" + + def __init__(self, _data, _subtype='octet-stream', + _encoder=encoders.encode_base64, **_params): + """Create an application/* type MIME document. + + _data is a string containing the raw application data. + + _subtype is the MIME content type subtype, defaulting to + 'octet-stream'. + + _encoder is a function which will perform the actual encoding for + transport of the application data, defaulting to base64 encoding. + + Any additional keyword arguments are passed to the base class + constructor, which turns them into parameters on the Content-Type + header. + """ + if _subtype is None: + raise TypeError('Invalid application MIME subtype') + MIMENonMultipart.__init__(self, 'application', _subtype, **_params) + self.set_payload(_data) + _encoder(self) diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/application.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/application.pyc new file mode 100644 index 0000000..877c0df Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/application.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/application.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/application.pyo new file mode 100644 index 0000000..877c0df Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/application.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/audio.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/audio.py new file mode 100644 index 0000000..c7290c4 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/audio.py @@ -0,0 +1,73 @@ +# Copyright (C) 2001-2006 Python Software Foundation +# Author: Anthony Baxter +# Contact: email-sig@python.org + +"""Class representing audio/* type MIME documents.""" + +__all__ = ['MIMEAudio'] + +import sndhdr + +from cStringIO import StringIO +from email import encoders +from email.mime.nonmultipart import MIMENonMultipart + + + +_sndhdr_MIMEmap = {'au' : 'basic', + 'wav' :'x-wav', + 'aiff':'x-aiff', + 'aifc':'x-aiff', + } + +# There are others in sndhdr that don't have MIME types. :( +# Additional ones to be added to sndhdr? midi, mp3, realaudio, wma?? +def _whatsnd(data): + """Try to identify a sound file type. + + sndhdr.what() has a pretty cruddy interface, unfortunately. This is why + we re-do it here. It would be easier to reverse engineer the Unix 'file' + command and use the standard 'magic' file, as shipped with a modern Unix. + """ + hdr = data[:512] + fakefile = StringIO(hdr) + for testfn in sndhdr.tests: + res = testfn(hdr, fakefile) + if res is not None: + return _sndhdr_MIMEmap.get(res[0]) + return None + + + +class MIMEAudio(MIMENonMultipart): + """Class for generating audio/* MIME documents.""" + + def __init__(self, _audiodata, _subtype=None, + _encoder=encoders.encode_base64, **_params): + """Create an audio/* type MIME document. + + _audiodata is a string containing the raw audio data. If this data + can be decoded by the standard Python `sndhdr' module, then the + subtype will be automatically included in the Content-Type header. + Otherwise, you can specify the specific audio subtype via the + _subtype parameter. If _subtype is not given, and no subtype can be + guessed, a TypeError is raised. + + _encoder is a function which will perform the actual encoding for + transport of the image data. It takes one argument, which is this + Image instance. It should use get_payload() and set_payload() to + change the payload to the encoded form. It should also add any + Content-Transfer-Encoding or other headers to the message as + necessary. The default encoding is Base64. + + Any additional keyword arguments are passed to the base class + constructor, which turns them into parameters on the Content-Type + header. + """ + if _subtype is None: + _subtype = _whatsnd(_audiodata) + if _subtype is None: + raise TypeError('Could not find audio MIME subtype') + MIMENonMultipart.__init__(self, 'audio', _subtype, **_params) + self.set_payload(_audiodata) + _encoder(self) diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/audio.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/audio.pyc new file mode 100644 index 0000000..1f58399 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/audio.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/audio.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/audio.pyo new file mode 100644 index 0000000..1f58399 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/audio.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/base.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/base.py new file mode 100644 index 0000000..ac91925 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/base.py @@ -0,0 +1,26 @@ +# Copyright (C) 2001-2006 Python Software Foundation +# Author: Barry Warsaw +# Contact: email-sig@python.org + +"""Base class for MIME specializations.""" + +__all__ = ['MIMEBase'] + +from email import message + + + +class MIMEBase(message.Message): + """Base class for MIME specializations.""" + + def __init__(self, _maintype, _subtype, **_params): + """This constructor adds a Content-Type: and a MIME-Version: header. + + The Content-Type: header is taken from the _maintype and _subtype + arguments. Additional parameters for this header are taken from the + keyword arguments. + """ + message.Message.__init__(self) + ctype = '%s/%s' % (_maintype, _subtype) + self.add_header('Content-Type', ctype, **_params) + self['MIME-Version'] = '1.0' diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/base.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/base.pyc new file mode 100644 index 0000000..9fa4028 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/base.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/base.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/base.pyo new file mode 100644 index 0000000..9fa4028 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/base.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/image.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/image.py new file mode 100644 index 0000000..5563823 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/image.py @@ -0,0 +1,46 @@ +# Copyright (C) 2001-2006 Python Software Foundation +# Author: Barry Warsaw +# Contact: email-sig@python.org + +"""Class representing image/* type MIME documents.""" + +__all__ = ['MIMEImage'] + +import imghdr + +from email import encoders +from email.mime.nonmultipart import MIMENonMultipart + + + +class MIMEImage(MIMENonMultipart): + """Class for generating image/* type MIME documents.""" + + def __init__(self, _imagedata, _subtype=None, + _encoder=encoders.encode_base64, **_params): + """Create an image/* type MIME document. + + _imagedata is a string containing the raw image data. If this data + can be decoded by the standard Python `imghdr' module, then the + subtype will be automatically included in the Content-Type header. + Otherwise, you can specify the specific image subtype via the _subtype + parameter. + + _encoder is a function which will perform the actual encoding for + transport of the image data. It takes one argument, which is this + Image instance. It should use get_payload() and set_payload() to + change the payload to the encoded form. It should also add any + Content-Transfer-Encoding or other headers to the message as + necessary. The default encoding is Base64. + + Any additional keyword arguments are passed to the base class + constructor, which turns them into parameters on the Content-Type + header. + """ + if _subtype is None: + _subtype = imghdr.what(None, _imagedata) + if _subtype is None: + raise TypeError('Could not guess image MIME subtype') + MIMENonMultipart.__init__(self, 'image', _subtype, **_params) + self.set_payload(_imagedata) + _encoder(self) diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/image.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/image.pyc new file mode 100644 index 0000000..a4245fb Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/image.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/image.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/image.pyo new file mode 100644 index 0000000..a4245fb Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/image.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/message.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/message.py new file mode 100644 index 0000000..275dbfd --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/message.py @@ -0,0 +1,34 @@ +# Copyright (C) 2001-2006 Python Software Foundation +# Author: Barry Warsaw +# Contact: email-sig@python.org + +"""Class representing message/* MIME documents.""" + +__all__ = ['MIMEMessage'] + +from email import message +from email.mime.nonmultipart import MIMENonMultipart + + + +class MIMEMessage(MIMENonMultipart): + """Class representing message/* MIME documents.""" + + def __init__(self, _msg, _subtype='rfc822'): + """Create a message/* type MIME document. + + _msg is a message object and must be an instance of Message, or a + derived class of Message, otherwise a TypeError is raised. + + Optional _subtype defines the subtype of the contained message. The + default is "rfc822" (this is defined by the MIME standard, even though + the term "rfc822" is technically outdated by RFC 2822). + """ + MIMENonMultipart.__init__(self, 'message', _subtype) + if not isinstance(_msg, message.Message): + raise TypeError('Argument is not an instance of Message') + # It's convenient to use this base class method. We need to do it + # this way or we'll get an exception + message.Message.attach(self, _msg) + # And be sure our default type is set correctly + self.set_default_type('message/rfc822') diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/message.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/message.pyc new file mode 100644 index 0000000..24255ba Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/message.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/message.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/message.pyo new file mode 100644 index 0000000..24255ba Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/message.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/multipart.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/multipart.py new file mode 100644 index 0000000..9661865 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/multipart.py @@ -0,0 +1,47 @@ +# Copyright (C) 2002-2006 Python Software Foundation +# Author: Barry Warsaw +# Contact: email-sig@python.org + +"""Base class for MIME multipart/* type messages.""" + +__all__ = ['MIMEMultipart'] + +from email.mime.base import MIMEBase + + + +class MIMEMultipart(MIMEBase): + """Base class for MIME multipart/* type messages.""" + + def __init__(self, _subtype='mixed', boundary=None, _subparts=None, + **_params): + """Creates a multipart/* type message. + + By default, creates a multipart/mixed message, with proper + Content-Type and MIME-Version headers. + + _subtype is the subtype of the multipart content type, defaulting to + `mixed'. + + boundary is the multipart boundary string. By default it is + calculated as needed. + + _subparts is a sequence of initial subparts for the payload. It + must be an iterable object, such as a list. You can always + attach new subparts to the message by using the attach() method. + + Additional parameters for the Content-Type header are taken from the + keyword arguments (or passed into the _params argument). + """ + MIMEBase.__init__(self, 'multipart', _subtype, **_params) + + # Initialise _payload to an empty list as the Message superclass's + # implementation of is_multipart assumes that _payload is a list for + # multipart messages. + self._payload = [] + + if _subparts: + for p in _subparts: + self.attach(p) + if boundary: + self.set_boundary(boundary) diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/multipart.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/multipart.pyc new file mode 100644 index 0000000..de72269 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/multipart.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/multipart.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/multipart.pyo new file mode 100644 index 0000000..de72269 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/multipart.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/nonmultipart.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/nonmultipart.py new file mode 100644 index 0000000..fc3b9eb --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/nonmultipart.py @@ -0,0 +1,22 @@ +# Copyright (C) 2002-2006 Python Software Foundation +# Author: Barry Warsaw +# Contact: email-sig@python.org + +"""Base class for MIME type messages that are not multipart.""" + +__all__ = ['MIMENonMultipart'] + +from email import errors +from email.mime.base import MIMEBase + + + +class MIMENonMultipart(MIMEBase): + """Base class for MIME multipart/* type messages.""" + + def attach(self, payload): + # The public API prohibits attaching multiple subparts to MIMEBase + # derived subtypes since none of them are, by definition, of content + # type multipart/* + raise errors.MultipartConversionError( + 'Cannot attach additional subparts to non-multipart/*') diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/nonmultipart.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/nonmultipart.pyc new file mode 100644 index 0000000..d28b04c Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/nonmultipart.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/nonmultipart.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/nonmultipart.pyo new file mode 100644 index 0000000..d28b04c Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/nonmultipart.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/text.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/text.py new file mode 100644 index 0000000..5747db5 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/text.py @@ -0,0 +1,30 @@ +# Copyright (C) 2001-2006 Python Software Foundation +# Author: Barry Warsaw +# Contact: email-sig@python.org + +"""Class representing text/* type MIME documents.""" + +__all__ = ['MIMEText'] + +from email.encoders import encode_7or8bit +from email.mime.nonmultipart import MIMENonMultipart + + + +class MIMEText(MIMENonMultipart): + """Class for generating text/* type MIME documents.""" + + def __init__(self, _text, _subtype='plain', _charset='us-ascii'): + """Create a text/* type MIME document. + + _text is the string for this message object. + + _subtype is the MIME sub content type, defaulting to "plain". + + _charset is the character set parameter added to the Content-Type + header. This defaults to "us-ascii". Note that as a side-effect, the + Content-Transfer-Encoding header will also be set. + """ + MIMENonMultipart.__init__(self, 'text', _subtype, + **{'charset': _charset}) + self.set_payload(_text, _charset) diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/text.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/text.pyc new file mode 100644 index 0000000..47d8880 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/text.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/text.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/text.pyo new file mode 100644 index 0000000..47d8880 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/mime/text.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/parser.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/parser.py new file mode 100644 index 0000000..2fcaf25 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/parser.py @@ -0,0 +1,91 @@ +# Copyright (C) 2001-2006 Python Software Foundation +# Author: Barry Warsaw, Thomas Wouters, Anthony Baxter +# Contact: email-sig@python.org + +"""A parser of RFC 2822 and MIME email messages.""" + +__all__ = ['Parser', 'HeaderParser'] + +import warnings +from cStringIO import StringIO + +from email.feedparser import FeedParser +from email.message import Message + + + +class Parser: + def __init__(self, *args, **kws): + """Parser of RFC 2822 and MIME email messages. + + Creates an in-memory object tree representing the email message, which + can then be manipulated and turned over to a Generator to return the + textual representation of the message. + + The string must be formatted as a block of RFC 2822 headers and header + continuation lines, optionally preceeded by a `Unix-from' header. The + header block is terminated either by the end of the string or by a + blank line. + + _class is the class to instantiate for new message objects when they + must be created. This class must have a constructor that can take + zero arguments. Default is Message.Message. + """ + if len(args) >= 1: + if '_class' in kws: + raise TypeError("Multiple values for keyword arg '_class'") + kws['_class'] = args[0] + if len(args) == 2: + if 'strict' in kws: + raise TypeError("Multiple values for keyword arg 'strict'") + kws['strict'] = args[1] + if len(args) > 2: + raise TypeError('Too many arguments') + if '_class' in kws: + self._class = kws['_class'] + del kws['_class'] + else: + self._class = Message + if 'strict' in kws: + warnings.warn("'strict' argument is deprecated (and ignored)", + DeprecationWarning, 2) + del kws['strict'] + if kws: + raise TypeError('Unexpected keyword arguments') + + def parse(self, fp, headersonly=False): + """Create a message structure from the data in a file. + + Reads all the data from the file and returns the root of the message + structure. Optional headersonly is a flag specifying whether to stop + parsing after reading the headers or not. The default is False, + meaning it parses the entire contents of the file. + """ + feedparser = FeedParser(self._class) + if headersonly: + feedparser._set_headersonly() + while True: + data = fp.read(8192) + if not data: + break + feedparser.feed(data) + return feedparser.close() + + def parsestr(self, text, headersonly=False): + """Create a message structure from a string. + + Returns the root of the message structure. Optional headersonly is a + flag specifying whether to stop parsing after reading the headers or + not. The default is False, meaning it parses the entire contents of + the file. + """ + return self.parse(StringIO(text), headersonly=headersonly) + + + +class HeaderParser(Parser): + def parse(self, fp, headersonly=True): + return Parser.parse(self, fp, True) + + def parsestr(self, text, headersonly=True): + return Parser.parsestr(self, text, True) diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/parser.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/parser.pyc new file mode 100644 index 0000000..3d69e12 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/parser.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/parser.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/parser.pyo new file mode 100644 index 0000000..3d69e12 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/parser.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/quoprimime.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/quoprimime.py new file mode 100644 index 0000000..0c18a9e --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/quoprimime.py @@ -0,0 +1,336 @@ +# Copyright (C) 2001-2006 Python Software Foundation +# Author: Ben Gertzfield +# Contact: email-sig@python.org + +"""Quoted-printable content transfer encoding per RFCs 2045-2047. + +This module handles the content transfer encoding method defined in RFC 2045 +to encode US ASCII-like 8-bit data called `quoted-printable'. It is used to +safely encode text that is in a character set similar to the 7-bit US ASCII +character set, but that includes some 8-bit characters that are normally not +allowed in email bodies or headers. + +Quoted-printable is very space-inefficient for encoding binary files; use the +email.base64mime module for that instead. + +This module provides an interface to encode and decode both headers and bodies +with quoted-printable encoding. + +RFC 2045 defines a method for including character set information in an +`encoded-word' in a header. This method is commonly used for 8-bit real names +in To:/From:/Cc: etc. fields, as well as Subject: lines. + +This module does not do the line wrapping or end-of-line character +conversion necessary for proper internationalized headers; it only +does dumb encoding and decoding. To deal with the various line +wrapping issues, use the email.header module. +""" + +__all__ = [ + 'body_decode', + 'body_encode', + 'body_quopri_check', + 'body_quopri_len', + 'decode', + 'decodestring', + 'encode', + 'encodestring', + 'header_decode', + 'header_encode', + 'header_quopri_check', + 'header_quopri_len', + 'quote', + 'unquote', + ] + +import re + +from string import hexdigits +from email.utils import fix_eols + +CRLF = '\r\n' +NL = '\n' + +# See also Charset.py +MISC_LEN = 7 + +hqre = re.compile(r'[^-a-zA-Z0-9!*+/ ]') +bqre = re.compile(r'[^ !-<>-~\t]') + + + +# Helpers +def header_quopri_check(c): + """Return True if the character should be escaped with header quopri.""" + return bool(hqre.match(c)) + + +def body_quopri_check(c): + """Return True if the character should be escaped with body quopri.""" + return bool(bqre.match(c)) + + +def header_quopri_len(s): + """Return the length of str when it is encoded with header quopri.""" + count = 0 + for c in s: + if hqre.match(c): + count += 3 + else: + count += 1 + return count + + +def body_quopri_len(str): + """Return the length of str when it is encoded with body quopri.""" + count = 0 + for c in str: + if bqre.match(c): + count += 3 + else: + count += 1 + return count + + +def _max_append(L, s, maxlen, extra=''): + if not L: + L.append(s.lstrip()) + elif len(L[-1]) + len(s) <= maxlen: + L[-1] += extra + s + else: + L.append(s.lstrip()) + + +def unquote(s): + """Turn a string in the form =AB to the ASCII character with value 0xab""" + return chr(int(s[1:3], 16)) + + +def quote(c): + return "=%02X" % ord(c) + + + +def header_encode(header, charset="iso-8859-1", keep_eols=False, + maxlinelen=76, eol=NL): + """Encode a single header line with quoted-printable (like) encoding. + + Defined in RFC 2045, this `Q' encoding is similar to quoted-printable, but + used specifically for email header fields to allow charsets with mostly 7 + bit characters (and some 8 bit) to remain more or less readable in non-RFC + 2045 aware mail clients. + + charset names the character set to use to encode the header. It defaults + to iso-8859-1. + + The resulting string will be in the form: + + "=?charset?q?I_f=E2rt_in_your_g=E8n=E8ral_dire=E7tion?\\n + =?charset?q?Silly_=C8nglish_Kn=EEghts?=" + + with each line wrapped safely at, at most, maxlinelen characters (defaults + to 76 characters). If maxlinelen is None, the entire string is encoded in + one chunk with no splitting. + + End-of-line characters (\\r, \\n, \\r\\n) will be automatically converted + to the canonical email line separator \\r\\n unless the keep_eols + parameter is True (the default is False). + + Each line of the header will be terminated in the value of eol, which + defaults to "\\n". Set this to "\\r\\n" if you are using the result of + this function directly in email. + """ + # Return empty headers unchanged + if not header: + return header + + if not keep_eols: + header = fix_eols(header) + + # Quopri encode each line, in encoded chunks no greater than maxlinelen in + # length, after the RFC chrome is added in. + quoted = [] + if maxlinelen is None: + # An obnoxiously large number that's good enough + max_encoded = 100000 + else: + max_encoded = maxlinelen - len(charset) - MISC_LEN - 1 + + for c in header: + # Space may be represented as _ instead of =20 for readability + if c == ' ': + _max_append(quoted, '_', max_encoded) + # These characters can be included verbatim + elif not hqre.match(c): + _max_append(quoted, c, max_encoded) + # Otherwise, replace with hex value like =E2 + else: + _max_append(quoted, "=%02X" % ord(c), max_encoded) + + # Now add the RFC chrome to each encoded chunk and glue the chunks + # together. BAW: should we be able to specify the leading whitespace in + # the joiner? + joiner = eol + ' ' + return joiner.join(['=?%s?q?%s?=' % (charset, line) for line in quoted]) + + + +def encode(body, binary=False, maxlinelen=76, eol=NL): + """Encode with quoted-printable, wrapping at maxlinelen characters. + + If binary is False (the default), end-of-line characters will be converted + to the canonical email end-of-line sequence \\r\\n. Otherwise they will + be left verbatim. + + Each line of encoded text will end with eol, which defaults to "\\n". Set + this to "\\r\\n" if you will be using the result of this function directly + in an email. + + Each line will be wrapped at, at most, maxlinelen characters (defaults to + 76 characters). Long lines will have the `soft linefeed' quoted-printable + character "=" appended to them, so the decoded text will be identical to + the original text. + """ + if not body: + return body + + if not binary: + body = fix_eols(body) + + # BAW: We're accumulating the body text by string concatenation. That + # can't be very efficient, but I don't have time now to rewrite it. It + # just feels like this algorithm could be more efficient. + encoded_body = '' + lineno = -1 + # Preserve line endings here so we can check later to see an eol needs to + # be added to the output later. + lines = body.splitlines(1) + for line in lines: + # But strip off line-endings for processing this line. + if line.endswith(CRLF): + line = line[:-2] + elif line[-1] in CRLF: + line = line[:-1] + + lineno += 1 + encoded_line = '' + prev = None + linelen = len(line) + # Now we need to examine every character to see if it needs to be + # quopri encoded. BAW: again, string concatenation is inefficient. + for j in range(linelen): + c = line[j] + prev = c + if bqre.match(c): + c = quote(c) + elif j+1 == linelen: + # Check for whitespace at end of line; special case + if c not in ' \t': + encoded_line += c + prev = c + continue + # Check to see to see if the line has reached its maximum length + if len(encoded_line) + len(c) >= maxlinelen: + encoded_body += encoded_line + '=' + eol + encoded_line = '' + encoded_line += c + # Now at end of line.. + if prev and prev in ' \t': + # Special case for whitespace at end of file + if lineno + 1 == len(lines): + prev = quote(prev) + if len(encoded_line) + len(prev) > maxlinelen: + encoded_body += encoded_line + '=' + eol + prev + else: + encoded_body += encoded_line + prev + # Just normal whitespace at end of line + else: + encoded_body += encoded_line + prev + '=' + eol + encoded_line = '' + # Now look at the line we just finished and it has a line ending, we + # need to add eol to the end of the line. + if lines[lineno].endswith(CRLF) or lines[lineno][-1] in CRLF: + encoded_body += encoded_line + eol + else: + encoded_body += encoded_line + encoded_line = '' + return encoded_body + + +# For convenience and backwards compatibility w/ standard base64 module +body_encode = encode +encodestring = encode + + + +# BAW: I'm not sure if the intent was for the signature of this function to be +# the same as base64MIME.decode() or not... +def decode(encoded, eol=NL): + """Decode a quoted-printable string. + + Lines are separated with eol, which defaults to \\n. + """ + if not encoded: + return encoded + # BAW: see comment in encode() above. Again, we're building up the + # decoded string with string concatenation, which could be done much more + # efficiently. + decoded = '' + + for line in encoded.splitlines(): + line = line.rstrip() + if not line: + decoded += eol + continue + + i = 0 + n = len(line) + while i < n: + c = line[i] + if c != '=': + decoded += c + i += 1 + # Otherwise, c == "=". Are we at the end of the line? If so, add + # a soft line break. + elif i+1 == n: + i += 1 + continue + # Decode if in form =AB + elif i+2 < n and line[i+1] in hexdigits and line[i+2] in hexdigits: + decoded += unquote(line[i:i+3]) + i += 3 + # Otherwise, not in form =AB, pass literally + else: + decoded += c + i += 1 + + if i == n: + decoded += eol + # Special case if original string did not end with eol + if not encoded.endswith(eol) and decoded.endswith(eol): + decoded = decoded[:-1] + return decoded + + +# For convenience and backwards compatibility w/ standard base64 module +body_decode = decode +decodestring = decode + + + +def _unquote_match(match): + """Turn a match in the form =AB to the ASCII character with value 0xab""" + s = match.group(0) + return unquote(s) + + +# Header decoding is done a bit differently +def header_decode(s): + """Decode a string encoded with RFC 2045 MIME header `Q' encoding. + + This function does not parse a full MIME header value encoded with + quoted-printable (like =?iso-8895-1?q?Hello_World?=) -- please use + the high level email.header class for that functionality. + """ + s = s.replace('_', ' ') + return re.sub(r'=[a-fA-F0-9]{2}', _unquote_match, s) diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/quoprimime.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/quoprimime.pyc new file mode 100644 index 0000000..811f00a Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/quoprimime.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/quoprimime.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/quoprimime.pyo new file mode 100644 index 0000000..811f00a Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/quoprimime.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/__init__.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/__init__.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/__init__.pyc new file mode 100644 index 0000000..8f1c05d Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/__init__.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/__init__.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/__init__.pyo new file mode 100644 index 0000000..8f1c05d Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/__init__.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/PyBanner048.gif b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/PyBanner048.gif new file mode 100644 index 0000000..1a5c87f Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/PyBanner048.gif differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/audiotest.au b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/audiotest.au new file mode 100644 index 0000000..f76b050 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/audiotest.au differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_01.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_01.txt new file mode 100644 index 0000000..7e33bcf --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_01.txt @@ -0,0 +1,19 @@ +Return-Path: +Delivered-To: bbb@zzz.org +Received: by mail.zzz.org (Postfix, from userid 889) + id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +Message-ID: <15090.61304.110929.45684@aaa.zzz.org> +From: bbb@ddd.com (John X. Doe) +To: bbb@zzz.org +Subject: This is a test message +Date: Fri, 4 May 2001 14:05:44 -0400 + + +Hi, + +Do you like this message? + +-Me diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_02.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_02.txt new file mode 100644 index 0000000..43f2480 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_02.txt @@ -0,0 +1,135 @@ +MIME-version: 1.0 +From: ppp-request@zzz.org +Sender: ppp-admin@zzz.org +To: ppp@zzz.org +Subject: Ppp digest, Vol 1 #2 - 5 msgs +Date: Fri, 20 Apr 2001 20:18:00 -0400 (EDT) +X-Mailer: Mailman v2.0.4 +X-Mailman-Version: 2.0.4 +Content-Type: multipart/mixed; boundary="192.168.1.2.889.32614.987812255.500.21814" + +--192.168.1.2.889.32614.987812255.500.21814 +Content-type: text/plain; charset=us-ascii +Content-description: Masthead (Ppp digest, Vol 1 #2) + +Send Ppp mailing list submissions to + ppp@zzz.org + +To subscribe or unsubscribe via the World Wide Web, visit + http://www.zzz.org/mailman/listinfo/ppp +or, via email, send a message with subject or body 'help' to + ppp-request@zzz.org + +You can reach the person managing the list at + ppp-admin@zzz.org + +When replying, please edit your Subject line so it is more specific +than "Re: Contents of Ppp digest..." + + +--192.168.1.2.889.32614.987812255.500.21814 +Content-type: text/plain; charset=us-ascii +Content-description: Today's Topics (5 msgs) + +Today's Topics: + + 1. testing #1 (Barry A. Warsaw) + 2. testing #2 (Barry A. Warsaw) + 3. testing #3 (Barry A. Warsaw) + 4. testing #4 (Barry A. Warsaw) + 5. testing #5 (Barry A. Warsaw) + +--192.168.1.2.889.32614.987812255.500.21814 +Content-Type: multipart/digest; boundary="__--__--" + +--__--__-- + +Message: 1 +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +Date: Fri, 20 Apr 2001 20:16:13 -0400 +To: ppp@zzz.org +From: barry@digicool.com (Barry A. Warsaw) +Subject: [Ppp] testing #1 +Precedence: bulk + + +hello + + +--__--__-- + +Message: 2 +Date: Fri, 20 Apr 2001 20:16:21 -0400 +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +To: ppp@zzz.org +From: barry@digicool.com (Barry A. Warsaw) +Precedence: bulk + + +hello + + +--__--__-- + +Message: 3 +Date: Fri, 20 Apr 2001 20:16:25 -0400 +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +To: ppp@zzz.org +From: barry@digicool.com (Barry A. Warsaw) +Subject: [Ppp] testing #3 +Precedence: bulk + + +hello + + +--__--__-- + +Message: 4 +Date: Fri, 20 Apr 2001 20:16:28 -0400 +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +To: ppp@zzz.org +From: barry@digicool.com (Barry A. Warsaw) +Subject: [Ppp] testing #4 +Precedence: bulk + + +hello + + +--__--__-- + +Message: 5 +Date: Fri, 20 Apr 2001 20:16:32 -0400 +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +To: ppp@zzz.org +From: barry@digicool.com (Barry A. Warsaw) +Subject: [Ppp] testing #5 +Precedence: bulk + + +hello + + + + +--__--__---- +--192.168.1.2.889.32614.987812255.500.21814 +Content-type: text/plain; charset=us-ascii +Content-description: Digest Footer + +_______________________________________________ +Ppp mailing list +Ppp@zzz.org +http://www.zzz.org/mailman/listinfo/ppp + + +--192.168.1.2.889.32614.987812255.500.21814-- + +End of Ppp Digest + diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_03.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_03.txt new file mode 100644 index 0000000..c748ebf --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_03.txt @@ -0,0 +1,16 @@ +Return-Path: +Delivered-To: bbb@zzz.org +Received: by mail.zzz.org (Postfix, from userid 889) + id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) +Message-ID: <15090.61304.110929.45684@aaa.zzz.org> +From: bbb@ddd.com (John X. Doe) +To: bbb@zzz.org +Subject: This is a test message +Date: Fri, 4 May 2001 14:05:44 -0400 + + +Hi, + +Do you like this message? + +-Me diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_04.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_04.txt new file mode 100644 index 0000000..1f633c4 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_04.txt @@ -0,0 +1,37 @@ +Return-Path: +Delivered-To: barry@python.org +Received: by mail.python.org (Postfix, from userid 889) + id C2BF0D37C6; Tue, 11 Sep 2001 00:05:05 -0400 (EDT) +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="h90VIIIKmx" +Content-Transfer-Encoding: 7bit +Message-ID: <15261.36209.358846.118674@anthem.python.org> +From: barry@python.org (Barry A. Warsaw) +To: barry@python.org +Subject: a simple multipart +Date: Tue, 11 Sep 2001 00:05:05 -0400 +X-Mailer: VM 6.95 under 21.4 (patch 4) "Artificial Intelligence" XEmacs Lucid +X-Attribution: BAW +X-Oblique-Strategy: Make a door into a window + + +--h90VIIIKmx +Content-Type: text/plain +Content-Disposition: inline; + filename="msg.txt" +Content-Transfer-Encoding: 7bit + +a simple kind of mirror +to reflect upon our own + +--h90VIIIKmx +Content-Type: text/plain +Content-Disposition: inline; + filename="msg.txt" +Content-Transfer-Encoding: 7bit + +a simple kind of mirror +to reflect upon our own + +--h90VIIIKmx-- + diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_05.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_05.txt new file mode 100644 index 0000000..87d5e9c --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_05.txt @@ -0,0 +1,28 @@ +From: foo +Subject: bar +To: baz +MIME-Version: 1.0 +Content-Type: multipart/report; report-type=delivery-status; + boundary="D1690A7AC1.996856090/mail.example.com" +Message-Id: <20010803162810.0CA8AA7ACC@mail.example.com> + +This is a MIME-encapsulated message. + +--D1690A7AC1.996856090/mail.example.com +Content-Type: text/plain + +Yadda yadda yadda + +--D1690A7AC1.996856090/mail.example.com + +Yadda yadda yadda + +--D1690A7AC1.996856090/mail.example.com +Content-Type: message/rfc822 + +From: nobody@python.org + +Yadda yadda yadda + +--D1690A7AC1.996856090/mail.example.com-- + diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_06.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_06.txt new file mode 100644 index 0000000..69f3a47 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_06.txt @@ -0,0 +1,33 @@ +Return-Path: +Delivered-To: barry@python.org +MIME-Version: 1.0 +Content-Type: message/rfc822 +Content-Description: forwarded message +Content-Transfer-Encoding: 7bit +Message-ID: <15265.9482.641338.555352@python.org> +From: barry@zope.com (Barry A. Warsaw) +Sender: barry@python.org +To: barry@python.org +Subject: forwarded message from Barry A. Warsaw +Date: Thu, 13 Sep 2001 17:28:42 -0400 +X-Mailer: VM 6.95 under 21.4 (patch 4) "Artificial Intelligence" XEmacs Lucid +X-Attribution: BAW +X-Oblique-Strategy: Be dirty +X-Url: http://barry.wooz.org + +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Return-Path: +Delivered-To: barry@python.org +Message-ID: <15265.9468.713530.98441@python.org> +From: barry@zope.com (Barry A. Warsaw) +Sender: barry@python.org +To: barry@python.org +Subject: testing +Date: Thu, 13 Sep 2001 17:28:28 -0400 +X-Mailer: VM 6.95 under 21.4 (patch 4) "Artificial Intelligence" XEmacs Lucid +X-Attribution: BAW +X-Oblique-Strategy: Spectrum analysis +X-Url: http://barry.wooz.org + + diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_07.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_07.txt new file mode 100644 index 0000000..721f3a0 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_07.txt @@ -0,0 +1,83 @@ +MIME-Version: 1.0 +From: Barry +To: Dingus Lovers +Subject: Here is your dingus fish +Date: Fri, 20 Apr 2001 19:35:02 -0400 +Content-Type: multipart/mixed; boundary="BOUNDARY" + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" + +Hi there, + +This is the dingus fish. + +--BOUNDARY +Content-Type: image/gif; name="dingusfish.gif" +Content-Transfer-Encoding: base64 +content-disposition: attachment; filename="dingusfish.gif" + +R0lGODdhAAEAAfAAAP///wAAACwAAAAAAAEAAQAC/oSPqcvtD6OctNqLs968+w+G4kiW5omm6sq2 +7gvH8kzX9o3n+s73/g8MCofEovGITGICTKbyCV0FDNOo9SqpQqpOrJfXzTQj2vD3TGtqL+NtGQ2f +qTXmxzuOd7WXdcc9DyjU53ewFni4s0fGhdiYaEhGBelICTNoV1j5NUnFcrmUqemjNifJVWpaOqaI +oFq3SspZsSraE7sHq3jr1MZqWvi662vxV4tD+pvKW6aLDOCLyur8PDwbanyDeq0N3DctbQYeLDvR +RY6t95m6UB0d3mwIrV7e2VGNvjjffukeJp4w7F65KecGFsTHQGAygOrgrWs1jt28Rc88KESYcGLA +/obvTkH6p+CinWJiJmIMqXGQwH/y4qk0SYjgQTczT3ajKZGfuI0uJ4kkVI/DT5s3/ejkxI0aT4Y+ +YTYgWbImUaXk9nlLmnSh1qJiJFl0OpUqRK4oOy7NyRQtHWofhoYVxkwWXKUSn0YsS+fUV6lhqfYb +6ayd3Z5qQdG1B7bvQzaJjwUV2lixMUZ7JVsOlfjWVr/3NB/uFvnySBN6Dcb6rGwaRM3wsormw5cC +M9NxWy/bWdufudCvy8bOAjXjVVwta/uO21sE5RHBCzNFXtgq9ORtH4eYjVP4Yryo026nvkFmCeyA +B29efV6ravCMK5JwWd5897Qrx7ll38o6iHDZ/rXPR//feevhF4l7wjUGX3xq1eeRfM4RSJGBIV1D +z1gKPkfWag3mVBVvva1RlX5bAJTPR/2YqNtw/FkIYYEi/pIZiAdpcxpoHtmnYYoZtvhUftzdx5ZX +JSKDW405zkGcZzzGZ6KEv4FI224oDmijlEf+xp6MJK5ojY/ASeVUR+wsKRuJ+XFZ5o7ZeEime8t1 +ouUsU6YjF5ZtUihhkGfCdFQLWQFJ3UXxmElfhQnR+eCdcDbkFZp6vTRmj56ApCihn5QGpaToNZmR +n3NVSpZcQpZ2KEONusaiCsKAug0wkQbJSFO+PTSjneGxOuFjPlUk3ovWvdIerjUg9ZGIOtGq/qeX +eCYrrCX+1UPsgTKGGRSbzd5q156d/gpfbJxe66eD5iQKrXj7RGgruGxs62qebBHUKS32CKluCiqZ +qh+pmehmEb71noAUoe5e9Zm17S7773V10pjrtG4CmuurCV/n6zLK5turWNhqOvFXbjhZrMD0YhKe +wR0zOyuvsh6MWrGoIuzvyWu5y1WIFAqmJselypxXh6dKLNOKEB98L88bS2rkNqqlKzCNJp9c0G0j +Gzh0iRrCbHSXmPR643QS+4rWhgFmnSbSuXCjS0xAOWkU2UdLqyuUNfHSFdUouy3bm5i5GnDM3tG8 +doJ4r5tqu3pPbRSVfvs8uJzeNXhp3n4j/tZ42SwH7eaWUUOjc3qFV9453UHTXZfcLH+OeNs5g36x +lBnHvTm7EbMbLeuaLncao8vWCXimfo1o+843Ak6y4ChNeGntvAYvfLK4ezmoyNIbNCLTCXO9ZV3A +E8/s88RczPzDwI4Ob7XZyl7+9Miban29h+tJZPrE21wgvBphDfrrfPdCTPKJD/y98L1rZwHcV6Jq +Zab0metpuNIX/qAFPoz171WUaUb4HAhBSzHuHfjzHb3kha/2Cctis/ORArVHNYfFyYRH2pYIRzic +isVOfPWD1b6mRTqpCRBozzof6UZVvFXRxWIr3GGrEviGYgyPMfahheiSaLs/9QeFu7oZ/ndSY8DD +ya9x+uPed+7mxN2IzIISBOMLFYWVqC3Pew1T2nFuuCiwZS5/v6II10i4t1OJcUH2U9zxKodHsGGv +Oa+zkvNUYUOa/TCCRutF9MzDwdlUMJADTCGSbDQ5OV4PTamDoPEi6Ecc/RF5RWwkcdSXvSOaDWSn +I9LlvubFTQpuc6JKXLcKeb+xdbKRBnwREemXyjg6ME65aJiOuBgrktzykfPLJBKR9ClMavJ62/Ff +BlNIyod9yX9wcSXexnXFpvkrbXk64xsx5Db7wXKP5fSgsvwIMM/9631VLBfkmtbHRXpqmtei52hG +pUwSlo+BASQoeILDOBgREECxBBh5/iYmNsQ9dIv5+OI++QkqdsJPc3uykz5fkM+OraeekcQF7X4n +B5S67za5U967PmooGQhUXfF7afXyCD7ONdRe17QogYjVx38uLwtrS6nhTnm15LQUnu9E2uK6CNI/ +1HOABj0ESwOjut4FEpFQpdNAm4K2LHnDWHNcmKB2ioKBogysVZtMO2nSxUdZ8Yk2kJc7URioLVI0 +YgmtIwZj4LoeKemgnOnbUdGnzZ4Oa6scqiolBGqS6RgWNLu0RMhcaE6rhhU4hiuqFXPAG8fGwTPW +FKeLMtdVmXLSs5YJGF/YeVm7rREMlY3UYE+yCxbaMXX8y15m5zVHq6GOKDMynzII/jdUHdyVqIy0 +ifX2+r/EgtZcvRzSb72gU9ui87M2VecjKildW/aFqaYhKoryUjfB/g4qtyVuc60xFDGmCxwjW+qu +zjuwl2GkOWn66+3QiiEctvd04OVvcCVzjgT7lrkvjVGKKHmmlDUKowSeikb5kK/mJReuWOxONx+s +ULsl+Lqb0CVn0SrVyJ6wt4t6yTeSCafhPhAf0OXn6L60UMxiLolFAtmN35S2Ob1lZpQ1r/n0Qb5D +oQ1zJiRVDgF8N3Q8TYfbi3DyWCy3lT1nxyBs6FT3S2GOzWRlxwKvlRP0RPJA9SjxEy0UoEnkA+M4 +cnzLMJrBGWLFEaaUb5lvpqbq/loOaU5+DFuHPxo82/OZuM8FXG3oVNZhtWpMpb/0Xu5m/LfLhHZQ +7yuVI0MqZ7NE43imC8jH3IwGZlbPm0xkJYs7+2U48hXTsFSMqgGDvai0kLxyynKNT/waj+q1c1tz +GjOpPBgdCSq3UKZxCSsqFIY+O6JbAWGWcV1pwqLyj5sGqCF1xb1F3varUWqrJv6cN3PrUXzijtfZ +FshpBL3Xwr4GIPvU2N8EjrJgS1zl21rbXQMXeXc5jjFyrhpCzijSv/RQtyPSzHCFMhlME95fHglt +pRsX+dfSQjUeHAlpWzJ5iOo79Ldnaxai6bXTcGO3fp07ri7HLEmXXPlYi8bv/qVxvNcdra6m7Rlb +6JBTb5fd66VhFRjGArh2n7R1rDW4P5NOT9K0I183T2scYkeZ3q/VFyLb09U9ajzXBS8Kgkhc4mBS +kYY9cy3Vy9lUnuNJH8HGIclUilwnBtjUOH0gteGOZ4c/XNrhXLSYDyxfnD8z1pDy7rYRvDolhnbe +UMzxCZUs40s6s7UIvBnLgc0+vKuOkIXeOrDymlp+Zxra4MZLBbVrqD/jTJ597pDmnw5c4+DbyB88 +9Cg9DodYcSuMZT/114pptqc/EuTjRPvH/z5slzI3tluOEBBLqOXLOX+0I5929tO97wkvl/atCz+y +xJrdwteW2FNW/NSmBP+f/maYtVs/bYyBC7Ox3jsYZHL05CIrBa/nS+b3bHfiYm4Ueil1YZZSgAUI +fFZ1dxUmeA2oQRQ3RuGXNGLFV9/XbGFGPV6kfzk1TBBCd+izc7q1H+OHMJwmaBX2IQNYVAKHYepV +SSGCe6CnbYHHETKGNe43EDvFgZr0gB/nVHPHZ80VV1ojOiI3XDvYIkl4ayo4bxQIgrFXWTvBI0nH +VElWMuw2aLUWCRHHf8ymVCHjFlJnOSojfevCYyyyZDH0IcvHhrsnQ5O1OsWzONuVVKIxSxiFZ/tR +fKDAf6xFTnw4O9Qig2VCfW2hJQrmMOuHW0W3dLQmCMO2ccdUd/xyfflH/olTiHZVdGwb8nIwRzSE +J15jFlOJuBZBZ4CiyHyd2IFylFlB+HgHhYabhWOGwYO1ZH/Og1dtQlFMk352CGRSIFTapnWQEUtN +l4zv8S0aaCFDyGCBqDUxZYpxGHX01y/JuH1xhn7TOCnNCI4eKDs5WGX4R425F4vF1o3BJ4vO0otq +I3rimI7jJY1jISqnBxknCIvruF83mF5wN4X7qGLIhR8A2Vg0yFERSIXn9Vv3GHy3Vj/WIkKddlYi +yIMv2I/VMjTLpW7pt05SWIZR0RPyxpB4SIUM9lBPGBl0GC7oSEEwRYLe4pJpZY2P0zbI1n+Oc44w +qY3PUnmF0ixjVpDD/mJ9wpOBGTVgXlaCaZiPcIWK5NiKBIiPdGaQ0TWGvAiG7nMchdZb7Vgf8zNi +MuMyzRdy/lePe9iC4TRx7WhhOQI/QiSVNAmAa2lT/piFbuh7ofJoYSZzrSZ1bvmWw3eN2nKUPVky +uPN5/VRfohRd0VYZoqhKIlU6TXYhJxmPUIloAwc1bPmHEpaZYZORHNlXUJM07hATwHR8MJYqkwWR +WaIezFhxSFlc8/Fq82hEnpeRozg3ULhhr9lAGtVEkCg5ZNRuuVleBPaZadhG0ZgkyPmDOTOKzViM +YgOcpukKqQcbjAWS0IleQ2ROjdh6A+md1qWdBRSX7iSYgFRTtRmBpJioieXJiHfJiMGIR9fJOn8I +MSfXYhspn4ooSa2mSAj4n+8Bmg03fBJZoPOJgsVZRxu1oOMRPXYYjdqjihFaEoZpXBREanuJoRI6 +cibFinq4ngUKh/wQd/H5ofYCZ0HJXR62opZFaAT0iFIZo4DIiUojkjeqKiuoZirKo5Y1a7AWckGa +BkuYoD5lpDK6eUs6CkDqpETwl1EqpfhJpVeKpVl6EgUAADs= + +--BOUNDARY-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_08.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_08.txt new file mode 100644 index 0000000..b563083 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_08.txt @@ -0,0 +1,24 @@ +MIME-Version: 1.0 +From: Barry Warsaw +To: Dingus Lovers +Subject: Lyrics +Date: Fri, 20 Apr 2001 19:35:02 -0400 +Content-Type: multipart/mixed; boundary="BOUNDARY" + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" + + +--BOUNDARY +Content-Type: text/html; charset="iso-8859-1" + + +--BOUNDARY +Content-Type: text/plain; charset="iso-8859-2" + + +--BOUNDARY +Content-Type: text/plain; charset="koi8-r" + + +--BOUNDARY-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_09.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_09.txt new file mode 100644 index 0000000..575c4c2 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_09.txt @@ -0,0 +1,24 @@ +MIME-Version: 1.0 +From: Barry Warsaw +To: Dingus Lovers +Subject: Lyrics +Date: Fri, 20 Apr 2001 19:35:02 -0400 +Content-Type: multipart/mixed; boundary="BOUNDARY" + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" + + +--BOUNDARY +Content-Type: text/html; charset="iso-8859-1" + + +--BOUNDARY +Content-Type: text/plain + + +--BOUNDARY +Content-Type: text/plain; charset="koi8-r" + + +--BOUNDARY-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_10.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_10.txt new file mode 100644 index 0000000..0790396 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_10.txt @@ -0,0 +1,39 @@ +MIME-Version: 1.0 +From: Barry Warsaw +To: Dingus Lovers +Subject: Lyrics +Date: Fri, 20 Apr 2001 19:35:02 -0400 +Content-Type: multipart/mixed; boundary="BOUNDARY" + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" +Content-Transfer-Encoding: 7bit + +This is a 7bit encoded message. + +--BOUNDARY +Content-Type: text/html; charset="iso-8859-1" +Content-Transfer-Encoding: Quoted-Printable + +=A1This is a Quoted Printable encoded message! + +--BOUNDARY +Content-Type: text/plain; charset="iso-8859-1" +Content-Transfer-Encoding: Base64 + +VGhpcyBpcyBhIEJhc2U2NCBlbmNvZGVkIG1lc3NhZ2Uu + + +--BOUNDARY +Content-Type: text/plain; charset="iso-8859-1" +Content-Transfer-Encoding: Base64 + +VGhpcyBpcyBhIEJhc2U2NCBlbmNvZGVkIG1lc3NhZ2UuCg== + + +--BOUNDARY +Content-Type: text/plain; charset="iso-8859-1" + +This has no Content-Transfer-Encoding: header. + +--BOUNDARY-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_11.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_11.txt new file mode 100644 index 0000000..8f7f199 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_11.txt @@ -0,0 +1,7 @@ +Content-Type: message/rfc822 +MIME-Version: 1.0 +Subject: The enclosing message + +Subject: An enclosed message + +Here is the body of the message. diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_12.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_12.txt new file mode 100644 index 0000000..4bec8d9 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_12.txt @@ -0,0 +1,36 @@ +MIME-Version: 1.0 +From: Barry Warsaw +To: Dingus Lovers +Subject: Lyrics +Date: Fri, 20 Apr 2001 19:35:02 -0400 +Content-Type: multipart/mixed; boundary="BOUNDARY" + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" + + +--BOUNDARY +Content-Type: text/html; charset="iso-8859-1" + + +--BOUNDARY +Content-Type: multipart/mixed; boundary="ANOTHER" + +--ANOTHER +Content-Type: text/plain; charset="iso-8859-2" + + +--ANOTHER +Content-Type: text/plain; charset="iso-8859-3" + +--ANOTHER-- + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" + + +--BOUNDARY +Content-Type: text/plain; charset="koi8-r" + + +--BOUNDARY-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_12a.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_12a.txt new file mode 100644 index 0000000..e94224e --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_12a.txt @@ -0,0 +1,38 @@ +MIME-Version: 1.0 +From: Barry Warsaw +To: Dingus Lovers +Subject: Lyrics +Date: Fri, 20 Apr 2001 19:35:02 -0400 +Content-Type: multipart/mixed; boundary="BOUNDARY" + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" + + +--BOUNDARY +Content-Type: text/html; charset="iso-8859-1" + + +--BOUNDARY +Content-Type: multipart/mixed; boundary="ANOTHER" + +--ANOTHER +Content-Type: text/plain; charset="iso-8859-2" + + +--ANOTHER +Content-Type: text/plain; charset="iso-8859-3" + + +--ANOTHER-- + + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" + + +--BOUNDARY +Content-Type: text/plain; charset="koi8-r" + + +--BOUNDARY-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_13.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_13.txt new file mode 100644 index 0000000..8e6d52d --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_13.txt @@ -0,0 +1,94 @@ +MIME-Version: 1.0 +From: Barry +To: Dingus Lovers +Subject: Here is your dingus fish +Date: Fri, 20 Apr 2001 19:35:02 -0400 +Content-Type: multipart/mixed; boundary="OUTER" + +--OUTER +Content-Type: text/plain; charset="us-ascii" + +A text/plain part + +--OUTER +Content-Type: multipart/mixed; boundary=BOUNDARY + + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" + +Hi there, + +This is the dingus fish. + +--BOUNDARY +Content-Type: image/gif; name="dingusfish.gif" +Content-Transfer-Encoding: base64 +content-disposition: attachment; filename="dingusfish.gif" + +R0lGODdhAAEAAfAAAP///wAAACwAAAAAAAEAAQAC/oSPqcvtD6OctNqLs968+w+G4kiW5omm6sq2 +7gvH8kzX9o3n+s73/g8MCofEovGITGICTKbyCV0FDNOo9SqpQqpOrJfXzTQj2vD3TGtqL+NtGQ2f +qTXmxzuOd7WXdcc9DyjU53ewFni4s0fGhdiYaEhGBelICTNoV1j5NUnFcrmUqemjNifJVWpaOqaI +oFq3SspZsSraE7sHq3jr1MZqWvi662vxV4tD+pvKW6aLDOCLyur8PDwbanyDeq0N3DctbQYeLDvR +RY6t95m6UB0d3mwIrV7e2VGNvjjffukeJp4w7F65KecGFsTHQGAygOrgrWs1jt28Rc88KESYcGLA +/obvTkH6p+CinWJiJmIMqXGQwH/y4qk0SYjgQTczT3ajKZGfuI0uJ4kkVI/DT5s3/ejkxI0aT4Y+ +YTYgWbImUaXk9nlLmnSh1qJiJFl0OpUqRK4oOy7NyRQtHWofhoYVxkwWXKUSn0YsS+fUV6lhqfYb +6ayd3Z5qQdG1B7bvQzaJjwUV2lixMUZ7JVsOlfjWVr/3NB/uFvnySBN6Dcb6rGwaRM3wsormw5cC +M9NxWy/bWdufudCvy8bOAjXjVVwta/uO21sE5RHBCzNFXtgq9ORtH4eYjVP4Yryo026nvkFmCeyA +B29efV6ravCMK5JwWd5897Qrx7ll38o6iHDZ/rXPR//feevhF4l7wjUGX3xq1eeRfM4RSJGBIV1D +z1gKPkfWag3mVBVvva1RlX5bAJTPR/2YqNtw/FkIYYEi/pIZiAdpcxpoHtmnYYoZtvhUftzdx5ZX +JSKDW405zkGcZzzGZ6KEv4FI224oDmijlEf+xp6MJK5ojY/ASeVUR+wsKRuJ+XFZ5o7ZeEime8t1 +ouUsU6YjF5ZtUihhkGfCdFQLWQFJ3UXxmElfhQnR+eCdcDbkFZp6vTRmj56ApCihn5QGpaToNZmR +n3NVSpZcQpZ2KEONusaiCsKAug0wkQbJSFO+PTSjneGxOuFjPlUk3ovWvdIerjUg9ZGIOtGq/qeX +eCYrrCX+1UPsgTKGGRSbzd5q156d/gpfbJxe66eD5iQKrXj7RGgruGxs62qebBHUKS32CKluCiqZ +qh+pmehmEb71noAUoe5e9Zm17S7773V10pjrtG4CmuurCV/n6zLK5turWNhqOvFXbjhZrMD0YhKe +wR0zOyuvsh6MWrGoIuzvyWu5y1WIFAqmJselypxXh6dKLNOKEB98L88bS2rkNqqlKzCNJp9c0G0j +Gzh0iRrCbHSXmPR643QS+4rWhgFmnSbSuXCjS0xAOWkU2UdLqyuUNfHSFdUouy3bm5i5GnDM3tG8 +doJ4r5tqu3pPbRSVfvs8uJzeNXhp3n4j/tZ42SwH7eaWUUOjc3qFV9453UHTXZfcLH+OeNs5g36x +lBnHvTm7EbMbLeuaLncao8vWCXimfo1o+843Ak6y4ChNeGntvAYvfLK4ezmoyNIbNCLTCXO9ZV3A +E8/s88RczPzDwI4Ob7XZyl7+9Miban29h+tJZPrE21wgvBphDfrrfPdCTPKJD/y98L1rZwHcV6Jq +Zab0metpuNIX/qAFPoz171WUaUb4HAhBSzHuHfjzHb3kha/2Cctis/ORArVHNYfFyYRH2pYIRzic +isVOfPWD1b6mRTqpCRBozzof6UZVvFXRxWIr3GGrEviGYgyPMfahheiSaLs/9QeFu7oZ/ndSY8DD +ya9x+uPed+7mxN2IzIISBOMLFYWVqC3Pew1T2nFuuCiwZS5/v6II10i4t1OJcUH2U9zxKodHsGGv +Oa+zkvNUYUOa/TCCRutF9MzDwdlUMJADTCGSbDQ5OV4PTamDoPEi6Ecc/RF5RWwkcdSXvSOaDWSn +I9LlvubFTQpuc6JKXLcKeb+xdbKRBnwREemXyjg6ME65aJiOuBgrktzykfPLJBKR9ClMavJ62/Ff +BlNIyod9yX9wcSXexnXFpvkrbXk64xsx5Db7wXKP5fSgsvwIMM/9631VLBfkmtbHRXpqmtei52hG +pUwSlo+BASQoeILDOBgREECxBBh5/iYmNsQ9dIv5+OI++QkqdsJPc3uykz5fkM+OraeekcQF7X4n +B5S67za5U967PmooGQhUXfF7afXyCD7ONdRe17QogYjVx38uLwtrS6nhTnm15LQUnu9E2uK6CNI/ +1HOABj0ESwOjut4FEpFQpdNAm4K2LHnDWHNcmKB2ioKBogysVZtMO2nSxUdZ8Yk2kJc7URioLVI0 +YgmtIwZj4LoeKemgnOnbUdGnzZ4Oa6scqiolBGqS6RgWNLu0RMhcaE6rhhU4hiuqFXPAG8fGwTPW +FKeLMtdVmXLSs5YJGF/YeVm7rREMlY3UYE+yCxbaMXX8y15m5zVHq6GOKDMynzII/jdUHdyVqIy0 +ifX2+r/EgtZcvRzSb72gU9ui87M2VecjKildW/aFqaYhKoryUjfB/g4qtyVuc60xFDGmCxwjW+qu +zjuwl2GkOWn66+3QiiEctvd04OVvcCVzjgT7lrkvjVGKKHmmlDUKowSeikb5kK/mJReuWOxONx+s +ULsl+Lqb0CVn0SrVyJ6wt4t6yTeSCafhPhAf0OXn6L60UMxiLolFAtmN35S2Ob1lZpQ1r/n0Qb5D +oQ1zJiRVDgF8N3Q8TYfbi3DyWCy3lT1nxyBs6FT3S2GOzWRlxwKvlRP0RPJA9SjxEy0UoEnkA+M4 +cnzLMJrBGWLFEaaUb5lvpqbq/loOaU5+DFuHPxo82/OZuM8FXG3oVNZhtWpMpb/0Xu5m/LfLhHZQ +7yuVI0MqZ7NE43imC8jH3IwGZlbPm0xkJYs7+2U48hXTsFSMqgGDvai0kLxyynKNT/waj+q1c1tz +GjOpPBgdCSq3UKZxCSsqFIY+O6JbAWGWcV1pwqLyj5sGqCF1xb1F3varUWqrJv6cN3PrUXzijtfZ +FshpBL3Xwr4GIPvU2N8EjrJgS1zl21rbXQMXeXc5jjFyrhpCzijSv/RQtyPSzHCFMhlME95fHglt +pRsX+dfSQjUeHAlpWzJ5iOo79Ldnaxai6bXTcGO3fp07ri7HLEmXXPlYi8bv/qVxvNcdra6m7Rlb +6JBTb5fd66VhFRjGArh2n7R1rDW4P5NOT9K0I183T2scYkeZ3q/VFyLb09U9ajzXBS8Kgkhc4mBS +kYY9cy3Vy9lUnuNJH8HGIclUilwnBtjUOH0gteGOZ4c/XNrhXLSYDyxfnD8z1pDy7rYRvDolhnbe +UMzxCZUs40s6s7UIvBnLgc0+vKuOkIXeOrDymlp+Zxra4MZLBbVrqD/jTJ597pDmnw5c4+DbyB88 +9Cg9DodYcSuMZT/114pptqc/EuTjRPvH/z5slzI3tluOEBBLqOXLOX+0I5929tO97wkvl/atCz+y +xJrdwteW2FNW/NSmBP+f/maYtVs/bYyBC7Ox3jsYZHL05CIrBa/nS+b3bHfiYm4Ueil1YZZSgAUI +fFZ1dxUmeA2oQRQ3RuGXNGLFV9/XbGFGPV6kfzk1TBBCd+izc7q1H+OHMJwmaBX2IQNYVAKHYepV +SSGCe6CnbYHHETKGNe43EDvFgZr0gB/nVHPHZ80VV1ojOiI3XDvYIkl4ayo4bxQIgrFXWTvBI0nH +VElWMuw2aLUWCRHHf8ymVCHjFlJnOSojfevCYyyyZDH0IcvHhrsnQ5O1OsWzONuVVKIxSxiFZ/tR +fKDAf6xFTnw4O9Qig2VCfW2hJQrmMOuHW0W3dLQmCMO2ccdUd/xyfflH/olTiHZVdGwb8nIwRzSE +J15jFlOJuBZBZ4CiyHyd2IFylFlB+HgHhYabhWOGwYO1ZH/Og1dtQlFMk352CGRSIFTapnWQEUtN +l4zv8S0aaCFDyGCBqDUxZYpxGHX01y/JuH1xhn7TOCnNCI4eKDs5WGX4R425F4vF1o3BJ4vO0otq +I3rimI7jJY1jISqnBxknCIvruF83mF5wN4X7qGLIhR8A2Vg0yFERSIXn9Vv3GHy3Vj/WIkKddlYi +yIMv2I/VMjTLpW7pt05SWIZR0RPyxpB4SIUM9lBPGBl0GC7oSEEwRYLe4pJpZY2P0zbI1n+Oc44w +qY3PUnmF0ixjVpDD/mJ9wpOBGTVgXlaCaZiPcIWK5NiKBIiPdGaQ0TWGvAiG7nMchdZb7Vgf8zNi +MuMyzRdy/lePe9iC4TRx7WhhOQI/QiSVNAmAa2lT/piFbuh7ofJoYSZzrSZ1bvmWw3eN2nKUPVky +uPN5/VRfohRd0VYZoqhKIlU6TXYhJxmPUIloAwc1bPmHEpaZYZORHNlXUJM07hATwHR8MJYqkwWR +WaIezFhxSFlc8/Fq82hEnpeRozg3ULhhr9lAGtVEkCg5ZNRuuVleBPaZadhG0ZgkyPmDOTOKzViM +YgOcpukKqQcbjAWS0IleQ2ROjdh6A+md1qWdBRSX7iSYgFRTtRmBpJioieXJiHfJiMGIR9fJOn8I +MSfXYhspn4ooSa2mSAj4n+8Bmg03fBJZoPOJgsVZRxu1oOMRPXYYjdqjihFaEoZpXBREanuJoRI6 +cibFinq4ngUKh/wQd/H5ofYCZ0HJXR62opZFaAT0iFIZo4DIiUojkjeqKiuoZirKo5Y1a7AWckGa +BkuYoD5lpDK6eUs6CkDqpETwl1EqpfhJpVeKpVl6EgUAADs= + +--BOUNDARY-- + +--OUTER-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_14.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_14.txt new file mode 100644 index 0000000..5d98d2f --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_14.txt @@ -0,0 +1,23 @@ +Return-Path: +Delivered-To: bbb@zzz.org +Received: by mail.zzz.org (Postfix, from userid 889) + id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) +MIME-Version: 1.0 +Content-Type: text; charset=us-ascii +Content-Transfer-Encoding: 7bit +Message-ID: <15090.61304.110929.45684@aaa.zzz.org> +From: bbb@ddd.com (John X. Doe) +To: bbb@zzz.org +Subject: This is a test message +Date: Fri, 4 May 2001 14:05:44 -0400 + + +Hi, + +I'm sorry but I'm using a drainbread ISP, which although big and +wealthy can't seem to generate standard compliant email. :( + +This message has a Content-Type: header with no subtype. I hope you +can still read it. + +-Me diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_15.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_15.txt new file mode 100644 index 0000000..33b8487 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_15.txt @@ -0,0 +1,52 @@ +Return-Path: +Received: from fepD.post.tele.dk (195.41.46.149) by mail.groupcare.dk (LSMTP for Windows NT v1.1b) with SMTP id <0.0014F8A2@mail.groupcare.dk>; Mon, 30 Apr 2001 12:17:50 +0200 +User-Agent: Microsoft-Outlook-Express-Macintosh-Edition/5.02.2106 +Subject: XX +From: xx@xx.dk +To: XX +Message-ID: +Mime-version: 1.0 +Content-type: multipart/mixed; + boundary="MS_Mac_OE_3071477847_720252_MIME_Part" + +> Denne meddelelse er i MIME-format. Da dit postl¾sningsprogram ikke forstŒr dette format, kan del af eller hele meddelelsen v¾re ul¾selig. + +--MS_Mac_OE_3071477847_720252_MIME_Part +Content-type: multipart/alternative; + boundary="MS_Mac_OE_3071477847_720252_MIME_Part" + + +--MS_Mac_OE_3071477847_720252_MIME_Part +Content-type: text/plain; charset="ISO-8859-1" +Content-transfer-encoding: quoted-printable + +Some removed test. + +--MS_Mac_OE_3071477847_720252_MIME_Part +Content-type: text/html; charset="ISO-8859-1" +Content-transfer-encoding: quoted-printable + + + +Some removed HTML + + +Some removed text. + + + + +--MS_Mac_OE_3071477847_720252_MIME_Part-- + + +--MS_Mac_OE_3071477847_720252_MIME_Part +Content-type: image/gif; name="xx.gif"; + x-mac-creator="6F676C65"; + x-mac-type="47494666" +Content-disposition: attachment +Content-transfer-encoding: base64 + +Some removed base64 encoded chars. + +--MS_Mac_OE_3071477847_720252_MIME_Part-- + diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_16.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_16.txt new file mode 100644 index 0000000..56167e9 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_16.txt @@ -0,0 +1,123 @@ +Return-Path: <> +Delivered-To: scr-admin@socal-raves.org +Received: from cougar.noc.ucla.edu (cougar.noc.ucla.edu [169.232.10.18]) + by babylon.socal-raves.org (Postfix) with ESMTP id CCC2C51B84 + for ; Sun, 23 Sep 2001 20:13:54 -0700 (PDT) +Received: from sims-ms-daemon by cougar.noc.ucla.edu + (Sun Internet Mail Server sims.3.5.2000.03.23.18.03.p10) + id <0GK500B01D0B8Y@cougar.noc.ucla.edu> for scr-admin@socal-raves.org; Sun, + 23 Sep 2001 20:14:35 -0700 (PDT) +Received: from cougar.noc.ucla.edu + (Sun Internet Mail Server sims.3.5.2000.03.23.18.03.p10) + id <0GK500B01D0B8X@cougar.noc.ucla.edu>; Sun, 23 Sep 2001 20:14:35 -0700 (PDT) +Date: Sun, 23 Sep 2001 20:14:35 -0700 (PDT) +From: Internet Mail Delivery +Subject: Delivery Notification: Delivery has failed +To: scr-admin@socal-raves.org +Message-id: <0GK500B04D0B8X@cougar.noc.ucla.edu> +MIME-version: 1.0 +Sender: scr-owner@socal-raves.org +Errors-To: scr-owner@socal-raves.org +X-BeenThere: scr@socal-raves.org +X-Mailman-Version: 2.1a3 +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: SoCal-Raves +List-Unsubscribe: , + +List-Archive: +Content-Type: multipart/report; boundary="Boundary_(ID_PGS2F2a+z+/jL7hupKgRhA)" + + +--Boundary_(ID_PGS2F2a+z+/jL7hupKgRhA) +Content-type: text/plain; charset=ISO-8859-1 + +This report relates to a message you sent with the following header fields: + + Message-id: <002001c144a6$8752e060$56104586@oxy.edu> + Date: Sun, 23 Sep 2001 20:10:55 -0700 + From: "Ian T. Henry" + To: SoCal Raves + Subject: [scr] yeah for Ians!! + +Your message cannot be delivered to the following recipients: + + Recipient address: jangel1@cougar.noc.ucla.edu + Reason: recipient reached disk quota + + +--Boundary_(ID_PGS2F2a+z+/jL7hupKgRhA) +Content-type: message/DELIVERY-STATUS + +Original-envelope-id: 0GK500B4HD0888@cougar.noc.ucla.edu +Reporting-MTA: dns; cougar.noc.ucla.edu + +Action: failed +Status: 5.0.0 (recipient reached disk quota) +Original-recipient: rfc822;jangel1@cougar.noc.ucla.edu +Final-recipient: rfc822;jangel1@cougar.noc.ucla.edu + +--Boundary_(ID_PGS2F2a+z+/jL7hupKgRhA) +Content-type: MESSAGE/RFC822 + +Return-path: scr-admin@socal-raves.org +Received: from sims-ms-daemon by cougar.noc.ucla.edu + (Sun Internet Mail Server sims.3.5.2000.03.23.18.03.p10) + id <0GK500B01D0B8X@cougar.noc.ucla.edu>; Sun, 23 Sep 2001 20:14:35 -0700 (PDT) +Received: from panther.noc.ucla.edu by cougar.noc.ucla.edu + (Sun Internet Mail Server sims.3.5.2000.03.23.18.03.p10) + with ESMTP id <0GK500B4GD0888@cougar.noc.ucla.edu> for jangel1@sims-ms-daemon; + Sun, 23 Sep 2001 20:14:33 -0700 (PDT) +Received: from babylon.socal-raves.org + (ip-209-85-222-117.dreamhost.com [209.85.222.117]) + by panther.noc.ucla.edu (8.9.1a/8.9.1) with ESMTP id UAA09793 for + ; Sun, 23 Sep 2001 20:14:32 -0700 (PDT) +Received: from babylon (localhost [127.0.0.1]) by babylon.socal-raves.org + (Postfix) with ESMTP id D3B2951B70; Sun, 23 Sep 2001 20:13:47 -0700 (PDT) +Received: by babylon.socal-raves.org (Postfix, from userid 60001) + id A611F51B82; Sun, 23 Sep 2001 20:13:46 -0700 (PDT) +Received: from tiger.cc.oxy.edu (tiger.cc.oxy.edu [134.69.3.112]) + by babylon.socal-raves.org (Postfix) with ESMTP id ADA7351B70 for + ; Sun, 23 Sep 2001 20:13:44 -0700 (PDT) +Received: from ent (n16h86.dhcp.oxy.edu [134.69.16.86]) + by tiger.cc.oxy.edu (8.8.8/8.8.8) with SMTP id UAA08100 for + ; Sun, 23 Sep 2001 20:14:24 -0700 (PDT) +Date: Sun, 23 Sep 2001 20:10:55 -0700 +From: "Ian T. Henry" +Subject: [scr] yeah for Ians!! +Sender: scr-admin@socal-raves.org +To: SoCal Raves +Errors-to: scr-admin@socal-raves.org +Message-id: <002001c144a6$8752e060$56104586@oxy.edu> +MIME-version: 1.0 +X-Mailer: Microsoft Outlook Express 5.50.4522.1200 +Content-type: text/plain; charset=us-ascii +Precedence: bulk +Delivered-to: scr-post@babylon.socal-raves.org +Delivered-to: scr@socal-raves.org +X-Converted-To-Plain-Text: from multipart/alternative by demime 0.98e +X-Converted-To-Plain-Text: Alternative section used was text/plain +X-BeenThere: scr@socal-raves.org +X-Mailman-Version: 2.1a3 +List-Help: +List-Post: +List-Subscribe: , + +List-Id: SoCal-Raves +List-Unsubscribe: , + +List-Archive: + +I always love to find more Ian's that are over 3 years old!! + +Ian +_______________________________________________ +For event info, list questions, or to unsubscribe, see http://www.socal-raves.org/ + + + +--Boundary_(ID_PGS2F2a+z+/jL7hupKgRhA)-- + diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_17.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_17.txt new file mode 100644 index 0000000..8d86e41 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_17.txt @@ -0,0 +1,12 @@ +MIME-Version: 1.0 +From: Barry +To: Dingus Lovers +Subject: Here is your dingus fish +Date: Fri, 20 Apr 2001 19:35:02 -0400 +Content-Type: multipart/mixed; boundary="BOUNDARY" + +Hi there, + +This is the dingus fish. + +[Non-text (image/gif) part of message omitted, filename dingusfish.gif] diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_18.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_18.txt new file mode 100644 index 0000000..f9f4904 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_18.txt @@ -0,0 +1,6 @@ +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Foobar-Spoink-Defrobnit: wasnipoop; giraffes="very-long-necked-animals"; + spooge="yummy"; hippos="gargantuan"; marshmallows="gooey" + diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_19.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_19.txt new file mode 100644 index 0000000..49bf7fc --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_19.txt @@ -0,0 +1,43 @@ +Send Ppp mailing list submissions to + ppp@zzz.org + +To subscribe or unsubscribe via the World Wide Web, visit + http://www.zzz.org/mailman/listinfo/ppp +or, via email, send a message with subject or body 'help' to + ppp-request@zzz.org + +You can reach the person managing the list at + ppp-admin@zzz.org + +When replying, please edit your Subject line so it is more specific +than "Re: Contents of Ppp digest..." + +Today's Topics: + + 1. testing #1 (Barry A. Warsaw) + 2. testing #2 (Barry A. Warsaw) + 3. testing #3 (Barry A. Warsaw) + 4. testing #4 (Barry A. Warsaw) + 5. testing #5 (Barry A. Warsaw) + +hello + + +hello + + +hello + + +hello + + +hello + + + +_______________________________________________ +Ppp mailing list +Ppp@zzz.org +http://www.zzz.org/mailman/listinfo/ppp + diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_20.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_20.txt new file mode 100644 index 0000000..1a6a887 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_20.txt @@ -0,0 +1,22 @@ +Return-Path: +Delivered-To: bbb@zzz.org +Received: by mail.zzz.org (Postfix, from userid 889) + id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +Message-ID: <15090.61304.110929.45684@aaa.zzz.org> +From: bbb@ddd.com (John X. Doe) +To: bbb@zzz.org +Cc: ccc@zzz.org +CC: ddd@zzz.org +cc: eee@zzz.org +Subject: This is a test message +Date: Fri, 4 May 2001 14:05:44 -0400 + + +Hi, + +Do you like this message? + +-Me diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_21.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_21.txt new file mode 100644 index 0000000..23590b2 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_21.txt @@ -0,0 +1,20 @@ +From: aperson@dom.ain +To: bperson@dom.ain +Subject: Test +Content-Type: multipart/mixed; boundary="BOUNDARY" + +MIME message +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +One +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +Two +--BOUNDARY-- +End of MIME message diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_22.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_22.txt new file mode 100644 index 0000000..af9de5f --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_22.txt @@ -0,0 +1,46 @@ +Mime-Version: 1.0 +Message-Id: +Date: Tue, 16 Oct 2001 13:59:25 +0300 +To: a@example.com +From: b@example.com +Content-Type: multipart/mixed; boundary="============_-1208892523==_============" + +--============_-1208892523==_============ +Content-Type: text/plain; charset="us-ascii" ; format="flowed" + +Text text text. +--============_-1208892523==_============ +Content-Id: +Content-Type: image/jpeg; name="wibble.JPG" + ; x-mac-type="4A504547" + ; x-mac-creator="474B4F4E" +Content-Disposition: attachment; filename="wibble.JPG" +Content-Transfer-Encoding: base64 + +/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB +AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAALCAXABIEBAREA +g6bCjjw/pIZSjO6FWFpldjySOmCNrO7DBZibUXhTwtCixw+GtAijVdqxxaPp0aKvmGXa +qrbBQvms0mAMeYS/3iTV1dG0hHaRNK01XblnWxtVdjkHLMIgTyqnk9VB7CrP2KzIINpa +4O7I+zxYO9WV8jZg71Zlb+8rMDkEirAVQFAUAKAFAAAUAYAUDgADgY6DjpRtXj5RxjHA +4wQRj0wQCMdCAewpaKKK/9k= +--============_-1208892523==_============ +Content-Id: +Content-Type: image/jpeg; name="wibble2.JPG" + ; x-mac-type="4A504547" + ; x-mac-creator="474B4F4E" +Content-Disposition: attachment; filename="wibble2.JPG" +Content-Transfer-Encoding: base64 + +/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB +AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAALCAXABJ0BAREA +/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA +W6NFJJBEkU10kKGTcWMDwxuU+0JHvk8qAtOpNwqSR0n8c3BlDyXHlqsUltHEiTvdXLxR +7vMiGDNJAJWkAMk8ZkCFp5G2oo5W++INrbQtNfTQxJAuXlupz9oS4d5Y1W+E2XlWZJJE +Y7LWYQxTLE1zuMbfBPxw8X2fibVdIbSbI6nLZxX635t9TjtYreWR7WGKJTLJFFKSlozO +0ShxIXM43uC3/9k= +--============_-1208892523==_============ +Content-Type: text/plain; charset="us-ascii" ; format="flowed" + +Text text text. +--============_-1208892523==_============-- + diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_23.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_23.txt new file mode 100644 index 0000000..bb2e8ec --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_23.txt @@ -0,0 +1,8 @@ +From: aperson@dom.ain +Content-Type: multipart/mixed; boundary="BOUNDARY" + +--BOUNDARY +Content-Type: text/plain + +A message part +--BOUNDARY-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_24.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_24.txt new file mode 100644 index 0000000..4e52339 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_24.txt @@ -0,0 +1,10 @@ +Content-Type: multipart/mixed; boundary="BOUNDARY" +MIME-Version: 1.0 +Subject: A subject +To: aperson@dom.ain +From: bperson@dom.ain + +--BOUNDARY + + +--BOUNDARY-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_25.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_25.txt new file mode 100644 index 0000000..9e35275 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_25.txt @@ -0,0 +1,117 @@ +From MAILER-DAEMON Fri Apr 06 16:46:09 2001 +Received: from [204.245.199.98] (helo=zinfandel.lacita.com) + by www.linux.org.uk with esmtp (Exim 3.13 #1) + id 14lYR6-0008Iv-00 + for linuxuser-admin@www.linux.org.uk; Fri, 06 Apr 2001 16:46:09 +0100 +Received: from localhost (localhost) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with internal id JAB03225; Fri, 6 Apr 2001 09:23:06 -0800 (GMT-0800) +Date: Fri, 6 Apr 2001 09:23:06 -0800 (GMT-0800) +From: Mail Delivery Subsystem +Subject: Returned mail: Too many hops 19 (17 max): from via [199.164.235.226], to +Message-Id: <200104061723.JAB03225@zinfandel.lacita.com> +To: +To: postmaster@zinfandel.lacita.com +MIME-Version: 1.0 +Content-Type: multipart/report; report-type=delivery-status; + bo +Auto-Submitted: auto-generated (failure) + +This is a MIME-encapsulated message + +--JAB03225.986577786/zinfandel.lacita.com + +The original message was received at Fri, 6 Apr 2001 09:23:03 -0800 (GMT-0800) +from [199.164.235.226] + + ----- The following addresses have delivery notifications ----- + (unrecoverable error) + + ----- Transcript of session follows ----- +554 Too many hops 19 (17 max): from via [199.164.235.226], to + +--JAB03225.986577786/zinfandel.lacita.com +Content-Type: message/delivery-status + +Reporting-MTA: dns; zinfandel.lacita.com +Received-From-MTA: dns; [199.164.235.226] +Arrival-Date: Fri, 6 Apr 2001 09:23:03 -0800 (GMT-0800) + +Final-Recipient: rfc822; scoffman@wellpartner.com +Action: failed +Status: 5.4.6 +Last-Attempt-Date: Fri, 6 Apr 2001 09:23:06 -0800 (GMT-0800) + +--JAB03225.986577786/zinfandel.lacita.com +Content-Type: text/rfc822-headers + +Return-Path: linuxuser-admin@www.linux.org.uk +Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03225 for ; Fri, 6 Apr 2001 09:23:03 -0800 (GMT-0800) +Received: from zinfandel.lacita.com ([204.245.199.98]) + by + fo +Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03221 for ; Fri, 6 Apr 2001 09:22:18 -0800 (GMT-0800) +Received: from zinfandel.lacita.com ([204.245.199.98]) + by + fo +Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03217 for ; Fri, 6 Apr 2001 09:21:37 -0800 (GMT-0800) +Received: from zinfandel.lacita.com ([204.245.199.98]) + by + fo +Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03213 for ; Fri, 6 Apr 2001 09:20:56 -0800 (GMT-0800) +Received: from zinfandel.lacita.com ([204.245.199.98]) + by + fo +Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03209 for ; Fri, 6 Apr 2001 09:20:15 -0800 (GMT-0800) +Received: from zinfandel.lacita.com ([204.245.199.98]) + by + fo +Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03205 for ; Fri, 6 Apr 2001 09:19:33 -0800 (GMT-0800) +Received: from zinfandel.lacita.com ([204.245.199.98]) + by + fo +Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03201 for ; Fri, 6 Apr 2001 09:18:52 -0800 (GMT-0800) +Received: from zinfandel.lacita.com ([204.245.199.98]) + by + fo +Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03197 for ; Fri, 6 Apr 2001 09:17:54 -0800 (GMT-0800) +Received: from www.linux.org.uk (parcelfarce.linux.theplanet.co.uk [195.92.249.252]) + by + fo +Received: from localhost.localdomain + ([ + by + id +Received: from [212.1.130.11] (helo=s1.uklinux.net ident=root) + by + id + fo +Received: from server (ppp-2-22.cvx4.telinco.net [212.1.149.22]) + by + fo +From: Daniel James +Organization: LinuxUser +To: linuxuser@www.linux.org.uk +X-Mailer: KMail [version 1.1.99] +Content-Type: text/plain; + c +MIME-Version: 1.0 +Message-Id: <01040616033903.00962@server> +Content-Transfer-Encoding: 8bit +Subject: [LinuxUser] bulletin no. 45 +Sender: linuxuser-admin@www.linux.org.uk +Errors-To: linuxuser-admin@www.linux.org.uk +X-BeenThere: linuxuser@www.linux.org.uk +X-Mailman-Version: 2.0.3 +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Unsubscribe: , + +Date: Fri, 6 Apr 2001 16:03:39 +0100 + +--JAB03225.986577786/zinfandel.lacita.com-- + + diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_26.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_26.txt new file mode 100644 index 0000000..e13203a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_26.txt @@ -0,0 +1,45 @@ +Received: from xcar [192.168.0.2] by jeeves.wooster.local + (SMTPD32-7.07 EVAL) id AFF92F0214; Sun, 12 May 2002 08:55:37 +0100 +Date: Sun, 12 May 2002 08:56:15 +0100 +From: Father Time +To: timbo@jeeves.wooster.local +Subject: IMAP file test +Message-ID: <6df65d354b.father.time@rpc.wooster.local> +X-Organization: Home +User-Agent: Messenger-Pro/2.50a (MsgServe/1.50) (RISC-OS/4.02) POPstar/2.03 +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="1618492860--2051301190--113853680" +Status: R +X-UIDL: 319998302 + +This message is in MIME format which your mailer apparently does not support. +You either require a newer version of your software which supports MIME, or +a separate MIME decoding utility. Alternatively, ask the sender of this +message to resend it in a different format. + +--1618492860--2051301190--113853680 +Content-Type: text/plain; charset=us-ascii + +Simple email with attachment. + + +--1618492860--2051301190--113853680 +Content-Type: application/riscos; name="clock.bmp,69c"; type=BMP; load=&fff69c4b; exec=&355dd4d1; access=&03 +Content-Disposition: attachment; filename="clock.bmp" +Content-Transfer-Encoding: base64 + +Qk12AgAAAAAAAHYAAAAoAAAAIAAAACAAAAABAAQAAAAAAAAAAADXDQAA1w0AAAAAAAAA +AAAAAAAAAAAAiAAAiAAAAIiIAIgAAACIAIgAiIgAALu7uwCIiIgAERHdACLuIgAz//8A +zAAAAN0R3QDu7iIA////AAAAAAAAAAAAAAAAAAAAAAAAAAi3AAAAAAAAADeAAAAAAAAA +C3ADMzMzMANwAAAAAAAAAAAHMAAAAANwAAAAAAAAAACAMAd3zPfwAwgAAAAAAAAIAwd/ +f8x/f3AwgAAAAAAAgDB0x/f3//zPAwgAAAAAAAcHfM9////8z/AwAAAAAAiwd/f3//// +////A4AAAAAAcEx/f///////zAMAAAAAiwfM9////3///8zwOAAAAAcHf3////B///// +8DAAAAALB/f3///wd3d3//AwAAAABwTPf//wCQAAD/zAMAAAAAsEx/f///B////8wDAA +AAAHB39////wf/////AwAAAACwf39///8H/////wMAAAAIcHfM9///B////M8DgAAAAA +sHTH///wf///xAMAAAAACHB3f3//8H////cDgAAAAAALB3zH//D//M9wMAAAAAAAgLB0 +z39///xHAwgAAAAAAAgLB3d3RHd3cDCAAAAAAAAAgLAHd0R3cAMIAAAAAAAAgAgLcAAA +AAMwgAgAAAAACDAAAAu7t7cwAAgDgAAAAABzcIAAAAAAAAgDMwAAAAAAN7uwgAAAAAgH +MzMAAAAACH97tzAAAAALu3c3gAAAAAAL+7tzDABAu7f7cAAAAAAACA+3MA7EQAv/sIAA +AAAAAAAIAAAAAAAAAIAAAAAA + +--1618492860--2051301190--113853680-- \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_27.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_27.txt new file mode 100644 index 0000000..d019176 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_27.txt @@ -0,0 +1,15 @@ +Return-Path: +Received: by mail.dom.ain (Postfix, from userid 889) + id B9D0AD35DB; Tue, 4 Jun 2002 21:46:59 -0400 (EDT) +Message-ID: <15613.28051.707126.569693@dom.ain> +Date: Tue, 4 Jun 2002 21:46:59 -0400 +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +Subject: bug demonstration + 12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 + more text +From: aperson@dom.ain (Anne P. Erson) +To: bperson@dom.ain (Barney P. Erson) + +test diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_28.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_28.txt new file mode 100644 index 0000000..1e4824c --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_28.txt @@ -0,0 +1,25 @@ +From: aperson@dom.ain +MIME-Version: 1.0 +Content-Type: multipart/digest; boundary=BOUNDARY + +--BOUNDARY +Content-Type: message/rfc822 + +Content-Type: text/plain; charset=us-ascii +To: aa@bb.org +From: cc@dd.org +Subject: ee + +message 1 + +--BOUNDARY +Content-Type: message/rfc822 + +Content-Type: text/plain; charset=us-ascii +To: aa@bb.org +From: cc@dd.org +Subject: ee + +message 2 + +--BOUNDARY-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_29.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_29.txt new file mode 100644 index 0000000..1fab561 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_29.txt @@ -0,0 +1,22 @@ +Return-Path: +Delivered-To: bbb@zzz.org +Received: by mail.zzz.org (Postfix, from userid 889) + id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii; + title*0*="us-ascii'en'This%20is%20even%20more%20"; + title*1*="%2A%2A%2Afun%2A%2A%2A%20"; + title*2="isn't it!" +Content-Transfer-Encoding: 7bit +Message-ID: <15090.61304.110929.45684@aaa.zzz.org> +From: bbb@ddd.com (John X. Doe) +To: bbb@zzz.org +Subject: This is a test message +Date: Fri, 4 May 2001 14:05:44 -0400 + + +Hi, + +Do you like this message? + +-Me diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_30.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_30.txt new file mode 100644 index 0000000..4334bb6 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_30.txt @@ -0,0 +1,23 @@ +From: aperson@dom.ain +MIME-Version: 1.0 +Content-Type: multipart/digest; boundary=BOUNDARY + +--BOUNDARY + +Content-Type: text/plain; charset=us-ascii +To: aa@bb.org +From: cc@dd.org +Subject: ee + +message 1 + +--BOUNDARY + +Content-Type: text/plain; charset=us-ascii +To: aa@bb.org +From: cc@dd.org +Subject: ee + +message 2 + +--BOUNDARY-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_31.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_31.txt new file mode 100644 index 0000000..1e58e56 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_31.txt @@ -0,0 +1,15 @@ +From: aperson@dom.ain +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary=BOUNDARY_ + +--BOUNDARY +Content-Type: text/plain + +message 1 + +--BOUNDARY +Content-Type: text/plain + +message 2 + +--BOUNDARY-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_32.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_32.txt new file mode 100644 index 0000000..07ec5af --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_32.txt @@ -0,0 +1,14 @@ +Delivered-To: freebsd-isp@freebsd.org +Date: Tue, 26 Sep 2000 12:23:03 -0500 +From: Anne Person +To: Barney Dude +Subject: Re: Limiting Perl CPU Utilization... +Mime-Version: 1.0 +Content-Type: text/plain; charset*=ansi-x3.4-1968''us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.3.8i +Sender: owner-freebsd-isp@FreeBSD.ORG +Precedence: bulk +X-Loop: FreeBSD.org + +Some message. diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_33.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_33.txt new file mode 100644 index 0000000..042787a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_33.txt @@ -0,0 +1,29 @@ +Delivered-To: freebsd-isp@freebsd.org +Date: Wed, 27 Sep 2000 11:11:09 -0500 +From: Anne Person +To: Barney Dude +Subject: Re: Limiting Perl CPU Utilization... +Mime-Version: 1.0 +Content-Type: multipart/signed; micalg*=ansi-x3.4-1968''pgp-md5; + protocol*=ansi-x3.4-1968''application%2Fpgp-signature; + boundary*="ansi-x3.4-1968''EeQfGwPcQSOJBaQU" +Content-Disposition: inline +Sender: owner-freebsd-isp@FreeBSD.ORG +Precedence: bulk +X-Loop: FreeBSD.org + + +--EeQfGwPcQSOJBaQU +Content-Type: text/plain; charset*=ansi-x3.4-1968''us-ascii +Content-Disposition: inline +Content-Transfer-Encoding: quoted-printable + +part 1 + +--EeQfGwPcQSOJBaQU +Content-Type: text/plain +Content-Disposition: inline + +part 2 + +--EeQfGwPcQSOJBaQU-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_34.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_34.txt new file mode 100644 index 0000000..055dfea --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_34.txt @@ -0,0 +1,19 @@ +From: aperson@dom.ain +To: bperson@dom.ain +Content-Type: multipart/digest; boundary=XYZ + +--XYZ +Content-Type: text/plain + + +This is a text plain part that is counter to recommended practice in +RFC 2046, $5.1.5, but is not illegal + +--XYZ + +From: cperson@dom.ain +To: dperson@dom.ain + +A submessage + +--XYZ-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_35.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_35.txt new file mode 100644 index 0000000..be7d5a2 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_35.txt @@ -0,0 +1,4 @@ +From: aperson@dom.ain +To: bperson@dom.ain +Subject: here's something interesting +counter to RFC 2822, there's no separating newline here diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_36.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_36.txt new file mode 100644 index 0000000..5632c30 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_36.txt @@ -0,0 +1,40 @@ +Mime-Version: 1.0 +Content-Type: Multipart/Mixed; Boundary="NextPart" +To: IETF-Announce:; +From: Internet-Drafts@ietf.org +Subject: I-D ACTION:draft-ietf-mboned-mix-00.txt +Date: Tue, 22 Dec 1998 16:55:06 -0500 + +--NextPart + +Blah blah blah + +--NextPart +Content-Type: Multipart/Alternative; Boundary="OtherAccess" + +--OtherAccess +Content-Type: Message/External-body; + access-type="mail-server"; + server="mailserv@ietf.org" + +Content-Type: text/plain +Content-ID: <19981222151406.I-D@ietf.org> + +ENCODING mime +FILE /internet-drafts/draft-ietf-mboned-mix-00.txt + +--OtherAccess +Content-Type: Message/External-body; + name="draft-ietf-mboned-mix-00.txt"; + site="ftp.ietf.org"; + access-type="anon-ftp"; + directory="internet-drafts" + +Content-Type: text/plain +Content-ID: <19981222151406.I-D@ietf.org> + + +--OtherAccess-- + +--NextPart-- + diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_37.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_37.txt new file mode 100644 index 0000000..038d34a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_37.txt @@ -0,0 +1,22 @@ +Content-Type: multipart/mixed; boundary=ABCDE + +--ABCDE +Content-Type: text/x-one + +Blah + +--ABCDE +--ABCDE +Content-Type: text/x-two + +Blah + +--ABCDE +--ABCDE +--ABCDE +--ABCDE +Content-Type: text/x-two + +Blah + +--ABCDE-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_38.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_38.txt new file mode 100644 index 0000000..006df81 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_38.txt @@ -0,0 +1,101 @@ +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" + +------- =_aaaaaaaaaa0 +Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa1" +Content-ID: <20592.1022586929.1@example.com> + +------- =_aaaaaaaaaa1 +Content-Type: multipart/alternative; boundary="----- =_aaaaaaaaaa2" +Content-ID: <20592.1022586929.2@example.com> + +------- =_aaaaaaaaaa2 +Content-Type: text/plain +Content-ID: <20592.1022586929.3@example.com> +Content-Description: very tricky +Content-Transfer-Encoding: 7bit + + +Unlike the test test_nested-multiples-with-internal-boundary, this +piece of text not only contains the outer boundary tags +------- =_aaaaaaaaaa1 +and +------- =_aaaaaaaaaa0 +but puts them at the start of a line! And, to be even nastier, it +even includes a couple of end tags, such as this one: + +------- =_aaaaaaaaaa1-- + +and this one, which is from a multipart we haven't even seen yet! + +------- =_aaaaaaaaaa4-- + +This will, I'm sure, cause much breakage of MIME parsers. But, as +far as I can tell, it's perfectly legal. I have not yet ever seen +a case of this in the wild, but I've seen *similar* things. + + +------- =_aaaaaaaaaa2 +Content-Type: application/octet-stream +Content-ID: <20592.1022586929.4@example.com> +Content-Description: patch2 +Content-Transfer-Encoding: base64 + +XXX + +------- =_aaaaaaaaaa2-- + +------- =_aaaaaaaaaa1 +Content-Type: multipart/alternative; boundary="----- =_aaaaaaaaaa3" +Content-ID: <20592.1022586929.6@example.com> + +------- =_aaaaaaaaaa3 +Content-Type: application/octet-stream +Content-ID: <20592.1022586929.7@example.com> +Content-Description: patch3 +Content-Transfer-Encoding: base64 + +XXX + +------- =_aaaaaaaaaa3 +Content-Type: application/octet-stream +Content-ID: <20592.1022586929.8@example.com> +Content-Description: patch4 +Content-Transfer-Encoding: base64 + +XXX + +------- =_aaaaaaaaaa3-- + +------- =_aaaaaaaaaa1 +Content-Type: multipart/alternative; boundary="----- =_aaaaaaaaaa4" +Content-ID: <20592.1022586929.10@example.com> + +------- =_aaaaaaaaaa4 +Content-Type: application/octet-stream +Content-ID: <20592.1022586929.11@example.com> +Content-Description: patch5 +Content-Transfer-Encoding: base64 + +XXX + +------- =_aaaaaaaaaa4 +Content-Type: application/octet-stream +Content-ID: <20592.1022586929.12@example.com> +Content-Description: patch6 +Content-Transfer-Encoding: base64 + +XXX + +------- =_aaaaaaaaaa4-- + +------- =_aaaaaaaaaa1-- + +------- =_aaaaaaaaaa0 +Content-Type: text/plain; charset="us-ascii" +Content-ID: <20592.1022586929.15@example.com> + +-- +It's never too late to have a happy childhood. + +------- =_aaaaaaaaaa0-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_39.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_39.txt new file mode 100644 index 0000000..124b269 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_39.txt @@ -0,0 +1,83 @@ +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" + +------- =_aaaaaaaaaa0 +Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa1" +Content-ID: <20592.1022586929.1@example.com> + +------- =_aaaaaaaaaa1 +Content-Type: multipart/alternative; boundary="----- =_aaaaaaaaaa1" +Content-ID: <20592.1022586929.2@example.com> + +------- =_aaaaaaaaaa1 +Content-Type: application/octet-stream +Content-ID: <20592.1022586929.3@example.com> +Content-Description: patch1 +Content-Transfer-Encoding: base64 + +XXX + +------- =_aaaaaaaaaa1 +Content-Type: application/octet-stream +Content-ID: <20592.1022586929.4@example.com> +Content-Description: patch2 +Content-Transfer-Encoding: base64 + +XXX + +------- =_aaaaaaaaaa1-- + +------- =_aaaaaaaaaa1 +Content-Type: multipart/alternative; boundary="----- =_aaaaaaaaaa1" +Content-ID: <20592.1022586929.6@example.com> + +------- =_aaaaaaaaaa1 +Content-Type: application/octet-stream +Content-ID: <20592.1022586929.7@example.com> +Content-Description: patch3 +Content-Transfer-Encoding: base64 + +XXX + +------- =_aaaaaaaaaa1 +Content-Type: application/octet-stream +Content-ID: <20592.1022586929.8@example.com> +Content-Description: patch4 +Content-Transfer-Encoding: base64 + +XXX + +------- =_aaaaaaaaaa1-- + +------- =_aaaaaaaaaa1 +Content-Type: multipart/alternative; boundary="----- =_aaaaaaaaaa1" +Content-ID: <20592.1022586929.10@example.com> + +------- =_aaaaaaaaaa1 +Content-Type: application/octet-stream +Content-ID: <20592.1022586929.11@example.com> +Content-Description: patch5 +Content-Transfer-Encoding: base64 + +XXX + +------- =_aaaaaaaaaa1 +Content-Type: application/octet-stream +Content-ID: <20592.1022586929.12@example.com> +Content-Description: patch6 +Content-Transfer-Encoding: base64 + +XXX + +------- =_aaaaaaaaaa1-- + +------- =_aaaaaaaaaa1-- + +------- =_aaaaaaaaaa0 +Content-Type: text/plain; charset="us-ascii" +Content-ID: <20592.1022586929.15@example.com> + +-- +It's never too late to have a happy childhood. + +------- =_aaaaaaaaaa0-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_40.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_40.txt new file mode 100644 index 0000000..1435fa1 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_40.txt @@ -0,0 +1,10 @@ +MIME-Version: 1.0 +Content-Type: text/html; boundary="--961284236552522269" + +----961284236552522269 +Content-Type: text/html; +Content-Transfer-Encoding: 7Bit + + + +----961284236552522269-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_41.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_41.txt new file mode 100644 index 0000000..76cdd1c --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_41.txt @@ -0,0 +1,8 @@ +From: "Allison Dunlap" +To: yyy@example.com +Subject: 64423 +Date: Sun, 11 Jul 2004 16:09:27 -0300 +MIME-Version: 1.0 +Content-Type: multipart/alternative; + +Blah blah blah diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_42.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_42.txt new file mode 100644 index 0000000..a75f8f4 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_42.txt @@ -0,0 +1,20 @@ +Content-Type: multipart/mixed; boundary="AAA" +From: Mail Delivery Subsystem +To: yyy@example.com + +This is a MIME-encapsulated message + +--AAA + +Stuff + +--AAA +Content-Type: message/rfc822 + +From: webmaster@python.org +To: zzz@example.com +Content-Type: multipart/mixed; boundary="BBB" + +--BBB-- + +--AAA-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_43.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_43.txt new file mode 100644 index 0000000..797d12c --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_43.txt @@ -0,0 +1,217 @@ +From SRS0=aO/p=ON=bag.python.org=None@bounce2.pobox.com Fri Nov 26 21:40:36 2004 +X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil] + [nil nil nil nil nil nil nil "MAILER DAEMON <>" "MAILER DAEMON <>" nil nil "Banned file: auto__mail.python.bat in mail from you" "^From:" nil nil nil nil "Banned file: auto__mail.python.bat in mail from you" nil nil nil nil nil nil nil] + nil) +MIME-Version: 1.0 +Message-Id: +Content-Type: multipart/report; report-type=delivery-status; + charset=utf-8; + boundary="----------=_1101526904-1956-5" +X-Virus-Scanned: by XS4ALL Virus Scanner +X-UIDL: 4\G!!! +To: +Subject: Banned file: auto__mail.python.bat in mail from you +Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +This is a multi-part message in MIME format... + +------------=_1101526904-1956-5 +Content-Type: text/plain; charset="utf-8" +Content-Disposition: inline +Content-Transfer-Encoding: 7bit + +BANNED FILENAME ALERT + +Your message to: xxxxxxx@dot.ca.gov, xxxxxxxxxxxxx@dot.ca.gov, xxxxxxxxxx@dot.ca.gov, xxxxxxxx@dot.ca.gov, xxxxxxxxxx@dot.ca.gov, xxxxxx@dot.ca.gov, xxxxxxxxxx@dot.ca.gov, xxxxxx@dot.ca.gov, xxxxxx@dot.ca.gov, xxxxxxxxxxxxxxxx@dot.ca.gov, xxxxxxxxxxx@dot.ca.gov, xxxxxxxxxx@dot.ca.gov, xxxxxxxxxx@dot.ca.gov, xxxxxxxxxxxx@dot.ca.gov, xxxxxxxxxxxx@dot.ca.gov, xxxxxxx@dot.ca.gov, xxxxxxxxx@dot.ca.gov, xxxxxxxxxx@dot.ca.gov, xxxxxx@dot.ca.gov, xxx@dot.ca.gov, xxxxxxx@dot.ca.gov, xxxxxxx@dot.ca.gov, xxxxxxxxxxxxxxx@dot.ca.gov, xxxxxxxxxx@dot.ca.gov, xxxxxxx@dot.ca.gov, xxx@dot.ca.gov, xxxxxxxx@dot.ca.gov, xxxxxxxxxxxxx@dot.ca.gov, xxxxxxxxxxxxx@dot.ca.gov, xxxxxxxxxxx@dot.ca.gov, xxxxxxxxx@dot.ca.gov, xxxxxxxxxx@dot.ca.gov, xxxxxxxxxxxx@dot.ca.gov, xxxxxxx@dot.ca.gov, xxxxxxxxxxxxxxx@dot.ca.gov, xxxxxxxxxxxxx@dot.ca.gov, xxxx@dot.ca.gov, xxxxxxxx@dot.ca.gov, xxxxxxxxxx@dot.ca.gov, xxxxxxxxxxxxxxxxxx@dot.ca.gov +was blocked by our Spam Firewall. The email you sent with the following subject has NOT BEEN DELIVERED: + +Subject: Delivery_failure_notice + +An attachment in that mail was of a file type that the Spam Firewall is set to block. + + + +------------=_1101526904-1956-5 +Content-Type: message/delivery-status +Content-Disposition: inline +Content-Transfer-Encoding: 7bit +Content-Description: Delivery error report + +Reporting-MTA: dns; sacspam01.dot.ca.gov +Received-From-MTA: smtp; sacspam01.dot.ca.gov ([127.0.0.1]) +Arrival-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxxxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxxxxxxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxxxxxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +Final-Recipient: rfc822; xxxxxxx@dot.ca.gov +Action: failed +Status: 5.7.1 +Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat +Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST) + +------------=_1101526904-1956-5 +Content-Type: text/rfc822-headers +Content-Disposition: inline +Content-Transfer-Encoding: 7bit +Content-Description: Undelivered-message headers + +Received: from kgsav.org (ppp-70-242-162-63.dsl.spfdmo.swbell.net [70.242.162.63]) + by sacspam01.dot.ca.gov (Spam Firewall) with SMTP + id A232AD03DE3A; Fri, 26 Nov 2004 19:41:35 -0800 (PST) +From: webmaster@python.org +To: xxxxx@dot.ca.gov +Date: Sat, 27 Nov 2004 03:35:30 UTC +Subject: Delivery_failure_notice +Importance: Normal +X-Priority: 3 (Normal) +X-MSMail-Priority: Normal +Message-ID: +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="====67bd2b7a5.f99f7" +Content-Transfer-Encoding: 7bit + +------------=_1101526904-1956-5-- + diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_44.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_44.txt new file mode 100644 index 0000000..15a2252 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_44.txt @@ -0,0 +1,33 @@ +Return-Path: +Delivered-To: barry@python.org +Received: by mail.python.org (Postfix, from userid 889) + id C2BF0D37C6; Tue, 11 Sep 2001 00:05:05 -0400 (EDT) +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="h90VIIIKmx" +Content-Transfer-Encoding: 7bit +Message-ID: <15261.36209.358846.118674@anthem.python.org> +From: barry@python.org (Barry A. Warsaw) +To: barry@python.org +Subject: a simple multipart +Date: Tue, 11 Sep 2001 00:05:05 -0400 +X-Mailer: VM 6.95 under 21.4 (patch 4) "Artificial Intelligence" XEmacs Lucid +X-Attribution: BAW +X-Oblique-Strategy: Make a door into a window + + +--h90VIIIKmx +Content-Type: text/plain; name="msg.txt" +Content-Transfer-Encoding: 7bit + +a simple kind of mirror +to reflect upon our own + +--h90VIIIKmx +Content-Type: text/plain; name="msg.txt" +Content-Transfer-Encoding: 7bit + +a simple kind of mirror +to reflect upon our own + +--h90VIIIKmx-- + diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_45.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_45.txt new file mode 100644 index 0000000..58fde95 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_45.txt @@ -0,0 +1,33 @@ +From: +To: +Subject: test +X-Long-Line: Some really long line contains a lot of text and thus has to be rewrapped because it is some + really long + line +MIME-Version: 1.0 +Content-Type: multipart/signed; boundary="borderline"; + protocol="application/pgp-signature"; micalg=pgp-sha1 + +This is an OpenPGP/MIME signed message (RFC 2440 and 3156) +--borderline +Content-Type: text/plain +X-Long-Line: Another really long line contains a lot of text and thus has to be rewrapped because it is another + really long + line + +This is the signed contents. + +--borderline +Content-Type: application/pgp-signature; name="signature.asc" +Content-Description: OpenPGP digital signature +Content-Disposition: attachment; filename="signature.asc" + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.0.6 (GNU/Linux) + +iD8DBQFG03voRhp6o4m9dFsRApSZAKCCAN3IkJlVRg6NvAiMHlvvIuMGPQCeLZtj +FGwfnRHFBFO/S4/DKysm0lI= +=t7+s +-----END PGP SIGNATURE----- + +--borderline-- diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_46.txt b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_46.txt new file mode 100644 index 0000000..1e22c4f --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/data/msg_46.txt @@ -0,0 +1,23 @@ +Return-Path: +Delivery-Date: Mon, 08 Feb 2010 14:05:16 +0100 +Received: from example.org (example.org [64.5.53.58]) + by example.net (node=mxbap2) with ESMTP (Nemesis) + id UNIQUE for someone@example.com; Mon, 08 Feb 2010 14:05:16 +0100 +Date: Mon, 01 Feb 2010 12:21:16 +0100 +From: "Sender" +To: +Subject: GroupwiseForwardingTest +Mime-Version: 1.0 +Content-Type: message/rfc822 + +Return-path: +Message-ID: <4B66B890.4070408@teconcept.de> +Date: Mon, 01 Feb 2010 12:18:40 +0100 +From: "Dr. Sender" +MIME-Version: 1.0 +To: "Recipient" +Subject: GroupwiseForwardingTest +Content-Type: text/plain; charset=ISO-8859-15 +Content-Transfer-Encoding: 7bit + +Testing email forwarding with Groupwise 1.2.2010 diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email.py new file mode 100644 index 0000000..b32da9d --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email.py @@ -0,0 +1,3558 @@ +# Copyright (C) 2001-2010 Python Software Foundation +# Contact: email-sig@python.org +# email package unit tests + +import os +import sys +import time +import base64 +import difflib +import unittest +import warnings +import textwrap +from cStringIO import StringIO + +import email + +from email.Charset import Charset +from email.Header import Header, decode_header, make_header +from email.Parser import Parser, HeaderParser +from email.Generator import Generator, DecodedGenerator +from email.Message import Message +from email.MIMEAudio import MIMEAudio +from email.MIMEText import MIMEText +from email.MIMEImage import MIMEImage +from email.MIMEBase import MIMEBase +from email.MIMEMessage import MIMEMessage +from email.MIMEMultipart import MIMEMultipart +from email import Utils +from email import Errors +from email import Encoders +from email import Iterators +from email import base64MIME +from email import quopriMIME + +from test.test_support import findfile, run_unittest +from email.test import __file__ as landmark + + +NL = '\n' +EMPTYSTRING = '' +SPACE = ' ' + + + +def openfile(filename, mode='r'): + path = os.path.join(os.path.dirname(landmark), 'data', filename) + return open(path, mode) + + + +# Base test class +class TestEmailBase(unittest.TestCase): + def ndiffAssertEqual(self, first, second): + """Like assertEqual except use ndiff for readable output.""" + if first != second: + sfirst = str(first) + ssecond = str(second) + diff = difflib.ndiff(sfirst.splitlines(), ssecond.splitlines()) + fp = StringIO() + print >> fp, NL, NL.join(diff) + raise self.failureException, fp.getvalue() + + def _msgobj(self, filename): + fp = openfile(findfile(filename)) + try: + msg = email.message_from_file(fp) + finally: + fp.close() + return msg + + + +# Test various aspects of the Message class's API +class TestMessageAPI(TestEmailBase): + def test_get_all(self): + eq = self.assertEqual + msg = self._msgobj('msg_20.txt') + eq(msg.get_all('cc'), ['ccc@zzz.org', 'ddd@zzz.org', 'eee@zzz.org']) + eq(msg.get_all('xx', 'n/a'), 'n/a') + + def test_getset_charset(self): + eq = self.assertEqual + msg = Message() + eq(msg.get_charset(), None) + charset = Charset('iso-8859-1') + msg.set_charset(charset) + eq(msg['mime-version'], '1.0') + eq(msg.get_content_type(), 'text/plain') + eq(msg['content-type'], 'text/plain; charset="iso-8859-1"') + eq(msg.get_param('charset'), 'iso-8859-1') + eq(msg['content-transfer-encoding'], 'quoted-printable') + eq(msg.get_charset().input_charset, 'iso-8859-1') + # Remove the charset + msg.set_charset(None) + eq(msg.get_charset(), None) + eq(msg['content-type'], 'text/plain') + # Try adding a charset when there's already MIME headers present + msg = Message() + msg['MIME-Version'] = '2.0' + msg['Content-Type'] = 'text/x-weird' + msg['Content-Transfer-Encoding'] = 'quinted-puntable' + msg.set_charset(charset) + eq(msg['mime-version'], '2.0') + eq(msg['content-type'], 'text/x-weird; charset="iso-8859-1"') + eq(msg['content-transfer-encoding'], 'quinted-puntable') + + def test_set_charset_from_string(self): + eq = self.assertEqual + msg = Message() + msg.set_charset('us-ascii') + eq(msg.get_charset().input_charset, 'us-ascii') + eq(msg['content-type'], 'text/plain; charset="us-ascii"') + + def test_set_payload_with_charset(self): + msg = Message() + charset = Charset('iso-8859-1') + msg.set_payload('This is a string payload', charset) + self.assertEqual(msg.get_charset().input_charset, 'iso-8859-1') + + def test_get_charsets(self): + eq = self.assertEqual + + msg = self._msgobj('msg_08.txt') + charsets = msg.get_charsets() + eq(charsets, [None, 'us-ascii', 'iso-8859-1', 'iso-8859-2', 'koi8-r']) + + msg = self._msgobj('msg_09.txt') + charsets = msg.get_charsets('dingbat') + eq(charsets, ['dingbat', 'us-ascii', 'iso-8859-1', 'dingbat', + 'koi8-r']) + + msg = self._msgobj('msg_12.txt') + charsets = msg.get_charsets() + eq(charsets, [None, 'us-ascii', 'iso-8859-1', None, 'iso-8859-2', + 'iso-8859-3', 'us-ascii', 'koi8-r']) + + def test_get_filename(self): + eq = self.assertEqual + + msg = self._msgobj('msg_04.txt') + filenames = [p.get_filename() for p in msg.get_payload()] + eq(filenames, ['msg.txt', 'msg.txt']) + + msg = self._msgobj('msg_07.txt') + subpart = msg.get_payload(1) + eq(subpart.get_filename(), 'dingusfish.gif') + + def test_get_filename_with_name_parameter(self): + eq = self.assertEqual + + msg = self._msgobj('msg_44.txt') + filenames = [p.get_filename() for p in msg.get_payload()] + eq(filenames, ['msg.txt', 'msg.txt']) + + def test_get_boundary(self): + eq = self.assertEqual + msg = self._msgobj('msg_07.txt') + # No quotes! + eq(msg.get_boundary(), 'BOUNDARY') + + def test_set_boundary(self): + eq = self.assertEqual + # This one has no existing boundary parameter, but the Content-Type: + # header appears fifth. + msg = self._msgobj('msg_01.txt') + msg.set_boundary('BOUNDARY') + header, value = msg.items()[4] + eq(header.lower(), 'content-type') + eq(value, 'text/plain; charset="us-ascii"; boundary="BOUNDARY"') + # This one has a Content-Type: header, with a boundary, stuck in the + # middle of its headers. Make sure the order is preserved; it should + # be fifth. + msg = self._msgobj('msg_04.txt') + msg.set_boundary('BOUNDARY') + header, value = msg.items()[4] + eq(header.lower(), 'content-type') + eq(value, 'multipart/mixed; boundary="BOUNDARY"') + # And this one has no Content-Type: header at all. + msg = self._msgobj('msg_03.txt') + self.assertRaises(Errors.HeaderParseError, + msg.set_boundary, 'BOUNDARY') + + def test_make_boundary(self): + msg = MIMEMultipart('form-data') + # Note that when the boundary gets created is an implementation + # detail and might change. + self.assertEqual(msg.items()[0][1], 'multipart/form-data') + # Trigger creation of boundary + msg.as_string() + self.assertEqual(msg.items()[0][1][:33], + 'multipart/form-data; boundary="==') + # XXX: there ought to be tests of the uniqueness of the boundary, too. + + def test_message_rfc822_only(self): + # Issue 7970: message/rfc822 not in multipart parsed by + # HeaderParser caused an exception when flattened. + fp = openfile(findfile('msg_46.txt')) + msgdata = fp.read() + parser = email.Parser.HeaderParser() + msg = parser.parsestr(msgdata) + out = StringIO() + gen = email.Generator.Generator(out, True, 0) + gen.flatten(msg, False) + self.assertEqual(out.getvalue(), msgdata) + + def test_get_decoded_payload(self): + eq = self.assertEqual + msg = self._msgobj('msg_10.txt') + # The outer message is a multipart + eq(msg.get_payload(decode=True), None) + # Subpart 1 is 7bit encoded + eq(msg.get_payload(0).get_payload(decode=True), + 'This is a 7bit encoded message.\n') + # Subpart 2 is quopri + eq(msg.get_payload(1).get_payload(decode=True), + '\xa1This is a Quoted Printable encoded message!\n') + # Subpart 3 is base64 + eq(msg.get_payload(2).get_payload(decode=True), + 'This is a Base64 encoded message.') + # Subpart 4 is base64 with a trailing newline, which + # used to be stripped (issue 7143). + eq(msg.get_payload(3).get_payload(decode=True), + 'This is a Base64 encoded message.\n') + # Subpart 5 has no Content-Transfer-Encoding: header. + eq(msg.get_payload(4).get_payload(decode=True), + 'This has no Content-Transfer-Encoding: header.\n') + + def test_get_decoded_uu_payload(self): + eq = self.assertEqual + msg = Message() + msg.set_payload('begin 666 -\n+:&5L;&\\@=V]R;&0 \n \nend\n') + for cte in ('x-uuencode', 'uuencode', 'uue', 'x-uue'): + msg['content-transfer-encoding'] = cte + eq(msg.get_payload(decode=True), 'hello world') + # Now try some bogus data + msg.set_payload('foo') + eq(msg.get_payload(decode=True), 'foo') + + def test_decode_bogus_uu_payload_quietly(self): + msg = Message() + msg.set_payload('begin 664 foo.txt\n%' % i for i in range(10)]) + msg.set_payload('Test') + sfp = StringIO() + g = Generator(sfp) + g.flatten(msg) + eq(sfp.getvalue(), """\ +From: test@dom.ain +References: <0@dom.ain> <1@dom.ain> <2@dom.ain> <3@dom.ain> <4@dom.ain> + <5@dom.ain> <6@dom.ain> <7@dom.ain> <8@dom.ain> <9@dom.ain> + +Test""") + + def test_no_split_long_header(self): + eq = self.ndiffAssertEqual + hstr = 'References: ' + 'x' * 80 + h = Header(hstr, continuation_ws='\t') + eq(h.encode(), """\ +References: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx""") + + def test_splitting_multiple_long_lines(self): + eq = self.ndiffAssertEqual + hstr = """\ +from babylon.socal-raves.org (localhost [127.0.0.1]); by babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; for ; Sat, 2 Feb 2002 17:00:06 -0800 (PST) +\tfrom babylon.socal-raves.org (localhost [127.0.0.1]); by babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; for ; Sat, 2 Feb 2002 17:00:06 -0800 (PST) +\tfrom babylon.socal-raves.org (localhost [127.0.0.1]); by babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; for ; Sat, 2 Feb 2002 17:00:06 -0800 (PST) +""" + h = Header(hstr, continuation_ws='\t') + eq(h.encode(), """\ +from babylon.socal-raves.org (localhost [127.0.0.1]); +\tby babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; +\tfor ; +\tSat, 2 Feb 2002 17:00:06 -0800 (PST) +\tfrom babylon.socal-raves.org (localhost [127.0.0.1]); +\tby babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; +\tfor ; +\tSat, 2 Feb 2002 17:00:06 -0800 (PST) +\tfrom babylon.socal-raves.org (localhost [127.0.0.1]); +\tby babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; +\tfor ; +\tSat, 2 Feb 2002 17:00:06 -0800 (PST)""") + + def test_splitting_first_line_only_is_long(self): + eq = self.ndiffAssertEqual + hstr = """\ +from modemcable093.139-201-24.que.mc.videotron.ca ([24.201.139.93] helo=cthulhu.gerg.ca) +\tby kronos.mems-exchange.org with esmtp (Exim 4.05) +\tid 17k4h5-00034i-00 +\tfor test@mems-exchange.org; Wed, 28 Aug 2002 11:25:20 -0400""" + h = Header(hstr, maxlinelen=78, header_name='Received', + continuation_ws='\t') + eq(h.encode(), """\ +from modemcable093.139-201-24.que.mc.videotron.ca ([24.201.139.93] +\thelo=cthulhu.gerg.ca) +\tby kronos.mems-exchange.org with esmtp (Exim 4.05) +\tid 17k4h5-00034i-00 +\tfor test@mems-exchange.org; Wed, 28 Aug 2002 11:25:20 -0400""") + + def test_long_8bit_header(self): + eq = self.ndiffAssertEqual + msg = Message() + h = Header('Britische Regierung gibt', 'iso-8859-1', + header_name='Subject') + h.append('gr\xfcnes Licht f\xfcr Offshore-Windkraftprojekte') + msg['Subject'] = h + eq(msg.as_string(), """\ +Subject: =?iso-8859-1?q?Britische_Regierung_gibt?= =?iso-8859-1?q?gr=FCnes?= + =?iso-8859-1?q?_Licht_f=FCr_Offshore-Windkraftprojekte?= + +""") + + def test_long_8bit_header_no_charset(self): + eq = self.ndiffAssertEqual + msg = Message() + msg['Reply-To'] = 'Britische Regierung gibt gr\xfcnes Licht f\xfcr Offshore-Windkraftprojekte ' + eq(msg.as_string(), """\ +Reply-To: Britische Regierung gibt gr\xfcnes Licht f\xfcr Offshore-Windkraftprojekte + +""") + + def test_long_to_header(self): + eq = self.ndiffAssertEqual + to = '"Someone Test #A" ,,"Someone Test #B" , "Someone Test #C" , "Someone Test #D" ' + msg = Message() + msg['To'] = to + eq(msg.as_string(0), '''\ +To: "Someone Test #A" , , + "Someone Test #B" , + "Someone Test #C" , + "Someone Test #D" + +''') + + def test_long_line_after_append(self): + eq = self.ndiffAssertEqual + s = 'This is an example of string which has almost the limit of header length.' + h = Header(s) + h.append('Add another line.') + eq(h.encode(), """\ +This is an example of string which has almost the limit of header length. + Add another line.""") + + def test_shorter_line_with_append(self): + eq = self.ndiffAssertEqual + s = 'This is a shorter line.' + h = Header(s) + h.append('Add another sentence. (Surprise?)') + eq(h.encode(), + 'This is a shorter line. Add another sentence. (Surprise?)') + + def test_long_field_name(self): + eq = self.ndiffAssertEqual + fn = 'X-Very-Very-Very-Long-Header-Name' + gs = "Die Mieter treten hier ein werden mit einem Foerderband komfortabel den Korridor entlang, an s\xfcdl\xfcndischen Wandgem\xe4lden vorbei, gegen die rotierenden Klingen bef\xf6rdert. " + h = Header(gs, 'iso-8859-1', header_name=fn) + # BAW: this seems broken because the first line is too long + eq(h.encode(), """\ +=?iso-8859-1?q?Die_Mieter_treten_hier_?= + =?iso-8859-1?q?ein_werden_mit_einem_Foerderband_komfortabel_den_Korridor_?= + =?iso-8859-1?q?entlang=2C_an_s=FCdl=FCndischen_Wandgem=E4lden_vorbei=2C_g?= + =?iso-8859-1?q?egen_die_rotierenden_Klingen_bef=F6rdert=2E_?=""") + + def test_long_received_header(self): + h = 'from FOO.TLD (vizworld.acl.foo.tld [123.452.678.9]) by hrothgar.la.mastaler.com (tmda-ofmipd) with ESMTP; Wed, 05 Mar 2003 18:10:18 -0700' + msg = Message() + msg['Received-1'] = Header(h, continuation_ws='\t') + msg['Received-2'] = h + self.assertEqual(msg.as_string(), """\ +Received-1: from FOO.TLD (vizworld.acl.foo.tld [123.452.678.9]) by +\throthgar.la.mastaler.com (tmda-ofmipd) with ESMTP; +\tWed, 05 Mar 2003 18:10:18 -0700 +Received-2: from FOO.TLD (vizworld.acl.foo.tld [123.452.678.9]) by + hrothgar.la.mastaler.com (tmda-ofmipd) with ESMTP; + Wed, 05 Mar 2003 18:10:18 -0700 + +""") + + def test_string_headerinst_eq(self): + h = '<15975.17901.207240.414604@sgigritzmann1.mathematik.tu-muenchen.de> (David Bremner\'s message of "Thu, 6 Mar 2003 13:58:21 +0100")' + msg = Message() + msg['Received'] = Header(h, header_name='Received', + continuation_ws='\t') + msg['Received'] = h + self.ndiffAssertEqual(msg.as_string(), """\ +Received: <15975.17901.207240.414604@sgigritzmann1.mathematik.tu-muenchen.de> +\t(David Bremner's message of "Thu, 6 Mar 2003 13:58:21 +0100") +Received: <15975.17901.207240.414604@sgigritzmann1.mathematik.tu-muenchen.de> + (David Bremner's message of "Thu, 6 Mar 2003 13:58:21 +0100") + +""") + + def test_long_unbreakable_lines_with_continuation(self): + eq = self.ndiffAssertEqual + msg = Message() + t = """\ + iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEUAAAAkHiJeRUIcGBi9 + locQDQ4zJykFBAXJfWDjAAACYUlEQVR4nF2TQY/jIAyFc6lydlG5x8Nyp1Y69wj1PN2I5gzp""" + msg['Face-1'] = t + msg['Face-2'] = Header(t, header_name='Face-2') + eq(msg.as_string(), """\ +Face-1: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEUAAAAkHiJeRUIcGBi9 + locQDQ4zJykFBAXJfWDjAAACYUlEQVR4nF2TQY/jIAyFc6lydlG5x8Nyp1Y69wj1PN2I5gzp +Face-2: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEUAAAAkHiJeRUIcGBi9 + locQDQ4zJykFBAXJfWDjAAACYUlEQVR4nF2TQY/jIAyFc6lydlG5x8Nyp1Y69wj1PN2I5gzp + +""") + + def test_another_long_multiline_header(self): + eq = self.ndiffAssertEqual + m = '''\ +Received: from siimage.com ([172.25.1.3]) by zima.siliconimage.com with Microsoft SMTPSVC(5.0.2195.4905); + Wed, 16 Oct 2002 07:41:11 -0700''' + msg = email.message_from_string(m) + eq(msg.as_string(), '''\ +Received: from siimage.com ([172.25.1.3]) by zima.siliconimage.com with + Microsoft SMTPSVC(5.0.2195.4905); Wed, 16 Oct 2002 07:41:11 -0700 + +''') + + def test_long_lines_with_different_header(self): + eq = self.ndiffAssertEqual + h = """\ +List-Unsubscribe: , + """ + msg = Message() + msg['List'] = h + msg['List'] = Header(h, header_name='List') + eq(msg.as_string(), """\ +List: List-Unsubscribe: , + +List: List-Unsubscribe: , + + +""") + + + +# Test mangling of "From " lines in the body of a message +class TestFromMangling(unittest.TestCase): + def setUp(self): + self.msg = Message() + self.msg['From'] = 'aaa@bbb.org' + self.msg.set_payload("""\ +From the desk of A.A.A.: +Blah blah blah +""") + + def test_mangled_from(self): + s = StringIO() + g = Generator(s, mangle_from_=True) + g.flatten(self.msg) + self.assertEqual(s.getvalue(), """\ +From: aaa@bbb.org + +>From the desk of A.A.A.: +Blah blah blah +""") + + def test_dont_mangle_from(self): + s = StringIO() + g = Generator(s, mangle_from_=False) + g.flatten(self.msg) + self.assertEqual(s.getvalue(), """\ +From: aaa@bbb.org + +From the desk of A.A.A.: +Blah blah blah +""") + + def test_mangle_from_in_preamble_and_epilog(self): + s = StringIO() + g = Generator(s, mangle_from_=True) + msg = email.message_from_string(textwrap.dedent("""\ + From: foo@bar.com + Mime-Version: 1.0 + Content-Type: multipart/mixed; boundary=XXX + + From somewhere unknown + + --XXX + Content-Type: text/plain + + foo + + --XXX-- + + From somewhere unknowable + """)) + g.flatten(msg) + self.assertEqual(len([1 for x in s.getvalue().split('\n') + if x.startswith('>From ')]), 2) + + +# Test the basic MIMEAudio class +class TestMIMEAudio(unittest.TestCase): + def setUp(self): + # Make sure we pick up the audiotest.au that lives in email/test/data. + # In Python, there's an audiotest.au living in Lib/test but that isn't + # included in some binary distros that don't include the test + # package. The trailing empty string on the .join() is significant + # since findfile() will do a dirname(). + datadir = os.path.join(os.path.dirname(landmark), 'data', '') + fp = open(findfile('audiotest.au', datadir), 'rb') + try: + self._audiodata = fp.read() + finally: + fp.close() + self._au = MIMEAudio(self._audiodata) + + def test_guess_minor_type(self): + self.assertEqual(self._au.get_content_type(), 'audio/basic') + + def test_encoding(self): + payload = self._au.get_payload() + self.assertEqual(base64.decodestring(payload), self._audiodata) + + def test_checkSetMinor(self): + au = MIMEAudio(self._audiodata, 'fish') + self.assertEqual(au.get_content_type(), 'audio/fish') + + def test_add_header(self): + eq = self.assertEqual + unless = self.assertTrue + self._au.add_header('Content-Disposition', 'attachment', + filename='audiotest.au') + eq(self._au['content-disposition'], + 'attachment; filename="audiotest.au"') + eq(self._au.get_params(header='content-disposition'), + [('attachment', ''), ('filename', 'audiotest.au')]) + eq(self._au.get_param('filename', header='content-disposition'), + 'audiotest.au') + missing = [] + eq(self._au.get_param('attachment', header='content-disposition'), '') + unless(self._au.get_param('foo', failobj=missing, + header='content-disposition') is missing) + # Try some missing stuff + unless(self._au.get_param('foobar', missing) is missing) + unless(self._au.get_param('attachment', missing, + header='foobar') is missing) + + + +# Test the basic MIMEImage class +class TestMIMEImage(unittest.TestCase): + def setUp(self): + fp = openfile('PyBanner048.gif') + try: + self._imgdata = fp.read() + finally: + fp.close() + self._im = MIMEImage(self._imgdata) + + def test_guess_minor_type(self): + self.assertEqual(self._im.get_content_type(), 'image/gif') + + def test_encoding(self): + payload = self._im.get_payload() + self.assertEqual(base64.decodestring(payload), self._imgdata) + + def test_checkSetMinor(self): + im = MIMEImage(self._imgdata, 'fish') + self.assertEqual(im.get_content_type(), 'image/fish') + + def test_add_header(self): + eq = self.assertEqual + unless = self.assertTrue + self._im.add_header('Content-Disposition', 'attachment', + filename='dingusfish.gif') + eq(self._im['content-disposition'], + 'attachment; filename="dingusfish.gif"') + eq(self._im.get_params(header='content-disposition'), + [('attachment', ''), ('filename', 'dingusfish.gif')]) + eq(self._im.get_param('filename', header='content-disposition'), + 'dingusfish.gif') + missing = [] + eq(self._im.get_param('attachment', header='content-disposition'), '') + unless(self._im.get_param('foo', failobj=missing, + header='content-disposition') is missing) + # Try some missing stuff + unless(self._im.get_param('foobar', missing) is missing) + unless(self._im.get_param('attachment', missing, + header='foobar') is missing) + + + +# Test the basic MIMEText class +class TestMIMEText(unittest.TestCase): + def setUp(self): + self._msg = MIMEText('hello there') + + def test_types(self): + eq = self.assertEqual + unless = self.assertTrue + eq(self._msg.get_content_type(), 'text/plain') + eq(self._msg.get_param('charset'), 'us-ascii') + missing = [] + unless(self._msg.get_param('foobar', missing) is missing) + unless(self._msg.get_param('charset', missing, header='foobar') + is missing) + + def test_payload(self): + self.assertEqual(self._msg.get_payload(), 'hello there') + self.assertTrue(not self._msg.is_multipart()) + + def test_charset(self): + eq = self.assertEqual + msg = MIMEText('hello there', _charset='us-ascii') + eq(msg.get_charset().input_charset, 'us-ascii') + eq(msg['content-type'], 'text/plain; charset="us-ascii"') + + def test_7bit_unicode_input(self): + eq = self.assertEqual + msg = MIMEText(u'hello there', _charset='us-ascii') + eq(msg.get_charset().input_charset, 'us-ascii') + eq(msg['content-type'], 'text/plain; charset="us-ascii"') + + def test_7bit_unicode_input_no_charset(self): + eq = self.assertEqual + msg = MIMEText(u'hello there') + eq(msg.get_charset(), 'us-ascii') + eq(msg['content-type'], 'text/plain; charset="us-ascii"') + self.assertTrue('hello there' in msg.as_string()) + + def test_8bit_unicode_input(self): + teststr = u'\u043a\u0438\u0440\u0438\u043b\u0438\u0446\u0430' + eq = self.assertEqual + msg = MIMEText(teststr, _charset='utf-8') + eq(msg.get_charset().output_charset, 'utf-8') + eq(msg['content-type'], 'text/plain; charset="utf-8"') + eq(msg.get_payload(decode=True), teststr.encode('utf-8')) + + def test_8bit_unicode_input_no_charset(self): + teststr = u'\u043a\u0438\u0440\u0438\u043b\u0438\u0446\u0430' + self.assertRaises(UnicodeEncodeError, MIMEText, teststr) + + + +# Test complicated multipart/* messages +class TestMultipart(TestEmailBase): + def setUp(self): + fp = openfile('PyBanner048.gif') + try: + data = fp.read() + finally: + fp.close() + + container = MIMEBase('multipart', 'mixed', boundary='BOUNDARY') + image = MIMEImage(data, name='dingusfish.gif') + image.add_header('content-disposition', 'attachment', + filename='dingusfish.gif') + intro = MIMEText('''\ +Hi there, + +This is the dingus fish. +''') + container.attach(intro) + container.attach(image) + container['From'] = 'Barry ' + container['To'] = 'Dingus Lovers ' + container['Subject'] = 'Here is your dingus fish' + + now = 987809702.54848599 + timetuple = time.localtime(now) + if timetuple[-1] == 0: + tzsecs = time.timezone + else: + tzsecs = time.altzone + if tzsecs > 0: + sign = '-' + else: + sign = '+' + tzoffset = ' %s%04d' % (sign, tzsecs // 36) + container['Date'] = time.strftime( + '%a, %d %b %Y %H:%M:%S', + time.localtime(now)) + tzoffset + self._msg = container + self._im = image + self._txt = intro + + def test_hierarchy(self): + # convenience + eq = self.assertEqual + unless = self.assertTrue + raises = self.assertRaises + # tests + m = self._msg + unless(m.is_multipart()) + eq(m.get_content_type(), 'multipart/mixed') + eq(len(m.get_payload()), 2) + raises(IndexError, m.get_payload, 2) + m0 = m.get_payload(0) + m1 = m.get_payload(1) + unless(m0 is self._txt) + unless(m1 is self._im) + eq(m.get_payload(), [m0, m1]) + unless(not m0.is_multipart()) + unless(not m1.is_multipart()) + + def test_empty_multipart_idempotent(self): + text = """\ +Content-Type: multipart/mixed; boundary="BOUNDARY" +MIME-Version: 1.0 +Subject: A subject +To: aperson@dom.ain +From: bperson@dom.ain + + +--BOUNDARY + + +--BOUNDARY-- +""" + msg = Parser().parsestr(text) + self.ndiffAssertEqual(text, msg.as_string()) + + def test_no_parts_in_a_multipart_with_none_epilogue(self): + outer = MIMEBase('multipart', 'mixed') + outer['Subject'] = 'A subject' + outer['To'] = 'aperson@dom.ain' + outer['From'] = 'bperson@dom.ain' + outer.set_boundary('BOUNDARY') + self.ndiffAssertEqual(outer.as_string(), '''\ +Content-Type: multipart/mixed; boundary="BOUNDARY" +MIME-Version: 1.0 +Subject: A subject +To: aperson@dom.ain +From: bperson@dom.ain + +--BOUNDARY + +--BOUNDARY--''') + + def test_no_parts_in_a_multipart_with_empty_epilogue(self): + outer = MIMEBase('multipart', 'mixed') + outer['Subject'] = 'A subject' + outer['To'] = 'aperson@dom.ain' + outer['From'] = 'bperson@dom.ain' + outer.preamble = '' + outer.epilogue = '' + outer.set_boundary('BOUNDARY') + self.ndiffAssertEqual(outer.as_string(), '''\ +Content-Type: multipart/mixed; boundary="BOUNDARY" +MIME-Version: 1.0 +Subject: A subject +To: aperson@dom.ain +From: bperson@dom.ain + + +--BOUNDARY + +--BOUNDARY-- +''') + + def test_one_part_in_a_multipart(self): + eq = self.ndiffAssertEqual + outer = MIMEBase('multipart', 'mixed') + outer['Subject'] = 'A subject' + outer['To'] = 'aperson@dom.ain' + outer['From'] = 'bperson@dom.ain' + outer.set_boundary('BOUNDARY') + msg = MIMEText('hello world') + outer.attach(msg) + eq(outer.as_string(), '''\ +Content-Type: multipart/mixed; boundary="BOUNDARY" +MIME-Version: 1.0 +Subject: A subject +To: aperson@dom.ain +From: bperson@dom.ain + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +hello world +--BOUNDARY--''') + + def test_seq_parts_in_a_multipart_with_empty_preamble(self): + eq = self.ndiffAssertEqual + outer = MIMEBase('multipart', 'mixed') + outer['Subject'] = 'A subject' + outer['To'] = 'aperson@dom.ain' + outer['From'] = 'bperson@dom.ain' + outer.preamble = '' + msg = MIMEText('hello world') + outer.attach(msg) + outer.set_boundary('BOUNDARY') + eq(outer.as_string(), '''\ +Content-Type: multipart/mixed; boundary="BOUNDARY" +MIME-Version: 1.0 +Subject: A subject +To: aperson@dom.ain +From: bperson@dom.ain + + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +hello world +--BOUNDARY--''') + + + def test_seq_parts_in_a_multipart_with_none_preamble(self): + eq = self.ndiffAssertEqual + outer = MIMEBase('multipart', 'mixed') + outer['Subject'] = 'A subject' + outer['To'] = 'aperson@dom.ain' + outer['From'] = 'bperson@dom.ain' + outer.preamble = None + msg = MIMEText('hello world') + outer.attach(msg) + outer.set_boundary('BOUNDARY') + eq(outer.as_string(), '''\ +Content-Type: multipart/mixed; boundary="BOUNDARY" +MIME-Version: 1.0 +Subject: A subject +To: aperson@dom.ain +From: bperson@dom.ain + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +hello world +--BOUNDARY--''') + + + def test_seq_parts_in_a_multipart_with_none_epilogue(self): + eq = self.ndiffAssertEqual + outer = MIMEBase('multipart', 'mixed') + outer['Subject'] = 'A subject' + outer['To'] = 'aperson@dom.ain' + outer['From'] = 'bperson@dom.ain' + outer.epilogue = None + msg = MIMEText('hello world') + outer.attach(msg) + outer.set_boundary('BOUNDARY') + eq(outer.as_string(), '''\ +Content-Type: multipart/mixed; boundary="BOUNDARY" +MIME-Version: 1.0 +Subject: A subject +To: aperson@dom.ain +From: bperson@dom.ain + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +hello world +--BOUNDARY--''') + + + def test_seq_parts_in_a_multipart_with_empty_epilogue(self): + eq = self.ndiffAssertEqual + outer = MIMEBase('multipart', 'mixed') + outer['Subject'] = 'A subject' + outer['To'] = 'aperson@dom.ain' + outer['From'] = 'bperson@dom.ain' + outer.epilogue = '' + msg = MIMEText('hello world') + outer.attach(msg) + outer.set_boundary('BOUNDARY') + eq(outer.as_string(), '''\ +Content-Type: multipart/mixed; boundary="BOUNDARY" +MIME-Version: 1.0 +Subject: A subject +To: aperson@dom.ain +From: bperson@dom.ain + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +hello world +--BOUNDARY-- +''') + + + def test_seq_parts_in_a_multipart_with_nl_epilogue(self): + eq = self.ndiffAssertEqual + outer = MIMEBase('multipart', 'mixed') + outer['Subject'] = 'A subject' + outer['To'] = 'aperson@dom.ain' + outer['From'] = 'bperson@dom.ain' + outer.epilogue = '\n' + msg = MIMEText('hello world') + outer.attach(msg) + outer.set_boundary('BOUNDARY') + eq(outer.as_string(), '''\ +Content-Type: multipart/mixed; boundary="BOUNDARY" +MIME-Version: 1.0 +Subject: A subject +To: aperson@dom.ain +From: bperson@dom.ain + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +hello world +--BOUNDARY-- + +''') + + def test_message_external_body(self): + eq = self.assertEqual + msg = self._msgobj('msg_36.txt') + eq(len(msg.get_payload()), 2) + msg1 = msg.get_payload(1) + eq(msg1.get_content_type(), 'multipart/alternative') + eq(len(msg1.get_payload()), 2) + for subpart in msg1.get_payload(): + eq(subpart.get_content_type(), 'message/external-body') + eq(len(subpart.get_payload()), 1) + subsubpart = subpart.get_payload(0) + eq(subsubpart.get_content_type(), 'text/plain') + + def test_double_boundary(self): + # msg_37.txt is a multipart that contains two dash-boundary's in a + # row. Our interpretation of RFC 2046 calls for ignoring the second + # and subsequent boundaries. + msg = self._msgobj('msg_37.txt') + self.assertEqual(len(msg.get_payload()), 3) + + def test_nested_inner_contains_outer_boundary(self): + eq = self.ndiffAssertEqual + # msg_38.txt has an inner part that contains outer boundaries. My + # interpretation of RFC 2046 (based on sections 5.1 and 5.1.2) say + # these are illegal and should be interpreted as unterminated inner + # parts. + msg = self._msgobj('msg_38.txt') + sfp = StringIO() + Iterators._structure(msg, sfp) + eq(sfp.getvalue(), """\ +multipart/mixed + multipart/mixed + multipart/alternative + text/plain + text/plain + text/plain + text/plain +""") + + def test_nested_with_same_boundary(self): + eq = self.ndiffAssertEqual + # msg 39.txt is similarly evil in that it's got inner parts that use + # the same boundary as outer parts. Again, I believe the way this is + # parsed is closest to the spirit of RFC 2046 + msg = self._msgobj('msg_39.txt') + sfp = StringIO() + Iterators._structure(msg, sfp) + eq(sfp.getvalue(), """\ +multipart/mixed + multipart/mixed + multipart/alternative + application/octet-stream + application/octet-stream + text/plain +""") + + def test_boundary_in_non_multipart(self): + msg = self._msgobj('msg_40.txt') + self.assertEqual(msg.as_string(), '''\ +MIME-Version: 1.0 +Content-Type: text/html; boundary="--961284236552522269" + +----961284236552522269 +Content-Type: text/html; +Content-Transfer-Encoding: 7Bit + + + +----961284236552522269-- +''') + + def test_boundary_with_leading_space(self): + eq = self.assertEqual + msg = email.message_from_string('''\ +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary=" XXXX" + +-- XXXX +Content-Type: text/plain + + +-- XXXX +Content-Type: text/plain + +-- XXXX-- +''') + self.assertTrue(msg.is_multipart()) + eq(msg.get_boundary(), ' XXXX') + eq(len(msg.get_payload()), 2) + + def test_boundary_without_trailing_newline(self): + m = Parser().parsestr("""\ +Content-Type: multipart/mixed; boundary="===============0012394164==" +MIME-Version: 1.0 + +--===============0012394164== +Content-Type: image/file1.jpg +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 + +YXNkZg== +--===============0012394164==--""") + self.assertEqual(m.get_payload(0).get_payload(), 'YXNkZg==') + + + +# Test some badly formatted messages +class TestNonConformant(TestEmailBase): + def test_parse_missing_minor_type(self): + eq = self.assertEqual + msg = self._msgobj('msg_14.txt') + eq(msg.get_content_type(), 'text/plain') + eq(msg.get_content_maintype(), 'text') + eq(msg.get_content_subtype(), 'plain') + + def test_same_boundary_inner_outer(self): + unless = self.assertTrue + msg = self._msgobj('msg_15.txt') + # XXX We can probably eventually do better + inner = msg.get_payload(0) + unless(hasattr(inner, 'defects')) + self.assertEqual(len(inner.defects), 1) + unless(isinstance(inner.defects[0], + Errors.StartBoundaryNotFoundDefect)) + + def test_multipart_no_boundary(self): + unless = self.assertTrue + msg = self._msgobj('msg_25.txt') + unless(isinstance(msg.get_payload(), str)) + self.assertEqual(len(msg.defects), 2) + unless(isinstance(msg.defects[0], Errors.NoBoundaryInMultipartDefect)) + unless(isinstance(msg.defects[1], + Errors.MultipartInvariantViolationDefect)) + + def test_invalid_content_type(self): + eq = self.assertEqual + neq = self.ndiffAssertEqual + msg = Message() + # RFC 2045, $5.2 says invalid yields text/plain + msg['Content-Type'] = 'text' + eq(msg.get_content_maintype(), 'text') + eq(msg.get_content_subtype(), 'plain') + eq(msg.get_content_type(), 'text/plain') + # Clear the old value and try something /really/ invalid + del msg['content-type'] + msg['Content-Type'] = 'foo' + eq(msg.get_content_maintype(), 'text') + eq(msg.get_content_subtype(), 'plain') + eq(msg.get_content_type(), 'text/plain') + # Still, make sure that the message is idempotently generated + s = StringIO() + g = Generator(s) + g.flatten(msg) + neq(s.getvalue(), 'Content-Type: foo\n\n') + + def test_no_start_boundary(self): + eq = self.ndiffAssertEqual + msg = self._msgobj('msg_31.txt') + eq(msg.get_payload(), """\ +--BOUNDARY +Content-Type: text/plain + +message 1 + +--BOUNDARY +Content-Type: text/plain + +message 2 + +--BOUNDARY-- +""") + + def test_no_separating_blank_line(self): + eq = self.ndiffAssertEqual + msg = self._msgobj('msg_35.txt') + eq(msg.as_string(), """\ +From: aperson@dom.ain +To: bperson@dom.ain +Subject: here's something interesting + +counter to RFC 2822, there's no separating newline here +""") + + def test_lying_multipart(self): + unless = self.assertTrue + msg = self._msgobj('msg_41.txt') + unless(hasattr(msg, 'defects')) + self.assertEqual(len(msg.defects), 2) + unless(isinstance(msg.defects[0], Errors.NoBoundaryInMultipartDefect)) + unless(isinstance(msg.defects[1], + Errors.MultipartInvariantViolationDefect)) + + def test_missing_start_boundary(self): + outer = self._msgobj('msg_42.txt') + # The message structure is: + # + # multipart/mixed + # text/plain + # message/rfc822 + # multipart/mixed [*] + # + # [*] This message is missing its start boundary + bad = outer.get_payload(1).get_payload(0) + self.assertEqual(len(bad.defects), 1) + self.assertTrue(isinstance(bad.defects[0], + Errors.StartBoundaryNotFoundDefect)) + + def test_first_line_is_continuation_header(self): + eq = self.assertEqual + m = ' Line 1\nLine 2\nLine 3' + msg = email.message_from_string(m) + eq(msg.keys(), []) + eq(msg.get_payload(), 'Line 2\nLine 3') + eq(len(msg.defects), 1) + self.assertTrue(isinstance(msg.defects[0], + Errors.FirstHeaderLineIsContinuationDefect)) + eq(msg.defects[0].line, ' Line 1\n') + + + + +# Test RFC 2047 header encoding and decoding +class TestRFC2047(unittest.TestCase): + def test_rfc2047_multiline(self): + eq = self.assertEqual + s = """Re: =?mac-iceland?q?r=8Aksm=9Arg=8Cs?= baz + foo bar =?mac-iceland?q?r=8Aksm=9Arg=8Cs?=""" + dh = decode_header(s) + eq(dh, [ + ('Re:', None), + ('r\x8aksm\x9arg\x8cs', 'mac-iceland'), + ('baz foo bar', None), + ('r\x8aksm\x9arg\x8cs', 'mac-iceland')]) + eq(str(make_header(dh)), + """Re: =?mac-iceland?q?r=8Aksm=9Arg=8Cs?= baz foo bar + =?mac-iceland?q?r=8Aksm=9Arg=8Cs?=""") + + def test_whitespace_eater_unicode(self): + eq = self.assertEqual + s = '=?ISO-8859-1?Q?Andr=E9?= Pirard ' + dh = decode_header(s) + eq(dh, [('Andr\xe9', 'iso-8859-1'), ('Pirard ', None)]) + hu = unicode(make_header(dh)).encode('latin-1') + eq(hu, 'Andr\xe9 Pirard ') + + def test_whitespace_eater_unicode_2(self): + eq = self.assertEqual + s = 'The =?iso-8859-1?b?cXVpY2sgYnJvd24gZm94?= jumped over the =?iso-8859-1?b?bGF6eSBkb2c=?=' + dh = decode_header(s) + eq(dh, [('The', None), ('quick brown fox', 'iso-8859-1'), + ('jumped over the', None), ('lazy dog', 'iso-8859-1')]) + hu = make_header(dh).__unicode__() + eq(hu, u'The quick brown fox jumped over the lazy dog') + + def test_rfc2047_without_whitespace(self): + s = 'Sm=?ISO-8859-1?B?9g==?=rg=?ISO-8859-1?B?5Q==?=sbord' + dh = decode_header(s) + self.assertEqual(dh, [(s, None)]) + + def test_rfc2047_with_whitespace(self): + s = 'Sm =?ISO-8859-1?B?9g==?= rg =?ISO-8859-1?B?5Q==?= sbord' + dh = decode_header(s) + self.assertEqual(dh, [('Sm', None), ('\xf6', 'iso-8859-1'), + ('rg', None), ('\xe5', 'iso-8859-1'), + ('sbord', None)]) + + def test_rfc2047_B_bad_padding(self): + s = '=?iso-8859-1?B?%s?=' + data = [ # only test complete bytes + ('dm==', 'v'), ('dm=', 'v'), ('dm', 'v'), + ('dmk=', 'vi'), ('dmk', 'vi') + ] + for q, a in data: + dh = decode_header(s % q) + self.assertEqual(dh, [(a, 'iso-8859-1')]) + + def test_rfc2047_Q_invalid_digits(self): + # issue 10004. + s = '=?iso-8659-1?Q?andr=e9=zz?=' + self.assertEqual(decode_header(s), + [(b'andr\xe9=zz', 'iso-8659-1')]) + + +# Test the MIMEMessage class +class TestMIMEMessage(TestEmailBase): + def setUp(self): + fp = openfile('msg_11.txt') + try: + self._text = fp.read() + finally: + fp.close() + + def test_type_error(self): + self.assertRaises(TypeError, MIMEMessage, 'a plain string') + + def test_valid_argument(self): + eq = self.assertEqual + unless = self.assertTrue + subject = 'A sub-message' + m = Message() + m['Subject'] = subject + r = MIMEMessage(m) + eq(r.get_content_type(), 'message/rfc822') + payload = r.get_payload() + unless(isinstance(payload, list)) + eq(len(payload), 1) + subpart = payload[0] + unless(subpart is m) + eq(subpart['subject'], subject) + + def test_bad_multipart(self): + eq = self.assertEqual + msg1 = Message() + msg1['Subject'] = 'subpart 1' + msg2 = Message() + msg2['Subject'] = 'subpart 2' + r = MIMEMessage(msg1) + self.assertRaises(Errors.MultipartConversionError, r.attach, msg2) + + def test_generate(self): + # First craft the message to be encapsulated + m = Message() + m['Subject'] = 'An enclosed message' + m.set_payload('Here is the body of the message.\n') + r = MIMEMessage(m) + r['Subject'] = 'The enclosing message' + s = StringIO() + g = Generator(s) + g.flatten(r) + self.assertEqual(s.getvalue(), """\ +Content-Type: message/rfc822 +MIME-Version: 1.0 +Subject: The enclosing message + +Subject: An enclosed message + +Here is the body of the message. +""") + + def test_parse_message_rfc822(self): + eq = self.assertEqual + unless = self.assertTrue + msg = self._msgobj('msg_11.txt') + eq(msg.get_content_type(), 'message/rfc822') + payload = msg.get_payload() + unless(isinstance(payload, list)) + eq(len(payload), 1) + submsg = payload[0] + self.assertTrue(isinstance(submsg, Message)) + eq(submsg['subject'], 'An enclosed message') + eq(submsg.get_payload(), 'Here is the body of the message.\n') + + def test_dsn(self): + eq = self.assertEqual + unless = self.assertTrue + # msg 16 is a Delivery Status Notification, see RFC 1894 + msg = self._msgobj('msg_16.txt') + eq(msg.get_content_type(), 'multipart/report') + unless(msg.is_multipart()) + eq(len(msg.get_payload()), 3) + # Subpart 1 is a text/plain, human readable section + subpart = msg.get_payload(0) + eq(subpart.get_content_type(), 'text/plain') + eq(subpart.get_payload(), """\ +This report relates to a message you sent with the following header fields: + + Message-id: <002001c144a6$8752e060$56104586@oxy.edu> + Date: Sun, 23 Sep 2001 20:10:55 -0700 + From: "Ian T. Henry" + To: SoCal Raves + Subject: [scr] yeah for Ians!! + +Your message cannot be delivered to the following recipients: + + Recipient address: jangel1@cougar.noc.ucla.edu + Reason: recipient reached disk quota + +""") + # Subpart 2 contains the machine parsable DSN information. It + # consists of two blocks of headers, represented by two nested Message + # objects. + subpart = msg.get_payload(1) + eq(subpart.get_content_type(), 'message/delivery-status') + eq(len(subpart.get_payload()), 2) + # message/delivery-status should treat each block as a bunch of + # headers, i.e. a bunch of Message objects. + dsn1 = subpart.get_payload(0) + unless(isinstance(dsn1, Message)) + eq(dsn1['original-envelope-id'], '0GK500B4HD0888@cougar.noc.ucla.edu') + eq(dsn1.get_param('dns', header='reporting-mta'), '') + # Try a missing one + eq(dsn1.get_param('nsd', header='reporting-mta'), None) + dsn2 = subpart.get_payload(1) + unless(isinstance(dsn2, Message)) + eq(dsn2['action'], 'failed') + eq(dsn2.get_params(header='original-recipient'), + [('rfc822', ''), ('jangel1@cougar.noc.ucla.edu', '')]) + eq(dsn2.get_param('rfc822', header='final-recipient'), '') + # Subpart 3 is the original message + subpart = msg.get_payload(2) + eq(subpart.get_content_type(), 'message/rfc822') + payload = subpart.get_payload() + unless(isinstance(payload, list)) + eq(len(payload), 1) + subsubpart = payload[0] + unless(isinstance(subsubpart, Message)) + eq(subsubpart.get_content_type(), 'text/plain') + eq(subsubpart['message-id'], + '<002001c144a6$8752e060$56104586@oxy.edu>') + + def test_epilogue(self): + eq = self.ndiffAssertEqual + fp = openfile('msg_21.txt') + try: + text = fp.read() + finally: + fp.close() + msg = Message() + msg['From'] = 'aperson@dom.ain' + msg['To'] = 'bperson@dom.ain' + msg['Subject'] = 'Test' + msg.preamble = 'MIME message' + msg.epilogue = 'End of MIME message\n' + msg1 = MIMEText('One') + msg2 = MIMEText('Two') + msg.add_header('Content-Type', 'multipart/mixed', boundary='BOUNDARY') + msg.attach(msg1) + msg.attach(msg2) + sfp = StringIO() + g = Generator(sfp) + g.flatten(msg) + eq(sfp.getvalue(), text) + + def test_no_nl_preamble(self): + eq = self.ndiffAssertEqual + msg = Message() + msg['From'] = 'aperson@dom.ain' + msg['To'] = 'bperson@dom.ain' + msg['Subject'] = 'Test' + msg.preamble = 'MIME message' + msg.epilogue = '' + msg1 = MIMEText('One') + msg2 = MIMEText('Two') + msg.add_header('Content-Type', 'multipart/mixed', boundary='BOUNDARY') + msg.attach(msg1) + msg.attach(msg2) + eq(msg.as_string(), """\ +From: aperson@dom.ain +To: bperson@dom.ain +Subject: Test +Content-Type: multipart/mixed; boundary="BOUNDARY" + +MIME message +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +One +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +Two +--BOUNDARY-- +""") + + def test_default_type(self): + eq = self.assertEqual + fp = openfile('msg_30.txt') + try: + msg = email.message_from_file(fp) + finally: + fp.close() + container1 = msg.get_payload(0) + eq(container1.get_default_type(), 'message/rfc822') + eq(container1.get_content_type(), 'message/rfc822') + container2 = msg.get_payload(1) + eq(container2.get_default_type(), 'message/rfc822') + eq(container2.get_content_type(), 'message/rfc822') + container1a = container1.get_payload(0) + eq(container1a.get_default_type(), 'text/plain') + eq(container1a.get_content_type(), 'text/plain') + container2a = container2.get_payload(0) + eq(container2a.get_default_type(), 'text/plain') + eq(container2a.get_content_type(), 'text/plain') + + def test_default_type_with_explicit_container_type(self): + eq = self.assertEqual + fp = openfile('msg_28.txt') + try: + msg = email.message_from_file(fp) + finally: + fp.close() + container1 = msg.get_payload(0) + eq(container1.get_default_type(), 'message/rfc822') + eq(container1.get_content_type(), 'message/rfc822') + container2 = msg.get_payload(1) + eq(container2.get_default_type(), 'message/rfc822') + eq(container2.get_content_type(), 'message/rfc822') + container1a = container1.get_payload(0) + eq(container1a.get_default_type(), 'text/plain') + eq(container1a.get_content_type(), 'text/plain') + container2a = container2.get_payload(0) + eq(container2a.get_default_type(), 'text/plain') + eq(container2a.get_content_type(), 'text/plain') + + def test_default_type_non_parsed(self): + eq = self.assertEqual + neq = self.ndiffAssertEqual + # Set up container + container = MIMEMultipart('digest', 'BOUNDARY') + container.epilogue = '' + # Set up subparts + subpart1a = MIMEText('message 1\n') + subpart2a = MIMEText('message 2\n') + subpart1 = MIMEMessage(subpart1a) + subpart2 = MIMEMessage(subpart2a) + container.attach(subpart1) + container.attach(subpart2) + eq(subpart1.get_content_type(), 'message/rfc822') + eq(subpart1.get_default_type(), 'message/rfc822') + eq(subpart2.get_content_type(), 'message/rfc822') + eq(subpart2.get_default_type(), 'message/rfc822') + neq(container.as_string(0), '''\ +Content-Type: multipart/digest; boundary="BOUNDARY" +MIME-Version: 1.0 + +--BOUNDARY +Content-Type: message/rfc822 +MIME-Version: 1.0 + +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +message 1 + +--BOUNDARY +Content-Type: message/rfc822 +MIME-Version: 1.0 + +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +message 2 + +--BOUNDARY-- +''') + del subpart1['content-type'] + del subpart1['mime-version'] + del subpart2['content-type'] + del subpart2['mime-version'] + eq(subpart1.get_content_type(), 'message/rfc822') + eq(subpart1.get_default_type(), 'message/rfc822') + eq(subpart2.get_content_type(), 'message/rfc822') + eq(subpart2.get_default_type(), 'message/rfc822') + neq(container.as_string(0), '''\ +Content-Type: multipart/digest; boundary="BOUNDARY" +MIME-Version: 1.0 + +--BOUNDARY + +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +message 1 + +--BOUNDARY + +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +message 2 + +--BOUNDARY-- +''') + + def test_mime_attachments_in_constructor(self): + eq = self.assertEqual + text1 = MIMEText('') + text2 = MIMEText('') + msg = MIMEMultipart(_subparts=(text1, text2)) + eq(len(msg.get_payload()), 2) + eq(msg.get_payload(0), text1) + eq(msg.get_payload(1), text2) + + def test_default_multipart_constructor(self): + msg = MIMEMultipart() + self.assertTrue(msg.is_multipart()) + + +# A general test of parser->model->generator idempotency. IOW, read a message +# in, parse it into a message object tree, then without touching the tree, +# regenerate the plain text. The original text and the transformed text +# should be identical. Note: that we ignore the Unix-From since that may +# contain a changed date. +class TestIdempotent(TestEmailBase): + def _msgobj(self, filename): + fp = openfile(filename) + try: + data = fp.read() + finally: + fp.close() + msg = email.message_from_string(data) + return msg, data + + def _idempotent(self, msg, text): + eq = self.ndiffAssertEqual + s = StringIO() + g = Generator(s, maxheaderlen=0) + g.flatten(msg) + eq(text, s.getvalue()) + + def test_parse_text_message(self): + eq = self.assertEqual + msg, text = self._msgobj('msg_01.txt') + eq(msg.get_content_type(), 'text/plain') + eq(msg.get_content_maintype(), 'text') + eq(msg.get_content_subtype(), 'plain') + eq(msg.get_params()[1], ('charset', 'us-ascii')) + eq(msg.get_param('charset'), 'us-ascii') + eq(msg.preamble, None) + eq(msg.epilogue, None) + self._idempotent(msg, text) + + def test_parse_untyped_message(self): + eq = self.assertEqual + msg, text = self._msgobj('msg_03.txt') + eq(msg.get_content_type(), 'text/plain') + eq(msg.get_params(), None) + eq(msg.get_param('charset'), None) + self._idempotent(msg, text) + + def test_simple_multipart(self): + msg, text = self._msgobj('msg_04.txt') + self._idempotent(msg, text) + + def test_MIME_digest(self): + msg, text = self._msgobj('msg_02.txt') + self._idempotent(msg, text) + + def test_long_header(self): + msg, text = self._msgobj('msg_27.txt') + self._idempotent(msg, text) + + def test_MIME_digest_with_part_headers(self): + msg, text = self._msgobj('msg_28.txt') + self._idempotent(msg, text) + + def test_mixed_with_image(self): + msg, text = self._msgobj('msg_06.txt') + self._idempotent(msg, text) + + def test_multipart_report(self): + msg, text = self._msgobj('msg_05.txt') + self._idempotent(msg, text) + + def test_dsn(self): + msg, text = self._msgobj('msg_16.txt') + self._idempotent(msg, text) + + def test_preamble_epilogue(self): + msg, text = self._msgobj('msg_21.txt') + self._idempotent(msg, text) + + def test_multipart_one_part(self): + msg, text = self._msgobj('msg_23.txt') + self._idempotent(msg, text) + + def test_multipart_no_parts(self): + msg, text = self._msgobj('msg_24.txt') + self._idempotent(msg, text) + + def test_no_start_boundary(self): + msg, text = self._msgobj('msg_31.txt') + self._idempotent(msg, text) + + def test_rfc2231_charset(self): + msg, text = self._msgobj('msg_32.txt') + self._idempotent(msg, text) + + def test_more_rfc2231_parameters(self): + msg, text = self._msgobj('msg_33.txt') + self._idempotent(msg, text) + + def test_text_plain_in_a_multipart_digest(self): + msg, text = self._msgobj('msg_34.txt') + self._idempotent(msg, text) + + def test_nested_multipart_mixeds(self): + msg, text = self._msgobj('msg_12a.txt') + self._idempotent(msg, text) + + def test_message_external_body_idempotent(self): + msg, text = self._msgobj('msg_36.txt') + self._idempotent(msg, text) + + def test_content_type(self): + eq = self.assertEqual + unless = self.assertTrue + # Get a message object and reset the seek pointer for other tests + msg, text = self._msgobj('msg_05.txt') + eq(msg.get_content_type(), 'multipart/report') + # Test the Content-Type: parameters + params = {} + for pk, pv in msg.get_params(): + params[pk] = pv + eq(params['report-type'], 'delivery-status') + eq(params['boundary'], 'D1690A7AC1.996856090/mail.example.com') + eq(msg.preamble, 'This is a MIME-encapsulated message.\n') + eq(msg.epilogue, '\n') + eq(len(msg.get_payload()), 3) + # Make sure the subparts are what we expect + msg1 = msg.get_payload(0) + eq(msg1.get_content_type(), 'text/plain') + eq(msg1.get_payload(), 'Yadda yadda yadda\n') + msg2 = msg.get_payload(1) + eq(msg2.get_content_type(), 'text/plain') + eq(msg2.get_payload(), 'Yadda yadda yadda\n') + msg3 = msg.get_payload(2) + eq(msg3.get_content_type(), 'message/rfc822') + self.assertTrue(isinstance(msg3, Message)) + payload = msg3.get_payload() + unless(isinstance(payload, list)) + eq(len(payload), 1) + msg4 = payload[0] + unless(isinstance(msg4, Message)) + eq(msg4.get_payload(), 'Yadda yadda yadda\n') + + def test_parser(self): + eq = self.assertEqual + unless = self.assertTrue + msg, text = self._msgobj('msg_06.txt') + # Check some of the outer headers + eq(msg.get_content_type(), 'message/rfc822') + # Make sure the payload is a list of exactly one sub-Message, and that + # that submessage has a type of text/plain + payload = msg.get_payload() + unless(isinstance(payload, list)) + eq(len(payload), 1) + msg1 = payload[0] + self.assertTrue(isinstance(msg1, Message)) + eq(msg1.get_content_type(), 'text/plain') + self.assertTrue(isinstance(msg1.get_payload(), str)) + eq(msg1.get_payload(), '\n') + + + +# Test various other bits of the package's functionality +class TestMiscellaneous(TestEmailBase): + def test_message_from_string(self): + fp = openfile('msg_01.txt') + try: + text = fp.read() + finally: + fp.close() + msg = email.message_from_string(text) + s = StringIO() + # Don't wrap/continue long headers since we're trying to test + # idempotency. + g = Generator(s, maxheaderlen=0) + g.flatten(msg) + self.assertEqual(text, s.getvalue()) + + def test_message_from_file(self): + fp = openfile('msg_01.txt') + try: + text = fp.read() + fp.seek(0) + msg = email.message_from_file(fp) + s = StringIO() + # Don't wrap/continue long headers since we're trying to test + # idempotency. + g = Generator(s, maxheaderlen=0) + g.flatten(msg) + self.assertEqual(text, s.getvalue()) + finally: + fp.close() + + def test_message_from_string_with_class(self): + unless = self.assertTrue + fp = openfile('msg_01.txt') + try: + text = fp.read() + finally: + fp.close() + # Create a subclass + class MyMessage(Message): + pass + + msg = email.message_from_string(text, MyMessage) + unless(isinstance(msg, MyMessage)) + # Try something more complicated + fp = openfile('msg_02.txt') + try: + text = fp.read() + finally: + fp.close() + msg = email.message_from_string(text, MyMessage) + for subpart in msg.walk(): + unless(isinstance(subpart, MyMessage)) + + def test_message_from_file_with_class(self): + unless = self.assertTrue + # Create a subclass + class MyMessage(Message): + pass + + fp = openfile('msg_01.txt') + try: + msg = email.message_from_file(fp, MyMessage) + finally: + fp.close() + unless(isinstance(msg, MyMessage)) + # Try something more complicated + fp = openfile('msg_02.txt') + try: + msg = email.message_from_file(fp, MyMessage) + finally: + fp.close() + for subpart in msg.walk(): + unless(isinstance(subpart, MyMessage)) + + def test__all__(self): + module = __import__('email') + all = module.__all__ + all.sort() + self.assertEqual(all, [ + # Old names + 'Charset', 'Encoders', 'Errors', 'Generator', + 'Header', 'Iterators', 'MIMEAudio', 'MIMEBase', + 'MIMEImage', 'MIMEMessage', 'MIMEMultipart', + 'MIMENonMultipart', 'MIMEText', 'Message', + 'Parser', 'Utils', 'base64MIME', + # new names + 'base64mime', 'charset', 'encoders', 'errors', 'generator', + 'header', 'iterators', 'message', 'message_from_file', + 'message_from_string', 'mime', 'parser', + 'quopriMIME', 'quoprimime', 'utils', + ]) + + def test_formatdate(self): + now = time.time() + self.assertEqual(Utils.parsedate(Utils.formatdate(now))[:6], + time.gmtime(now)[:6]) + + def test_formatdate_localtime(self): + now = time.time() + self.assertEqual( + Utils.parsedate(Utils.formatdate(now, localtime=True))[:6], + time.localtime(now)[:6]) + + def test_formatdate_usegmt(self): + now = time.time() + self.assertEqual( + Utils.formatdate(now, localtime=False), + time.strftime('%a, %d %b %Y %H:%M:%S -0000', time.gmtime(now))) + self.assertEqual( + Utils.formatdate(now, localtime=False, usegmt=True), + time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime(now))) + + def test_parsedate_none(self): + self.assertEqual(Utils.parsedate(''), None) + + def test_parsedate_compact(self): + # The FWS after the comma is optional + self.assertEqual(Utils.parsedate('Wed,3 Apr 2002 14:58:26 +0800'), + Utils.parsedate('Wed, 3 Apr 2002 14:58:26 +0800')) + + def test_parsedate_no_dayofweek(self): + eq = self.assertEqual + eq(Utils.parsedate_tz('25 Feb 2003 13:47:26 -0800'), + (2003, 2, 25, 13, 47, 26, 0, 1, -1, -28800)) + + def test_parsedate_compact_no_dayofweek(self): + eq = self.assertEqual + eq(Utils.parsedate_tz('5 Feb 2003 13:47:26 -0800'), + (2003, 2, 5, 13, 47, 26, 0, 1, -1, -28800)) + + def test_parsedate_acceptable_to_time_functions(self): + eq = self.assertEqual + timetup = Utils.parsedate('5 Feb 2003 13:47:26 -0800') + t = int(time.mktime(timetup)) + eq(time.localtime(t)[:6], timetup[:6]) + eq(int(time.strftime('%Y', timetup)), 2003) + timetup = Utils.parsedate_tz('5 Feb 2003 13:47:26 -0800') + t = int(time.mktime(timetup[:9])) + eq(time.localtime(t)[:6], timetup[:6]) + eq(int(time.strftime('%Y', timetup[:9])), 2003) + + def test_mktime_tz(self): + self.assertEqual(Utils.mktime_tz((1970, 1, 1, 0, 0, 0, + -1, -1, -1, 0)), 0) + self.assertEqual(Utils.mktime_tz((1970, 1, 1, 0, 0, 0, + -1, -1, -1, 1234)), -1234) + + def test_parsedate_y2k(self): + """Test for parsing a date with a two-digit year. + + Parsing a date with a two-digit year should return the correct + four-digit year. RFC822 allows two-digit years, but RFC2822 (which + obsoletes RFC822) requires four-digit years. + + """ + self.assertEqual(Utils.parsedate_tz('25 Feb 03 13:47:26 -0800'), + Utils.parsedate_tz('25 Feb 2003 13:47:26 -0800')) + self.assertEqual(Utils.parsedate_tz('25 Feb 71 13:47:26 -0800'), + Utils.parsedate_tz('25 Feb 1971 13:47:26 -0800')) + + def test_parseaddr_empty(self): + self.assertEqual(Utils.parseaddr('<>'), ('', '')) + self.assertEqual(Utils.formataddr(Utils.parseaddr('<>')), '') + + def test_noquote_dump(self): + self.assertEqual( + Utils.formataddr(('A Silly Person', 'person@dom.ain')), + 'A Silly Person ') + + def test_escape_dump(self): + self.assertEqual( + Utils.formataddr(('A (Very) Silly Person', 'person@dom.ain')), + r'"A \(Very\) Silly Person" ') + a = r'A \(Special\) Person' + b = 'person@dom.ain' + self.assertEqual(Utils.parseaddr(Utils.formataddr((a, b))), (a, b)) + + def test_escape_backslashes(self): + self.assertEqual( + Utils.formataddr(('Arthur \Backslash\ Foobar', 'person@dom.ain')), + r'"Arthur \\Backslash\\ Foobar" ') + a = r'Arthur \Backslash\ Foobar' + b = 'person@dom.ain' + self.assertEqual(Utils.parseaddr(Utils.formataddr((a, b))), (a, b)) + + def test_name_with_dot(self): + x = 'John X. Doe ' + y = '"John X. Doe" ' + a, b = ('John X. Doe', 'jxd@example.com') + self.assertEqual(Utils.parseaddr(x), (a, b)) + self.assertEqual(Utils.parseaddr(y), (a, b)) + # formataddr() quotes the name if there's a dot in it + self.assertEqual(Utils.formataddr((a, b)), y) + + def test_parseaddr_preserves_quoted_pairs_in_addresses(self): + # issue 10005. Note that in the third test the second pair of + # backslashes is not actually a quoted pair because it is not inside a + # comment or quoted string: the address being parsed has a quoted + # string containing a quoted backslash, followed by 'example' and two + # backslashes, followed by another quoted string containing a space and + # the word 'example'. parseaddr copies those two backslashes + # literally. Per rfc5322 this is not technically correct since a \ may + # not appear in an address outside of a quoted string. It is probably + # a sensible Postel interpretation, though. + eq = self.assertEqual + eq(Utils.parseaddr('""example" example"@example.com'), + ('', '""example" example"@example.com')) + eq(Utils.parseaddr('"\\"example\\" example"@example.com'), + ('', '"\\"example\\" example"@example.com')) + eq(Utils.parseaddr('"\\\\"example\\\\" example"@example.com'), + ('', '"\\\\"example\\\\" example"@example.com')) + + def test_multiline_from_comment(self): + x = """\ +Foo +\tBar """ + self.assertEqual(Utils.parseaddr(x), ('Foo Bar', 'foo@example.com')) + + def test_quote_dump(self): + self.assertEqual( + Utils.formataddr(('A Silly; Person', 'person@dom.ain')), + r'"A Silly; Person" ') + + def test_fix_eols(self): + eq = self.assertEqual + eq(Utils.fix_eols('hello'), 'hello') + eq(Utils.fix_eols('hello\n'), 'hello\r\n') + eq(Utils.fix_eols('hello\r'), 'hello\r\n') + eq(Utils.fix_eols('hello\r\n'), 'hello\r\n') + eq(Utils.fix_eols('hello\n\r'), 'hello\r\n\r\n') + + def test_charset_richcomparisons(self): + eq = self.assertEqual + ne = self.assertNotEqual + cset1 = Charset() + cset2 = Charset() + eq(cset1, 'us-ascii') + eq(cset1, 'US-ASCII') + eq(cset1, 'Us-AsCiI') + eq('us-ascii', cset1) + eq('US-ASCII', cset1) + eq('Us-AsCiI', cset1) + ne(cset1, 'usascii') + ne(cset1, 'USASCII') + ne(cset1, 'UsAsCiI') + ne('usascii', cset1) + ne('USASCII', cset1) + ne('UsAsCiI', cset1) + eq(cset1, cset2) + eq(cset2, cset1) + + def test_getaddresses(self): + eq = self.assertEqual + eq(Utils.getaddresses(['aperson@dom.ain (Al Person)', + 'Bud Person ']), + [('Al Person', 'aperson@dom.ain'), + ('Bud Person', 'bperson@dom.ain')]) + + def test_getaddresses_nasty(self): + eq = self.assertEqual + eq(Utils.getaddresses(['foo: ;']), [('', '')]) + eq(Utils.getaddresses( + ['[]*-- =~$']), + [('', ''), ('', ''), ('', '*--')]) + eq(Utils.getaddresses( + ['foo: ;', '"Jason R. Mastaler" ']), + [('', ''), ('Jason R. Mastaler', 'jason@dom.ain')]) + + def test_getaddresses_embedded_comment(self): + """Test proper handling of a nested comment""" + eq = self.assertEqual + addrs = Utils.getaddresses(['User ((nested comment)) ']) + eq(addrs[0][1], 'foo@bar.com') + + def test_utils_quote_unquote(self): + eq = self.assertEqual + msg = Message() + msg.add_header('content-disposition', 'attachment', + filename='foo\\wacky"name') + eq(msg.get_filename(), 'foo\\wacky"name') + + def test_get_body_encoding_with_bogus_charset(self): + charset = Charset('not a charset') + self.assertEqual(charset.get_body_encoding(), 'base64') + + def test_get_body_encoding_with_uppercase_charset(self): + eq = self.assertEqual + msg = Message() + msg['Content-Type'] = 'text/plain; charset=UTF-8' + eq(msg['content-type'], 'text/plain; charset=UTF-8') + charsets = msg.get_charsets() + eq(len(charsets), 1) + eq(charsets[0], 'utf-8') + charset = Charset(charsets[0]) + eq(charset.get_body_encoding(), 'base64') + msg.set_payload('hello world', charset=charset) + eq(msg.get_payload(), 'aGVsbG8gd29ybGQ=\n') + eq(msg.get_payload(decode=True), 'hello world') + eq(msg['content-transfer-encoding'], 'base64') + # Try another one + msg = Message() + msg['Content-Type'] = 'text/plain; charset="US-ASCII"' + charsets = msg.get_charsets() + eq(len(charsets), 1) + eq(charsets[0], 'us-ascii') + charset = Charset(charsets[0]) + eq(charset.get_body_encoding(), Encoders.encode_7or8bit) + msg.set_payload('hello world', charset=charset) + eq(msg.get_payload(), 'hello world') + eq(msg['content-transfer-encoding'], '7bit') + + def test_charsets_case_insensitive(self): + lc = Charset('us-ascii') + uc = Charset('US-ASCII') + self.assertEqual(lc.get_body_encoding(), uc.get_body_encoding()) + + def test_partial_falls_inside_message_delivery_status(self): + eq = self.ndiffAssertEqual + # The Parser interface provides chunks of data to FeedParser in 8192 + # byte gulps. SF bug #1076485 found one of those chunks inside + # message/delivery-status header block, which triggered an + # unreadline() of NeedMoreData. + msg = self._msgobj('msg_43.txt') + sfp = StringIO() + Iterators._structure(msg, sfp) + eq(sfp.getvalue(), """\ +multipart/report + text/plain + message/delivery-status + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/rfc822-headers +""") + + + +# Test the iterator/generators +class TestIterators(TestEmailBase): + def test_body_line_iterator(self): + eq = self.assertEqual + neq = self.ndiffAssertEqual + # First a simple non-multipart message + msg = self._msgobj('msg_01.txt') + it = Iterators.body_line_iterator(msg) + lines = list(it) + eq(len(lines), 6) + neq(EMPTYSTRING.join(lines), msg.get_payload()) + # Now a more complicated multipart + msg = self._msgobj('msg_02.txt') + it = Iterators.body_line_iterator(msg) + lines = list(it) + eq(len(lines), 43) + fp = openfile('msg_19.txt') + try: + neq(EMPTYSTRING.join(lines), fp.read()) + finally: + fp.close() + + def test_typed_subpart_iterator(self): + eq = self.assertEqual + msg = self._msgobj('msg_04.txt') + it = Iterators.typed_subpart_iterator(msg, 'text') + lines = [] + subparts = 0 + for subpart in it: + subparts += 1 + lines.append(subpart.get_payload()) + eq(subparts, 2) + eq(EMPTYSTRING.join(lines), """\ +a simple kind of mirror +to reflect upon our own +a simple kind of mirror +to reflect upon our own +""") + + def test_typed_subpart_iterator_default_type(self): + eq = self.assertEqual + msg = self._msgobj('msg_03.txt') + it = Iterators.typed_subpart_iterator(msg, 'text', 'plain') + lines = [] + subparts = 0 + for subpart in it: + subparts += 1 + lines.append(subpart.get_payload()) + eq(subparts, 1) + eq(EMPTYSTRING.join(lines), """\ + +Hi, + +Do you like this message? + +-Me +""") + + def test_pushCR_LF(self): + '''FeedParser BufferedSubFile.push() assumed it received complete + line endings. A CR ending one push() followed by a LF starting + the next push() added an empty line. + ''' + imt = [ + ("a\r \n", 2), + ("b", 0), + ("c\n", 1), + ("", 0), + ("d\r\n", 1), + ("e\r", 0), + ("\nf", 1), + ("\r\n", 1), + ] + from email.feedparser import BufferedSubFile, NeedMoreData + bsf = BufferedSubFile() + om = [] + nt = 0 + for il, n in imt: + bsf.push(il) + nt += n + n1 = 0 + while True: + ol = bsf.readline() + if ol == NeedMoreData: + break + om.append(ol) + n1 += 1 + self.assertTrue(n == n1) + self.assertTrue(len(om) == nt) + self.assertTrue(''.join([il for il, n in imt]) == ''.join(om)) + + + +class TestParsers(TestEmailBase): + def test_header_parser(self): + eq = self.assertEqual + # Parse only the headers of a complex multipart MIME document + fp = openfile('msg_02.txt') + try: + msg = HeaderParser().parse(fp) + finally: + fp.close() + eq(msg['from'], 'ppp-request@zzz.org') + eq(msg['to'], 'ppp@zzz.org') + eq(msg.get_content_type(), 'multipart/mixed') + self.assertFalse(msg.is_multipart()) + self.assertTrue(isinstance(msg.get_payload(), str)) + + def test_whitespace_continuation(self): + eq = self.assertEqual + # This message contains a line after the Subject: header that has only + # whitespace, but it is not empty! + msg = email.message_from_string("""\ +From: aperson@dom.ain +To: bperson@dom.ain +Subject: the next line has a space on it +\x20 +Date: Mon, 8 Apr 2002 15:09:19 -0400 +Message-ID: spam + +Here's the message body +""") + eq(msg['subject'], 'the next line has a space on it\n ') + eq(msg['message-id'], 'spam') + eq(msg.get_payload(), "Here's the message body\n") + + def test_whitespace_continuation_last_header(self): + eq = self.assertEqual + # Like the previous test, but the subject line is the last + # header. + msg = email.message_from_string("""\ +From: aperson@dom.ain +To: bperson@dom.ain +Date: Mon, 8 Apr 2002 15:09:19 -0400 +Message-ID: spam +Subject: the next line has a space on it +\x20 + +Here's the message body +""") + eq(msg['subject'], 'the next line has a space on it\n ') + eq(msg['message-id'], 'spam') + eq(msg.get_payload(), "Here's the message body\n") + + def test_crlf_separation(self): + eq = self.assertEqual + fp = openfile('msg_26.txt', mode='rb') + try: + msg = Parser().parse(fp) + finally: + fp.close() + eq(len(msg.get_payload()), 2) + part1 = msg.get_payload(0) + eq(part1.get_content_type(), 'text/plain') + eq(part1.get_payload(), 'Simple email with attachment.\r\n\r\n') + part2 = msg.get_payload(1) + eq(part2.get_content_type(), 'application/riscos') + + def test_multipart_digest_with_extra_mime_headers(self): + eq = self.assertEqual + neq = self.ndiffAssertEqual + fp = openfile('msg_28.txt') + try: + msg = email.message_from_file(fp) + finally: + fp.close() + # Structure is: + # multipart/digest + # message/rfc822 + # text/plain + # message/rfc822 + # text/plain + eq(msg.is_multipart(), 1) + eq(len(msg.get_payload()), 2) + part1 = msg.get_payload(0) + eq(part1.get_content_type(), 'message/rfc822') + eq(part1.is_multipart(), 1) + eq(len(part1.get_payload()), 1) + part1a = part1.get_payload(0) + eq(part1a.is_multipart(), 0) + eq(part1a.get_content_type(), 'text/plain') + neq(part1a.get_payload(), 'message 1\n') + # next message/rfc822 + part2 = msg.get_payload(1) + eq(part2.get_content_type(), 'message/rfc822') + eq(part2.is_multipart(), 1) + eq(len(part2.get_payload()), 1) + part2a = part2.get_payload(0) + eq(part2a.is_multipart(), 0) + eq(part2a.get_content_type(), 'text/plain') + neq(part2a.get_payload(), 'message 2\n') + + def test_three_lines(self): + # A bug report by Andrew McNamara + lines = ['From: Andrew Person From', 'From']) + eq(msg.get_payload(), 'body') + + def test_rfc2822_space_not_allowed_in_header(self): + eq = self.assertEqual + m = '>From foo@example.com 11:25:53\nFrom: bar\n!"#QUX;~: zoo\n\nbody' + msg = email.message_from_string(m) + eq(len(msg.keys()), 0) + + def test_rfc2822_one_character_header(self): + eq = self.assertEqual + m = 'A: first header\nB: second header\nCC: third header\n\nbody' + msg = email.message_from_string(m) + headers = msg.keys() + headers.sort() + eq(headers, ['A', 'B', 'CC']) + eq(msg.get_payload(), 'body') + + def test_CRLFLF_at_end_of_part(self): + # issue 5610: feedparser should not eat two chars from body part ending + # with "\r\n\n". + m = ( + "From: foo@bar.com\n" + "To: baz\n" + "Mime-Version: 1.0\n" + "Content-Type: multipart/mixed; boundary=BOUNDARY\n" + "\n" + "--BOUNDARY\n" + "Content-Type: text/plain\n" + "\n" + "body ending with CRLF newline\r\n" + "\n" + "--BOUNDARY--\n" + ) + msg = email.message_from_string(m) + self.assertTrue(msg.get_payload(0).get_payload().endswith('\r\n')) + + +class TestBase64(unittest.TestCase): + def test_len(self): + eq = self.assertEqual + eq(base64MIME.base64_len('hello'), + len(base64MIME.encode('hello', eol=''))) + for size in range(15): + if size == 0 : bsize = 0 + elif size <= 3 : bsize = 4 + elif size <= 6 : bsize = 8 + elif size <= 9 : bsize = 12 + elif size <= 12: bsize = 16 + else : bsize = 20 + eq(base64MIME.base64_len('x'*size), bsize) + + def test_decode(self): + eq = self.assertEqual + eq(base64MIME.decode(''), '') + eq(base64MIME.decode('aGVsbG8='), 'hello') + eq(base64MIME.decode('aGVsbG8=', 'X'), 'hello') + eq(base64MIME.decode('aGVsbG8NCndvcmxk\n', 'X'), 'helloXworld') + + def test_encode(self): + eq = self.assertEqual + eq(base64MIME.encode(''), '') + eq(base64MIME.encode('hello'), 'aGVsbG8=\n') + # Test the binary flag + eq(base64MIME.encode('hello\n'), 'aGVsbG8K\n') + eq(base64MIME.encode('hello\n', 0), 'aGVsbG8NCg==\n') + # Test the maxlinelen arg + eq(base64MIME.encode('xxxx ' * 20, maxlinelen=40), """\ +eHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg +eHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg +eHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg +eHh4eCB4eHh4IA== +""") + # Test the eol argument + eq(base64MIME.encode('xxxx ' * 20, maxlinelen=40, eol='\r\n'), """\ +eHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg\r +eHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg\r +eHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg\r +eHh4eCB4eHh4IA==\r +""") + + def test_header_encode(self): + eq = self.assertEqual + he = base64MIME.header_encode + eq(he('hello'), '=?iso-8859-1?b?aGVsbG8=?=') + eq(he('hello\nworld'), '=?iso-8859-1?b?aGVsbG8NCndvcmxk?=') + # Test the charset option + eq(he('hello', charset='iso-8859-2'), '=?iso-8859-2?b?aGVsbG8=?=') + # Test the keep_eols flag + eq(he('hello\nworld', keep_eols=True), + '=?iso-8859-1?b?aGVsbG8Kd29ybGQ=?=') + # Test the maxlinelen argument + eq(he('xxxx ' * 20, maxlinelen=40), """\ +=?iso-8859-1?b?eHh4eCB4eHh4IHh4eHggeHg=?= + =?iso-8859-1?b?eHggeHh4eCB4eHh4IHh4eHg=?= + =?iso-8859-1?b?IHh4eHggeHh4eCB4eHh4IHg=?= + =?iso-8859-1?b?eHh4IHh4eHggeHh4eCB4eHg=?= + =?iso-8859-1?b?eCB4eHh4IHh4eHggeHh4eCA=?= + =?iso-8859-1?b?eHh4eCB4eHh4IHh4eHgg?=""") + # Test the eol argument + eq(he('xxxx ' * 20, maxlinelen=40, eol='\r\n'), """\ +=?iso-8859-1?b?eHh4eCB4eHh4IHh4eHggeHg=?=\r + =?iso-8859-1?b?eHggeHh4eCB4eHh4IHh4eHg=?=\r + =?iso-8859-1?b?IHh4eHggeHh4eCB4eHh4IHg=?=\r + =?iso-8859-1?b?eHh4IHh4eHggeHh4eCB4eHg=?=\r + =?iso-8859-1?b?eCB4eHh4IHh4eHggeHh4eCA=?=\r + =?iso-8859-1?b?eHh4eCB4eHh4IHh4eHgg?=""") + + + +class TestQuopri(unittest.TestCase): + def setUp(self): + self.hlit = [chr(x) for x in range(ord('a'), ord('z')+1)] + \ + [chr(x) for x in range(ord('A'), ord('Z')+1)] + \ + [chr(x) for x in range(ord('0'), ord('9')+1)] + \ + ['!', '*', '+', '-', '/', ' '] + self.hnon = [chr(x) for x in range(256) if chr(x) not in self.hlit] + assert len(self.hlit) + len(self.hnon) == 256 + self.blit = [chr(x) for x in range(ord(' '), ord('~')+1)] + ['\t'] + self.blit.remove('=') + self.bnon = [chr(x) for x in range(256) if chr(x) not in self.blit] + assert len(self.blit) + len(self.bnon) == 256 + + def test_header_quopri_check(self): + for c in self.hlit: + self.assertFalse(quopriMIME.header_quopri_check(c)) + for c in self.hnon: + self.assertTrue(quopriMIME.header_quopri_check(c)) + + def test_body_quopri_check(self): + for c in self.blit: + self.assertFalse(quopriMIME.body_quopri_check(c)) + for c in self.bnon: + self.assertTrue(quopriMIME.body_quopri_check(c)) + + def test_header_quopri_len(self): + eq = self.assertEqual + hql = quopriMIME.header_quopri_len + enc = quopriMIME.header_encode + for s in ('hello', 'h@e@l@l@o@'): + # Empty charset and no line-endings. 7 == RFC chrome + eq(hql(s), len(enc(s, charset='', eol=''))-7) + for c in self.hlit: + eq(hql(c), 1) + for c in self.hnon: + eq(hql(c), 3) + + def test_body_quopri_len(self): + eq = self.assertEqual + bql = quopriMIME.body_quopri_len + for c in self.blit: + eq(bql(c), 1) + for c in self.bnon: + eq(bql(c), 3) + + def test_quote_unquote_idempotent(self): + for x in range(256): + c = chr(x) + self.assertEqual(quopriMIME.unquote(quopriMIME.quote(c)), c) + + def test_header_encode(self): + eq = self.assertEqual + he = quopriMIME.header_encode + eq(he('hello'), '=?iso-8859-1?q?hello?=') + eq(he('hello\nworld'), '=?iso-8859-1?q?hello=0D=0Aworld?=') + # Test the charset option + eq(he('hello', charset='iso-8859-2'), '=?iso-8859-2?q?hello?=') + # Test the keep_eols flag + eq(he('hello\nworld', keep_eols=True), '=?iso-8859-1?q?hello=0Aworld?=') + # Test a non-ASCII character + eq(he('hello\xc7there'), '=?iso-8859-1?q?hello=C7there?=') + # Test the maxlinelen argument + eq(he('xxxx ' * 20, maxlinelen=40), """\ +=?iso-8859-1?q?xxxx_xxxx_xxxx_xxxx_xx?= + =?iso-8859-1?q?xx_xxxx_xxxx_xxxx_xxxx?= + =?iso-8859-1?q?_xxxx_xxxx_xxxx_xxxx_x?= + =?iso-8859-1?q?xxx_xxxx_xxxx_xxxx_xxx?= + =?iso-8859-1?q?x_xxxx_xxxx_?=""") + # Test the eol argument + eq(he('xxxx ' * 20, maxlinelen=40, eol='\r\n'), """\ +=?iso-8859-1?q?xxxx_xxxx_xxxx_xxxx_xx?=\r + =?iso-8859-1?q?xx_xxxx_xxxx_xxxx_xxxx?=\r + =?iso-8859-1?q?_xxxx_xxxx_xxxx_xxxx_x?=\r + =?iso-8859-1?q?xxx_xxxx_xxxx_xxxx_xxx?=\r + =?iso-8859-1?q?x_xxxx_xxxx_?=""") + + def test_decode(self): + eq = self.assertEqual + eq(quopriMIME.decode(''), '') + eq(quopriMIME.decode('hello'), 'hello') + eq(quopriMIME.decode('hello', 'X'), 'hello') + eq(quopriMIME.decode('hello\nworld', 'X'), 'helloXworld') + + def test_encode(self): + eq = self.assertEqual + eq(quopriMIME.encode(''), '') + eq(quopriMIME.encode('hello'), 'hello') + # Test the binary flag + eq(quopriMIME.encode('hello\r\nworld'), 'hello\nworld') + eq(quopriMIME.encode('hello\r\nworld', 0), 'hello\nworld') + # Test the maxlinelen arg + eq(quopriMIME.encode('xxxx ' * 20, maxlinelen=40), """\ +xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx= + xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxx= +x xxxx xxxx xxxx xxxx=20""") + # Test the eol argument + eq(quopriMIME.encode('xxxx ' * 20, maxlinelen=40, eol='\r\n'), """\ +xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx=\r + xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxx=\r +x xxxx xxxx xxxx xxxx=20""") + eq(quopriMIME.encode("""\ +one line + +two line"""), """\ +one line + +two line""") + + + +# Test the Charset class +class TestCharset(unittest.TestCase): + def tearDown(self): + from email import Charset as CharsetModule + try: + del CharsetModule.CHARSETS['fake'] + except KeyError: + pass + + def test_idempotent(self): + eq = self.assertEqual + # Make sure us-ascii = no Unicode conversion + c = Charset('us-ascii') + s = 'Hello World!' + sp = c.to_splittable(s) + eq(s, c.from_splittable(sp)) + # test 8-bit idempotency with us-ascii + s = '\xa4\xa2\xa4\xa4\xa4\xa6\xa4\xa8\xa4\xaa' + sp = c.to_splittable(s) + eq(s, c.from_splittable(sp)) + + def test_body_encode(self): + eq = self.assertEqual + # Try a charset with QP body encoding + c = Charset('iso-8859-1') + eq('hello w=F6rld', c.body_encode('hello w\xf6rld')) + # Try a charset with Base64 body encoding + c = Charset('utf-8') + eq('aGVsbG8gd29ybGQ=\n', c.body_encode('hello world')) + # Try a charset with None body encoding + c = Charset('us-ascii') + eq('hello world', c.body_encode('hello world')) + # Try the convert argument, where input codec != output codec + c = Charset('euc-jp') + # With apologies to Tokio Kikuchi ;) + try: + eq('\x1b$B5FCO;~IW\x1b(B', + c.body_encode('\xb5\xc6\xc3\xcf\xbb\xfe\xc9\xd7')) + eq('\xb5\xc6\xc3\xcf\xbb\xfe\xc9\xd7', + c.body_encode('\xb5\xc6\xc3\xcf\xbb\xfe\xc9\xd7', False)) + except LookupError: + # We probably don't have the Japanese codecs installed + pass + # Testing SF bug #625509, which we have to fake, since there are no + # built-in encodings where the header encoding is QP but the body + # encoding is not. + from email import Charset as CharsetModule + CharsetModule.add_charset('fake', CharsetModule.QP, None) + c = Charset('fake') + eq('hello w\xf6rld', c.body_encode('hello w\xf6rld')) + + def test_unicode_charset_name(self): + charset = Charset(u'us-ascii') + self.assertEqual(str(charset), 'us-ascii') + self.assertRaises(Errors.CharsetError, Charset, 'asc\xffii') + + def test_codecs_aliases_accepted(self): + charset = Charset('utf8') + self.assertEqual(str(charset), 'utf-8') + + +# Test multilingual MIME headers. +class TestHeader(TestEmailBase): + def test_simple(self): + eq = self.ndiffAssertEqual + h = Header('Hello World!') + eq(h.encode(), 'Hello World!') + h.append(' Goodbye World!') + eq(h.encode(), 'Hello World! Goodbye World!') + + def test_simple_surprise(self): + eq = self.ndiffAssertEqual + h = Header('Hello World!') + eq(h.encode(), 'Hello World!') + h.append('Goodbye World!') + eq(h.encode(), 'Hello World! Goodbye World!') + + def test_header_needs_no_decoding(self): + h = 'no decoding needed' + self.assertEqual(decode_header(h), [(h, None)]) + + def test_long(self): + h = Header("I am the very model of a modern Major-General; I've information vegetable, animal, and mineral; I know the kings of England, and I quote the fights historical from Marathon to Waterloo, in order categorical; I'm very well acquainted, too, with matters mathematical; I understand equations, both the simple and quadratical; about binomial theorem I'm teeming with a lot o' news, with many cheerful facts about the square of the hypotenuse.", + maxlinelen=76) + for l in h.encode(splitchars=' ').split('\n '): + self.assertTrue(len(l) <= 76) + + def test_multilingual(self): + eq = self.ndiffAssertEqual + g = Charset("iso-8859-1") + cz = Charset("iso-8859-2") + utf8 = Charset("utf-8") + g_head = "Die Mieter treten hier ein werden mit einem Foerderband komfortabel den Korridor entlang, an s\xfcdl\xfcndischen Wandgem\xe4lden vorbei, gegen die rotierenden Klingen bef\xf6rdert. " + cz_head = "Finan\xe8ni metropole se hroutily pod tlakem jejich d\xf9vtipu.. " + utf8_head = u"\u6b63\u78ba\u306b\u8a00\u3046\u3068\u7ffb\u8a33\u306f\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u4e00\u90e8\u306f\u30c9\u30a4\u30c4\u8a9e\u3067\u3059\u304c\u3001\u3042\u3068\u306f\u3067\u305f\u3089\u3081\u3067\u3059\u3002\u5b9f\u969b\u306b\u306f\u300cWenn ist das Nunstuck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput.\u300d\u3068\u8a00\u3063\u3066\u3044\u307e\u3059\u3002".encode("utf-8") + h = Header(g_head, g) + h.append(cz_head, cz) + h.append(utf8_head, utf8) + enc = h.encode() + eq(enc, """\ +=?iso-8859-1?q?Die_Mieter_treten_hier_ein_werden_mit_einem_Foerderband_ko?= + =?iso-8859-1?q?mfortabel_den_Korridor_entlang=2C_an_s=FCdl=FCndischen_Wan?= + =?iso-8859-1?q?dgem=E4lden_vorbei=2C_gegen_die_rotierenden_Klingen_bef=F6?= + =?iso-8859-1?q?rdert=2E_?= =?iso-8859-2?q?Finan=E8ni_metropole_se_hroutily?= + =?iso-8859-2?q?_pod_tlakem_jejich_d=F9vtipu=2E=2E_?= =?utf-8?b?5q2j56K6?= + =?utf-8?b?44Gr6KiA44GG44Go57+76Kiz44Gv44GV44KM44Gm44GE44G+44Gb44KT44CC?= + =?utf-8?b?5LiA6YOo44Gv44OJ44Kk44OE6Kqe44Gn44GZ44GM44CB44GC44Go44Gv44Gn?= + =?utf-8?b?44Gf44KJ44KB44Gn44GZ44CC5a6f6Zqb44Gr44Gv44CMV2VubiBpc3QgZGFz?= + =?utf-8?q?_Nunstuck_git_und_Slotermeyer=3F_Ja!_Beiherhund_das_Oder_die_Fl?= + =?utf-8?b?aXBwZXJ3YWxkdCBnZXJzcHV0LuOAjeOBqOiogOOBo+OBpuOBhOOBvuOBmQ==?= + =?utf-8?b?44CC?=""") + eq(decode_header(enc), + [(g_head, "iso-8859-1"), (cz_head, "iso-8859-2"), + (utf8_head, "utf-8")]) + ustr = unicode(h) + eq(ustr.encode('utf-8'), + 'Die Mieter treten hier ein werden mit einem Foerderband ' + 'komfortabel den Korridor entlang, an s\xc3\xbcdl\xc3\xbcndischen ' + 'Wandgem\xc3\xa4lden vorbei, gegen die rotierenden Klingen ' + 'bef\xc3\xb6rdert. Finan\xc4\x8dni metropole se hroutily pod ' + 'tlakem jejich d\xc5\xafvtipu.. \xe6\xad\xa3\xe7\xa2\xba\xe3\x81' + '\xab\xe8\xa8\x80\xe3\x81\x86\xe3\x81\xa8\xe7\xbf\xbb\xe8\xa8\xb3' + '\xe3\x81\xaf\xe3\x81\x95\xe3\x82\x8c\xe3\x81\xa6\xe3\x81\x84\xe3' + '\x81\xbe\xe3\x81\x9b\xe3\x82\x93\xe3\x80\x82\xe4\xb8\x80\xe9\x83' + '\xa8\xe3\x81\xaf\xe3\x83\x89\xe3\x82\xa4\xe3\x83\x84\xe8\xaa\x9e' + '\xe3\x81\xa7\xe3\x81\x99\xe3\x81\x8c\xe3\x80\x81\xe3\x81\x82\xe3' + '\x81\xa8\xe3\x81\xaf\xe3\x81\xa7\xe3\x81\x9f\xe3\x82\x89\xe3\x82' + '\x81\xe3\x81\xa7\xe3\x81\x99\xe3\x80\x82\xe5\xae\x9f\xe9\x9a\x9b' + '\xe3\x81\xab\xe3\x81\xaf\xe3\x80\x8cWenn ist das Nunstuck git ' + 'und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt ' + 'gersput.\xe3\x80\x8d\xe3\x81\xa8\xe8\xa8\x80\xe3\x81\xa3\xe3\x81' + '\xa6\xe3\x81\x84\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82') + # Test make_header() + newh = make_header(decode_header(enc)) + eq(newh, enc) + + def test_header_ctor_default_args(self): + eq = self.ndiffAssertEqual + h = Header() + eq(h, '') + h.append('foo', Charset('iso-8859-1')) + eq(h, '=?iso-8859-1?q?foo?=') + + def test_explicit_maxlinelen(self): + eq = self.ndiffAssertEqual + hstr = 'A very long line that must get split to something other than at the 76th character boundary to test the non-default behavior' + h = Header(hstr) + eq(h.encode(), '''\ +A very long line that must get split to something other than at the 76th + character boundary to test the non-default behavior''') + h = Header(hstr, header_name='Subject') + eq(h.encode(), '''\ +A very long line that must get split to something other than at the + 76th character boundary to test the non-default behavior''') + h = Header(hstr, maxlinelen=1024, header_name='Subject') + eq(h.encode(), hstr) + + def test_us_ascii_header(self): + eq = self.assertEqual + s = 'hello' + x = decode_header(s) + eq(x, [('hello', None)]) + h = make_header(x) + eq(s, h.encode()) + + def test_string_charset(self): + eq = self.assertEqual + h = Header() + h.append('hello', 'iso-8859-1') + eq(h, '=?iso-8859-1?q?hello?=') + +## def test_unicode_error(self): +## raises = self.assertRaises +## raises(UnicodeError, Header, u'[P\xf6stal]', 'us-ascii') +## raises(UnicodeError, Header, '[P\xf6stal]', 'us-ascii') +## h = Header() +## raises(UnicodeError, h.append, u'[P\xf6stal]', 'us-ascii') +## raises(UnicodeError, h.append, '[P\xf6stal]', 'us-ascii') +## raises(UnicodeError, Header, u'\u83ca\u5730\u6642\u592b', 'iso-8859-1') + + def test_utf8_shortest(self): + eq = self.assertEqual + h = Header(u'p\xf6stal', 'utf-8') + eq(h.encode(), '=?utf-8?q?p=C3=B6stal?=') + h = Header(u'\u83ca\u5730\u6642\u592b', 'utf-8') + eq(h.encode(), '=?utf-8?b?6I+K5Zyw5pmC5aSr?=') + + def test_bad_8bit_header(self): + raises = self.assertRaises + eq = self.assertEqual + x = 'Ynwp4dUEbay Auction Semiar- No Charge \x96 Earn Big' + raises(UnicodeError, Header, x) + h = Header() + raises(UnicodeError, h.append, x) + eq(str(Header(x, errors='replace')), x) + h.append(x, errors='replace') + eq(str(h), x) + + def test_encoded_adjacent_nonencoded(self): + eq = self.assertEqual + h = Header() + h.append('hello', 'iso-8859-1') + h.append('world') + s = h.encode() + eq(s, '=?iso-8859-1?q?hello?= world') + h = make_header(decode_header(s)) + eq(h.encode(), s) + + def test_whitespace_eater(self): + eq = self.assertEqual + s = 'Subject: =?koi8-r?b?8NLP18XSy8EgzsEgxsnOwczYztk=?= =?koi8-r?q?=CA?= zz.' + parts = decode_header(s) + eq(parts, [('Subject:', None), ('\xf0\xd2\xcf\xd7\xc5\xd2\xcb\xc1 \xce\xc1 \xc6\xc9\xce\xc1\xcc\xd8\xce\xd9\xca', 'koi8-r'), ('zz.', None)]) + hdr = make_header(parts) + eq(hdr.encode(), + 'Subject: =?koi8-r?b?8NLP18XSy8EgzsEgxsnOwczYztnK?= zz.') + + def test_broken_base64_header(self): + raises = self.assertRaises + s = 'Subject: =?EUC-KR?B?CSixpLDtKSC/7Liuvsax4iC6uLmwMcijIKHaILzSwd/H0SC8+LCjwLsgv7W/+Mj3I ?=' + raises(Errors.HeaderParseError, decode_header, s) + + # Issue 1078919 + def test_ascii_add_header(self): + msg = Message() + msg.add_header('Content-Disposition', 'attachment', + filename='bud.gif') + self.assertEqual('attachment; filename="bud.gif"', + msg['Content-Disposition']) + + def test_nonascii_add_header_via_triple(self): + msg = Message() + msg.add_header('Content-Disposition', 'attachment', + filename=('iso-8859-1', '', 'Fu\xdfballer.ppt')) + self.assertEqual( + 'attachment; filename*="iso-8859-1\'\'Fu%DFballer.ppt"', + msg['Content-Disposition']) + + def test_encode_unaliased_charset(self): + # Issue 1379416: when the charset has no output conversion, + # output was accidentally getting coerced to unicode. + res = Header('abc','iso-8859-2').encode() + self.assertEqual(res, '=?iso-8859-2?q?abc?=') + self.assertIsInstance(res, str) + + +# Test RFC 2231 header parameters (en/de)coding +class TestRFC2231(TestEmailBase): + def test_get_param(self): + eq = self.assertEqual + msg = self._msgobj('msg_29.txt') + eq(msg.get_param('title'), + ('us-ascii', 'en', 'This is even more ***fun*** isn\'t it!')) + eq(msg.get_param('title', unquote=False), + ('us-ascii', 'en', '"This is even more ***fun*** isn\'t it!"')) + + def test_set_param(self): + eq = self.assertEqual + msg = Message() + msg.set_param('title', 'This is even more ***fun*** isn\'t it!', + charset='us-ascii') + eq(msg.get_param('title'), + ('us-ascii', '', 'This is even more ***fun*** isn\'t it!')) + msg.set_param('title', 'This is even more ***fun*** isn\'t it!', + charset='us-ascii', language='en') + eq(msg.get_param('title'), + ('us-ascii', 'en', 'This is even more ***fun*** isn\'t it!')) + msg = self._msgobj('msg_01.txt') + msg.set_param('title', 'This is even more ***fun*** isn\'t it!', + charset='us-ascii', language='en') + self.ndiffAssertEqual(msg.as_string(), """\ +Return-Path: +Delivered-To: bbb@zzz.org +Received: by mail.zzz.org (Postfix, from userid 889) + id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Message-ID: <15090.61304.110929.45684@aaa.zzz.org> +From: bbb@ddd.com (John X. Doe) +To: bbb@zzz.org +Subject: This is a test message +Date: Fri, 4 May 2001 14:05:44 -0400 +Content-Type: text/plain; charset=us-ascii; + title*="us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21" + + +Hi, + +Do you like this message? + +-Me +""") + + def test_del_param(self): + eq = self.ndiffAssertEqual + msg = self._msgobj('msg_01.txt') + msg.set_param('foo', 'bar', charset='us-ascii', language='en') + msg.set_param('title', 'This is even more ***fun*** isn\'t it!', + charset='us-ascii', language='en') + msg.del_param('foo', header='Content-Type') + eq(msg.as_string(), """\ +Return-Path: +Delivered-To: bbb@zzz.org +Received: by mail.zzz.org (Postfix, from userid 889) + id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Message-ID: <15090.61304.110929.45684@aaa.zzz.org> +From: bbb@ddd.com (John X. Doe) +To: bbb@zzz.org +Subject: This is a test message +Date: Fri, 4 May 2001 14:05:44 -0400 +Content-Type: text/plain; charset="us-ascii"; + title*="us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21" + + +Hi, + +Do you like this message? + +-Me +""") + + def test_rfc2231_get_content_charset(self): + eq = self.assertEqual + msg = self._msgobj('msg_32.txt') + eq(msg.get_content_charset(), 'us-ascii') + + def test_rfc2231_no_language_or_charset(self): + m = '''\ +Content-Transfer-Encoding: 8bit +Content-Disposition: inline; filename="file____C__DOCUMENTS_20AND_20SETTINGS_FABIEN_LOCAL_20SETTINGS_TEMP_nsmail.htm" +Content-Type: text/html; NAME*0=file____C__DOCUMENTS_20AND_20SETTINGS_FABIEN_LOCAL_20SETTINGS_TEM; NAME*1=P_nsmail.htm + +''' + msg = email.message_from_string(m) + param = msg.get_param('NAME') + self.assertFalse(isinstance(param, tuple)) + self.assertEqual( + param, + 'file____C__DOCUMENTS_20AND_20SETTINGS_FABIEN_LOCAL_20SETTINGS_TEMP_nsmail.htm') + + def test_rfc2231_no_language_or_charset_in_filename(self): + m = '''\ +Content-Disposition: inline; +\tfilename*0*="''This%20is%20even%20more%20"; +\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; +\tfilename*2="is it not.pdf" + +''' + msg = email.message_from_string(m) + self.assertEqual(msg.get_filename(), + 'This is even more ***fun*** is it not.pdf') + + def test_rfc2231_no_language_or_charset_in_filename_encoded(self): + m = '''\ +Content-Disposition: inline; +\tfilename*0*="''This%20is%20even%20more%20"; +\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; +\tfilename*2="is it not.pdf" + +''' + msg = email.message_from_string(m) + self.assertEqual(msg.get_filename(), + 'This is even more ***fun*** is it not.pdf') + + def test_rfc2231_partly_encoded(self): + m = '''\ +Content-Disposition: inline; +\tfilename*0="''This%20is%20even%20more%20"; +\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; +\tfilename*2="is it not.pdf" + +''' + msg = email.message_from_string(m) + self.assertEqual( + msg.get_filename(), + 'This%20is%20even%20more%20***fun*** is it not.pdf') + + def test_rfc2231_partly_nonencoded(self): + m = '''\ +Content-Disposition: inline; +\tfilename*0="This%20is%20even%20more%20"; +\tfilename*1="%2A%2A%2Afun%2A%2A%2A%20"; +\tfilename*2="is it not.pdf" + +''' + msg = email.message_from_string(m) + self.assertEqual( + msg.get_filename(), + 'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20is it not.pdf') + + def test_rfc2231_no_language_or_charset_in_boundary(self): + m = '''\ +Content-Type: multipart/alternative; +\tboundary*0*="''This%20is%20even%20more%20"; +\tboundary*1*="%2A%2A%2Afun%2A%2A%2A%20"; +\tboundary*2="is it not.pdf" + +''' + msg = email.message_from_string(m) + self.assertEqual(msg.get_boundary(), + 'This is even more ***fun*** is it not.pdf') + + def test_rfc2231_no_language_or_charset_in_charset(self): + # This is a nonsensical charset value, but tests the code anyway + m = '''\ +Content-Type: text/plain; +\tcharset*0*="This%20is%20even%20more%20"; +\tcharset*1*="%2A%2A%2Afun%2A%2A%2A%20"; +\tcharset*2="is it not.pdf" + +''' + msg = email.message_from_string(m) + self.assertEqual(msg.get_content_charset(), + 'this is even more ***fun*** is it not.pdf') + + def test_rfc2231_bad_encoding_in_filename(self): + m = '''\ +Content-Disposition: inline; +\tfilename*0*="bogus'xx'This%20is%20even%20more%20"; +\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; +\tfilename*2="is it not.pdf" + +''' + msg = email.message_from_string(m) + self.assertEqual(msg.get_filename(), + 'This is even more ***fun*** is it not.pdf') + + def test_rfc2231_bad_encoding_in_charset(self): + m = """\ +Content-Type: text/plain; charset*=bogus''utf-8%E2%80%9D + +""" + msg = email.message_from_string(m) + # This should return None because non-ascii characters in the charset + # are not allowed. + self.assertEqual(msg.get_content_charset(), None) + + def test_rfc2231_bad_character_in_charset(self): + m = """\ +Content-Type: text/plain; charset*=ascii''utf-8%E2%80%9D + +""" + msg = email.message_from_string(m) + # This should return None because non-ascii characters in the charset + # are not allowed. + self.assertEqual(msg.get_content_charset(), None) + + def test_rfc2231_bad_character_in_filename(self): + m = '''\ +Content-Disposition: inline; +\tfilename*0*="ascii'xx'This%20is%20even%20more%20"; +\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; +\tfilename*2*="is it not.pdf%E2" + +''' + msg = email.message_from_string(m) + self.assertEqual(msg.get_filename(), + u'This is even more ***fun*** is it not.pdf\ufffd') + + def test_rfc2231_unknown_encoding(self): + m = """\ +Content-Transfer-Encoding: 8bit +Content-Disposition: inline; filename*=X-UNKNOWN''myfile.txt + +""" + msg = email.message_from_string(m) + self.assertEqual(msg.get_filename(), 'myfile.txt') + + def test_rfc2231_single_tick_in_filename_extended(self): + eq = self.assertEqual + m = """\ +Content-Type: application/x-foo; +\tname*0*=\"Frank's\"; name*1*=\" Document\" + +""" + msg = email.message_from_string(m) + charset, language, s = msg.get_param('name') + eq(charset, None) + eq(language, None) + eq(s, "Frank's Document") + + def test_rfc2231_single_tick_in_filename(self): + m = """\ +Content-Type: application/x-foo; name*0=\"Frank's\"; name*1=\" Document\" + +""" + msg = email.message_from_string(m) + param = msg.get_param('name') + self.assertFalse(isinstance(param, tuple)) + self.assertEqual(param, "Frank's Document") + + def test_rfc2231_tick_attack_extended(self): + eq = self.assertEqual + m = """\ +Content-Type: application/x-foo; +\tname*0*=\"us-ascii'en-us'Frank's\"; name*1*=\" Document\" + +""" + msg = email.message_from_string(m) + charset, language, s = msg.get_param('name') + eq(charset, 'us-ascii') + eq(language, 'en-us') + eq(s, "Frank's Document") + + def test_rfc2231_tick_attack(self): + m = """\ +Content-Type: application/x-foo; +\tname*0=\"us-ascii'en-us'Frank's\"; name*1=\" Document\" + +""" + msg = email.message_from_string(m) + param = msg.get_param('name') + self.assertFalse(isinstance(param, tuple)) + self.assertEqual(param, "us-ascii'en-us'Frank's Document") + + def test_rfc2231_no_extended_values(self): + eq = self.assertEqual + m = """\ +Content-Type: application/x-foo; name=\"Frank's Document\" + +""" + msg = email.message_from_string(m) + eq(msg.get_param('name'), "Frank's Document") + + def test_rfc2231_encoded_then_unencoded_segments(self): + eq = self.assertEqual + m = """\ +Content-Type: application/x-foo; +\tname*0*=\"us-ascii'en-us'My\"; +\tname*1=\" Document\"; +\tname*2*=\" For You\" + +""" + msg = email.message_from_string(m) + charset, language, s = msg.get_param('name') + eq(charset, 'us-ascii') + eq(language, 'en-us') + eq(s, 'My Document For You') + + def test_rfc2231_unencoded_then_encoded_segments(self): + eq = self.assertEqual + m = """\ +Content-Type: application/x-foo; +\tname*0=\"us-ascii'en-us'My\"; +\tname*1*=\" Document\"; +\tname*2*=\" For You\" + +""" + msg = email.message_from_string(m) + charset, language, s = msg.get_param('name') + eq(charset, 'us-ascii') + eq(language, 'en-us') + eq(s, 'My Document For You') + + + +# Tests to ensure that signed parts of an email are completely preserved, as +# required by RFC1847 section 2.1. Note that these are incomplete, because the +# email package does not currently always preserve the body. See issue 1670765. +class TestSigned(TestEmailBase): + + def _msg_and_obj(self, filename): + fp = openfile(findfile(filename)) + try: + original = fp.read() + msg = email.message_from_string(original) + finally: + fp.close() + return original, msg + + def _signed_parts_eq(self, original, result): + # Extract the first mime part of each message + import re + repart = re.compile(r'^--([^\n]+)\n(.*?)\n--\1$', re.S | re.M) + inpart = repart.search(original).group(2) + outpart = repart.search(result).group(2) + self.assertEqual(outpart, inpart) + + def test_long_headers_as_string(self): + original, msg = self._msg_and_obj('msg_45.txt') + result = msg.as_string() + self._signed_parts_eq(original, result) + + def test_long_headers_flatten(self): + original, msg = self._msg_and_obj('msg_45.txt') + fp = StringIO() + Generator(fp).flatten(msg) + result = fp.getvalue() + self._signed_parts_eq(original, result) + + + +def _testclasses(): + mod = sys.modules[__name__] + return [getattr(mod, name) for name in dir(mod) if name.startswith('Test')] + + +def suite(): + suite = unittest.TestSuite() + for testclass in _testclasses(): + suite.addTest(unittest.makeSuite(testclass)) + return suite + + +def test_main(): + for testclass in _testclasses(): + run_unittest(testclass) + + + +if __name__ == '__main__': + unittest.main(defaultTest='suite') diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email.pyc new file mode 100644 index 0000000..bcd16ef Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email.pyo new file mode 100644 index 0000000..4f30b33 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_codecs.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_codecs.py new file mode 100644 index 0000000..532750a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_codecs.py @@ -0,0 +1,77 @@ +# Copyright (C) 2002-2006 Python Software Foundation +# Contact: email-sig@python.org +# email package unit tests for (optional) Asian codecs + +import unittest +from test.test_support import run_unittest + +from email.test.test_email import TestEmailBase +from email.charset import Charset +from email.header import Header, decode_header +from email.message import Message + +# We're compatible with Python 2.3, but it doesn't have the built-in Asian +# codecs, so we have to skip all these tests. +try: + unicode('foo', 'euc-jp') +except LookupError: + raise unittest.SkipTest + + + +class TestEmailAsianCodecs(TestEmailBase): + def test_japanese_codecs(self): + eq = self.ndiffAssertEqual + j = Charset("euc-jp") + g = Charset("iso-8859-1") + h = Header("Hello World!") + jhello = '\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc\xa5\xeb\xa5\xc9\xa1\xaa' + ghello = 'Gr\xfc\xdf Gott!' + h.append(jhello, j) + h.append(ghello, g) + # BAW: This used to -- and maybe should -- fold the two iso-8859-1 + # chunks into a single encoded word. However it doesn't violate the + # standard to have them as two encoded chunks and maybe it's + # reasonable for each .append() call to result in a separate + # encoded word. + eq(h.encode(), """\ +Hello World! =?iso-2022-jp?b?GyRCJU8lbSE8JW8hPCVrJUkhKhsoQg==?= + =?iso-8859-1?q?Gr=FC=DF?= =?iso-8859-1?q?_Gott!?=""") + eq(decode_header(h.encode()), + [('Hello World!', None), + ('\x1b$B%O%m!<%o!<%k%I!*\x1b(B', 'iso-2022-jp'), + ('Gr\xfc\xdf Gott!', 'iso-8859-1')]) + long = 'test-ja \xa4\xd8\xc5\xea\xb9\xc6\xa4\xb5\xa4\xec\xa4\xbf\xa5\xe1\xa1\xbc\xa5\xeb\xa4\xcf\xbb\xca\xb2\xf1\xbc\xd4\xa4\xce\xbe\xb5\xc7\xa7\xa4\xf2\xc2\xd4\xa4\xc3\xa4\xc6\xa4\xa4\xa4\xde\xa4\xb9' + h = Header(long, j, header_name="Subject") + # test a very long header + enc = h.encode() + # TK: splitting point may differ by codec design and/or Header encoding + eq(enc , """\ +=?iso-2022-jp?b?dGVzdC1qYSAbJEIkWEVqOUYkNSRsJD8lYSE8JWskTztKGyhC?= + =?iso-2022-jp?b?GyRCMnE8VCROPjVHJyRyQlQkQyRGJCQkXiQ5GyhC?=""") + # TK: full decode comparison + eq(h.__unicode__().encode('euc-jp'), long) + + def test_payload_encoding(self): + jhello = '\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc\xa5\xeb\xa5\xc9\xa1\xaa' + jcode = 'euc-jp' + msg = Message() + msg.set_payload(jhello, jcode) + ustr = unicode(msg.get_payload(), msg.get_content_charset()) + self.assertEqual(jhello, ustr.encode(jcode)) + + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(TestEmailAsianCodecs)) + return suite + + +def test_main(): + run_unittest(TestEmailAsianCodecs) + + + +if __name__ == '__main__': + unittest.main(defaultTest='suite') diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_codecs.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_codecs.pyc new file mode 100644 index 0000000..4e95697 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_codecs.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_codecs.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_codecs.pyo new file mode 100644 index 0000000..4e95697 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_codecs.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_codecs_renamed.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_codecs_renamed.py new file mode 100644 index 0000000..532750a --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_codecs_renamed.py @@ -0,0 +1,77 @@ +# Copyright (C) 2002-2006 Python Software Foundation +# Contact: email-sig@python.org +# email package unit tests for (optional) Asian codecs + +import unittest +from test.test_support import run_unittest + +from email.test.test_email import TestEmailBase +from email.charset import Charset +from email.header import Header, decode_header +from email.message import Message + +# We're compatible with Python 2.3, but it doesn't have the built-in Asian +# codecs, so we have to skip all these tests. +try: + unicode('foo', 'euc-jp') +except LookupError: + raise unittest.SkipTest + + + +class TestEmailAsianCodecs(TestEmailBase): + def test_japanese_codecs(self): + eq = self.ndiffAssertEqual + j = Charset("euc-jp") + g = Charset("iso-8859-1") + h = Header("Hello World!") + jhello = '\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc\xa5\xeb\xa5\xc9\xa1\xaa' + ghello = 'Gr\xfc\xdf Gott!' + h.append(jhello, j) + h.append(ghello, g) + # BAW: This used to -- and maybe should -- fold the two iso-8859-1 + # chunks into a single encoded word. However it doesn't violate the + # standard to have them as two encoded chunks and maybe it's + # reasonable for each .append() call to result in a separate + # encoded word. + eq(h.encode(), """\ +Hello World! =?iso-2022-jp?b?GyRCJU8lbSE8JW8hPCVrJUkhKhsoQg==?= + =?iso-8859-1?q?Gr=FC=DF?= =?iso-8859-1?q?_Gott!?=""") + eq(decode_header(h.encode()), + [('Hello World!', None), + ('\x1b$B%O%m!<%o!<%k%I!*\x1b(B', 'iso-2022-jp'), + ('Gr\xfc\xdf Gott!', 'iso-8859-1')]) + long = 'test-ja \xa4\xd8\xc5\xea\xb9\xc6\xa4\xb5\xa4\xec\xa4\xbf\xa5\xe1\xa1\xbc\xa5\xeb\xa4\xcf\xbb\xca\xb2\xf1\xbc\xd4\xa4\xce\xbe\xb5\xc7\xa7\xa4\xf2\xc2\xd4\xa4\xc3\xa4\xc6\xa4\xa4\xa4\xde\xa4\xb9' + h = Header(long, j, header_name="Subject") + # test a very long header + enc = h.encode() + # TK: splitting point may differ by codec design and/or Header encoding + eq(enc , """\ +=?iso-2022-jp?b?dGVzdC1qYSAbJEIkWEVqOUYkNSRsJD8lYSE8JWskTztKGyhC?= + =?iso-2022-jp?b?GyRCMnE8VCROPjVHJyRyQlQkQyRGJCQkXiQ5GyhC?=""") + # TK: full decode comparison + eq(h.__unicode__().encode('euc-jp'), long) + + def test_payload_encoding(self): + jhello = '\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc\xa5\xeb\xa5\xc9\xa1\xaa' + jcode = 'euc-jp' + msg = Message() + msg.set_payload(jhello, jcode) + ustr = unicode(msg.get_payload(), msg.get_content_charset()) + self.assertEqual(jhello, ustr.encode(jcode)) + + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(TestEmailAsianCodecs)) + return suite + + +def test_main(): + run_unittest(TestEmailAsianCodecs) + + + +if __name__ == '__main__': + unittest.main(defaultTest='suite') diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_codecs_renamed.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_codecs_renamed.pyc new file mode 100644 index 0000000..5337733 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_codecs_renamed.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_codecs_renamed.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_codecs_renamed.pyo new file mode 100644 index 0000000..5337733 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_codecs_renamed.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_renamed.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_renamed.py new file mode 100644 index 0000000..0c97e98 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_renamed.py @@ -0,0 +1,3329 @@ +# Copyright (C) 2001-2007 Python Software Foundation +# Contact: email-sig@python.org +# email package unit tests + +import os +import sys +import time +import base64 +import difflib +import unittest +import warnings +from cStringIO import StringIO + +import email + +from email.charset import Charset +from email.header import Header, decode_header, make_header +from email.parser import Parser, HeaderParser +from email.generator import Generator, DecodedGenerator +from email.message import Message +from email.mime.application import MIMEApplication +from email.mime.audio import MIMEAudio +from email.mime.text import MIMEText +from email.mime.image import MIMEImage +from email.mime.base import MIMEBase +from email.mime.message import MIMEMessage +from email.mime.multipart import MIMEMultipart +from email import utils +from email import errors +from email import encoders +from email import iterators +from email import base64mime +from email import quoprimime + +from test.test_support import findfile, run_unittest +from email.test import __file__ as landmark + + +NL = '\n' +EMPTYSTRING = '' +SPACE = ' ' + + + +def openfile(filename, mode='r'): + path = os.path.join(os.path.dirname(landmark), 'data', filename) + return open(path, mode) + + + +# Base test class +class TestEmailBase(unittest.TestCase): + def ndiffAssertEqual(self, first, second): + """Like assertEqual except use ndiff for readable output.""" + if first != second: + sfirst = str(first) + ssecond = str(second) + diff = difflib.ndiff(sfirst.splitlines(), ssecond.splitlines()) + fp = StringIO() + print >> fp, NL, NL.join(diff) + raise self.failureException, fp.getvalue() + + def _msgobj(self, filename): + fp = openfile(findfile(filename)) + try: + msg = email.message_from_file(fp) + finally: + fp.close() + return msg + + + +# Test various aspects of the Message class's API +class TestMessageAPI(TestEmailBase): + def test_get_all(self): + eq = self.assertEqual + msg = self._msgobj('msg_20.txt') + eq(msg.get_all('cc'), ['ccc@zzz.org', 'ddd@zzz.org', 'eee@zzz.org']) + eq(msg.get_all('xx', 'n/a'), 'n/a') + + def test_getset_charset(self): + eq = self.assertEqual + msg = Message() + eq(msg.get_charset(), None) + charset = Charset('iso-8859-1') + msg.set_charset(charset) + eq(msg['mime-version'], '1.0') + eq(msg.get_content_type(), 'text/plain') + eq(msg['content-type'], 'text/plain; charset="iso-8859-1"') + eq(msg.get_param('charset'), 'iso-8859-1') + eq(msg['content-transfer-encoding'], 'quoted-printable') + eq(msg.get_charset().input_charset, 'iso-8859-1') + # Remove the charset + msg.set_charset(None) + eq(msg.get_charset(), None) + eq(msg['content-type'], 'text/plain') + # Try adding a charset when there's already MIME headers present + msg = Message() + msg['MIME-Version'] = '2.0' + msg['Content-Type'] = 'text/x-weird' + msg['Content-Transfer-Encoding'] = 'quinted-puntable' + msg.set_charset(charset) + eq(msg['mime-version'], '2.0') + eq(msg['content-type'], 'text/x-weird; charset="iso-8859-1"') + eq(msg['content-transfer-encoding'], 'quinted-puntable') + + def test_set_charset_from_string(self): + eq = self.assertEqual + msg = Message() + msg.set_charset('us-ascii') + eq(msg.get_charset().input_charset, 'us-ascii') + eq(msg['content-type'], 'text/plain; charset="us-ascii"') + + def test_set_payload_with_charset(self): + msg = Message() + charset = Charset('iso-8859-1') + msg.set_payload('This is a string payload', charset) + self.assertEqual(msg.get_charset().input_charset, 'iso-8859-1') + + def test_get_charsets(self): + eq = self.assertEqual + + msg = self._msgobj('msg_08.txt') + charsets = msg.get_charsets() + eq(charsets, [None, 'us-ascii', 'iso-8859-1', 'iso-8859-2', 'koi8-r']) + + msg = self._msgobj('msg_09.txt') + charsets = msg.get_charsets('dingbat') + eq(charsets, ['dingbat', 'us-ascii', 'iso-8859-1', 'dingbat', + 'koi8-r']) + + msg = self._msgobj('msg_12.txt') + charsets = msg.get_charsets() + eq(charsets, [None, 'us-ascii', 'iso-8859-1', None, 'iso-8859-2', + 'iso-8859-3', 'us-ascii', 'koi8-r']) + + def test_get_filename(self): + eq = self.assertEqual + + msg = self._msgobj('msg_04.txt') + filenames = [p.get_filename() for p in msg.get_payload()] + eq(filenames, ['msg.txt', 'msg.txt']) + + msg = self._msgobj('msg_07.txt') + subpart = msg.get_payload(1) + eq(subpart.get_filename(), 'dingusfish.gif') + + def test_get_filename_with_name_parameter(self): + eq = self.assertEqual + + msg = self._msgobj('msg_44.txt') + filenames = [p.get_filename() for p in msg.get_payload()] + eq(filenames, ['msg.txt', 'msg.txt']) + + def test_get_boundary(self): + eq = self.assertEqual + msg = self._msgobj('msg_07.txt') + # No quotes! + eq(msg.get_boundary(), 'BOUNDARY') + + def test_set_boundary(self): + eq = self.assertEqual + # This one has no existing boundary parameter, but the Content-Type: + # header appears fifth. + msg = self._msgobj('msg_01.txt') + msg.set_boundary('BOUNDARY') + header, value = msg.items()[4] + eq(header.lower(), 'content-type') + eq(value, 'text/plain; charset="us-ascii"; boundary="BOUNDARY"') + # This one has a Content-Type: header, with a boundary, stuck in the + # middle of its headers. Make sure the order is preserved; it should + # be fifth. + msg = self._msgobj('msg_04.txt') + msg.set_boundary('BOUNDARY') + header, value = msg.items()[4] + eq(header.lower(), 'content-type') + eq(value, 'multipart/mixed; boundary="BOUNDARY"') + # And this one has no Content-Type: header at all. + msg = self._msgobj('msg_03.txt') + self.assertRaises(errors.HeaderParseError, + msg.set_boundary, 'BOUNDARY') + + def test_get_decoded_payload(self): + eq = self.assertEqual + msg = self._msgobj('msg_10.txt') + # The outer message is a multipart + eq(msg.get_payload(decode=True), None) + # Subpart 1 is 7bit encoded + eq(msg.get_payload(0).get_payload(decode=True), + 'This is a 7bit encoded message.\n') + # Subpart 2 is quopri + eq(msg.get_payload(1).get_payload(decode=True), + '\xa1This is a Quoted Printable encoded message!\n') + # Subpart 3 is base64 + eq(msg.get_payload(2).get_payload(decode=True), + 'This is a Base64 encoded message.') + # Subpart 4 is base64 with a trailing newline, which + # used to be stripped (issue 7143). + eq(msg.get_payload(3).get_payload(decode=True), + 'This is a Base64 encoded message.\n') + # Subpart 5 has no Content-Transfer-Encoding: header. + eq(msg.get_payload(4).get_payload(decode=True), + 'This has no Content-Transfer-Encoding: header.\n') + + def test_get_decoded_uu_payload(self): + eq = self.assertEqual + msg = Message() + msg.set_payload('begin 666 -\n+:&5L;&\\@=V]R;&0 \n \nend\n') + for cte in ('x-uuencode', 'uuencode', 'uue', 'x-uue'): + msg['content-transfer-encoding'] = cte + eq(msg.get_payload(decode=True), 'hello world') + # Now try some bogus data + msg.set_payload('foo') + eq(msg.get_payload(decode=True), 'foo') + + def test_decoded_generator(self): + eq = self.assertEqual + msg = self._msgobj('msg_07.txt') + fp = openfile('msg_17.txt') + try: + text = fp.read() + finally: + fp.close() + s = StringIO() + g = DecodedGenerator(s) + g.flatten(msg) + eq(s.getvalue(), text) + + def test__contains__(self): + msg = Message() + msg['From'] = 'Me' + msg['to'] = 'You' + # Check for case insensitivity + self.assertTrue('from' in msg) + self.assertTrue('From' in msg) + self.assertTrue('FROM' in msg) + self.assertTrue('to' in msg) + self.assertTrue('To' in msg) + self.assertTrue('TO' in msg) + + def test_as_string(self): + eq = self.assertEqual + msg = self._msgobj('msg_01.txt') + fp = openfile('msg_01.txt') + try: + # BAW 30-Mar-2009 Evil be here. So, the generator is broken with + # respect to long line breaking. It's also not idempotent when a + # header from a parsed message is continued with tabs rather than + # spaces. Before we fixed bug 1974 it was reversedly broken, + # i.e. headers that were continued with spaces got continued with + # tabs. For Python 2.x there's really no good fix and in Python + # 3.x all this stuff is re-written to be right(er). Chris Withers + # convinced me that using space as the default continuation + # character is less bad for more applications. + text = fp.read().replace('\t', ' ') + finally: + fp.close() + self.ndiffAssertEqual(text, msg.as_string()) + fullrepr = str(msg) + lines = fullrepr.split('\n') + self.assertTrue(lines[0].startswith('From ')) + eq(text, NL.join(lines[1:])) + + def test_bad_param(self): + msg = email.message_from_string("Content-Type: blarg; baz; boo\n") + self.assertEqual(msg.get_param('baz'), '') + + def test_missing_filename(self): + msg = email.message_from_string("From: foo\n") + self.assertEqual(msg.get_filename(), None) + + def test_bogus_filename(self): + msg = email.message_from_string( + "Content-Disposition: blarg; filename\n") + self.assertEqual(msg.get_filename(), '') + + def test_missing_boundary(self): + msg = email.message_from_string("From: foo\n") + self.assertEqual(msg.get_boundary(), None) + + def test_get_params(self): + eq = self.assertEqual + msg = email.message_from_string( + 'X-Header: foo=one; bar=two; baz=three\n') + eq(msg.get_params(header='x-header'), + [('foo', 'one'), ('bar', 'two'), ('baz', 'three')]) + msg = email.message_from_string( + 'X-Header: foo; bar=one; baz=two\n') + eq(msg.get_params(header='x-header'), + [('foo', ''), ('bar', 'one'), ('baz', 'two')]) + eq(msg.get_params(), None) + msg = email.message_from_string( + 'X-Header: foo; bar="one"; baz=two\n') + eq(msg.get_params(header='x-header'), + [('foo', ''), ('bar', 'one'), ('baz', 'two')]) + + def test_get_param_liberal(self): + msg = Message() + msg['Content-Type'] = 'Content-Type: Multipart/mixed; boundary = "CPIMSSMTPC06p5f3tG"' + self.assertEqual(msg.get_param('boundary'), 'CPIMSSMTPC06p5f3tG') + + def test_get_param(self): + eq = self.assertEqual + msg = email.message_from_string( + "X-Header: foo=one; bar=two; baz=three\n") + eq(msg.get_param('bar', header='x-header'), 'two') + eq(msg.get_param('quuz', header='x-header'), None) + eq(msg.get_param('quuz'), None) + msg = email.message_from_string( + 'X-Header: foo; bar="one"; baz=two\n') + eq(msg.get_param('foo', header='x-header'), '') + eq(msg.get_param('bar', header='x-header'), 'one') + eq(msg.get_param('baz', header='x-header'), 'two') + # XXX: We are not RFC-2045 compliant! We cannot parse: + # msg["Content-Type"] = 'text/plain; weird="hey; dolly? [you] @ <\\"home\\">?"' + # msg.get_param("weird") + # yet. + + def test_get_param_funky_continuation_lines(self): + msg = self._msgobj('msg_22.txt') + self.assertEqual(msg.get_payload(1).get_param('name'), 'wibble.JPG') + + def test_get_param_with_semis_in_quotes(self): + msg = email.message_from_string( + 'Content-Type: image/pjpeg; name="Jim&&Jill"\n') + self.assertEqual(msg.get_param('name'), 'Jim&&Jill') + self.assertEqual(msg.get_param('name', unquote=False), + '"Jim&&Jill"') + + def test_has_key(self): + msg = email.message_from_string('Header: exists') + self.assertTrue(msg.has_key('header')) + self.assertTrue(msg.has_key('Header')) + self.assertTrue(msg.has_key('HEADER')) + self.assertFalse(msg.has_key('headeri')) + + def test_set_param(self): + eq = self.assertEqual + msg = Message() + msg.set_param('charset', 'iso-2022-jp') + eq(msg.get_param('charset'), 'iso-2022-jp') + msg.set_param('importance', 'high value') + eq(msg.get_param('importance'), 'high value') + eq(msg.get_param('importance', unquote=False), '"high value"') + eq(msg.get_params(), [('text/plain', ''), + ('charset', 'iso-2022-jp'), + ('importance', 'high value')]) + eq(msg.get_params(unquote=False), [('text/plain', ''), + ('charset', '"iso-2022-jp"'), + ('importance', '"high value"')]) + msg.set_param('charset', 'iso-9999-xx', header='X-Jimmy') + eq(msg.get_param('charset', header='X-Jimmy'), 'iso-9999-xx') + + def test_del_param(self): + eq = self.assertEqual + msg = self._msgobj('msg_05.txt') + eq(msg.get_params(), + [('multipart/report', ''), ('report-type', 'delivery-status'), + ('boundary', 'D1690A7AC1.996856090/mail.example.com')]) + old_val = msg.get_param("report-type") + msg.del_param("report-type") + eq(msg.get_params(), + [('multipart/report', ''), + ('boundary', 'D1690A7AC1.996856090/mail.example.com')]) + msg.set_param("report-type", old_val) + eq(msg.get_params(), + [('multipart/report', ''), + ('boundary', 'D1690A7AC1.996856090/mail.example.com'), + ('report-type', old_val)]) + + def test_del_param_on_other_header(self): + msg = Message() + msg.add_header('Content-Disposition', 'attachment', filename='bud.gif') + msg.del_param('filename', 'content-disposition') + self.assertEqual(msg['content-disposition'], 'attachment') + + def test_set_type(self): + eq = self.assertEqual + msg = Message() + self.assertRaises(ValueError, msg.set_type, 'text') + msg.set_type('text/plain') + eq(msg['content-type'], 'text/plain') + msg.set_param('charset', 'us-ascii') + eq(msg['content-type'], 'text/plain; charset="us-ascii"') + msg.set_type('text/html') + eq(msg['content-type'], 'text/html; charset="us-ascii"') + + def test_set_type_on_other_header(self): + msg = Message() + msg['X-Content-Type'] = 'text/plain' + msg.set_type('application/octet-stream', 'X-Content-Type') + self.assertEqual(msg['x-content-type'], 'application/octet-stream') + + def test_get_content_type_missing(self): + msg = Message() + self.assertEqual(msg.get_content_type(), 'text/plain') + + def test_get_content_type_missing_with_default_type(self): + msg = Message() + msg.set_default_type('message/rfc822') + self.assertEqual(msg.get_content_type(), 'message/rfc822') + + def test_get_content_type_from_message_implicit(self): + msg = self._msgobj('msg_30.txt') + self.assertEqual(msg.get_payload(0).get_content_type(), + 'message/rfc822') + + def test_get_content_type_from_message_explicit(self): + msg = self._msgobj('msg_28.txt') + self.assertEqual(msg.get_payload(0).get_content_type(), + 'message/rfc822') + + def test_get_content_type_from_message_text_plain_implicit(self): + msg = self._msgobj('msg_03.txt') + self.assertEqual(msg.get_content_type(), 'text/plain') + + def test_get_content_type_from_message_text_plain_explicit(self): + msg = self._msgobj('msg_01.txt') + self.assertEqual(msg.get_content_type(), 'text/plain') + + def test_get_content_maintype_missing(self): + msg = Message() + self.assertEqual(msg.get_content_maintype(), 'text') + + def test_get_content_maintype_missing_with_default_type(self): + msg = Message() + msg.set_default_type('message/rfc822') + self.assertEqual(msg.get_content_maintype(), 'message') + + def test_get_content_maintype_from_message_implicit(self): + msg = self._msgobj('msg_30.txt') + self.assertEqual(msg.get_payload(0).get_content_maintype(), 'message') + + def test_get_content_maintype_from_message_explicit(self): + msg = self._msgobj('msg_28.txt') + self.assertEqual(msg.get_payload(0).get_content_maintype(), 'message') + + def test_get_content_maintype_from_message_text_plain_implicit(self): + msg = self._msgobj('msg_03.txt') + self.assertEqual(msg.get_content_maintype(), 'text') + + def test_get_content_maintype_from_message_text_plain_explicit(self): + msg = self._msgobj('msg_01.txt') + self.assertEqual(msg.get_content_maintype(), 'text') + + def test_get_content_subtype_missing(self): + msg = Message() + self.assertEqual(msg.get_content_subtype(), 'plain') + + def test_get_content_subtype_missing_with_default_type(self): + msg = Message() + msg.set_default_type('message/rfc822') + self.assertEqual(msg.get_content_subtype(), 'rfc822') + + def test_get_content_subtype_from_message_implicit(self): + msg = self._msgobj('msg_30.txt') + self.assertEqual(msg.get_payload(0).get_content_subtype(), 'rfc822') + + def test_get_content_subtype_from_message_explicit(self): + msg = self._msgobj('msg_28.txt') + self.assertEqual(msg.get_payload(0).get_content_subtype(), 'rfc822') + + def test_get_content_subtype_from_message_text_plain_implicit(self): + msg = self._msgobj('msg_03.txt') + self.assertEqual(msg.get_content_subtype(), 'plain') + + def test_get_content_subtype_from_message_text_plain_explicit(self): + msg = self._msgobj('msg_01.txt') + self.assertEqual(msg.get_content_subtype(), 'plain') + + def test_get_content_maintype_error(self): + msg = Message() + msg['Content-Type'] = 'no-slash-in-this-string' + self.assertEqual(msg.get_content_maintype(), 'text') + + def test_get_content_subtype_error(self): + msg = Message() + msg['Content-Type'] = 'no-slash-in-this-string' + self.assertEqual(msg.get_content_subtype(), 'plain') + + def test_replace_header(self): + eq = self.assertEqual + msg = Message() + msg.add_header('First', 'One') + msg.add_header('Second', 'Two') + msg.add_header('Third', 'Three') + eq(msg.keys(), ['First', 'Second', 'Third']) + eq(msg.values(), ['One', 'Two', 'Three']) + msg.replace_header('Second', 'Twenty') + eq(msg.keys(), ['First', 'Second', 'Third']) + eq(msg.values(), ['One', 'Twenty', 'Three']) + msg.add_header('First', 'Eleven') + msg.replace_header('First', 'One Hundred') + eq(msg.keys(), ['First', 'Second', 'Third', 'First']) + eq(msg.values(), ['One Hundred', 'Twenty', 'Three', 'Eleven']) + self.assertRaises(KeyError, msg.replace_header, 'Fourth', 'Missing') + + def test_broken_base64_payload(self): + x = 'AwDp0P7//y6LwKEAcPa/6Q=9' + msg = Message() + msg['content-type'] = 'audio/x-midi' + msg['content-transfer-encoding'] = 'base64' + msg.set_payload(x) + self.assertEqual(msg.get_payload(decode=True), x) + + + +# Test the email.encoders module +class TestEncoders(unittest.TestCase): + def test_encode_empty_payload(self): + eq = self.assertEqual + msg = Message() + msg.set_charset('us-ascii') + eq(msg['content-transfer-encoding'], '7bit') + + def test_default_cte(self): + eq = self.assertEqual + msg = MIMEText('hello world') + eq(msg['content-transfer-encoding'], '7bit') + + def test_default_cte(self): + eq = self.assertEqual + # With no explicit _charset its us-ascii, and all are 7-bit + msg = MIMEText('hello world') + eq(msg['content-transfer-encoding'], '7bit') + # Similar, but with 8-bit data + msg = MIMEText('hello \xf8 world') + eq(msg['content-transfer-encoding'], '8bit') + # And now with a different charset + msg = MIMEText('hello \xf8 world', _charset='iso-8859-1') + eq(msg['content-transfer-encoding'], 'quoted-printable') + + + +# Test long header wrapping +class TestLongHeaders(TestEmailBase): + def test_split_long_continuation(self): + eq = self.ndiffAssertEqual + msg = email.message_from_string("""\ +Subject: bug demonstration +\t12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 +\tmore text + +test +""") + sfp = StringIO() + g = Generator(sfp) + g.flatten(msg) + eq(sfp.getvalue(), """\ +Subject: bug demonstration + 12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 + more text + +test +""") + + def test_another_long_almost_unsplittable_header(self): + eq = self.ndiffAssertEqual + hstr = """\ +bug demonstration +\t12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 +\tmore text""" + h = Header(hstr, continuation_ws='\t') + eq(h.encode(), """\ +bug demonstration +\t12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 +\tmore text""") + h = Header(hstr) + eq(h.encode(), """\ +bug demonstration + 12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 + more text""") + + def test_long_nonstring(self): + eq = self.ndiffAssertEqual + g = Charset("iso-8859-1") + cz = Charset("iso-8859-2") + utf8 = Charset("utf-8") + g_head = "Die Mieter treten hier ein werden mit einem Foerderband komfortabel den Korridor entlang, an s\xfcdl\xfcndischen Wandgem\xe4lden vorbei, gegen die rotierenden Klingen bef\xf6rdert. " + cz_head = "Finan\xe8ni metropole se hroutily pod tlakem jejich d\xf9vtipu.. " + utf8_head = u"\u6b63\u78ba\u306b\u8a00\u3046\u3068\u7ffb\u8a33\u306f\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u4e00\u90e8\u306f\u30c9\u30a4\u30c4\u8a9e\u3067\u3059\u304c\u3001\u3042\u3068\u306f\u3067\u305f\u3089\u3081\u3067\u3059\u3002\u5b9f\u969b\u306b\u306f\u300cWenn ist das Nunstuck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput.\u300d\u3068\u8a00\u3063\u3066\u3044\u307e\u3059\u3002".encode("utf-8") + h = Header(g_head, g, header_name='Subject') + h.append(cz_head, cz) + h.append(utf8_head, utf8) + msg = Message() + msg['Subject'] = h + sfp = StringIO() + g = Generator(sfp) + g.flatten(msg) + eq(sfp.getvalue(), """\ +Subject: =?iso-8859-1?q?Die_Mieter_treten_hier_ein_werden_mit_einem_Foerd?= + =?iso-8859-1?q?erband_komfortabel_den_Korridor_entlang=2C_an_s=FCdl=FCndi?= + =?iso-8859-1?q?schen_Wandgem=E4lden_vorbei=2C_gegen_die_rotierenden_Kling?= + =?iso-8859-1?q?en_bef=F6rdert=2E_?= =?iso-8859-2?q?Finan=E8ni_met?= + =?iso-8859-2?q?ropole_se_hroutily_pod_tlakem_jejich_d=F9vtipu=2E=2E_?= + =?utf-8?b?5q2j56K644Gr6KiA44GG44Go57+76Kiz44Gv44GV44KM44Gm44GE?= + =?utf-8?b?44G+44Gb44KT44CC5LiA6YOo44Gv44OJ44Kk44OE6Kqe44Gn44GZ44GM44CB?= + =?utf-8?b?44GC44Go44Gv44Gn44Gf44KJ44KB44Gn44GZ44CC5a6f6Zqb44Gr44Gv44CM?= + =?utf-8?q?Wenn_ist_das_Nunstuck_git_und_Slotermeyer=3F_Ja!_Beiherhund_das?= + =?utf-8?b?IE9kZXIgZGllIEZsaXBwZXJ3YWxkdCBnZXJzcHV0LuOAjeOBqOiogOOBow==?= + =?utf-8?b?44Gm44GE44G+44GZ44CC?= + +""") + eq(h.encode(), """\ +=?iso-8859-1?q?Die_Mieter_treten_hier_ein_werden_mit_einem_Foerd?= + =?iso-8859-1?q?erband_komfortabel_den_Korridor_entlang=2C_an_s=FCdl=FCndi?= + =?iso-8859-1?q?schen_Wandgem=E4lden_vorbei=2C_gegen_die_rotierenden_Kling?= + =?iso-8859-1?q?en_bef=F6rdert=2E_?= =?iso-8859-2?q?Finan=E8ni_met?= + =?iso-8859-2?q?ropole_se_hroutily_pod_tlakem_jejich_d=F9vtipu=2E=2E_?= + =?utf-8?b?5q2j56K644Gr6KiA44GG44Go57+76Kiz44Gv44GV44KM44Gm44GE?= + =?utf-8?b?44G+44Gb44KT44CC5LiA6YOo44Gv44OJ44Kk44OE6Kqe44Gn44GZ44GM44CB?= + =?utf-8?b?44GC44Go44Gv44Gn44Gf44KJ44KB44Gn44GZ44CC5a6f6Zqb44Gr44Gv44CM?= + =?utf-8?q?Wenn_ist_das_Nunstuck_git_und_Slotermeyer=3F_Ja!_Beiherhund_das?= + =?utf-8?b?IE9kZXIgZGllIEZsaXBwZXJ3YWxkdCBnZXJzcHV0LuOAjeOBqOiogOOBow==?= + =?utf-8?b?44Gm44GE44G+44GZ44CC?=""") + + def test_long_header_encode(self): + eq = self.ndiffAssertEqual + h = Header('wasnipoop; giraffes="very-long-necked-animals"; ' + 'spooge="yummy"; hippos="gargantuan"; marshmallows="gooey"', + header_name='X-Foobar-Spoink-Defrobnit') + eq(h.encode(), '''\ +wasnipoop; giraffes="very-long-necked-animals"; + spooge="yummy"; hippos="gargantuan"; marshmallows="gooey"''') + + def test_long_header_encode_with_tab_continuation(self): + eq = self.ndiffAssertEqual + h = Header('wasnipoop; giraffes="very-long-necked-animals"; ' + 'spooge="yummy"; hippos="gargantuan"; marshmallows="gooey"', + header_name='X-Foobar-Spoink-Defrobnit', + continuation_ws='\t') + eq(h.encode(), '''\ +wasnipoop; giraffes="very-long-necked-animals"; +\tspooge="yummy"; hippos="gargantuan"; marshmallows="gooey"''') + + def test_header_splitter(self): + eq = self.ndiffAssertEqual + msg = MIMEText('') + # It'd be great if we could use add_header() here, but that doesn't + # guarantee an order of the parameters. + msg['X-Foobar-Spoink-Defrobnit'] = ( + 'wasnipoop; giraffes="very-long-necked-animals"; ' + 'spooge="yummy"; hippos="gargantuan"; marshmallows="gooey"') + sfp = StringIO() + g = Generator(sfp) + g.flatten(msg) + eq(sfp.getvalue(), '''\ +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Foobar-Spoink-Defrobnit: wasnipoop; giraffes="very-long-necked-animals"; + spooge="yummy"; hippos="gargantuan"; marshmallows="gooey" + +''') + + def test_no_semis_header_splitter(self): + eq = self.ndiffAssertEqual + msg = Message() + msg['From'] = 'test@dom.ain' + msg['References'] = SPACE.join(['<%d@dom.ain>' % i for i in range(10)]) + msg.set_payload('Test') + sfp = StringIO() + g = Generator(sfp) + g.flatten(msg) + eq(sfp.getvalue(), """\ +From: test@dom.ain +References: <0@dom.ain> <1@dom.ain> <2@dom.ain> <3@dom.ain> <4@dom.ain> + <5@dom.ain> <6@dom.ain> <7@dom.ain> <8@dom.ain> <9@dom.ain> + +Test""") + + def test_no_split_long_header(self): + eq = self.ndiffAssertEqual + hstr = 'References: ' + 'x' * 80 + h = Header(hstr, continuation_ws='\t') + eq(h.encode(), """\ +References: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx""") + + def test_splitting_multiple_long_lines(self): + eq = self.ndiffAssertEqual + hstr = """\ +from babylon.socal-raves.org (localhost [127.0.0.1]); by babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; for ; Sat, 2 Feb 2002 17:00:06 -0800 (PST) +\tfrom babylon.socal-raves.org (localhost [127.0.0.1]); by babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; for ; Sat, 2 Feb 2002 17:00:06 -0800 (PST) +\tfrom babylon.socal-raves.org (localhost [127.0.0.1]); by babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; for ; Sat, 2 Feb 2002 17:00:06 -0800 (PST) +""" + h = Header(hstr, continuation_ws='\t') + eq(h.encode(), """\ +from babylon.socal-raves.org (localhost [127.0.0.1]); +\tby babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; +\tfor ; +\tSat, 2 Feb 2002 17:00:06 -0800 (PST) +\tfrom babylon.socal-raves.org (localhost [127.0.0.1]); +\tby babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; +\tfor ; +\tSat, 2 Feb 2002 17:00:06 -0800 (PST) +\tfrom babylon.socal-raves.org (localhost [127.0.0.1]); +\tby babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; +\tfor ; +\tSat, 2 Feb 2002 17:00:06 -0800 (PST)""") + + def test_splitting_first_line_only_is_long(self): + eq = self.ndiffAssertEqual + hstr = """\ +from modemcable093.139-201-24.que.mc.videotron.ca ([24.201.139.93] helo=cthulhu.gerg.ca) +\tby kronos.mems-exchange.org with esmtp (Exim 4.05) +\tid 17k4h5-00034i-00 +\tfor test@mems-exchange.org; Wed, 28 Aug 2002 11:25:20 -0400""" + h = Header(hstr, maxlinelen=78, header_name='Received', + continuation_ws='\t') + eq(h.encode(), """\ +from modemcable093.139-201-24.que.mc.videotron.ca ([24.201.139.93] +\thelo=cthulhu.gerg.ca) +\tby kronos.mems-exchange.org with esmtp (Exim 4.05) +\tid 17k4h5-00034i-00 +\tfor test@mems-exchange.org; Wed, 28 Aug 2002 11:25:20 -0400""") + + def test_long_8bit_header(self): + eq = self.ndiffAssertEqual + msg = Message() + h = Header('Britische Regierung gibt', 'iso-8859-1', + header_name='Subject') + h.append('gr\xfcnes Licht f\xfcr Offshore-Windkraftprojekte') + msg['Subject'] = h + eq(msg.as_string(), """\ +Subject: =?iso-8859-1?q?Britische_Regierung_gibt?= =?iso-8859-1?q?gr=FCnes?= + =?iso-8859-1?q?_Licht_f=FCr_Offshore-Windkraftprojekte?= + +""") + + def test_long_8bit_header_no_charset(self): + eq = self.ndiffAssertEqual + msg = Message() + msg['Reply-To'] = 'Britische Regierung gibt gr\xfcnes Licht f\xfcr Offshore-Windkraftprojekte ' + eq(msg.as_string(), """\ +Reply-To: Britische Regierung gibt gr\xfcnes Licht f\xfcr Offshore-Windkraftprojekte + +""") + + def test_long_to_header(self): + eq = self.ndiffAssertEqual + to = '"Someone Test #A" ,,"Someone Test #B" , "Someone Test #C" , "Someone Test #D" ' + msg = Message() + msg['To'] = to + eq(msg.as_string(0), '''\ +To: "Someone Test #A" , , + "Someone Test #B" , + "Someone Test #C" , + "Someone Test #D" + +''') + + def test_long_line_after_append(self): + eq = self.ndiffAssertEqual + s = 'This is an example of string which has almost the limit of header length.' + h = Header(s) + h.append('Add another line.') + eq(h.encode(), """\ +This is an example of string which has almost the limit of header length. + Add another line.""") + + def test_shorter_line_with_append(self): + eq = self.ndiffAssertEqual + s = 'This is a shorter line.' + h = Header(s) + h.append('Add another sentence. (Surprise?)') + eq(h.encode(), + 'This is a shorter line. Add another sentence. (Surprise?)') + + def test_long_field_name(self): + eq = self.ndiffAssertEqual + fn = 'X-Very-Very-Very-Long-Header-Name' + gs = "Die Mieter treten hier ein werden mit einem Foerderband komfortabel den Korridor entlang, an s\xfcdl\xfcndischen Wandgem\xe4lden vorbei, gegen die rotierenden Klingen bef\xf6rdert. " + h = Header(gs, 'iso-8859-1', header_name=fn) + # BAW: this seems broken because the first line is too long + eq(h.encode(), """\ +=?iso-8859-1?q?Die_Mieter_treten_hier_?= + =?iso-8859-1?q?ein_werden_mit_einem_Foerderband_komfortabel_den_Korridor_?= + =?iso-8859-1?q?entlang=2C_an_s=FCdl=FCndischen_Wandgem=E4lden_vorbei=2C_g?= + =?iso-8859-1?q?egen_die_rotierenden_Klingen_bef=F6rdert=2E_?=""") + + def test_long_received_header(self): + h = 'from FOO.TLD (vizworld.acl.foo.tld [123.452.678.9]) by hrothgar.la.mastaler.com (tmda-ofmipd) with ESMTP; Wed, 05 Mar 2003 18:10:18 -0700' + msg = Message() + msg['Received-1'] = Header(h, continuation_ws='\t') + msg['Received-2'] = h + self.ndiffAssertEqual(msg.as_string(), """\ +Received-1: from FOO.TLD (vizworld.acl.foo.tld [123.452.678.9]) by +\throthgar.la.mastaler.com (tmda-ofmipd) with ESMTP; +\tWed, 05 Mar 2003 18:10:18 -0700 +Received-2: from FOO.TLD (vizworld.acl.foo.tld [123.452.678.9]) by + hrothgar.la.mastaler.com (tmda-ofmipd) with ESMTP; + Wed, 05 Mar 2003 18:10:18 -0700 + +""") + + def test_string_headerinst_eq(self): + h = '<15975.17901.207240.414604@sgigritzmann1.mathematik.tu-muenchen.de> (David Bremner\'s message of "Thu, 6 Mar 2003 13:58:21 +0100")' + msg = Message() + msg['Received'] = Header(h, header_name='Received-1', + continuation_ws='\t') + msg['Received'] = h + self.ndiffAssertEqual(msg.as_string(), """\ +Received: <15975.17901.207240.414604@sgigritzmann1.mathematik.tu-muenchen.de> +\t(David Bremner's message of "Thu, 6 Mar 2003 13:58:21 +0100") +Received: <15975.17901.207240.414604@sgigritzmann1.mathematik.tu-muenchen.de> + (David Bremner's message of "Thu, 6 Mar 2003 13:58:21 +0100") + +""") + + def test_long_unbreakable_lines_with_continuation(self): + eq = self.ndiffAssertEqual + msg = Message() + t = """\ + iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEUAAAAkHiJeRUIcGBi9 + locQDQ4zJykFBAXJfWDjAAACYUlEQVR4nF2TQY/jIAyFc6lydlG5x8Nyp1Y69wj1PN2I5gzp""" + msg['Face-1'] = t + msg['Face-2'] = Header(t, header_name='Face-2') + eq(msg.as_string(), """\ +Face-1: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEUAAAAkHiJeRUIcGBi9 + locQDQ4zJykFBAXJfWDjAAACYUlEQVR4nF2TQY/jIAyFc6lydlG5x8Nyp1Y69wj1PN2I5gzp +Face-2: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEUAAAAkHiJeRUIcGBi9 + locQDQ4zJykFBAXJfWDjAAACYUlEQVR4nF2TQY/jIAyFc6lydlG5x8Nyp1Y69wj1PN2I5gzp + +""") + + def test_another_long_multiline_header(self): + eq = self.ndiffAssertEqual + m = '''\ +Received: from siimage.com ([172.25.1.3]) by zima.siliconimage.com with Microsoft SMTPSVC(5.0.2195.4905); + Wed, 16 Oct 2002 07:41:11 -0700''' + msg = email.message_from_string(m) + eq(msg.as_string(), '''\ +Received: from siimage.com ([172.25.1.3]) by zima.siliconimage.com with + Microsoft SMTPSVC(5.0.2195.4905); Wed, 16 Oct 2002 07:41:11 -0700 + +''') + + def test_long_lines_with_different_header(self): + eq = self.ndiffAssertEqual + h = """\ +List-Unsubscribe: , + """ + msg = Message() + msg['List'] = h + msg['List'] = Header(h, header_name='List') + self.ndiffAssertEqual(msg.as_string(), """\ +List: List-Unsubscribe: , + +List: List-Unsubscribe: , + + +""") + + + +# Test mangling of "From " lines in the body of a message +class TestFromMangling(unittest.TestCase): + def setUp(self): + self.msg = Message() + self.msg['From'] = 'aaa@bbb.org' + self.msg.set_payload("""\ +From the desk of A.A.A.: +Blah blah blah +""") + + def test_mangled_from(self): + s = StringIO() + g = Generator(s, mangle_from_=True) + g.flatten(self.msg) + self.assertEqual(s.getvalue(), """\ +From: aaa@bbb.org + +>From the desk of A.A.A.: +Blah blah blah +""") + + def test_dont_mangle_from(self): + s = StringIO() + g = Generator(s, mangle_from_=False) + g.flatten(self.msg) + self.assertEqual(s.getvalue(), """\ +From: aaa@bbb.org + +From the desk of A.A.A.: +Blah blah blah +""") + + + +# Test the basic MIMEAudio class +class TestMIMEAudio(unittest.TestCase): + def setUp(self): + # Make sure we pick up the audiotest.au that lives in email/test/data. + # In Python, there's an audiotest.au living in Lib/test but that isn't + # included in some binary distros that don't include the test + # package. The trailing empty string on the .join() is significant + # since findfile() will do a dirname(). + datadir = os.path.join(os.path.dirname(landmark), 'data', '') + fp = open(findfile('audiotest.au', datadir), 'rb') + try: + self._audiodata = fp.read() + finally: + fp.close() + self._au = MIMEAudio(self._audiodata) + + def test_guess_minor_type(self): + self.assertEqual(self._au.get_content_type(), 'audio/basic') + + def test_encoding(self): + payload = self._au.get_payload() + self.assertEqual(base64.decodestring(payload), self._audiodata) + + def test_checkSetMinor(self): + au = MIMEAudio(self._audiodata, 'fish') + self.assertEqual(au.get_content_type(), 'audio/fish') + + def test_add_header(self): + eq = self.assertEqual + unless = self.assertTrue + self._au.add_header('Content-Disposition', 'attachment', + filename='audiotest.au') + eq(self._au['content-disposition'], + 'attachment; filename="audiotest.au"') + eq(self._au.get_params(header='content-disposition'), + [('attachment', ''), ('filename', 'audiotest.au')]) + eq(self._au.get_param('filename', header='content-disposition'), + 'audiotest.au') + missing = [] + eq(self._au.get_param('attachment', header='content-disposition'), '') + unless(self._au.get_param('foo', failobj=missing, + header='content-disposition') is missing) + # Try some missing stuff + unless(self._au.get_param('foobar', missing) is missing) + unless(self._au.get_param('attachment', missing, + header='foobar') is missing) + + + +# Test the basic MIMEImage class +class TestMIMEImage(unittest.TestCase): + def setUp(self): + fp = openfile('PyBanner048.gif') + try: + self._imgdata = fp.read() + finally: + fp.close() + self._im = MIMEImage(self._imgdata) + + def test_guess_minor_type(self): + self.assertEqual(self._im.get_content_type(), 'image/gif') + + def test_encoding(self): + payload = self._im.get_payload() + self.assertEqual(base64.decodestring(payload), self._imgdata) + + def test_checkSetMinor(self): + im = MIMEImage(self._imgdata, 'fish') + self.assertEqual(im.get_content_type(), 'image/fish') + + def test_add_header(self): + eq = self.assertEqual + unless = self.assertTrue + self._im.add_header('Content-Disposition', 'attachment', + filename='dingusfish.gif') + eq(self._im['content-disposition'], + 'attachment; filename="dingusfish.gif"') + eq(self._im.get_params(header='content-disposition'), + [('attachment', ''), ('filename', 'dingusfish.gif')]) + eq(self._im.get_param('filename', header='content-disposition'), + 'dingusfish.gif') + missing = [] + eq(self._im.get_param('attachment', header='content-disposition'), '') + unless(self._im.get_param('foo', failobj=missing, + header='content-disposition') is missing) + # Try some missing stuff + unless(self._im.get_param('foobar', missing) is missing) + unless(self._im.get_param('attachment', missing, + header='foobar') is missing) + + + +# Test the basic MIMEApplication class +class TestMIMEApplication(unittest.TestCase): + def test_headers(self): + eq = self.assertEqual + msg = MIMEApplication('\xfa\xfb\xfc\xfd\xfe\xff') + eq(msg.get_content_type(), 'application/octet-stream') + eq(msg['content-transfer-encoding'], 'base64') + + def test_body(self): + eq = self.assertEqual + bytes = '\xfa\xfb\xfc\xfd\xfe\xff' + msg = MIMEApplication(bytes) + eq(msg.get_payload(), '+vv8/f7/') + eq(msg.get_payload(decode=True), bytes) + + def test_binary_body_with_encode_7or8bit(self): + # Issue 17171. + bytesdata = b'\xfa\xfb\xfc\xfd\xfe\xff' + msg = MIMEApplication(bytesdata, _encoder=encoders.encode_7or8bit) + # Treated as a string, this will be invalid code points. + self.assertEqual(msg.get_payload(), bytesdata) + self.assertEqual(msg.get_payload(decode=True), bytesdata) + self.assertEqual(msg['Content-Transfer-Encoding'], '8bit') + s = StringIO() + g = Generator(s) + g.flatten(msg) + wireform = s.getvalue() + msg2 = email.message_from_string(wireform) + self.assertEqual(msg.get_payload(), bytesdata) + self.assertEqual(msg2.get_payload(decode=True), bytesdata) + self.assertEqual(msg2['Content-Transfer-Encoding'], '8bit') + + def test_binary_body_with_encode_noop(self): + # Issue 16564: This does not produce an RFC valid message, since to be + # valid it should have a CTE of binary. But the below works, and is + # documented as working this way. + bytesdata = b'\xfa\xfb\xfc\xfd\xfe\xff' + msg = MIMEApplication(bytesdata, _encoder=encoders.encode_noop) + self.assertEqual(msg.get_payload(), bytesdata) + self.assertEqual(msg.get_payload(decode=True), bytesdata) + s = StringIO() + g = Generator(s) + g.flatten(msg) + wireform = s.getvalue() + msg2 = email.message_from_string(wireform) + self.assertEqual(msg.get_payload(), bytesdata) + self.assertEqual(msg2.get_payload(decode=True), bytesdata) + + +# Test the basic MIMEText class +class TestMIMEText(unittest.TestCase): + def setUp(self): + self._msg = MIMEText('hello there') + + def test_types(self): + eq = self.assertEqual + unless = self.assertTrue + eq(self._msg.get_content_type(), 'text/plain') + eq(self._msg.get_param('charset'), 'us-ascii') + missing = [] + unless(self._msg.get_param('foobar', missing) is missing) + unless(self._msg.get_param('charset', missing, header='foobar') + is missing) + + def test_payload(self): + self.assertEqual(self._msg.get_payload(), 'hello there') + self.assertTrue(not self._msg.is_multipart()) + + def test_charset(self): + eq = self.assertEqual + msg = MIMEText('hello there', _charset='us-ascii') + eq(msg.get_charset().input_charset, 'us-ascii') + eq(msg['content-type'], 'text/plain; charset="us-ascii"') + + + +# Test complicated multipart/* messages +class TestMultipart(TestEmailBase): + def setUp(self): + fp = openfile('PyBanner048.gif') + try: + data = fp.read() + finally: + fp.close() + + container = MIMEBase('multipart', 'mixed', boundary='BOUNDARY') + image = MIMEImage(data, name='dingusfish.gif') + image.add_header('content-disposition', 'attachment', + filename='dingusfish.gif') + intro = MIMEText('''\ +Hi there, + +This is the dingus fish. +''') + container.attach(intro) + container.attach(image) + container['From'] = 'Barry ' + container['To'] = 'Dingus Lovers ' + container['Subject'] = 'Here is your dingus fish' + + now = 987809702.54848599 + timetuple = time.localtime(now) + if timetuple[-1] == 0: + tzsecs = time.timezone + else: + tzsecs = time.altzone + if tzsecs > 0: + sign = '-' + else: + sign = '+' + tzoffset = ' %s%04d' % (sign, tzsecs // 36) + container['Date'] = time.strftime( + '%a, %d %b %Y %H:%M:%S', + time.localtime(now)) + tzoffset + self._msg = container + self._im = image + self._txt = intro + + def test_hierarchy(self): + # convenience + eq = self.assertEqual + unless = self.assertTrue + raises = self.assertRaises + # tests + m = self._msg + unless(m.is_multipart()) + eq(m.get_content_type(), 'multipart/mixed') + eq(len(m.get_payload()), 2) + raises(IndexError, m.get_payload, 2) + m0 = m.get_payload(0) + m1 = m.get_payload(1) + unless(m0 is self._txt) + unless(m1 is self._im) + eq(m.get_payload(), [m0, m1]) + unless(not m0.is_multipart()) + unless(not m1.is_multipart()) + + def test_empty_multipart_idempotent(self): + text = """\ +Content-Type: multipart/mixed; boundary="BOUNDARY" +MIME-Version: 1.0 +Subject: A subject +To: aperson@dom.ain +From: bperson@dom.ain + + +--BOUNDARY + + +--BOUNDARY-- +""" + msg = Parser().parsestr(text) + self.ndiffAssertEqual(text, msg.as_string()) + + def test_no_parts_in_a_multipart_with_none_epilogue(self): + outer = MIMEBase('multipart', 'mixed') + outer['Subject'] = 'A subject' + outer['To'] = 'aperson@dom.ain' + outer['From'] = 'bperson@dom.ain' + outer.set_boundary('BOUNDARY') + self.ndiffAssertEqual(outer.as_string(), '''\ +Content-Type: multipart/mixed; boundary="BOUNDARY" +MIME-Version: 1.0 +Subject: A subject +To: aperson@dom.ain +From: bperson@dom.ain + +--BOUNDARY + +--BOUNDARY--''') + + def test_no_parts_in_a_multipart_with_empty_epilogue(self): + outer = MIMEBase('multipart', 'mixed') + outer['Subject'] = 'A subject' + outer['To'] = 'aperson@dom.ain' + outer['From'] = 'bperson@dom.ain' + outer.preamble = '' + outer.epilogue = '' + outer.set_boundary('BOUNDARY') + self.ndiffAssertEqual(outer.as_string(), '''\ +Content-Type: multipart/mixed; boundary="BOUNDARY" +MIME-Version: 1.0 +Subject: A subject +To: aperson@dom.ain +From: bperson@dom.ain + + +--BOUNDARY + +--BOUNDARY-- +''') + + def test_one_part_in_a_multipart(self): + eq = self.ndiffAssertEqual + outer = MIMEBase('multipart', 'mixed') + outer['Subject'] = 'A subject' + outer['To'] = 'aperson@dom.ain' + outer['From'] = 'bperson@dom.ain' + outer.set_boundary('BOUNDARY') + msg = MIMEText('hello world') + outer.attach(msg) + eq(outer.as_string(), '''\ +Content-Type: multipart/mixed; boundary="BOUNDARY" +MIME-Version: 1.0 +Subject: A subject +To: aperson@dom.ain +From: bperson@dom.ain + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +hello world +--BOUNDARY--''') + + def test_seq_parts_in_a_multipart_with_empty_preamble(self): + eq = self.ndiffAssertEqual + outer = MIMEBase('multipart', 'mixed') + outer['Subject'] = 'A subject' + outer['To'] = 'aperson@dom.ain' + outer['From'] = 'bperson@dom.ain' + outer.preamble = '' + msg = MIMEText('hello world') + outer.attach(msg) + outer.set_boundary('BOUNDARY') + eq(outer.as_string(), '''\ +Content-Type: multipart/mixed; boundary="BOUNDARY" +MIME-Version: 1.0 +Subject: A subject +To: aperson@dom.ain +From: bperson@dom.ain + + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +hello world +--BOUNDARY--''') + + + def test_seq_parts_in_a_multipart_with_none_preamble(self): + eq = self.ndiffAssertEqual + outer = MIMEBase('multipart', 'mixed') + outer['Subject'] = 'A subject' + outer['To'] = 'aperson@dom.ain' + outer['From'] = 'bperson@dom.ain' + outer.preamble = None + msg = MIMEText('hello world') + outer.attach(msg) + outer.set_boundary('BOUNDARY') + eq(outer.as_string(), '''\ +Content-Type: multipart/mixed; boundary="BOUNDARY" +MIME-Version: 1.0 +Subject: A subject +To: aperson@dom.ain +From: bperson@dom.ain + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +hello world +--BOUNDARY--''') + + + def test_seq_parts_in_a_multipart_with_none_epilogue(self): + eq = self.ndiffAssertEqual + outer = MIMEBase('multipart', 'mixed') + outer['Subject'] = 'A subject' + outer['To'] = 'aperson@dom.ain' + outer['From'] = 'bperson@dom.ain' + outer.epilogue = None + msg = MIMEText('hello world') + outer.attach(msg) + outer.set_boundary('BOUNDARY') + eq(outer.as_string(), '''\ +Content-Type: multipart/mixed; boundary="BOUNDARY" +MIME-Version: 1.0 +Subject: A subject +To: aperson@dom.ain +From: bperson@dom.ain + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +hello world +--BOUNDARY--''') + + + def test_seq_parts_in_a_multipart_with_empty_epilogue(self): + eq = self.ndiffAssertEqual + outer = MIMEBase('multipart', 'mixed') + outer['Subject'] = 'A subject' + outer['To'] = 'aperson@dom.ain' + outer['From'] = 'bperson@dom.ain' + outer.epilogue = '' + msg = MIMEText('hello world') + outer.attach(msg) + outer.set_boundary('BOUNDARY') + eq(outer.as_string(), '''\ +Content-Type: multipart/mixed; boundary="BOUNDARY" +MIME-Version: 1.0 +Subject: A subject +To: aperson@dom.ain +From: bperson@dom.ain + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +hello world +--BOUNDARY-- +''') + + + def test_seq_parts_in_a_multipart_with_nl_epilogue(self): + eq = self.ndiffAssertEqual + outer = MIMEBase('multipart', 'mixed') + outer['Subject'] = 'A subject' + outer['To'] = 'aperson@dom.ain' + outer['From'] = 'bperson@dom.ain' + outer.epilogue = '\n' + msg = MIMEText('hello world') + outer.attach(msg) + outer.set_boundary('BOUNDARY') + eq(outer.as_string(), '''\ +Content-Type: multipart/mixed; boundary="BOUNDARY" +MIME-Version: 1.0 +Subject: A subject +To: aperson@dom.ain +From: bperson@dom.ain + +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +hello world +--BOUNDARY-- + +''') + + def test_message_external_body(self): + eq = self.assertEqual + msg = self._msgobj('msg_36.txt') + eq(len(msg.get_payload()), 2) + msg1 = msg.get_payload(1) + eq(msg1.get_content_type(), 'multipart/alternative') + eq(len(msg1.get_payload()), 2) + for subpart in msg1.get_payload(): + eq(subpart.get_content_type(), 'message/external-body') + eq(len(subpart.get_payload()), 1) + subsubpart = subpart.get_payload(0) + eq(subsubpart.get_content_type(), 'text/plain') + + def test_double_boundary(self): + # msg_37.txt is a multipart that contains two dash-boundary's in a + # row. Our interpretation of RFC 2046 calls for ignoring the second + # and subsequent boundaries. + msg = self._msgobj('msg_37.txt') + self.assertEqual(len(msg.get_payload()), 3) + + def test_nested_inner_contains_outer_boundary(self): + eq = self.ndiffAssertEqual + # msg_38.txt has an inner part that contains outer boundaries. My + # interpretation of RFC 2046 (based on sections 5.1 and 5.1.2) say + # these are illegal and should be interpreted as unterminated inner + # parts. + msg = self._msgobj('msg_38.txt') + sfp = StringIO() + iterators._structure(msg, sfp) + eq(sfp.getvalue(), """\ +multipart/mixed + multipart/mixed + multipart/alternative + text/plain + text/plain + text/plain + text/plain +""") + + def test_nested_with_same_boundary(self): + eq = self.ndiffAssertEqual + # msg 39.txt is similarly evil in that it's got inner parts that use + # the same boundary as outer parts. Again, I believe the way this is + # parsed is closest to the spirit of RFC 2046 + msg = self._msgobj('msg_39.txt') + sfp = StringIO() + iterators._structure(msg, sfp) + eq(sfp.getvalue(), """\ +multipart/mixed + multipart/mixed + multipart/alternative + application/octet-stream + application/octet-stream + text/plain +""") + + def test_boundary_in_non_multipart(self): + msg = self._msgobj('msg_40.txt') + self.assertEqual(msg.as_string(), '''\ +MIME-Version: 1.0 +Content-Type: text/html; boundary="--961284236552522269" + +----961284236552522269 +Content-Type: text/html; +Content-Transfer-Encoding: 7Bit + + + +----961284236552522269-- +''') + + def test_boundary_with_leading_space(self): + eq = self.assertEqual + msg = email.message_from_string('''\ +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary=" XXXX" + +-- XXXX +Content-Type: text/plain + + +-- XXXX +Content-Type: text/plain + +-- XXXX-- +''') + self.assertTrue(msg.is_multipart()) + eq(msg.get_boundary(), ' XXXX') + eq(len(msg.get_payload()), 2) + + def test_boundary_without_trailing_newline(self): + m = Parser().parsestr("""\ +Content-Type: multipart/mixed; boundary="===============0012394164==" +MIME-Version: 1.0 + +--===============0012394164== +Content-Type: image/file1.jpg +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 + +YXNkZg== +--===============0012394164==--""") + self.assertEqual(m.get_payload(0).get_payload(), 'YXNkZg==') + + + +# Test some badly formatted messages +class TestNonConformant(TestEmailBase): + def test_parse_missing_minor_type(self): + eq = self.assertEqual + msg = self._msgobj('msg_14.txt') + eq(msg.get_content_type(), 'text/plain') + eq(msg.get_content_maintype(), 'text') + eq(msg.get_content_subtype(), 'plain') + + def test_same_boundary_inner_outer(self): + unless = self.assertTrue + msg = self._msgobj('msg_15.txt') + # XXX We can probably eventually do better + inner = msg.get_payload(0) + unless(hasattr(inner, 'defects')) + self.assertEqual(len(inner.defects), 1) + unless(isinstance(inner.defects[0], + errors.StartBoundaryNotFoundDefect)) + + def test_multipart_no_boundary(self): + unless = self.assertTrue + msg = self._msgobj('msg_25.txt') + unless(isinstance(msg.get_payload(), str)) + self.assertEqual(len(msg.defects), 2) + unless(isinstance(msg.defects[0], errors.NoBoundaryInMultipartDefect)) + unless(isinstance(msg.defects[1], + errors.MultipartInvariantViolationDefect)) + + def test_invalid_content_type(self): + eq = self.assertEqual + neq = self.ndiffAssertEqual + msg = Message() + # RFC 2045, $5.2 says invalid yields text/plain + msg['Content-Type'] = 'text' + eq(msg.get_content_maintype(), 'text') + eq(msg.get_content_subtype(), 'plain') + eq(msg.get_content_type(), 'text/plain') + # Clear the old value and try something /really/ invalid + del msg['content-type'] + msg['Content-Type'] = 'foo' + eq(msg.get_content_maintype(), 'text') + eq(msg.get_content_subtype(), 'plain') + eq(msg.get_content_type(), 'text/plain') + # Still, make sure that the message is idempotently generated + s = StringIO() + g = Generator(s) + g.flatten(msg) + neq(s.getvalue(), 'Content-Type: foo\n\n') + + def test_no_start_boundary(self): + eq = self.ndiffAssertEqual + msg = self._msgobj('msg_31.txt') + eq(msg.get_payload(), """\ +--BOUNDARY +Content-Type: text/plain + +message 1 + +--BOUNDARY +Content-Type: text/plain + +message 2 + +--BOUNDARY-- +""") + + def test_no_separating_blank_line(self): + eq = self.ndiffAssertEqual + msg = self._msgobj('msg_35.txt') + eq(msg.as_string(), """\ +From: aperson@dom.ain +To: bperson@dom.ain +Subject: here's something interesting + +counter to RFC 2822, there's no separating newline here +""") + + def test_lying_multipart(self): + unless = self.assertTrue + msg = self._msgobj('msg_41.txt') + unless(hasattr(msg, 'defects')) + self.assertEqual(len(msg.defects), 2) + unless(isinstance(msg.defects[0], errors.NoBoundaryInMultipartDefect)) + unless(isinstance(msg.defects[1], + errors.MultipartInvariantViolationDefect)) + + def test_missing_start_boundary(self): + outer = self._msgobj('msg_42.txt') + # The message structure is: + # + # multipart/mixed + # text/plain + # message/rfc822 + # multipart/mixed [*] + # + # [*] This message is missing its start boundary + bad = outer.get_payload(1).get_payload(0) + self.assertEqual(len(bad.defects), 1) + self.assertTrue(isinstance(bad.defects[0], + errors.StartBoundaryNotFoundDefect)) + + def test_first_line_is_continuation_header(self): + eq = self.assertEqual + m = ' Line 1\nLine 2\nLine 3' + msg = email.message_from_string(m) + eq(msg.keys(), []) + eq(msg.get_payload(), 'Line 2\nLine 3') + eq(len(msg.defects), 1) + self.assertTrue(isinstance(msg.defects[0], + errors.FirstHeaderLineIsContinuationDefect)) + eq(msg.defects[0].line, ' Line 1\n') + + + +# Test RFC 2047 header encoding and decoding +class TestRFC2047(unittest.TestCase): + def test_rfc2047_multiline(self): + eq = self.assertEqual + s = """Re: =?mac-iceland?q?r=8Aksm=9Arg=8Cs?= baz + foo bar =?mac-iceland?q?r=8Aksm=9Arg=8Cs?=""" + dh = decode_header(s) + eq(dh, [ + ('Re:', None), + ('r\x8aksm\x9arg\x8cs', 'mac-iceland'), + ('baz foo bar', None), + ('r\x8aksm\x9arg\x8cs', 'mac-iceland')]) + eq(str(make_header(dh)), + """Re: =?mac-iceland?q?r=8Aksm=9Arg=8Cs?= baz foo bar + =?mac-iceland?q?r=8Aksm=9Arg=8Cs?=""") + + def test_whitespace_eater_unicode(self): + eq = self.assertEqual + s = '=?ISO-8859-1?Q?Andr=E9?= Pirard ' + dh = decode_header(s) + eq(dh, [('Andr\xe9', 'iso-8859-1'), ('Pirard ', None)]) + hu = unicode(make_header(dh)).encode('latin-1') + eq(hu, 'Andr\xe9 Pirard ') + + def test_whitespace_eater_unicode_2(self): + eq = self.assertEqual + s = 'The =?iso-8859-1?b?cXVpY2sgYnJvd24gZm94?= jumped over the =?iso-8859-1?b?bGF6eSBkb2c=?=' + dh = decode_header(s) + eq(dh, [('The', None), ('quick brown fox', 'iso-8859-1'), + ('jumped over the', None), ('lazy dog', 'iso-8859-1')]) + hu = make_header(dh).__unicode__() + eq(hu, u'The quick brown fox jumped over the lazy dog') + + def test_rfc2047_missing_whitespace(self): + s = 'Sm=?ISO-8859-1?B?9g==?=rg=?ISO-8859-1?B?5Q==?=sbord' + dh = decode_header(s) + self.assertEqual(dh, [(s, None)]) + + def test_rfc2047_with_whitespace(self): + s = 'Sm =?ISO-8859-1?B?9g==?= rg =?ISO-8859-1?B?5Q==?= sbord' + dh = decode_header(s) + self.assertEqual(dh, [('Sm', None), ('\xf6', 'iso-8859-1'), + ('rg', None), ('\xe5', 'iso-8859-1'), + ('sbord', None)]) + + + +# Test the MIMEMessage class +class TestMIMEMessage(TestEmailBase): + def setUp(self): + fp = openfile('msg_11.txt') + try: + self._text = fp.read() + finally: + fp.close() + + def test_type_error(self): + self.assertRaises(TypeError, MIMEMessage, 'a plain string') + + def test_valid_argument(self): + eq = self.assertEqual + unless = self.assertTrue + subject = 'A sub-message' + m = Message() + m['Subject'] = subject + r = MIMEMessage(m) + eq(r.get_content_type(), 'message/rfc822') + payload = r.get_payload() + unless(isinstance(payload, list)) + eq(len(payload), 1) + subpart = payload[0] + unless(subpart is m) + eq(subpart['subject'], subject) + + def test_bad_multipart(self): + eq = self.assertEqual + msg1 = Message() + msg1['Subject'] = 'subpart 1' + msg2 = Message() + msg2['Subject'] = 'subpart 2' + r = MIMEMessage(msg1) + self.assertRaises(errors.MultipartConversionError, r.attach, msg2) + + def test_generate(self): + # First craft the message to be encapsulated + m = Message() + m['Subject'] = 'An enclosed message' + m.set_payload('Here is the body of the message.\n') + r = MIMEMessage(m) + r['Subject'] = 'The enclosing message' + s = StringIO() + g = Generator(s) + g.flatten(r) + self.assertEqual(s.getvalue(), """\ +Content-Type: message/rfc822 +MIME-Version: 1.0 +Subject: The enclosing message + +Subject: An enclosed message + +Here is the body of the message. +""") + + def test_parse_message_rfc822(self): + eq = self.assertEqual + unless = self.assertTrue + msg = self._msgobj('msg_11.txt') + eq(msg.get_content_type(), 'message/rfc822') + payload = msg.get_payload() + unless(isinstance(payload, list)) + eq(len(payload), 1) + submsg = payload[0] + self.assertTrue(isinstance(submsg, Message)) + eq(submsg['subject'], 'An enclosed message') + eq(submsg.get_payload(), 'Here is the body of the message.\n') + + def test_dsn(self): + eq = self.assertEqual + unless = self.assertTrue + # msg 16 is a Delivery Status Notification, see RFC 1894 + msg = self._msgobj('msg_16.txt') + eq(msg.get_content_type(), 'multipart/report') + unless(msg.is_multipart()) + eq(len(msg.get_payload()), 3) + # Subpart 1 is a text/plain, human readable section + subpart = msg.get_payload(0) + eq(subpart.get_content_type(), 'text/plain') + eq(subpart.get_payload(), """\ +This report relates to a message you sent with the following header fields: + + Message-id: <002001c144a6$8752e060$56104586@oxy.edu> + Date: Sun, 23 Sep 2001 20:10:55 -0700 + From: "Ian T. Henry" + To: SoCal Raves + Subject: [scr] yeah for Ians!! + +Your message cannot be delivered to the following recipients: + + Recipient address: jangel1@cougar.noc.ucla.edu + Reason: recipient reached disk quota + +""") + # Subpart 2 contains the machine parsable DSN information. It + # consists of two blocks of headers, represented by two nested Message + # objects. + subpart = msg.get_payload(1) + eq(subpart.get_content_type(), 'message/delivery-status') + eq(len(subpart.get_payload()), 2) + # message/delivery-status should treat each block as a bunch of + # headers, i.e. a bunch of Message objects. + dsn1 = subpart.get_payload(0) + unless(isinstance(dsn1, Message)) + eq(dsn1['original-envelope-id'], '0GK500B4HD0888@cougar.noc.ucla.edu') + eq(dsn1.get_param('dns', header='reporting-mta'), '') + # Try a missing one + eq(dsn1.get_param('nsd', header='reporting-mta'), None) + dsn2 = subpart.get_payload(1) + unless(isinstance(dsn2, Message)) + eq(dsn2['action'], 'failed') + eq(dsn2.get_params(header='original-recipient'), + [('rfc822', ''), ('jangel1@cougar.noc.ucla.edu', '')]) + eq(dsn2.get_param('rfc822', header='final-recipient'), '') + # Subpart 3 is the original message + subpart = msg.get_payload(2) + eq(subpart.get_content_type(), 'message/rfc822') + payload = subpart.get_payload() + unless(isinstance(payload, list)) + eq(len(payload), 1) + subsubpart = payload[0] + unless(isinstance(subsubpart, Message)) + eq(subsubpart.get_content_type(), 'text/plain') + eq(subsubpart['message-id'], + '<002001c144a6$8752e060$56104586@oxy.edu>') + + def test_epilogue(self): + eq = self.ndiffAssertEqual + fp = openfile('msg_21.txt') + try: + text = fp.read() + finally: + fp.close() + msg = Message() + msg['From'] = 'aperson@dom.ain' + msg['To'] = 'bperson@dom.ain' + msg['Subject'] = 'Test' + msg.preamble = 'MIME message' + msg.epilogue = 'End of MIME message\n' + msg1 = MIMEText('One') + msg2 = MIMEText('Two') + msg.add_header('Content-Type', 'multipart/mixed', boundary='BOUNDARY') + msg.attach(msg1) + msg.attach(msg2) + sfp = StringIO() + g = Generator(sfp) + g.flatten(msg) + eq(sfp.getvalue(), text) + + def test_no_nl_preamble(self): + eq = self.ndiffAssertEqual + msg = Message() + msg['From'] = 'aperson@dom.ain' + msg['To'] = 'bperson@dom.ain' + msg['Subject'] = 'Test' + msg.preamble = 'MIME message' + msg.epilogue = '' + msg1 = MIMEText('One') + msg2 = MIMEText('Two') + msg.add_header('Content-Type', 'multipart/mixed', boundary='BOUNDARY') + msg.attach(msg1) + msg.attach(msg2) + eq(msg.as_string(), """\ +From: aperson@dom.ain +To: bperson@dom.ain +Subject: Test +Content-Type: multipart/mixed; boundary="BOUNDARY" + +MIME message +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +One +--BOUNDARY +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +Two +--BOUNDARY-- +""") + + def test_default_type(self): + eq = self.assertEqual + fp = openfile('msg_30.txt') + try: + msg = email.message_from_file(fp) + finally: + fp.close() + container1 = msg.get_payload(0) + eq(container1.get_default_type(), 'message/rfc822') + eq(container1.get_content_type(), 'message/rfc822') + container2 = msg.get_payload(1) + eq(container2.get_default_type(), 'message/rfc822') + eq(container2.get_content_type(), 'message/rfc822') + container1a = container1.get_payload(0) + eq(container1a.get_default_type(), 'text/plain') + eq(container1a.get_content_type(), 'text/plain') + container2a = container2.get_payload(0) + eq(container2a.get_default_type(), 'text/plain') + eq(container2a.get_content_type(), 'text/plain') + + def test_default_type_with_explicit_container_type(self): + eq = self.assertEqual + fp = openfile('msg_28.txt') + try: + msg = email.message_from_file(fp) + finally: + fp.close() + container1 = msg.get_payload(0) + eq(container1.get_default_type(), 'message/rfc822') + eq(container1.get_content_type(), 'message/rfc822') + container2 = msg.get_payload(1) + eq(container2.get_default_type(), 'message/rfc822') + eq(container2.get_content_type(), 'message/rfc822') + container1a = container1.get_payload(0) + eq(container1a.get_default_type(), 'text/plain') + eq(container1a.get_content_type(), 'text/plain') + container2a = container2.get_payload(0) + eq(container2a.get_default_type(), 'text/plain') + eq(container2a.get_content_type(), 'text/plain') + + def test_default_type_non_parsed(self): + eq = self.assertEqual + neq = self.ndiffAssertEqual + # Set up container + container = MIMEMultipart('digest', 'BOUNDARY') + container.epilogue = '' + # Set up subparts + subpart1a = MIMEText('message 1\n') + subpart2a = MIMEText('message 2\n') + subpart1 = MIMEMessage(subpart1a) + subpart2 = MIMEMessage(subpart2a) + container.attach(subpart1) + container.attach(subpart2) + eq(subpart1.get_content_type(), 'message/rfc822') + eq(subpart1.get_default_type(), 'message/rfc822') + eq(subpart2.get_content_type(), 'message/rfc822') + eq(subpart2.get_default_type(), 'message/rfc822') + neq(container.as_string(0), '''\ +Content-Type: multipart/digest; boundary="BOUNDARY" +MIME-Version: 1.0 + +--BOUNDARY +Content-Type: message/rfc822 +MIME-Version: 1.0 + +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +message 1 + +--BOUNDARY +Content-Type: message/rfc822 +MIME-Version: 1.0 + +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +message 2 + +--BOUNDARY-- +''') + del subpart1['content-type'] + del subpart1['mime-version'] + del subpart2['content-type'] + del subpart2['mime-version'] + eq(subpart1.get_content_type(), 'message/rfc822') + eq(subpart1.get_default_type(), 'message/rfc822') + eq(subpart2.get_content_type(), 'message/rfc822') + eq(subpart2.get_default_type(), 'message/rfc822') + neq(container.as_string(0), '''\ +Content-Type: multipart/digest; boundary="BOUNDARY" +MIME-Version: 1.0 + +--BOUNDARY + +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +message 1 + +--BOUNDARY + +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +message 2 + +--BOUNDARY-- +''') + + def test_mime_attachments_in_constructor(self): + eq = self.assertEqual + text1 = MIMEText('') + text2 = MIMEText('') + msg = MIMEMultipart(_subparts=(text1, text2)) + eq(len(msg.get_payload()), 2) + eq(msg.get_payload(0), text1) + eq(msg.get_payload(1), text2) + + + +# A general test of parser->model->generator idempotency. IOW, read a message +# in, parse it into a message object tree, then without touching the tree, +# regenerate the plain text. The original text and the transformed text +# should be identical. Note: that we ignore the Unix-From since that may +# contain a changed date. +class TestIdempotent(TestEmailBase): + def _msgobj(self, filename): + fp = openfile(filename) + try: + data = fp.read() + finally: + fp.close() + msg = email.message_from_string(data) + return msg, data + + def _idempotent(self, msg, text): + eq = self.ndiffAssertEqual + s = StringIO() + g = Generator(s, maxheaderlen=0) + g.flatten(msg) + eq(text, s.getvalue()) + + def test_parse_text_message(self): + eq = self.assertEqual + msg, text = self._msgobj('msg_01.txt') + eq(msg.get_content_type(), 'text/plain') + eq(msg.get_content_maintype(), 'text') + eq(msg.get_content_subtype(), 'plain') + eq(msg.get_params()[1], ('charset', 'us-ascii')) + eq(msg.get_param('charset'), 'us-ascii') + eq(msg.preamble, None) + eq(msg.epilogue, None) + self._idempotent(msg, text) + + def test_parse_untyped_message(self): + eq = self.assertEqual + msg, text = self._msgobj('msg_03.txt') + eq(msg.get_content_type(), 'text/plain') + eq(msg.get_params(), None) + eq(msg.get_param('charset'), None) + self._idempotent(msg, text) + + def test_simple_multipart(self): + msg, text = self._msgobj('msg_04.txt') + self._idempotent(msg, text) + + def test_MIME_digest(self): + msg, text = self._msgobj('msg_02.txt') + self._idempotent(msg, text) + + def test_long_header(self): + msg, text = self._msgobj('msg_27.txt') + self._idempotent(msg, text) + + def test_MIME_digest_with_part_headers(self): + msg, text = self._msgobj('msg_28.txt') + self._idempotent(msg, text) + + def test_mixed_with_image(self): + msg, text = self._msgobj('msg_06.txt') + self._idempotent(msg, text) + + def test_multipart_report(self): + msg, text = self._msgobj('msg_05.txt') + self._idempotent(msg, text) + + def test_dsn(self): + msg, text = self._msgobj('msg_16.txt') + self._idempotent(msg, text) + + def test_preamble_epilogue(self): + msg, text = self._msgobj('msg_21.txt') + self._idempotent(msg, text) + + def test_multipart_one_part(self): + msg, text = self._msgobj('msg_23.txt') + self._idempotent(msg, text) + + def test_multipart_no_parts(self): + msg, text = self._msgobj('msg_24.txt') + self._idempotent(msg, text) + + def test_no_start_boundary(self): + msg, text = self._msgobj('msg_31.txt') + self._idempotent(msg, text) + + def test_rfc2231_charset(self): + msg, text = self._msgobj('msg_32.txt') + self._idempotent(msg, text) + + def test_more_rfc2231_parameters(self): + msg, text = self._msgobj('msg_33.txt') + self._idempotent(msg, text) + + def test_text_plain_in_a_multipart_digest(self): + msg, text = self._msgobj('msg_34.txt') + self._idempotent(msg, text) + + def test_nested_multipart_mixeds(self): + msg, text = self._msgobj('msg_12a.txt') + self._idempotent(msg, text) + + def test_message_external_body_idempotent(self): + msg, text = self._msgobj('msg_36.txt') + self._idempotent(msg, text) + + def test_content_type(self): + eq = self.assertEqual + unless = self.assertTrue + # Get a message object and reset the seek pointer for other tests + msg, text = self._msgobj('msg_05.txt') + eq(msg.get_content_type(), 'multipart/report') + # Test the Content-Type: parameters + params = {} + for pk, pv in msg.get_params(): + params[pk] = pv + eq(params['report-type'], 'delivery-status') + eq(params['boundary'], 'D1690A7AC1.996856090/mail.example.com') + eq(msg.preamble, 'This is a MIME-encapsulated message.\n') + eq(msg.epilogue, '\n') + eq(len(msg.get_payload()), 3) + # Make sure the subparts are what we expect + msg1 = msg.get_payload(0) + eq(msg1.get_content_type(), 'text/plain') + eq(msg1.get_payload(), 'Yadda yadda yadda\n') + msg2 = msg.get_payload(1) + eq(msg2.get_content_type(), 'text/plain') + eq(msg2.get_payload(), 'Yadda yadda yadda\n') + msg3 = msg.get_payload(2) + eq(msg3.get_content_type(), 'message/rfc822') + self.assertTrue(isinstance(msg3, Message)) + payload = msg3.get_payload() + unless(isinstance(payload, list)) + eq(len(payload), 1) + msg4 = payload[0] + unless(isinstance(msg4, Message)) + eq(msg4.get_payload(), 'Yadda yadda yadda\n') + + def test_parser(self): + eq = self.assertEqual + unless = self.assertTrue + msg, text = self._msgobj('msg_06.txt') + # Check some of the outer headers + eq(msg.get_content_type(), 'message/rfc822') + # Make sure the payload is a list of exactly one sub-Message, and that + # that submessage has a type of text/plain + payload = msg.get_payload() + unless(isinstance(payload, list)) + eq(len(payload), 1) + msg1 = payload[0] + self.assertTrue(isinstance(msg1, Message)) + eq(msg1.get_content_type(), 'text/plain') + self.assertTrue(isinstance(msg1.get_payload(), str)) + eq(msg1.get_payload(), '\n') + + + +# Test various other bits of the package's functionality +class TestMiscellaneous(TestEmailBase): + def test_message_from_string(self): + fp = openfile('msg_01.txt') + try: + text = fp.read() + finally: + fp.close() + msg = email.message_from_string(text) + s = StringIO() + # Don't wrap/continue long headers since we're trying to test + # idempotency. + g = Generator(s, maxheaderlen=0) + g.flatten(msg) + self.assertEqual(text, s.getvalue()) + + def test_message_from_file(self): + fp = openfile('msg_01.txt') + try: + text = fp.read() + fp.seek(0) + msg = email.message_from_file(fp) + s = StringIO() + # Don't wrap/continue long headers since we're trying to test + # idempotency. + g = Generator(s, maxheaderlen=0) + g.flatten(msg) + self.assertEqual(text, s.getvalue()) + finally: + fp.close() + + def test_message_from_string_with_class(self): + unless = self.assertTrue + fp = openfile('msg_01.txt') + try: + text = fp.read() + finally: + fp.close() + # Create a subclass + class MyMessage(Message): + pass + + msg = email.message_from_string(text, MyMessage) + unless(isinstance(msg, MyMessage)) + # Try something more complicated + fp = openfile('msg_02.txt') + try: + text = fp.read() + finally: + fp.close() + msg = email.message_from_string(text, MyMessage) + for subpart in msg.walk(): + unless(isinstance(subpart, MyMessage)) + + def test_message_from_file_with_class(self): + unless = self.assertTrue + # Create a subclass + class MyMessage(Message): + pass + + fp = openfile('msg_01.txt') + try: + msg = email.message_from_file(fp, MyMessage) + finally: + fp.close() + unless(isinstance(msg, MyMessage)) + # Try something more complicated + fp = openfile('msg_02.txt') + try: + msg = email.message_from_file(fp, MyMessage) + finally: + fp.close() + for subpart in msg.walk(): + unless(isinstance(subpart, MyMessage)) + + def test__all__(self): + module = __import__('email') + # Can't use sorted() here due to Python 2.3 compatibility + all = module.__all__[:] + all.sort() + self.assertEqual(all, [ + # Old names + 'Charset', 'Encoders', 'Errors', 'Generator', + 'Header', 'Iterators', 'MIMEAudio', 'MIMEBase', + 'MIMEImage', 'MIMEMessage', 'MIMEMultipart', + 'MIMENonMultipart', 'MIMEText', 'Message', + 'Parser', 'Utils', 'base64MIME', + # new names + 'base64mime', 'charset', 'encoders', 'errors', 'generator', + 'header', 'iterators', 'message', 'message_from_file', + 'message_from_string', 'mime', 'parser', + 'quopriMIME', 'quoprimime', 'utils', + ]) + + def test_formatdate(self): + now = time.time() + self.assertEqual(utils.parsedate(utils.formatdate(now))[:6], + time.gmtime(now)[:6]) + + def test_formatdate_localtime(self): + now = time.time() + self.assertEqual( + utils.parsedate(utils.formatdate(now, localtime=True))[:6], + time.localtime(now)[:6]) + + def test_formatdate_usegmt(self): + now = time.time() + self.assertEqual( + utils.formatdate(now, localtime=False), + time.strftime('%a, %d %b %Y %H:%M:%S -0000', time.gmtime(now))) + self.assertEqual( + utils.formatdate(now, localtime=False, usegmt=True), + time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime(now))) + + def test_parsedate_none(self): + self.assertEqual(utils.parsedate(''), None) + + def test_parsedate_compact(self): + # The FWS after the comma is optional + self.assertEqual(utils.parsedate('Wed,3 Apr 2002 14:58:26 +0800'), + utils.parsedate('Wed, 3 Apr 2002 14:58:26 +0800')) + + def test_parsedate_no_dayofweek(self): + eq = self.assertEqual + eq(utils.parsedate_tz('25 Feb 2003 13:47:26 -0800'), + (2003, 2, 25, 13, 47, 26, 0, 1, -1, -28800)) + + def test_parsedate_compact_no_dayofweek(self): + eq = self.assertEqual + eq(utils.parsedate_tz('5 Feb 2003 13:47:26 -0800'), + (2003, 2, 5, 13, 47, 26, 0, 1, -1, -28800)) + + def test_parsedate_acceptable_to_time_functions(self): + eq = self.assertEqual + timetup = utils.parsedate('5 Feb 2003 13:47:26 -0800') + t = int(time.mktime(timetup)) + eq(time.localtime(t)[:6], timetup[:6]) + eq(int(time.strftime('%Y', timetup)), 2003) + timetup = utils.parsedate_tz('5 Feb 2003 13:47:26 -0800') + t = int(time.mktime(timetup[:9])) + eq(time.localtime(t)[:6], timetup[:6]) + eq(int(time.strftime('%Y', timetup[:9])), 2003) + + def test_parseaddr_empty(self): + self.assertEqual(utils.parseaddr('<>'), ('', '')) + self.assertEqual(utils.formataddr(utils.parseaddr('<>')), '') + + def test_noquote_dump(self): + self.assertEqual( + utils.formataddr(('A Silly Person', 'person@dom.ain')), + 'A Silly Person ') + + def test_escape_dump(self): + self.assertEqual( + utils.formataddr(('A (Very) Silly Person', 'person@dom.ain')), + r'"A \(Very\) Silly Person" ') + a = r'A \(Special\) Person' + b = 'person@dom.ain' + self.assertEqual(utils.parseaddr(utils.formataddr((a, b))), (a, b)) + + def test_escape_backslashes(self): + self.assertEqual( + utils.formataddr(('Arthur \Backslash\ Foobar', 'person@dom.ain')), + r'"Arthur \\Backslash\\ Foobar" ') + a = r'Arthur \Backslash\ Foobar' + b = 'person@dom.ain' + self.assertEqual(utils.parseaddr(utils.formataddr((a, b))), (a, b)) + + def test_name_with_dot(self): + x = 'John X. Doe ' + y = '"John X. Doe" ' + a, b = ('John X. Doe', 'jxd@example.com') + self.assertEqual(utils.parseaddr(x), (a, b)) + self.assertEqual(utils.parseaddr(y), (a, b)) + # formataddr() quotes the name if there's a dot in it + self.assertEqual(utils.formataddr((a, b)), y) + + def test_multiline_from_comment(self): + x = """\ +Foo +\tBar """ + self.assertEqual(utils.parseaddr(x), ('Foo Bar', 'foo@example.com')) + + def test_quote_dump(self): + self.assertEqual( + utils.formataddr(('A Silly; Person', 'person@dom.ain')), + r'"A Silly; Person" ') + + def test_fix_eols(self): + eq = self.assertEqual + eq(utils.fix_eols('hello'), 'hello') + eq(utils.fix_eols('hello\n'), 'hello\r\n') + eq(utils.fix_eols('hello\r'), 'hello\r\n') + eq(utils.fix_eols('hello\r\n'), 'hello\r\n') + eq(utils.fix_eols('hello\n\r'), 'hello\r\n\r\n') + + def test_charset_richcomparisons(self): + eq = self.assertEqual + ne = self.assertNotEqual + cset1 = Charset() + cset2 = Charset() + eq(cset1, 'us-ascii') + eq(cset1, 'US-ASCII') + eq(cset1, 'Us-AsCiI') + eq('us-ascii', cset1) + eq('US-ASCII', cset1) + eq('Us-AsCiI', cset1) + ne(cset1, 'usascii') + ne(cset1, 'USASCII') + ne(cset1, 'UsAsCiI') + ne('usascii', cset1) + ne('USASCII', cset1) + ne('UsAsCiI', cset1) + eq(cset1, cset2) + eq(cset2, cset1) + + def test_getaddresses(self): + eq = self.assertEqual + eq(utils.getaddresses(['aperson@dom.ain (Al Person)', + 'Bud Person ']), + [('Al Person', 'aperson@dom.ain'), + ('Bud Person', 'bperson@dom.ain')]) + + def test_getaddresses_nasty(self): + eq = self.assertEqual + eq(utils.getaddresses(['foo: ;']), [('', '')]) + eq(utils.getaddresses( + ['[]*-- =~$']), + [('', ''), ('', ''), ('', '*--')]) + eq(utils.getaddresses( + ['foo: ;', '"Jason R. Mastaler" ']), + [('', ''), ('Jason R. Mastaler', 'jason@dom.ain')]) + + def test_getaddresses_embedded_comment(self): + """Test proper handling of a nested comment""" + eq = self.assertEqual + addrs = utils.getaddresses(['User ((nested comment)) ']) + eq(addrs[0][1], 'foo@bar.com') + + def test_utils_quote_unquote(self): + eq = self.assertEqual + msg = Message() + msg.add_header('content-disposition', 'attachment', + filename='foo\\wacky"name') + eq(msg.get_filename(), 'foo\\wacky"name') + + def test_get_body_encoding_with_bogus_charset(self): + charset = Charset('not a charset') + self.assertEqual(charset.get_body_encoding(), 'base64') + + def test_get_body_encoding_with_uppercase_charset(self): + eq = self.assertEqual + msg = Message() + msg['Content-Type'] = 'text/plain; charset=UTF-8' + eq(msg['content-type'], 'text/plain; charset=UTF-8') + charsets = msg.get_charsets() + eq(len(charsets), 1) + eq(charsets[0], 'utf-8') + charset = Charset(charsets[0]) + eq(charset.get_body_encoding(), 'base64') + msg.set_payload('hello world', charset=charset) + eq(msg.get_payload(), 'aGVsbG8gd29ybGQ=\n') + eq(msg.get_payload(decode=True), 'hello world') + eq(msg['content-transfer-encoding'], 'base64') + # Try another one + msg = Message() + msg['Content-Type'] = 'text/plain; charset="US-ASCII"' + charsets = msg.get_charsets() + eq(len(charsets), 1) + eq(charsets[0], 'us-ascii') + charset = Charset(charsets[0]) + eq(charset.get_body_encoding(), encoders.encode_7or8bit) + msg.set_payload('hello world', charset=charset) + eq(msg.get_payload(), 'hello world') + eq(msg['content-transfer-encoding'], '7bit') + + def test_charsets_case_insensitive(self): + lc = Charset('us-ascii') + uc = Charset('US-ASCII') + self.assertEqual(lc.get_body_encoding(), uc.get_body_encoding()) + + def test_partial_falls_inside_message_delivery_status(self): + eq = self.ndiffAssertEqual + # The Parser interface provides chunks of data to FeedParser in 8192 + # byte gulps. SF bug #1076485 found one of those chunks inside + # message/delivery-status header block, which triggered an + # unreadline() of NeedMoreData. + msg = self._msgobj('msg_43.txt') + sfp = StringIO() + iterators._structure(msg, sfp) + eq(sfp.getvalue(), """\ +multipart/report + text/plain + message/delivery-status + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/plain + text/rfc822-headers +""") + + + +# Test the iterator/generators +class TestIterators(TestEmailBase): + def test_body_line_iterator(self): + eq = self.assertEqual + neq = self.ndiffAssertEqual + # First a simple non-multipart message + msg = self._msgobj('msg_01.txt') + it = iterators.body_line_iterator(msg) + lines = list(it) + eq(len(lines), 6) + neq(EMPTYSTRING.join(lines), msg.get_payload()) + # Now a more complicated multipart + msg = self._msgobj('msg_02.txt') + it = iterators.body_line_iterator(msg) + lines = list(it) + eq(len(lines), 43) + fp = openfile('msg_19.txt') + try: + neq(EMPTYSTRING.join(lines), fp.read()) + finally: + fp.close() + + def test_typed_subpart_iterator(self): + eq = self.assertEqual + msg = self._msgobj('msg_04.txt') + it = iterators.typed_subpart_iterator(msg, 'text') + lines = [] + subparts = 0 + for subpart in it: + subparts += 1 + lines.append(subpart.get_payload()) + eq(subparts, 2) + eq(EMPTYSTRING.join(lines), """\ +a simple kind of mirror +to reflect upon our own +a simple kind of mirror +to reflect upon our own +""") + + def test_typed_subpart_iterator_default_type(self): + eq = self.assertEqual + msg = self._msgobj('msg_03.txt') + it = iterators.typed_subpart_iterator(msg, 'text', 'plain') + lines = [] + subparts = 0 + for subpart in it: + subparts += 1 + lines.append(subpart.get_payload()) + eq(subparts, 1) + eq(EMPTYSTRING.join(lines), """\ + +Hi, + +Do you like this message? + +-Me +""") + + + +class TestParsers(TestEmailBase): + def test_header_parser(self): + eq = self.assertEqual + # Parse only the headers of a complex multipart MIME document + fp = openfile('msg_02.txt') + try: + msg = HeaderParser().parse(fp) + finally: + fp.close() + eq(msg['from'], 'ppp-request@zzz.org') + eq(msg['to'], 'ppp@zzz.org') + eq(msg.get_content_type(), 'multipart/mixed') + self.assertFalse(msg.is_multipart()) + self.assertTrue(isinstance(msg.get_payload(), str)) + + def test_whitespace_continuation(self): + eq = self.assertEqual + # This message contains a line after the Subject: header that has only + # whitespace, but it is not empty! + msg = email.message_from_string("""\ +From: aperson@dom.ain +To: bperson@dom.ain +Subject: the next line has a space on it +\x20 +Date: Mon, 8 Apr 2002 15:09:19 -0400 +Message-ID: spam + +Here's the message body +""") + eq(msg['subject'], 'the next line has a space on it\n ') + eq(msg['message-id'], 'spam') + eq(msg.get_payload(), "Here's the message body\n") + + def test_whitespace_continuation_last_header(self): + eq = self.assertEqual + # Like the previous test, but the subject line is the last + # header. + msg = email.message_from_string("""\ +From: aperson@dom.ain +To: bperson@dom.ain +Date: Mon, 8 Apr 2002 15:09:19 -0400 +Message-ID: spam +Subject: the next line has a space on it +\x20 + +Here's the message body +""") + eq(msg['subject'], 'the next line has a space on it\n ') + eq(msg['message-id'], 'spam') + eq(msg.get_payload(), "Here's the message body\n") + + def test_crlf_separation(self): + eq = self.assertEqual + fp = openfile('msg_26.txt', mode='rb') + try: + msg = Parser().parse(fp) + finally: + fp.close() + eq(len(msg.get_payload()), 2) + part1 = msg.get_payload(0) + eq(part1.get_content_type(), 'text/plain') + eq(part1.get_payload(), 'Simple email with attachment.\r\n\r\n') + part2 = msg.get_payload(1) + eq(part2.get_content_type(), 'application/riscos') + + def test_multipart_digest_with_extra_mime_headers(self): + eq = self.assertEqual + neq = self.ndiffAssertEqual + fp = openfile('msg_28.txt') + try: + msg = email.message_from_file(fp) + finally: + fp.close() + # Structure is: + # multipart/digest + # message/rfc822 + # text/plain + # message/rfc822 + # text/plain + eq(msg.is_multipart(), 1) + eq(len(msg.get_payload()), 2) + part1 = msg.get_payload(0) + eq(part1.get_content_type(), 'message/rfc822') + eq(part1.is_multipart(), 1) + eq(len(part1.get_payload()), 1) + part1a = part1.get_payload(0) + eq(part1a.is_multipart(), 0) + eq(part1a.get_content_type(), 'text/plain') + neq(part1a.get_payload(), 'message 1\n') + # next message/rfc822 + part2 = msg.get_payload(1) + eq(part2.get_content_type(), 'message/rfc822') + eq(part2.is_multipart(), 1) + eq(len(part2.get_payload()), 1) + part2a = part2.get_payload(0) + eq(part2a.is_multipart(), 0) + eq(part2a.get_content_type(), 'text/plain') + neq(part2a.get_payload(), 'message 2\n') + + def test_three_lines(self): + # A bug report by Andrew McNamara + lines = ['From: Andrew Person From', 'From']) + eq(msg.get_payload(), 'body') + + def test_rfc2822_space_not_allowed_in_header(self): + eq = self.assertEqual + m = '>From foo@example.com 11:25:53\nFrom: bar\n!"#QUX;~: zoo\n\nbody' + msg = email.message_from_string(m) + eq(len(msg.keys()), 0) + + def test_rfc2822_one_character_header(self): + eq = self.assertEqual + m = 'A: first header\nB: second header\nCC: third header\n\nbody' + msg = email.message_from_string(m) + headers = msg.keys() + headers.sort() + eq(headers, ['A', 'B', 'CC']) + eq(msg.get_payload(), 'body') + + + +class TestBase64(unittest.TestCase): + def test_len(self): + eq = self.assertEqual + eq(base64mime.base64_len('hello'), + len(base64mime.encode('hello', eol=''))) + for size in range(15): + if size == 0 : bsize = 0 + elif size <= 3 : bsize = 4 + elif size <= 6 : bsize = 8 + elif size <= 9 : bsize = 12 + elif size <= 12: bsize = 16 + else : bsize = 20 + eq(base64mime.base64_len('x'*size), bsize) + + def test_decode(self): + eq = self.assertEqual + eq(base64mime.decode(''), '') + eq(base64mime.decode('aGVsbG8='), 'hello') + eq(base64mime.decode('aGVsbG8=', 'X'), 'hello') + eq(base64mime.decode('aGVsbG8NCndvcmxk\n', 'X'), 'helloXworld') + + def test_encode(self): + eq = self.assertEqual + eq(base64mime.encode(''), '') + eq(base64mime.encode('hello'), 'aGVsbG8=\n') + # Test the binary flag + eq(base64mime.encode('hello\n'), 'aGVsbG8K\n') + eq(base64mime.encode('hello\n', 0), 'aGVsbG8NCg==\n') + # Test the maxlinelen arg + eq(base64mime.encode('xxxx ' * 20, maxlinelen=40), """\ +eHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg +eHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg +eHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg +eHh4eCB4eHh4IA== +""") + # Test the eol argument + eq(base64mime.encode('xxxx ' * 20, maxlinelen=40, eol='\r\n'), """\ +eHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg\r +eHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg\r +eHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg\r +eHh4eCB4eHh4IA==\r +""") + + def test_header_encode(self): + eq = self.assertEqual + he = base64mime.header_encode + eq(he('hello'), '=?iso-8859-1?b?aGVsbG8=?=') + eq(he('hello\nworld'), '=?iso-8859-1?b?aGVsbG8NCndvcmxk?=') + # Test the charset option + eq(he('hello', charset='iso-8859-2'), '=?iso-8859-2?b?aGVsbG8=?=') + # Test the keep_eols flag + eq(he('hello\nworld', keep_eols=True), + '=?iso-8859-1?b?aGVsbG8Kd29ybGQ=?=') + # Test the maxlinelen argument + eq(he('xxxx ' * 20, maxlinelen=40), """\ +=?iso-8859-1?b?eHh4eCB4eHh4IHh4eHggeHg=?= + =?iso-8859-1?b?eHggeHh4eCB4eHh4IHh4eHg=?= + =?iso-8859-1?b?IHh4eHggeHh4eCB4eHh4IHg=?= + =?iso-8859-1?b?eHh4IHh4eHggeHh4eCB4eHg=?= + =?iso-8859-1?b?eCB4eHh4IHh4eHggeHh4eCA=?= + =?iso-8859-1?b?eHh4eCB4eHh4IHh4eHgg?=""") + # Test the eol argument + eq(he('xxxx ' * 20, maxlinelen=40, eol='\r\n'), """\ +=?iso-8859-1?b?eHh4eCB4eHh4IHh4eHggeHg=?=\r + =?iso-8859-1?b?eHggeHh4eCB4eHh4IHh4eHg=?=\r + =?iso-8859-1?b?IHh4eHggeHh4eCB4eHh4IHg=?=\r + =?iso-8859-1?b?eHh4IHh4eHggeHh4eCB4eHg=?=\r + =?iso-8859-1?b?eCB4eHh4IHh4eHggeHh4eCA=?=\r + =?iso-8859-1?b?eHh4eCB4eHh4IHh4eHgg?=""") + + + +class TestQuopri(unittest.TestCase): + def setUp(self): + self.hlit = [chr(x) for x in range(ord('a'), ord('z')+1)] + \ + [chr(x) for x in range(ord('A'), ord('Z')+1)] + \ + [chr(x) for x in range(ord('0'), ord('9')+1)] + \ + ['!', '*', '+', '-', '/', ' '] + self.hnon = [chr(x) for x in range(256) if chr(x) not in self.hlit] + assert len(self.hlit) + len(self.hnon) == 256 + self.blit = [chr(x) for x in range(ord(' '), ord('~')+1)] + ['\t'] + self.blit.remove('=') + self.bnon = [chr(x) for x in range(256) if chr(x) not in self.blit] + assert len(self.blit) + len(self.bnon) == 256 + + def test_header_quopri_check(self): + for c in self.hlit: + self.assertFalse(quoprimime.header_quopri_check(c)) + for c in self.hnon: + self.assertTrue(quoprimime.header_quopri_check(c)) + + def test_body_quopri_check(self): + for c in self.blit: + self.assertFalse(quoprimime.body_quopri_check(c)) + for c in self.bnon: + self.assertTrue(quoprimime.body_quopri_check(c)) + + def test_header_quopri_len(self): + eq = self.assertEqual + hql = quoprimime.header_quopri_len + enc = quoprimime.header_encode + for s in ('hello', 'h@e@l@l@o@'): + # Empty charset and no line-endings. 7 == RFC chrome + eq(hql(s), len(enc(s, charset='', eol=''))-7) + for c in self.hlit: + eq(hql(c), 1) + for c in self.hnon: + eq(hql(c), 3) + + def test_body_quopri_len(self): + eq = self.assertEqual + bql = quoprimime.body_quopri_len + for c in self.blit: + eq(bql(c), 1) + for c in self.bnon: + eq(bql(c), 3) + + def test_quote_unquote_idempotent(self): + for x in range(256): + c = chr(x) + self.assertEqual(quoprimime.unquote(quoprimime.quote(c)), c) + + def test_header_encode(self): + eq = self.assertEqual + he = quoprimime.header_encode + eq(he('hello'), '=?iso-8859-1?q?hello?=') + eq(he('hello\nworld'), '=?iso-8859-1?q?hello=0D=0Aworld?=') + # Test the charset option + eq(he('hello', charset='iso-8859-2'), '=?iso-8859-2?q?hello?=') + # Test the keep_eols flag + eq(he('hello\nworld', keep_eols=True), '=?iso-8859-1?q?hello=0Aworld?=') + # Test a non-ASCII character + eq(he('hello\xc7there'), '=?iso-8859-1?q?hello=C7there?=') + # Test the maxlinelen argument + eq(he('xxxx ' * 20, maxlinelen=40), """\ +=?iso-8859-1?q?xxxx_xxxx_xxxx_xxxx_xx?= + =?iso-8859-1?q?xx_xxxx_xxxx_xxxx_xxxx?= + =?iso-8859-1?q?_xxxx_xxxx_xxxx_xxxx_x?= + =?iso-8859-1?q?xxx_xxxx_xxxx_xxxx_xxx?= + =?iso-8859-1?q?x_xxxx_xxxx_?=""") + # Test the eol argument + eq(he('xxxx ' * 20, maxlinelen=40, eol='\r\n'), """\ +=?iso-8859-1?q?xxxx_xxxx_xxxx_xxxx_xx?=\r + =?iso-8859-1?q?xx_xxxx_xxxx_xxxx_xxxx?=\r + =?iso-8859-1?q?_xxxx_xxxx_xxxx_xxxx_x?=\r + =?iso-8859-1?q?xxx_xxxx_xxxx_xxxx_xxx?=\r + =?iso-8859-1?q?x_xxxx_xxxx_?=""") + + def test_decode(self): + eq = self.assertEqual + eq(quoprimime.decode(''), '') + eq(quoprimime.decode('hello'), 'hello') + eq(quoprimime.decode('hello', 'X'), 'hello') + eq(quoprimime.decode('hello\nworld', 'X'), 'helloXworld') + + def test_encode(self): + eq = self.assertEqual + eq(quoprimime.encode(''), '') + eq(quoprimime.encode('hello'), 'hello') + # Test the binary flag + eq(quoprimime.encode('hello\r\nworld'), 'hello\nworld') + eq(quoprimime.encode('hello\r\nworld', 0), 'hello\nworld') + # Test the maxlinelen arg + eq(quoprimime.encode('xxxx ' * 20, maxlinelen=40), """\ +xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx= + xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxx= +x xxxx xxxx xxxx xxxx=20""") + # Test the eol argument + eq(quoprimime.encode('xxxx ' * 20, maxlinelen=40, eol='\r\n'), """\ +xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx=\r + xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxx=\r +x xxxx xxxx xxxx xxxx=20""") + eq(quoprimime.encode("""\ +one line + +two line"""), """\ +one line + +two line""") + + + +# Test the Charset class +class TestCharset(unittest.TestCase): + def tearDown(self): + from email import charset as CharsetModule + try: + del CharsetModule.CHARSETS['fake'] + except KeyError: + pass + + def test_idempotent(self): + eq = self.assertEqual + # Make sure us-ascii = no Unicode conversion + c = Charset('us-ascii') + s = 'Hello World!' + sp = c.to_splittable(s) + eq(s, c.from_splittable(sp)) + # test 8-bit idempotency with us-ascii + s = '\xa4\xa2\xa4\xa4\xa4\xa6\xa4\xa8\xa4\xaa' + sp = c.to_splittable(s) + eq(s, c.from_splittable(sp)) + + def test_body_encode(self): + eq = self.assertEqual + # Try a charset with QP body encoding + c = Charset('iso-8859-1') + eq('hello w=F6rld', c.body_encode('hello w\xf6rld')) + # Try a charset with Base64 body encoding + c = Charset('utf-8') + eq('aGVsbG8gd29ybGQ=\n', c.body_encode('hello world')) + # Try a charset with None body encoding + c = Charset('us-ascii') + eq('hello world', c.body_encode('hello world')) + # Try the convert argument, where input codec != output codec + c = Charset('euc-jp') + # With apologies to Tokio Kikuchi ;) + try: + eq('\x1b$B5FCO;~IW\x1b(B', + c.body_encode('\xb5\xc6\xc3\xcf\xbb\xfe\xc9\xd7')) + eq('\xb5\xc6\xc3\xcf\xbb\xfe\xc9\xd7', + c.body_encode('\xb5\xc6\xc3\xcf\xbb\xfe\xc9\xd7', False)) + except LookupError: + # We probably don't have the Japanese codecs installed + pass + # Testing SF bug #625509, which we have to fake, since there are no + # built-in encodings where the header encoding is QP but the body + # encoding is not. + from email import charset as CharsetModule + CharsetModule.add_charset('fake', CharsetModule.QP, None) + c = Charset('fake') + eq('hello w\xf6rld', c.body_encode('hello w\xf6rld')) + + def test_unicode_charset_name(self): + charset = Charset(u'us-ascii') + self.assertEqual(str(charset), 'us-ascii') + self.assertRaises(errors.CharsetError, Charset, 'asc\xffii') + + + +# Test multilingual MIME headers. +class TestHeader(TestEmailBase): + def test_simple(self): + eq = self.ndiffAssertEqual + h = Header('Hello World!') + eq(h.encode(), 'Hello World!') + h.append(' Goodbye World!') + eq(h.encode(), 'Hello World! Goodbye World!') + + def test_simple_surprise(self): + eq = self.ndiffAssertEqual + h = Header('Hello World!') + eq(h.encode(), 'Hello World!') + h.append('Goodbye World!') + eq(h.encode(), 'Hello World! Goodbye World!') + + def test_header_needs_no_decoding(self): + h = 'no decoding needed' + self.assertEqual(decode_header(h), [(h, None)]) + + def test_long(self): + h = Header("I am the very model of a modern Major-General; I've information vegetable, animal, and mineral; I know the kings of England, and I quote the fights historical from Marathon to Waterloo, in order categorical; I'm very well acquainted, too, with matters mathematical; I understand equations, both the simple and quadratical; about binomial theorem I'm teeming with a lot o' news, with many cheerful facts about the square of the hypotenuse.", + maxlinelen=76) + for l in h.encode(splitchars=' ').split('\n '): + self.assertTrue(len(l) <= 76) + + def test_multilingual(self): + eq = self.ndiffAssertEqual + g = Charset("iso-8859-1") + cz = Charset("iso-8859-2") + utf8 = Charset("utf-8") + g_head = "Die Mieter treten hier ein werden mit einem Foerderband komfortabel den Korridor entlang, an s\xfcdl\xfcndischen Wandgem\xe4lden vorbei, gegen die rotierenden Klingen bef\xf6rdert. " + cz_head = "Finan\xe8ni metropole se hroutily pod tlakem jejich d\xf9vtipu.. " + utf8_head = u"\u6b63\u78ba\u306b\u8a00\u3046\u3068\u7ffb\u8a33\u306f\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u4e00\u90e8\u306f\u30c9\u30a4\u30c4\u8a9e\u3067\u3059\u304c\u3001\u3042\u3068\u306f\u3067\u305f\u3089\u3081\u3067\u3059\u3002\u5b9f\u969b\u306b\u306f\u300cWenn ist das Nunstuck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput.\u300d\u3068\u8a00\u3063\u3066\u3044\u307e\u3059\u3002".encode("utf-8") + h = Header(g_head, g) + h.append(cz_head, cz) + h.append(utf8_head, utf8) + enc = h.encode() + eq(enc, """\ +=?iso-8859-1?q?Die_Mieter_treten_hier_ein_werden_mit_einem_Foerderband_ko?= + =?iso-8859-1?q?mfortabel_den_Korridor_entlang=2C_an_s=FCdl=FCndischen_Wan?= + =?iso-8859-1?q?dgem=E4lden_vorbei=2C_gegen_die_rotierenden_Klingen_bef=F6?= + =?iso-8859-1?q?rdert=2E_?= =?iso-8859-2?q?Finan=E8ni_metropole_se_hroutily?= + =?iso-8859-2?q?_pod_tlakem_jejich_d=F9vtipu=2E=2E_?= =?utf-8?b?5q2j56K6?= + =?utf-8?b?44Gr6KiA44GG44Go57+76Kiz44Gv44GV44KM44Gm44GE44G+44Gb44KT44CC?= + =?utf-8?b?5LiA6YOo44Gv44OJ44Kk44OE6Kqe44Gn44GZ44GM44CB44GC44Go44Gv44Gn?= + =?utf-8?b?44Gf44KJ44KB44Gn44GZ44CC5a6f6Zqb44Gr44Gv44CMV2VubiBpc3QgZGFz?= + =?utf-8?q?_Nunstuck_git_und_Slotermeyer=3F_Ja!_Beiherhund_das_Oder_die_Fl?= + =?utf-8?b?aXBwZXJ3YWxkdCBnZXJzcHV0LuOAjeOBqOiogOOBo+OBpuOBhOOBvuOBmQ==?= + =?utf-8?b?44CC?=""") + eq(decode_header(enc), + [(g_head, "iso-8859-1"), (cz_head, "iso-8859-2"), + (utf8_head, "utf-8")]) + ustr = unicode(h) + eq(ustr.encode('utf-8'), + 'Die Mieter treten hier ein werden mit einem Foerderband ' + 'komfortabel den Korridor entlang, an s\xc3\xbcdl\xc3\xbcndischen ' + 'Wandgem\xc3\xa4lden vorbei, gegen die rotierenden Klingen ' + 'bef\xc3\xb6rdert. Finan\xc4\x8dni metropole se hroutily pod ' + 'tlakem jejich d\xc5\xafvtipu.. \xe6\xad\xa3\xe7\xa2\xba\xe3\x81' + '\xab\xe8\xa8\x80\xe3\x81\x86\xe3\x81\xa8\xe7\xbf\xbb\xe8\xa8\xb3' + '\xe3\x81\xaf\xe3\x81\x95\xe3\x82\x8c\xe3\x81\xa6\xe3\x81\x84\xe3' + '\x81\xbe\xe3\x81\x9b\xe3\x82\x93\xe3\x80\x82\xe4\xb8\x80\xe9\x83' + '\xa8\xe3\x81\xaf\xe3\x83\x89\xe3\x82\xa4\xe3\x83\x84\xe8\xaa\x9e' + '\xe3\x81\xa7\xe3\x81\x99\xe3\x81\x8c\xe3\x80\x81\xe3\x81\x82\xe3' + '\x81\xa8\xe3\x81\xaf\xe3\x81\xa7\xe3\x81\x9f\xe3\x82\x89\xe3\x82' + '\x81\xe3\x81\xa7\xe3\x81\x99\xe3\x80\x82\xe5\xae\x9f\xe9\x9a\x9b' + '\xe3\x81\xab\xe3\x81\xaf\xe3\x80\x8cWenn ist das Nunstuck git ' + 'und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt ' + 'gersput.\xe3\x80\x8d\xe3\x81\xa8\xe8\xa8\x80\xe3\x81\xa3\xe3\x81' + '\xa6\xe3\x81\x84\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82') + # Test make_header() + newh = make_header(decode_header(enc)) + eq(newh, enc) + + def test_header_ctor_default_args(self): + eq = self.ndiffAssertEqual + h = Header() + eq(h, '') + h.append('foo', Charset('iso-8859-1')) + eq(h, '=?iso-8859-1?q?foo?=') + + def test_explicit_maxlinelen(self): + eq = self.ndiffAssertEqual + hstr = 'A very long line that must get split to something other than at the 76th character boundary to test the non-default behavior' + h = Header(hstr) + eq(h.encode(), '''\ +A very long line that must get split to something other than at the 76th + character boundary to test the non-default behavior''') + h = Header(hstr, header_name='Subject') + eq(h.encode(), '''\ +A very long line that must get split to something other than at the + 76th character boundary to test the non-default behavior''') + h = Header(hstr, maxlinelen=1024, header_name='Subject') + eq(h.encode(), hstr) + + def test_us_ascii_header(self): + eq = self.assertEqual + s = 'hello' + x = decode_header(s) + eq(x, [('hello', None)]) + h = make_header(x) + eq(s, h.encode()) + + def test_string_charset(self): + eq = self.assertEqual + h = Header() + h.append('hello', 'iso-8859-1') + eq(h, '=?iso-8859-1?q?hello?=') + +## def test_unicode_error(self): +## raises = self.assertRaises +## raises(UnicodeError, Header, u'[P\xf6stal]', 'us-ascii') +## raises(UnicodeError, Header, '[P\xf6stal]', 'us-ascii') +## h = Header() +## raises(UnicodeError, h.append, u'[P\xf6stal]', 'us-ascii') +## raises(UnicodeError, h.append, '[P\xf6stal]', 'us-ascii') +## raises(UnicodeError, Header, u'\u83ca\u5730\u6642\u592b', 'iso-8859-1') + + def test_utf8_shortest(self): + eq = self.assertEqual + h = Header(u'p\xf6stal', 'utf-8') + eq(h.encode(), '=?utf-8?q?p=C3=B6stal?=') + h = Header(u'\u83ca\u5730\u6642\u592b', 'utf-8') + eq(h.encode(), '=?utf-8?b?6I+K5Zyw5pmC5aSr?=') + + def test_bad_8bit_header(self): + raises = self.assertRaises + eq = self.assertEqual + x = 'Ynwp4dUEbay Auction Semiar- No Charge \x96 Earn Big' + raises(UnicodeError, Header, x) + h = Header() + raises(UnicodeError, h.append, x) + eq(str(Header(x, errors='replace')), x) + h.append(x, errors='replace') + eq(str(h), x) + + def test_encoded_adjacent_nonencoded(self): + eq = self.assertEqual + h = Header() + h.append('hello', 'iso-8859-1') + h.append('world') + s = h.encode() + eq(s, '=?iso-8859-1?q?hello?= world') + h = make_header(decode_header(s)) + eq(h.encode(), s) + + def test_whitespace_eater(self): + eq = self.assertEqual + s = 'Subject: =?koi8-r?b?8NLP18XSy8EgzsEgxsnOwczYztk=?= =?koi8-r?q?=CA?= zz.' + parts = decode_header(s) + eq(parts, [('Subject:', None), ('\xf0\xd2\xcf\xd7\xc5\xd2\xcb\xc1 \xce\xc1 \xc6\xc9\xce\xc1\xcc\xd8\xce\xd9\xca', 'koi8-r'), ('zz.', None)]) + hdr = make_header(parts) + eq(hdr.encode(), + 'Subject: =?koi8-r?b?8NLP18XSy8EgzsEgxsnOwczYztnK?= zz.') + + def test_broken_base64_header(self): + raises = self.assertRaises + s = 'Subject: =?EUC-KR?B?CSixpLDtKSC/7Liuvsax4iC6uLmwMcijIKHaILzSwd/H0SC8+LCjwLsgv7W/+Mj3I ?=' + raises(errors.HeaderParseError, decode_header, s) + + + +# Test RFC 2231 header parameters (en/de)coding +class TestRFC2231(TestEmailBase): + def test_get_param(self): + eq = self.assertEqual + msg = self._msgobj('msg_29.txt') + eq(msg.get_param('title'), + ('us-ascii', 'en', 'This is even more ***fun*** isn\'t it!')) + eq(msg.get_param('title', unquote=False), + ('us-ascii', 'en', '"This is even more ***fun*** isn\'t it!"')) + + def test_set_param(self): + eq = self.assertEqual + msg = Message() + msg.set_param('title', 'This is even more ***fun*** isn\'t it!', + charset='us-ascii') + eq(msg.get_param('title'), + ('us-ascii', '', 'This is even more ***fun*** isn\'t it!')) + msg.set_param('title', 'This is even more ***fun*** isn\'t it!', + charset='us-ascii', language='en') + eq(msg.get_param('title'), + ('us-ascii', 'en', 'This is even more ***fun*** isn\'t it!')) + msg = self._msgobj('msg_01.txt') + msg.set_param('title', 'This is even more ***fun*** isn\'t it!', + charset='us-ascii', language='en') + self.ndiffAssertEqual(msg.as_string(), """\ +Return-Path: +Delivered-To: bbb@zzz.org +Received: by mail.zzz.org (Postfix, from userid 889) + id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Message-ID: <15090.61304.110929.45684@aaa.zzz.org> +From: bbb@ddd.com (John X. Doe) +To: bbb@zzz.org +Subject: This is a test message +Date: Fri, 4 May 2001 14:05:44 -0400 +Content-Type: text/plain; charset=us-ascii; + title*="us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21" + + +Hi, + +Do you like this message? + +-Me +""") + + def test_del_param(self): + eq = self.ndiffAssertEqual + msg = self._msgobj('msg_01.txt') + msg.set_param('foo', 'bar', charset='us-ascii', language='en') + msg.set_param('title', 'This is even more ***fun*** isn\'t it!', + charset='us-ascii', language='en') + msg.del_param('foo', header='Content-Type') + eq(msg.as_string(), """\ +Return-Path: +Delivered-To: bbb@zzz.org +Received: by mail.zzz.org (Postfix, from userid 889) + id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Message-ID: <15090.61304.110929.45684@aaa.zzz.org> +From: bbb@ddd.com (John X. Doe) +To: bbb@zzz.org +Subject: This is a test message +Date: Fri, 4 May 2001 14:05:44 -0400 +Content-Type: text/plain; charset="us-ascii"; + title*="us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21" + + +Hi, + +Do you like this message? + +-Me +""") + + def test_rfc2231_get_content_charset(self): + eq = self.assertEqual + msg = self._msgobj('msg_32.txt') + eq(msg.get_content_charset(), 'us-ascii') + + def test_rfc2231_no_language_or_charset(self): + m = '''\ +Content-Transfer-Encoding: 8bit +Content-Disposition: inline; filename="file____C__DOCUMENTS_20AND_20SETTINGS_FABIEN_LOCAL_20SETTINGS_TEMP_nsmail.htm" +Content-Type: text/html; NAME*0=file____C__DOCUMENTS_20AND_20SETTINGS_FABIEN_LOCAL_20SETTINGS_TEM; NAME*1=P_nsmail.htm + +''' + msg = email.message_from_string(m) + param = msg.get_param('NAME') + self.assertFalse(isinstance(param, tuple)) + self.assertEqual( + param, + 'file____C__DOCUMENTS_20AND_20SETTINGS_FABIEN_LOCAL_20SETTINGS_TEMP_nsmail.htm') + + def test_rfc2231_no_language_or_charset_in_filename(self): + m = '''\ +Content-Disposition: inline; +\tfilename*0*="''This%20is%20even%20more%20"; +\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; +\tfilename*2="is it not.pdf" + +''' + msg = email.message_from_string(m) + self.assertEqual(msg.get_filename(), + 'This is even more ***fun*** is it not.pdf') + + def test_rfc2231_no_language_or_charset_in_filename_encoded(self): + m = '''\ +Content-Disposition: inline; +\tfilename*0*="''This%20is%20even%20more%20"; +\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; +\tfilename*2="is it not.pdf" + +''' + msg = email.message_from_string(m) + self.assertEqual(msg.get_filename(), + 'This is even more ***fun*** is it not.pdf') + + def test_rfc2231_partly_encoded(self): + m = '''\ +Content-Disposition: inline; +\tfilename*0="''This%20is%20even%20more%20"; +\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; +\tfilename*2="is it not.pdf" + +''' + msg = email.message_from_string(m) + self.assertEqual( + msg.get_filename(), + 'This%20is%20even%20more%20***fun*** is it not.pdf') + + def test_rfc2231_partly_nonencoded(self): + m = '''\ +Content-Disposition: inline; +\tfilename*0="This%20is%20even%20more%20"; +\tfilename*1="%2A%2A%2Afun%2A%2A%2A%20"; +\tfilename*2="is it not.pdf" + +''' + msg = email.message_from_string(m) + self.assertEqual( + msg.get_filename(), + 'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20is it not.pdf') + + def test_rfc2231_no_language_or_charset_in_boundary(self): + m = '''\ +Content-Type: multipart/alternative; +\tboundary*0*="''This%20is%20even%20more%20"; +\tboundary*1*="%2A%2A%2Afun%2A%2A%2A%20"; +\tboundary*2="is it not.pdf" + +''' + msg = email.message_from_string(m) + self.assertEqual(msg.get_boundary(), + 'This is even more ***fun*** is it not.pdf') + + def test_rfc2231_no_language_or_charset_in_charset(self): + # This is a nonsensical charset value, but tests the code anyway + m = '''\ +Content-Type: text/plain; +\tcharset*0*="This%20is%20even%20more%20"; +\tcharset*1*="%2A%2A%2Afun%2A%2A%2A%20"; +\tcharset*2="is it not.pdf" + +''' + msg = email.message_from_string(m) + self.assertEqual(msg.get_content_charset(), + 'this is even more ***fun*** is it not.pdf') + + def test_rfc2231_bad_encoding_in_filename(self): + m = '''\ +Content-Disposition: inline; +\tfilename*0*="bogus'xx'This%20is%20even%20more%20"; +\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; +\tfilename*2="is it not.pdf" + +''' + msg = email.message_from_string(m) + self.assertEqual(msg.get_filename(), + 'This is even more ***fun*** is it not.pdf') + + def test_rfc2231_bad_encoding_in_charset(self): + m = """\ +Content-Type: text/plain; charset*=bogus''utf-8%E2%80%9D + +""" + msg = email.message_from_string(m) + # This should return None because non-ascii characters in the charset + # are not allowed. + self.assertEqual(msg.get_content_charset(), None) + + def test_rfc2231_bad_character_in_charset(self): + m = """\ +Content-Type: text/plain; charset*=ascii''utf-8%E2%80%9D + +""" + msg = email.message_from_string(m) + # This should return None because non-ascii characters in the charset + # are not allowed. + self.assertEqual(msg.get_content_charset(), None) + + def test_rfc2231_bad_character_in_filename(self): + m = '''\ +Content-Disposition: inline; +\tfilename*0*="ascii'xx'This%20is%20even%20more%20"; +\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; +\tfilename*2*="is it not.pdf%E2" + +''' + msg = email.message_from_string(m) + self.assertEqual(msg.get_filename(), + u'This is even more ***fun*** is it not.pdf\ufffd') + + def test_rfc2231_unknown_encoding(self): + m = """\ +Content-Transfer-Encoding: 8bit +Content-Disposition: inline; filename*=X-UNKNOWN''myfile.txt + +""" + msg = email.message_from_string(m) + self.assertEqual(msg.get_filename(), 'myfile.txt') + + def test_rfc2231_single_tick_in_filename_extended(self): + eq = self.assertEqual + m = """\ +Content-Type: application/x-foo; +\tname*0*=\"Frank's\"; name*1*=\" Document\" + +""" + msg = email.message_from_string(m) + charset, language, s = msg.get_param('name') + eq(charset, None) + eq(language, None) + eq(s, "Frank's Document") + + def test_rfc2231_single_tick_in_filename(self): + m = """\ +Content-Type: application/x-foo; name*0=\"Frank's\"; name*1=\" Document\" + +""" + msg = email.message_from_string(m) + param = msg.get_param('name') + self.assertFalse(isinstance(param, tuple)) + self.assertEqual(param, "Frank's Document") + + def test_rfc2231_tick_attack_extended(self): + eq = self.assertEqual + m = """\ +Content-Type: application/x-foo; +\tname*0*=\"us-ascii'en-us'Frank's\"; name*1*=\" Document\" + +""" + msg = email.message_from_string(m) + charset, language, s = msg.get_param('name') + eq(charset, 'us-ascii') + eq(language, 'en-us') + eq(s, "Frank's Document") + + def test_rfc2231_tick_attack(self): + m = """\ +Content-Type: application/x-foo; +\tname*0=\"us-ascii'en-us'Frank's\"; name*1=\" Document\" + +""" + msg = email.message_from_string(m) + param = msg.get_param('name') + self.assertFalse(isinstance(param, tuple)) + self.assertEqual(param, "us-ascii'en-us'Frank's Document") + + def test_rfc2231_no_extended_values(self): + eq = self.assertEqual + m = """\ +Content-Type: application/x-foo; name=\"Frank's Document\" + +""" + msg = email.message_from_string(m) + eq(msg.get_param('name'), "Frank's Document") + + def test_rfc2231_encoded_then_unencoded_segments(self): + eq = self.assertEqual + m = """\ +Content-Type: application/x-foo; +\tname*0*=\"us-ascii'en-us'My\"; +\tname*1=\" Document\"; +\tname*2*=\" For You\" + +""" + msg = email.message_from_string(m) + charset, language, s = msg.get_param('name') + eq(charset, 'us-ascii') + eq(language, 'en-us') + eq(s, 'My Document For You') + + def test_rfc2231_unencoded_then_encoded_segments(self): + eq = self.assertEqual + m = """\ +Content-Type: application/x-foo; +\tname*0=\"us-ascii'en-us'My\"; +\tname*1*=\" Document\"; +\tname*2*=\" For You\" + +""" + msg = email.message_from_string(m) + charset, language, s = msg.get_param('name') + eq(charset, 'us-ascii') + eq(language, 'en-us') + eq(s, 'My Document For You') + + + +def _testclasses(): + mod = sys.modules[__name__] + return [getattr(mod, name) for name in dir(mod) if name.startswith('Test')] + + +def suite(): + suite = unittest.TestSuite() + for testclass in _testclasses(): + suite.addTest(unittest.makeSuite(testclass)) + return suite + + +def test_main(): + for testclass in _testclasses(): + run_unittest(testclass) + + + +if __name__ == '__main__': + unittest.main(defaultTest='suite') diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_renamed.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_renamed.pyc new file mode 100644 index 0000000..02f29c7 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_renamed.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_renamed.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_renamed.pyo new file mode 100644 index 0000000..28d6a11 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_renamed.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_torture.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_torture.py new file mode 100644 index 0000000..9dfa602 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_torture.py @@ -0,0 +1,136 @@ +# Copyright (C) 2002-2004 Python Software Foundation +# +# A torture test of the email package. This should not be run as part of the +# standard Python test suite since it requires several meg of email messages +# collected in the wild. These source messages are not checked into the +# Python distro, but are available as part of the standalone email package at +# http://sf.net/projects/mimelib + +import sys +import os +import unittest +from cStringIO import StringIO +from types import ListType + +from email.test.test_email import TestEmailBase +from test.test_support import TestSkipped, run_unittest + +import email +from email import __file__ as testfile +from email.iterators import _structure + +def openfile(filename): + from os.path import join, dirname, abspath + path = abspath(join(dirname(testfile), os.pardir, 'moredata', filename)) + return open(path, 'r') + +# Prevent this test from running in the Python distro +try: + openfile('crispin-torture.txt') +except IOError: + raise TestSkipped + + + +class TortureBase(TestEmailBase): + def _msgobj(self, filename): + fp = openfile(filename) + try: + msg = email.message_from_file(fp) + finally: + fp.close() + return msg + + + +class TestCrispinTorture(TortureBase): + # Mark Crispin's torture test from the SquirrelMail project + def test_mondo_message(self): + eq = self.assertEqual + neq = self.ndiffAssertEqual + msg = self._msgobj('crispin-torture.txt') + payload = msg.get_payload() + eq(type(payload), ListType) + eq(len(payload), 12) + eq(msg.preamble, None) + eq(msg.epilogue, '\n') + # Probably the best way to verify the message is parsed correctly is to + # dump its structure and compare it against the known structure. + fp = StringIO() + _structure(msg, fp=fp) + neq(fp.getvalue(), """\ +multipart/mixed + text/plain + message/rfc822 + multipart/alternative + text/plain + multipart/mixed + text/richtext + application/andrew-inset + message/rfc822 + audio/basic + audio/basic + image/pbm + message/rfc822 + multipart/mixed + multipart/mixed + text/plain + audio/x-sun + multipart/mixed + image/gif + image/gif + application/x-be2 + application/atomicmail + audio/x-sun + message/rfc822 + multipart/mixed + text/plain + image/pgm + text/plain + message/rfc822 + multipart/mixed + text/plain + image/pbm + message/rfc822 + application/postscript + image/gif + message/rfc822 + multipart/mixed + audio/basic + audio/basic + message/rfc822 + multipart/mixed + application/postscript + text/plain + message/rfc822 + multipart/mixed + text/plain + multipart/parallel + image/gif + audio/basic + application/atomicmail + message/rfc822 + audio/x-sun +""") + + +def _testclasses(): + mod = sys.modules[__name__] + return [getattr(mod, name) for name in dir(mod) if name.startswith('Test')] + + +def suite(): + suite = unittest.TestSuite() + for testclass in _testclasses(): + suite.addTest(unittest.makeSuite(testclass)) + return suite + + +def test_main(): + for testclass in _testclasses(): + run_unittest(testclass) + + + +if __name__ == '__main__': + unittest.main(defaultTest='suite') diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_torture.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_torture.pyc new file mode 100644 index 0000000..bd70cd7 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_torture.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_torture.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_torture.pyo new file mode 100644 index 0000000..bd70cd7 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/test/test_email_torture.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/utils.py b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/utils.py new file mode 100644 index 0000000..c976021 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/utils.py @@ -0,0 +1,324 @@ +# Copyright (C) 2001-2010 Python Software Foundation +# Author: Barry Warsaw +# Contact: email-sig@python.org + +"""Miscellaneous utilities.""" + +__all__ = [ + 'collapse_rfc2231_value', + 'decode_params', + 'decode_rfc2231', + 'encode_rfc2231', + 'formataddr', + 'formatdate', + 'getaddresses', + 'make_msgid', + 'mktime_tz', + 'parseaddr', + 'parsedate', + 'parsedate_tz', + 'unquote', + ] + +import os +import re +import time +import base64 +import random +import socket +import urllib +import warnings + +from email._parseaddr import quote +from email._parseaddr import AddressList as _AddressList +from email._parseaddr import mktime_tz + +# We need wormarounds for bugs in these methods in older Pythons (see below) +from email._parseaddr import parsedate as _parsedate +from email._parseaddr import parsedate_tz as _parsedate_tz + +from quopri import decodestring as _qdecode + +# Intrapackage imports +from email.encoders import _bencode, _qencode + +COMMASPACE = ', ' +EMPTYSTRING = '' +UEMPTYSTRING = u'' +CRLF = '\r\n' +TICK = "'" + +specialsre = re.compile(r'[][\\()<>@,:;".]') +escapesre = re.compile(r'[][\\()"]') + + + +# Helpers + +def _identity(s): + return s + + +def _bdecode(s): + """Decodes a base64 string. + + This function is equivalent to base64.decodestring and it's retained only + for backward compatibility. It used to remove the last \\n of the decoded + string, if it had any (see issue 7143). + """ + if not s: + return s + return base64.decodestring(s) + + + +def fix_eols(s): + """Replace all line-ending characters with \\r\\n.""" + # Fix newlines with no preceding carriage return + s = re.sub(r'(?', name) + return '%s%s%s <%s>' % (quotes, name, quotes, address) + return address + + + +def getaddresses(fieldvalues): + """Return a list of (REALNAME, EMAIL) for each fieldvalue.""" + all = COMMASPACE.join(fieldvalues) + a = _AddressList(all) + return a.addresslist + + + +ecre = re.compile(r''' + =\? # literal =? + (?P[^?]*?) # non-greedy up to the next ? is the charset + \? # literal ? + (?P[qb]) # either a "q" or a "b", case insensitive + \? # literal ? + (?P.*?) # non-greedy up to the next ?= is the atom + \?= # literal ?= + ''', re.VERBOSE | re.IGNORECASE) + + + +def formatdate(timeval=None, localtime=False, usegmt=False): + """Returns a date string as specified by RFC 2822, e.g.: + + Fri, 09 Nov 2001 01:08:47 -0000 + + Optional timeval if given is a floating point time value as accepted by + gmtime() and localtime(), otherwise the current time is used. + + Optional localtime is a flag that when True, interprets timeval, and + returns a date relative to the local timezone instead of UTC, properly + taking daylight savings time into account. + + Optional argument usegmt means that the timezone is written out as + an ascii string, not numeric one (so "GMT" instead of "+0000"). This + is needed for HTTP, and is only used when localtime==False. + """ + # Note: we cannot use strftime() because that honors the locale and RFC + # 2822 requires that day and month names be the English abbreviations. + if timeval is None: + timeval = time.time() + if localtime: + now = time.localtime(timeval) + # Calculate timezone offset, based on whether the local zone has + # daylight savings time, and whether DST is in effect. + if time.daylight and now[-1]: + offset = time.altzone + else: + offset = time.timezone + hours, minutes = divmod(abs(offset), 3600) + # Remember offset is in seconds west of UTC, but the timezone is in + # minutes east of UTC, so the signs differ. + if offset > 0: + sign = '-' + else: + sign = '+' + zone = '%s%02d%02d' % (sign, hours, minutes // 60) + else: + now = time.gmtime(timeval) + # Timezone offset is always -0000 + if usegmt: + zone = 'GMT' + else: + zone = '-0000' + return '%s, %02d %s %04d %02d:%02d:%02d %s' % ( + ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'][now[6]], + now[2], + ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][now[1] - 1], + now[0], now[3], now[4], now[5], + zone) + + + +def make_msgid(idstring=None): + """Returns a string suitable for RFC 2822 compliant Message-ID, e.g: + + <20020201195627.33539.96671@nightshade.la.mastaler.com> + + Optional idstring if given is a string used to strengthen the + uniqueness of the message id. + """ + timeval = time.time() + utcdate = time.strftime('%Y%m%d%H%M%S', time.gmtime(timeval)) + pid = os.getpid() + randint = random.randrange(100000) + if idstring is None: + idstring = '' + else: + idstring = '.' + idstring + idhost = socket.getfqdn() + msgid = '<%s.%s.%s%s@%s>' % (utcdate, pid, randint, idstring, idhost) + return msgid + + + +# These functions are in the standalone mimelib version only because they've +# subsequently been fixed in the latest Python versions. We use this to worm +# around broken older Pythons. +def parsedate(data): + if not data: + return None + return _parsedate(data) + + +def parsedate_tz(data): + if not data: + return None + return _parsedate_tz(data) + + +def parseaddr(addr): + addrs = _AddressList(addr).addresslist + if not addrs: + return '', '' + return addrs[0] + + +# rfc822.unquote() doesn't properly de-backslash-ify in Python pre-2.3. +def unquote(str): + """Remove quotes from a string.""" + if len(str) > 1: + if str.startswith('"') and str.endswith('"'): + return str[1:-1].replace('\\\\', '\\').replace('\\"', '"') + if str.startswith('<') and str.endswith('>'): + return str[1:-1] + return str + + + +# RFC2231-related functions - parameter encoding and decoding +def decode_rfc2231(s): + """Decode string according to RFC 2231""" + parts = s.split(TICK, 2) + if len(parts) <= 2: + return None, None, s + return parts + + +def encode_rfc2231(s, charset=None, language=None): + """Encode string according to RFC 2231. + + If neither charset nor language is given, then s is returned as-is. If + charset is given but not language, the string is encoded using the empty + string for language. + """ + import urllib + s = urllib.quote(s, safe='') + if charset is None and language is None: + return s + if language is None: + language = '' + return "%s'%s'%s" % (charset, language, s) + + +rfc2231_continuation = re.compile(r'^(?P\w+)\*((?P[0-9]+)\*?)?$') + +def decode_params(params): + """Decode parameters list according to RFC 2231. + + params is a sequence of 2-tuples containing (param name, string value). + """ + # Copy params so we don't mess with the original + params = params[:] + new_params = [] + # Map parameter's name to a list of continuations. The values are a + # 3-tuple of the continuation number, the string value, and a flag + # specifying whether a particular segment is %-encoded. + rfc2231_params = {} + name, value = params.pop(0) + new_params.append((name, value)) + while params: + name, value = params.pop(0) + if name.endswith('*'): + encoded = True + else: + encoded = False + value = unquote(value) + mo = rfc2231_continuation.match(name) + if mo: + name, num = mo.group('name', 'num') + if num is not None: + num = int(num) + rfc2231_params.setdefault(name, []).append((num, value, encoded)) + else: + new_params.append((name, '"%s"' % quote(value))) + if rfc2231_params: + for name, continuations in rfc2231_params.items(): + value = [] + extended = False + # Sort by number + continuations.sort() + # And now append all values in numerical order, converting + # %-encodings for the encoded segments. If any of the + # continuation names ends in a *, then the entire string, after + # decoding segments and concatenating, must have the charset and + # language specifiers at the beginning of the string. + for num, s, encoded in continuations: + if encoded: + s = urllib.unquote(s) + extended = True + value.append(s) + value = quote(EMPTYSTRING.join(value)) + if extended: + charset, language, value = decode_rfc2231(value) + new_params.append((name, (charset, language, '"%s"' % value))) + else: + new_params.append((name, '"%s"' % value)) + return new_params + +def collapse_rfc2231_value(value, errors='replace', + fallback_charset='us-ascii'): + if isinstance(value, tuple): + rawval = unquote(value[2]) + charset = value[0] or 'us-ascii' + try: + return unicode(rawval, charset, errors) + except LookupError: + # XXX charset is unknown to Python. + return unicode(rawval, fallback_charset, errors) + else: + return unquote(value) diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/utils.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/utils.pyc new file mode 100644 index 0000000..0ff946e Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/utils.pyc differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/utils.pyo b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/utils.pyo new file mode 100644 index 0000000..0ff946e Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/email/utils.pyo differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/MacOS.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/MacOS.so new file mode 100644 index 0000000..09455e3 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/MacOS.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/Nav.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/Nav.so new file mode 100644 index 0000000..03c1aa2 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/Nav.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/Qt.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/Qt.so new file mode 100644 index 0000000..d1d9a03 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/Qt.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtCore.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtCore.so new file mode 100644 index 0000000..1782a9a Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtCore.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtDeclarative.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtDeclarative.so new file mode 100644 index 0000000..8768ca9 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtDeclarative.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtGui.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtGui.so new file mode 100644 index 0000000..d916428 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtGui.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtHelp.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtHelp.so new file mode 100644 index 0000000..69f5d6e Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtHelp.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtMultimedia.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtMultimedia.so new file mode 100644 index 0000000..da16787 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtMultimedia.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtNetwork.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtNetwork.so new file mode 100644 index 0000000..fab4bfc Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtNetwork.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtScriptTools.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtScriptTools.so new file mode 100644 index 0000000..a3a1625 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtScriptTools.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtSvg.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtSvg.so new file mode 100644 index 0000000..fdbfeb4 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtSvg.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtWebKit.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtWebKit.so new file mode 100644 index 0000000..d94d1df Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtWebKit.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtXmlPatterns.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtXmlPatterns.so new file mode 100644 index 0000000..fc85d4e Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtXmlPatterns.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_AE.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_AE.so new file mode 100644 index 0000000..911ec2a Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_AE.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Ctl.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Ctl.so new file mode 100644 index 0000000..17c6cb7 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Ctl.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Dlg.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Dlg.so new file mode 100644 index 0000000..d7199b7 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Dlg.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Evt.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Evt.so new file mode 100644 index 0000000..772c6fe Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Evt.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_File.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_File.so new file mode 100644 index 0000000..9db7017 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_File.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Menu.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Menu.so new file mode 100644 index 0000000..6eb757e Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Menu.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Qd.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Qd.so new file mode 100644 index 0000000..f320855 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Qd.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Res.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Res.so new file mode 100644 index 0000000..263548c Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Res.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Win.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Win.so new file mode 100644 index 0000000..a3b4dcb Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_Win.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_bisect.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_bisect.so new file mode 100644 index 0000000..735f6eb Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_bisect.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_cn.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_cn.so new file mode 100644 index 0000000..c32c6e2 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_cn.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_hk.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_hk.so new file mode 100644 index 0000000..b74c597 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_hk.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_iso2022.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_iso2022.so new file mode 100644 index 0000000..8c1c1dc Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_iso2022.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_jp.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_jp.so new file mode 100644 index 0000000..e154c87 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_jp.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_kr.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_kr.so new file mode 100644 index 0000000..c665be1 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_kr.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_tw.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_tw.so new file mode 100644 index 0000000..0789bd0 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_tw.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_collections.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_collections.so new file mode 100644 index 0000000..281b2b5 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_collections.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_functools.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_functools.so new file mode 100644 index 0000000..4798903 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_functools.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_hashlib.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_hashlib.so new file mode 100644 index 0000000..701c3aa Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_hashlib.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_heapq.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_heapq.so new file mode 100644 index 0000000..4617327 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_heapq.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_io.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_io.so new file mode 100644 index 0000000..2edeff8 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_io.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_json.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_json.so new file mode 100644 index 0000000..0267282 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_json.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_locale.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_locale.so new file mode 100644 index 0000000..96fc6b1 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_locale.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_multibytecodec.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_multibytecodec.so new file mode 100644 index 0000000..eff8277 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_multibytecodec.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_random.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_random.so new file mode 100644 index 0000000..cd41019 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_random.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_scproxy.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_scproxy.so new file mode 100644 index 0000000..dc3bfb4 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_scproxy.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_socket.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_socket.so new file mode 100644 index 0000000..db1b3b1 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_socket.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_ssl.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_ssl.so new file mode 100644 index 0000000..43a57f4 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_ssl.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_struct.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_struct.so new file mode 100644 index 0000000..fba9b93 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_struct.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_testcapi.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_testcapi.so new file mode 100644 index 0000000..518b550 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/_testcapi.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/array.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/array.so new file mode 100644 index 0000000..11d3f25 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/array.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/audioop.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/audioop.so new file mode 100644 index 0000000..00a637c Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/audioop.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/binascii.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/binascii.so new file mode 100644 index 0000000..34eea6a Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/binascii.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/bz2.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/bz2.so new file mode 100644 index 0000000..36cb849 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/bz2.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/cPickle.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/cPickle.so new file mode 100644 index 0000000..9984e64 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/cPickle.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/cStringIO.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/cStringIO.so new file mode 100644 index 0000000..a14f62c Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/cStringIO.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/datetime.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/datetime.so new file mode 100644 index 0000000..dc0e55f Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/datetime.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/fcntl.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/fcntl.so new file mode 100644 index 0000000..ddc9087 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/fcntl.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/gestalt.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/gestalt.so new file mode 100644 index 0000000..f45b0c4 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/gestalt.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/grp.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/grp.so new file mode 100644 index 0000000..ac91ad8 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/grp.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/itertools.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/itertools.so new file mode 100644 index 0000000..edc201a Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/itertools.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/math.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/math.so new file mode 100644 index 0000000..7576b6e Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/math.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/operator.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/operator.so new file mode 100644 index 0000000..543d980 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/operator.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/parser.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/parser.so new file mode 100644 index 0000000..cd3a6fb Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/parser.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/pyexpat.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/pyexpat.so new file mode 100644 index 0000000..8cc4522 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/pyexpat.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/resource.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/resource.so new file mode 100644 index 0000000..64c20e4 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/resource.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/select.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/select.so new file mode 100644 index 0000000..a2cde42 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/select.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/sip.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/sip.so new file mode 100644 index 0000000..5ac2cb4 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/sip.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/strop.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/strop.so new file mode 100644 index 0000000..5ca5879 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/strop.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/termios.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/termios.so new file mode 100644 index 0000000..a2f074e Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/termios.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/time.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/time.so new file mode 100644 index 0000000..bcef76a Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/time.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/unicodedata.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/unicodedata.so new file mode 100644 index 0000000..ae68acf Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/unicodedata.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/zlib.so b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/zlib.so new file mode 100644 index 0000000..d6a73e4 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/lib-dynload/zlib.so differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/site-packages.zip b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/site-packages.zip new file mode 100644 index 0000000..9a3deb9 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/site-packages.zip differ diff --git a/FeedTheMonkey.app/Contents/Resources/lib/python2.7/site.pyc b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/site.pyc new file mode 120000 index 0000000..66cd464 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/lib/python2.7/site.pyc @@ -0,0 +1 @@ +../../site.pyc \ No newline at end of file diff --git a/FeedTheMonkey.app/Contents/Resources/qt.conf b/FeedTheMonkey.app/Contents/Resources/qt.conf new file mode 100644 index 0000000..bf0b535 --- /dev/null +++ b/FeedTheMonkey.app/Contents/Resources/qt.conf @@ -0,0 +1,3 @@ +; Qt Configuration file +[Paths] +Plugins = Resources/qt_plugins diff --git a/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqgif.dylib b/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqgif.dylib new file mode 100644 index 0000000..837154c Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqgif.dylib differ diff --git a/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqico.dylib b/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqico.dylib new file mode 100644 index 0000000..7cc9242 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqico.dylib differ diff --git a/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqjpeg.dylib b/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqjpeg.dylib new file mode 100644 index 0000000..097e2b9 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqjpeg.dylib differ diff --git a/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqmng.dylib b/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqmng.dylib new file mode 100644 index 0000000..3d2f734 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqmng.dylib differ diff --git a/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqsvg.dylib b/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqsvg.dylib new file mode 100644 index 0000000..9578a15 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqsvg.dylib differ diff --git a/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqtga.dylib b/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqtga.dylib new file mode 100644 index 0000000..416aa25 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqtga.dylib differ diff --git a/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqtiff.dylib b/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqtiff.dylib new file mode 100644 index 0000000..ad9e98c Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/qt_plugins/imageformats/libqtiff.dylib differ diff --git a/FeedTheMonkey.app/Contents/Resources/site.pyc b/FeedTheMonkey.app/Contents/Resources/site.pyc new file mode 100644 index 0000000..505c6a9 Binary files /dev/null and b/FeedTheMonkey.app/Contents/Resources/site.pyc differ diff --git a/FeedTheMonkey.egg-info/PKG-INFO b/FeedTheMonkey.egg-info/PKG-INFO new file mode 100644 index 0000000..d6b39a8 --- /dev/null +++ b/FeedTheMonkey.egg-info/PKG-INFO @@ -0,0 +1,10 @@ +Metadata-Version: 1.0 +Name: FeedTheMonkey +Version: 0.1.1 +Summary: UNKNOWN +Home-page: http://jabs.nu/feedthemonkey +Author: Jeena Paradies +Author-email: spam@jeenaparadies.net +License: BSD license +Description: UNKNOWN +Platform: UNKNOWN diff --git a/FeedTheMonkey.egg-info/SOURCES.txt b/FeedTheMonkey.egg-info/SOURCES.txt new file mode 100644 index 0000000..d288ac9 --- /dev/null +++ b/FeedTheMonkey.egg-info/SOURCES.txt @@ -0,0 +1,6 @@ +feedthemonkey +setup.py +FeedTheMonkey.egg-info/PKG-INFO +FeedTheMonkey.egg-info/SOURCES.txt +FeedTheMonkey.egg-info/dependency_links.txt +FeedTheMonkey.egg-info/top_level.txt \ No newline at end of file diff --git a/FeedTheMonkey.egg-info/dependency_links.txt b/FeedTheMonkey.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/FeedTheMonkey.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/FeedTheMonkey.egg-info/top_level.txt b/FeedTheMonkey.egg-info/top_level.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/FeedTheMonkey.egg-info/top_level.txt @@ -0,0 +1 @@ + diff --git a/feedthemonkey b/feedthemonkey index 36005ab..ad63d1e 100755 --- a/feedthemonkey +++ b/feedthemonkey @@ -67,6 +67,9 @@ class MainWindow(QtGui.QMainWindow): viewMenu.addAction(mkAction("Zoom &Out", lambda: self.content.wb.setZoomFactor(self.content.wb.zoomFactor() - 0.2), "Ctrl+-")) viewMenu.addAction(mkAction("&Reset", lambda: self.content.wb.setZoomFactor(1), "Ctrl+0")) + windowMenu = mb.addMenu("&Window") + windowMenu.addAction(mkAction("Reset to Default", self.resetSplitter, "Ctrl+D")) + helpMenu = mb.addMenu("&Help") helpMenu.addAction(mkAction("&About", lambda: QtGui.QDesktopServices.openUrl(QtCore.QUrl("http://jabs.nu/feedthemonkey", QtCore.QUrl.TolerantMode)) )) @@ -100,6 +103,14 @@ class MainWindow(QtGui.QMainWindow): def splitterMoved(self, pos, index): settings.setValue("splitterSizes", self.splitter.saveState()); + def resetSplitter(self): + sizes = self.splitter.sizes() + top = sizes[0] + bottom = sizes[1] + sizes[0] = 200 + sizes[1] = bottom + top - 200 + self.splitter.setSizes(sizes) + def authenticate(self): dialog = Login() diff --git a/setup.py b/setup.py index 4b864b2..e04ccfd 100644 --- a/setup.py +++ b/setup.py @@ -48,8 +48,6 @@ if is_osx: if filename == "Icon.icns": files += [(dirname, [os.path.join(dirname, filename)])] -print setup_requires - setup( app = APP, name = "FeedTheMonkey",