tools v2.2
This commit is contained in:
@@ -1,21 +0,0 @@
|
||||
eReader PDB2PML - eReaderPDB2PML_vXX_plugin.zip
|
||||
|
||||
All credit given to The Dark Reverser for the original standalone script. I had the much easier job of converting it to a Calibre plugin.
|
||||
|
||||
This plugin is meant to convert secure Ereader files (PDB) to unsecured PMLZ files. Calibre can then convert it to whatever format you desire. It is meant to function without having to install any dependencies... other than having Calibre installed, of course. I've included the psyco libraries (compiled for each platform) for speed. If your system can use them, great! Otherwise, they won't be used and things will just work slower.
|
||||
|
||||
Installation:
|
||||
Go to Calibre's Preferences page... click on the Plugins button. Use the file dialog button to select the plugin's zip file (eReaderPDB2PML_vXX_plugin.zip) and click the 'Add' button. You're done.
|
||||
|
||||
Configuration:
|
||||
Highlight the plugin (eReader PDB 2 PML under the "File type plugins" category) and click the "Customize Plugin" button on Calibre's Preferences->Plugins page. Enter your name and last 8 digits of the credit card number separated by a comma: Your Name,12341234
|
||||
|
||||
If you've purchased books with more than one credit card, separate the info with a colon: Your Name,12341234:Other Name,23452345 (NOTE: Do NOT put quotes around your name like you do with the original script!!)
|
||||
|
||||
Troubleshooting:
|
||||
If you find that it's not working for you (imported pdb's are not converted to pmlz format), you can save a lot of time and trouble by trying to add the pdb to Calibre with the command line tools. This will print out a lot of helpful debugging info that can be copied into any online help requests. I'm going to ask you to do it first, anyway, so you might
|
||||
as well get used to it. ;)
|
||||
|
||||
Open a command prompt (terminal) and change to the directory where the ebook you're trying to import resides. Then type the command "calibredb add your_ebook.pdb". Don't type the quotes and obviously change the 'your_ebook.pdb' to whatever the filename of your book is. Copy the resulting output and paste it into any online help request you make.
|
||||
|
||||
** Note: the Mac version of Calibre doesn't install the command line tools by default. If you go to the 'Preferences' page and click on the miscellaneous button, you'll see the option to install the command line tools.
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# eReaderPDB2PML_v01_plugin.py
|
||||
# eReaderPDB2PML_plugin.py
|
||||
# Released under the terms of the GNU General Public Licence, version 3 or
|
||||
# later. <http://www.gnu.org/licenses/>
|
||||
#
|
||||
@@ -30,7 +30,8 @@
|
||||
# NOTE: Do NOT put quotes around your name like you do with the original script!!
|
||||
#
|
||||
# Revision history:
|
||||
# 0.1 - Initial release
|
||||
# 0.0.1 - Initial release
|
||||
# 0.0.2 - updated to distinguish it from earlier non-openssl version
|
||||
|
||||
import sys, os
|
||||
|
||||
@@ -42,7 +43,7 @@ class eRdrDeDRM(FileTypePlugin):
|
||||
Credit given to The Dark Reverser for the original standalone script.'
|
||||
supported_platforms = ['linux', 'osx', 'windows'] # Platforms this plugin will run on
|
||||
author = 'DiapDealer' # The author of this plugin
|
||||
version = (0, 0, 1) # The version number of this plugin
|
||||
version = (0, 0, 2) # The version number of this plugin
|
||||
file_types = set(['pdb']) # The file types that this plugin will be applied to
|
||||
on_import = True # Run this plugin during the import
|
||||
|
||||
@@ -52,7 +53,6 @@ class eRdrDeDRM(FileTypePlugin):
|
||||
pdir = 'windows' if iswindows else 'osx' if isosx else 'linux'
|
||||
ppath = os.path.join(self.sys_insertion_path, pdir)
|
||||
sys.path.insert(0, ppath)
|
||||
#sys.path.append(ppath)
|
||||
|
||||
global bookname, erdr2pml
|
||||
import erdr2pml
|
||||
|
||||
@@ -54,26 +54,30 @@
|
||||
# 0.13 - change to unbuffered stdout for use with gui front ends
|
||||
# 0.14 - contributed enhancement to support --make-pmlz switch
|
||||
# 0.15 - enabled high-ascii to pml character encoding. DropBook now works on Mac.
|
||||
# 0.16 - convert to use openssl DES (very very fast) or pure python DES if openssl's libcrypto is not available
|
||||
|
||||
__version__='0.15'
|
||||
Des = None
|
||||
|
||||
# Import Psyco if available
|
||||
try:
|
||||
# Dumb speed hack 1
|
||||
# http://psyco.sourceforge.net
|
||||
import psyco
|
||||
psyco.full()
|
||||
pass
|
||||
except ImportError:
|
||||
pass
|
||||
try:
|
||||
# Dumb speed hack 2
|
||||
# All map() calls converted to list comprehension (some use zip)
|
||||
# override zip with izip - saves memory and in rough testing
|
||||
# appears to be faster zip() is only used in the converted map() calls
|
||||
from itertools import izip as zip
|
||||
except ImportError:
|
||||
pass
|
||||
import openssl_des
|
||||
Des = openssl_des.load_libcrypto()
|
||||
|
||||
# if that did not work then use pure python implementation
|
||||
# of DES and try to speed it up with Psycho
|
||||
if Des == None:
|
||||
import python_des
|
||||
Des = python_des.Des
|
||||
# Import Psyco if available
|
||||
try:
|
||||
# Dumb speed hack 1
|
||||
# http://psyco.sourceforge.net
|
||||
import psyco
|
||||
psyco.full()
|
||||
pass
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
__version__='0.16'
|
||||
|
||||
class Unbuffered:
|
||||
def __init__(self, stream):
|
||||
@@ -101,223 +105,6 @@ import logging
|
||||
logging.basicConfig()
|
||||
#logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
ECB = 0
|
||||
CBC = 1
|
||||
class Des(object):
|
||||
__pc1 = [56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
|
||||
9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
|
||||
62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
|
||||
13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3]
|
||||
__left_rotations = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]
|
||||
__pc2 = [13, 16, 10, 23, 0, 4,2, 27, 14, 5, 20, 9,
|
||||
22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
|
||||
40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
|
||||
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31]
|
||||
__ip = [57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
|
||||
61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7,
|
||||
56, 48, 40, 32, 24, 16, 8, 0, 58, 50, 42, 34, 26, 18, 10, 2,
|
||||
60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6]
|
||||
__expansion_table = [31, 0, 1, 2, 3, 4, 3, 4, 5, 6, 7, 8,
|
||||
7, 8, 9, 10, 11, 12,11, 12, 13, 14, 15, 16,
|
||||
15, 16, 17, 18, 19, 20,19, 20, 21, 22, 23, 24,
|
||||
23, 24, 25, 26, 27, 28,27, 28, 29, 30, 31, 0]
|
||||
__sbox = [[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
|
||||
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
|
||||
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
|
||||
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13],
|
||||
[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
|
||||
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
|
||||
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
|
||||
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9],
|
||||
[10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
|
||||
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
|
||||
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
|
||||
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12],
|
||||
[7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
|
||||
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
|
||||
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
|
||||
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14],
|
||||
[2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
|
||||
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
|
||||
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
|
||||
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3],
|
||||
[12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
|
||||
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
|
||||
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
|
||||
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13],
|
||||
[4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
|
||||
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
|
||||
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
|
||||
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12],
|
||||
[13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
|
||||
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
|
||||
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
|
||||
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11],]
|
||||
__p = [15, 6, 19, 20, 28, 11,27, 16, 0, 14, 22, 25,
|
||||
4, 17, 30, 9, 1, 7,23,13, 31, 26, 2, 8,18, 12, 29, 5, 21, 10,3, 24]
|
||||
__fp = [39, 7, 47, 15, 55, 23, 63, 31,38, 6, 46, 14, 54, 22, 62, 30,
|
||||
37, 5, 45, 13, 53, 21, 61, 29,36, 4, 44, 12, 52, 20, 60, 28,
|
||||
35, 3, 43, 11, 51, 19, 59, 27,34, 2, 42, 10, 50, 18, 58, 26,
|
||||
33, 1, 41, 9, 49, 17, 57, 25,32, 0, 40, 8, 48, 16, 56, 24]
|
||||
# Type of crypting being done
|
||||
ENCRYPT = 0x00
|
||||
DECRYPT = 0x01
|
||||
def __init__(self, key, mode=ECB, IV=None):
|
||||
if len(key) != 8:
|
||||
raise ValueError("Invalid DES key size. Key must be exactly 8 bytes long.")
|
||||
self.block_size = 8
|
||||
self.key_size = 8
|
||||
self.__padding = ''
|
||||
self.setMode(mode)
|
||||
if IV:
|
||||
self.setIV(IV)
|
||||
self.L = []
|
||||
self.R = []
|
||||
self.Kn = [ [0] * 48 ] * 16 # 16 48-bit keys (K1 - K16)
|
||||
self.final = []
|
||||
self.setKey(key)
|
||||
def getKey(self):
|
||||
return self.__key
|
||||
def setKey(self, key):
|
||||
self.__key = key
|
||||
self.__create_sub_keys()
|
||||
def getMode(self):
|
||||
return self.__mode
|
||||
def setMode(self, mode):
|
||||
self.__mode = mode
|
||||
def getIV(self):
|
||||
return self.__iv
|
||||
def setIV(self, IV):
|
||||
if not IV or len(IV) != self.block_size:
|
||||
raise ValueError("Invalid Initial Value (IV), must be a multiple of " + str(self.block_size) + " bytes")
|
||||
self.__iv = IV
|
||||
def getPadding(self):
|
||||
return self.__padding
|
||||
def __String_to_BitList(self, data):
|
||||
l = len(data) * 8
|
||||
result = [0] * l
|
||||
pos = 0
|
||||
for c in data:
|
||||
i = 7
|
||||
ch = ord(c)
|
||||
while i >= 0:
|
||||
if ch & (1 << i) != 0:
|
||||
result[pos] = 1
|
||||
else:
|
||||
result[pos] = 0
|
||||
pos += 1
|
||||
i -= 1
|
||||
return result
|
||||
def __BitList_to_String(self, data):
|
||||
result = ''
|
||||
pos = 0
|
||||
c = 0
|
||||
while pos < len(data):
|
||||
c += data[pos] << (7 - (pos % 8))
|
||||
if (pos % 8) == 7:
|
||||
result += chr(c)
|
||||
c = 0
|
||||
pos += 1
|
||||
return result
|
||||
def __permutate(self, table, block):
|
||||
return [block[x] for x in table]
|
||||
def __create_sub_keys(self):
|
||||
key = self.__permutate(Des.__pc1, self.__String_to_BitList(self.getKey()))
|
||||
i = 0
|
||||
self.L = key[:28]
|
||||
self.R = key[28:]
|
||||
while i < 16:
|
||||
j = 0
|
||||
while j < Des.__left_rotations[i]:
|
||||
self.L.append(self.L[0])
|
||||
del self.L[0]
|
||||
self.R.append(self.R[0])
|
||||
del self.R[0]
|
||||
j += 1
|
||||
self.Kn[i] = self.__permutate(Des.__pc2, self.L + self.R)
|
||||
i += 1
|
||||
def __des_crypt(self, block, crypt_type):
|
||||
block = self.__permutate(Des.__ip, block)
|
||||
self.L = block[:32]
|
||||
self.R = block[32:]
|
||||
if crypt_type == Des.ENCRYPT:
|
||||
iteration = 0
|
||||
iteration_adjustment = 1
|
||||
else:
|
||||
iteration = 15
|
||||
iteration_adjustment = -1
|
||||
i = 0
|
||||
while i < 16:
|
||||
tempR = self.R[:]
|
||||
self.R = self.__permutate(Des.__expansion_table, self.R)
|
||||
self.R = [x ^ y for x,y in zip(self.R, self.Kn[iteration])]
|
||||
B = [self.R[:6], self.R[6:12], self.R[12:18], self.R[18:24], self.R[24:30], self.R[30:36], self.R[36:42], self.R[42:]]
|
||||
j = 0
|
||||
Bn = [0] * 32
|
||||
pos = 0
|
||||
while j < 8:
|
||||
m = (B[j][0] << 1) + B[j][5]
|
||||
n = (B[j][1] << 3) + (B[j][2] << 2) + (B[j][3] << 1) + B[j][4]
|
||||
v = Des.__sbox[j][(m << 4) + n]
|
||||
Bn[pos] = (v & 8) >> 3
|
||||
Bn[pos + 1] = (v & 4) >> 2
|
||||
Bn[pos + 2] = (v & 2) >> 1
|
||||
Bn[pos + 3] = v & 1
|
||||
pos += 4
|
||||
j += 1
|
||||
self.R = self.__permutate(Des.__p, Bn)
|
||||
self.R = [x ^ y for x, y in zip(self.R, self.L)]
|
||||
self.L = tempR
|
||||
i += 1
|
||||
iteration += iteration_adjustment
|
||||
self.final = self.__permutate(Des.__fp, self.R + self.L)
|
||||
return self.final
|
||||
def crypt(self, data, crypt_type):
|
||||
if not data:
|
||||
return ''
|
||||
if len(data) % self.block_size != 0:
|
||||
if crypt_type == Des.DECRYPT: # Decryption must work on 8 byte blocks
|
||||
raise ValueError("Invalid data length, data must be a multiple of " + str(self.block_size) + " bytes\n.")
|
||||
if not self.getPadding():
|
||||
raise ValueError("Invalid data length, data must be a multiple of " + str(self.block_size) + " bytes\n. Try setting the optional padding character")
|
||||
else:
|
||||
data += (self.block_size - (len(data) % self.block_size)) * self.getPadding()
|
||||
if self.getMode() == CBC:
|
||||
if self.getIV():
|
||||
iv = self.__String_to_BitList(self.getIV())
|
||||
else:
|
||||
raise ValueError("For CBC mode, you must supply the Initial Value (IV) for ciphering")
|
||||
i = 0
|
||||
dict = {}
|
||||
result = []
|
||||
while i < len(data):
|
||||
block = self.__String_to_BitList(data[i:i+8])
|
||||
if self.getMode() == CBC:
|
||||
if crypt_type == Des.ENCRYPT:
|
||||
block = [x ^ y for x, y in zip(block, iv)]
|
||||
processed_block = self.__des_crypt(block, crypt_type)
|
||||
if crypt_type == Des.DECRYPT:
|
||||
processed_block = [x ^ y for x, y in zip(processed_block, iv)]
|
||||
iv = block
|
||||
else:
|
||||
iv = processed_block
|
||||
else:
|
||||
processed_block = self.__des_crypt(block, crypt_type)
|
||||
result.append(self.__BitList_to_String(processed_block))
|
||||
i += 8
|
||||
if crypt_type == Des.DECRYPT and self.getPadding():
|
||||
s = result[-1]
|
||||
while s[-1] == self.getPadding():
|
||||
s = s[:-1]
|
||||
result[-1] = s
|
||||
return ''.join(result)
|
||||
def encrypt(self, data, pad=''):
|
||||
self.__padding = pad
|
||||
return self.crypt(data, Des.ENCRYPT)
|
||||
def decrypt(self, data, pad=''):
|
||||
self.__padding = pad
|
||||
return self.crypt(data, Des.DECRYPT)
|
||||
|
||||
class Sectionizer(object):
|
||||
def __init__(self, filename, ident):
|
||||
self.contents = file(filename, 'rb').read()
|
||||
@@ -685,8 +472,5 @@ def main(argv=None):
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
#import cProfile
|
||||
#command = """sys.exit(main())"""
|
||||
#cProfile.runctx( command, globals(), locals(), filename="cprofile.profile" )
|
||||
|
||||
sys.exit(main())
|
||||
|
||||
|
||||
90
Calibre_Plugins/eReaderPDB2PML_plugin/openssl_des.py
Normal file
90
Calibre_Plugins/eReaderPDB2PML_plugin/openssl_des.py
Normal file
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
|
||||
|
||||
# implement just enough of des from openssl to make erdr2pml.py happy
|
||||
|
||||
def load_libcrypto():
|
||||
from ctypes import CDLL, POINTER, c_void_p, c_char_p, c_char, c_int, c_long, \
|
||||
Structure, c_ulong, create_string_buffer, cast
|
||||
from ctypes.util import find_library
|
||||
import sys
|
||||
|
||||
if sys.platform.startswith('win'):
|
||||
libcrypto = find_library('libeay32')
|
||||
else:
|
||||
libcrypto = find_library('crypto')
|
||||
|
||||
if libcrypto is None:
|
||||
return None
|
||||
|
||||
libcrypto = CDLL(libcrypto)
|
||||
|
||||
# typedef struct DES_ks
|
||||
# {
|
||||
# union
|
||||
# {
|
||||
# DES_cblock cblock;
|
||||
# /* make sure things are correct size on machines with
|
||||
# * 8 byte longs */
|
||||
# DES_LONG deslong[2];
|
||||
# } ks[16];
|
||||
# } DES_key_schedule;
|
||||
|
||||
# just create a big enough place to hold everything
|
||||
# it will have alignment of structure so we should be okay (16 byte aligned?)
|
||||
class DES_KEY_SCHEDULE(Structure):
|
||||
_fields_ = [('DES_cblock1', c_char * 16),
|
||||
('DES_cblock2', c_char * 16),
|
||||
('DES_cblock3', c_char * 16),
|
||||
('DES_cblock4', c_char * 16),
|
||||
('DES_cblock5', c_char * 16),
|
||||
('DES_cblock6', c_char * 16),
|
||||
('DES_cblock7', c_char * 16),
|
||||
('DES_cblock8', c_char * 16),
|
||||
('DES_cblock9', c_char * 16),
|
||||
('DES_cblock10', c_char * 16),
|
||||
('DES_cblock11', c_char * 16),
|
||||
('DES_cblock12', c_char * 16),
|
||||
('DES_cblock13', c_char * 16),
|
||||
('DES_cblock14', c_char * 16),
|
||||
('DES_cblock15', c_char * 16),
|
||||
('DES_cblock16', c_char * 16)]
|
||||
|
||||
DES_KEY_SCHEDULE_p = POINTER(DES_KEY_SCHEDULE)
|
||||
|
||||
def F(restype, name, argtypes):
|
||||
func = getattr(libcrypto, name)
|
||||
func.restype = restype
|
||||
func.argtypes = argtypes
|
||||
return func
|
||||
|
||||
DES_set_key = F(None, 'DES_set_key',[c_char_p, DES_KEY_SCHEDULE_p])
|
||||
DES_ecb_encrypt = F(None, 'DES_ecb_encrypt',[c_char_p, c_char_p, DES_KEY_SCHEDULE_p, c_int])
|
||||
|
||||
|
||||
class DES(object):
|
||||
def __init__(self, key):
|
||||
if len(key) != 8 :
|
||||
raise Error('DES improper key used')
|
||||
return
|
||||
self.key = key
|
||||
self.keyschedule = DES_KEY_SCHEDULE()
|
||||
DES_set_key(self.key, self.keyschedule)
|
||||
def desdecrypt(self, data):
|
||||
ob = create_string_buffer(len(data))
|
||||
DES_ecb_encrypt(data, ob, self.keyschedule, 0)
|
||||
return ob.raw
|
||||
def decrypt(self, data):
|
||||
if not data:
|
||||
return ''
|
||||
i = 0
|
||||
result = []
|
||||
while i < len(data):
|
||||
block = data[i:i+8]
|
||||
processed_block = self.desdecrypt(block)
|
||||
result.append(processed_block)
|
||||
i += 8
|
||||
return ''.join(result)
|
||||
|
||||
return DES
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 41
|
||||
/svn/!svn/ver/70200/psyco/dist/py-support
|
||||
END
|
||||
core.py
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 49
|
||||
/svn/!svn/ver/70200/psyco/dist/py-support/core.py
|
||||
END
|
||||
support.py
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 52
|
||||
/svn/!svn/ver/49315/psyco/dist/py-support/support.py
|
||||
END
|
||||
classes.py
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 52
|
||||
/svn/!svn/ver/35003/psyco/dist/py-support/classes.py
|
||||
END
|
||||
__init__.py
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 53
|
||||
/svn/!svn/ver/35003/psyco/dist/py-support/__init__.py
|
||||
END
|
||||
logger.py
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 51
|
||||
/svn/!svn/ver/23284/psyco/dist/py-support/logger.py
|
||||
END
|
||||
kdictproxy.py
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 55
|
||||
/svn/!svn/ver/35003/psyco/dist/py-support/kdictproxy.py
|
||||
END
|
||||
profiler.py
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 53
|
||||
/svn/!svn/ver/70200/psyco/dist/py-support/profiler.py
|
||||
END
|
||||
@@ -1,7 +0,0 @@
|
||||
K 10
|
||||
svn:ignore
|
||||
V 14
|
||||
*~
|
||||
*.pyc
|
||||
*.pyo
|
||||
END
|
||||
@@ -1,266 +0,0 @@
|
||||
10
|
||||
|
||||
dir
|
||||
78269
|
||||
http://codespeak.net/svn/psyco/dist/py-support
|
||||
http://codespeak.net/svn
|
||||
|
||||
|
||||
|
||||
2009-12-18T16:35:35.119276Z
|
||||
70200
|
||||
arigo
|
||||
has-props
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
fd0d7bf2-dfb6-0310-8d31-b7ecfe96aada
|
||||
|
||||
core.py
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-25T15:10:42.000000Z
|
||||
3b362177a839893c9e867880b3a7cef3
|
||||
2009-12-18T16:35:35.119276Z
|
||||
70200
|
||||
arigo
|
||||
has-props
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
8144
|
||||
|
||||
support.py
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-25T15:10:42.000000Z
|
||||
b0551e975d774f2f7f58a29ed4b6b90e
|
||||
2007-12-03T12:27:25.632574Z
|
||||
49315
|
||||
arigo
|
||||
has-props
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
6043
|
||||
|
||||
classes.py
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-25T15:10:42.000000Z
|
||||
5932ed955198d16ec17285dfb195d341
|
||||
2006-11-26T13:03:26.949973Z
|
||||
35003
|
||||
arigo
|
||||
has-props
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1440
|
||||
|
||||
__init__.py
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-25T15:10:42.000000Z
|
||||
219582b5182dfa38a9119d059a71965f
|
||||
2006-11-26T13:03:26.949973Z
|
||||
35003
|
||||
arigo
|
||||
has-props
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1895
|
||||
|
||||
logger.py
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-25T15:10:42.000000Z
|
||||
aa21f905df036af43082e1ea2a2561ee
|
||||
2006-02-13T15:02:51.744168Z
|
||||
23284
|
||||
arigo
|
||||
has-props
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
2678
|
||||
|
||||
kdictproxy.py
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-25T15:10:42.000000Z
|
||||
1c8611748dcee5b29848bf25be3ec473
|
||||
2006-11-26T13:03:26.949973Z
|
||||
35003
|
||||
arigo
|
||||
has-props
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
4369
|
||||
|
||||
profiler.py
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-25T15:10:42.000000Z
|
||||
858162366cbc39cd9e249e35e6f510c4
|
||||
2009-12-18T16:35:35.119276Z
|
||||
70200
|
||||
arigo
|
||||
has-props
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
11238
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
K 13
|
||||
svn:eol-style
|
||||
V 6
|
||||
native
|
||||
K 12
|
||||
svn:keywords
|
||||
V 23
|
||||
Author Date Id Revision
|
||||
END
|
||||
@@ -1,9 +0,0 @@
|
||||
K 13
|
||||
svn:eol-style
|
||||
V 6
|
||||
native
|
||||
K 12
|
||||
svn:keywords
|
||||
V 23
|
||||
Author Date Id Revision
|
||||
END
|
||||
@@ -1,9 +0,0 @@
|
||||
K 13
|
||||
svn:eol-style
|
||||
V 6
|
||||
native
|
||||
K 12
|
||||
svn:keywords
|
||||
V 23
|
||||
Author Date Id Revision
|
||||
END
|
||||
@@ -1,9 +0,0 @@
|
||||
K 13
|
||||
svn:eol-style
|
||||
V 6
|
||||
native
|
||||
K 12
|
||||
svn:keywords
|
||||
V 23
|
||||
Author Date Id Revision
|
||||
END
|
||||
@@ -1,9 +0,0 @@
|
||||
K 13
|
||||
svn:eol-style
|
||||
V 6
|
||||
native
|
||||
K 12
|
||||
svn:keywords
|
||||
V 23
|
||||
Author Date Id Revision
|
||||
END
|
||||
@@ -1,9 +0,0 @@
|
||||
K 13
|
||||
svn:eol-style
|
||||
V 6
|
||||
native
|
||||
K 12
|
||||
svn:keywords
|
||||
V 23
|
||||
Author Date Id Revision
|
||||
END
|
||||
@@ -1,9 +0,0 @@
|
||||
K 13
|
||||
svn:eol-style
|
||||
V 6
|
||||
native
|
||||
K 12
|
||||
svn:keywords
|
||||
V 23
|
||||
Author Date Id Revision
|
||||
END
|
||||
@@ -1,54 +0,0 @@
|
||||
###########################################################################
|
||||
#
|
||||
# Psyco top-level file of the Psyco package.
|
||||
# Copyright (C) 2001-2002 Armin Rigo et.al.
|
||||
|
||||
"""Psyco -- the Python Specializing Compiler.
|
||||
|
||||
Typical usage: add the following lines to your application's main module,
|
||||
preferably after the other imports:
|
||||
|
||||
try:
|
||||
import psyco
|
||||
psyco.full()
|
||||
except ImportError:
|
||||
print 'Psyco not installed, the program will just run slower'
|
||||
"""
|
||||
###########################################################################
|
||||
|
||||
|
||||
#
|
||||
# This module is present to make 'psyco' a package and to
|
||||
# publish the main functions and variables.
|
||||
#
|
||||
# More documentation can be found in core.py.
|
||||
#
|
||||
|
||||
|
||||
# Try to import the dynamic-loading _psyco and report errors
|
||||
try:
|
||||
import _psyco
|
||||
except ImportError, e:
|
||||
extramsg = ''
|
||||
import sys, imp
|
||||
try:
|
||||
file, filename, (suffix, mode, type) = imp.find_module('_psyco', __path__)
|
||||
except ImportError:
|
||||
ext = [suffix for suffix, mode, type in imp.get_suffixes()
|
||||
if type == imp.C_EXTENSION]
|
||||
if ext:
|
||||
extramsg = (" (cannot locate the compiled extension '_psyco%s' "
|
||||
"in the package path '%s')" % (ext[0], '; '.join(__path__)))
|
||||
else:
|
||||
extramsg = (" (check that the compiled extension '%s' is for "
|
||||
"the correct Python version; this is Python %s)" %
|
||||
(filename, sys.version.split()[0]))
|
||||
raise ImportError, str(e) + extramsg
|
||||
|
||||
# Publish important data by importing them in the package
|
||||
from support import __version__, error, warning, _getrealframe, _getemulframe
|
||||
from support import version_info, __version__ as hexversion
|
||||
from core import full, profile, background, runonly, stop, cannotcompile
|
||||
from core import log, bind, unbind, proxy, unproxy, dumpcodebuf
|
||||
from _psyco import setfilter
|
||||
from _psyco import compact, compacttype
|
||||
@@ -1,42 +0,0 @@
|
||||
###########################################################################
|
||||
#
|
||||
# Psyco class support module.
|
||||
# Copyright (C) 2001-2002 Armin Rigo et.al.
|
||||
|
||||
"""Psyco class support module.
|
||||
|
||||
'psyco.classes.psyobj' is an alternate Psyco-optimized root for classes.
|
||||
Any class inheriting from it or using the metaclass '__metaclass__' might
|
||||
get optimized specifically for Psyco. It is equivalent to call
|
||||
psyco.bind() on the class object after its creation.
|
||||
|
||||
Importing everything from psyco.classes in a module will import the
|
||||
'__metaclass__' name, so all classes defined after a
|
||||
|
||||
from psyco.classes import *
|
||||
|
||||
will automatically use the Psyco-optimized metaclass.
|
||||
"""
|
||||
###########################################################################
|
||||
|
||||
__all__ = ['psyobj', 'psymetaclass', '__metaclass__']
|
||||
|
||||
|
||||
from _psyco import compacttype
|
||||
import core
|
||||
from types import FunctionType
|
||||
|
||||
class psymetaclass(compacttype):
|
||||
"Psyco-optimized meta-class. Turns all methods into Psyco proxies."
|
||||
|
||||
def __new__(cls, name, bases, dict):
|
||||
bindlist = dict.get('__psyco__bind__')
|
||||
if bindlist is None:
|
||||
bindlist = [key for key, value in dict.items()
|
||||
if isinstance(value, FunctionType)]
|
||||
for attr in bindlist:
|
||||
dict[attr] = core.proxy(dict[attr])
|
||||
return super(psymetaclass, cls).__new__(cls, name, bases, dict)
|
||||
|
||||
psyobj = psymetaclass("psyobj", (), {})
|
||||
__metaclass__ = psymetaclass
|
||||
@@ -1,231 +0,0 @@
|
||||
###########################################################################
|
||||
#
|
||||
# Psyco main functions.
|
||||
# Copyright (C) 2001-2002 Armin Rigo et.al.
|
||||
|
||||
"""Psyco main functions.
|
||||
|
||||
Here are the routines that you can use from your applications.
|
||||
These are mostly interfaces to the C core, but they depend on
|
||||
the Python version.
|
||||
|
||||
You can use these functions from the 'psyco' module instead of
|
||||
'psyco.core', e.g.
|
||||
|
||||
import psyco
|
||||
psyco.log('/tmp/psyco.log')
|
||||
psyco.profile()
|
||||
"""
|
||||
###########################################################################
|
||||
|
||||
import _psyco
|
||||
import types
|
||||
from support import *
|
||||
|
||||
newfunction = types.FunctionType
|
||||
newinstancemethod = types.MethodType
|
||||
|
||||
|
||||
# Default charge profiler values
|
||||
default_watermark = 0.09 # between 0.0 (0%) and 1.0 (100%)
|
||||
default_halflife = 0.5 # seconds
|
||||
default_pollfreq_profile = 20 # Hz
|
||||
default_pollfreq_background = 100 # Hz -- a maximum for sleep's resolution
|
||||
default_parentframe = 0.25 # should not be more than 0.5 (50%)
|
||||
|
||||
|
||||
def full(memory=None, time=None, memorymax=None, timemax=None):
|
||||
"""Compile as much as possible.
|
||||
|
||||
Typical use is for small scripts performing intensive computations
|
||||
or string handling."""
|
||||
import profiler
|
||||
p = profiler.FullCompiler()
|
||||
p.run(memory, time, memorymax, timemax)
|
||||
|
||||
|
||||
def profile(watermark = default_watermark,
|
||||
halflife = default_halflife,
|
||||
pollfreq = default_pollfreq_profile,
|
||||
parentframe = default_parentframe,
|
||||
memory=None, time=None, memorymax=None, timemax=None):
|
||||
"""Turn on profiling.
|
||||
|
||||
The 'watermark' parameter controls how easily running functions will
|
||||
be compiled. The smaller the value, the more functions are compiled."""
|
||||
import profiler
|
||||
p = profiler.ActivePassiveProfiler(watermark, halflife,
|
||||
pollfreq, parentframe)
|
||||
p.run(memory, time, memorymax, timemax)
|
||||
|
||||
|
||||
def background(watermark = default_watermark,
|
||||
halflife = default_halflife,
|
||||
pollfreq = default_pollfreq_background,
|
||||
parentframe = default_parentframe,
|
||||
memory=None, time=None, memorymax=None, timemax=None):
|
||||
"""Turn on passive profiling.
|
||||
|
||||
This is a very lightweight mode in which only intensively computing
|
||||
functions can be detected. The smaller the 'watermark', the more functions
|
||||
are compiled."""
|
||||
import profiler
|
||||
p = profiler.PassiveProfiler(watermark, halflife, pollfreq, parentframe)
|
||||
p.run(memory, time, memorymax, timemax)
|
||||
|
||||
|
||||
def runonly(memory=None, time=None, memorymax=None, timemax=None):
|
||||
"""Nonprofiler.
|
||||
|
||||
XXX check if this is useful and document."""
|
||||
import profiler
|
||||
p = profiler.RunOnly()
|
||||
p.run(memory, time, memorymax, timemax)
|
||||
|
||||
|
||||
def stop():
|
||||
"""Turn off all automatic compilation. bind() calls remain in effect."""
|
||||
import profiler
|
||||
profiler.go([])
|
||||
|
||||
|
||||
def log(logfile='', mode='w', top=10):
|
||||
"""Enable logging to the given file.
|
||||
|
||||
If the file name is unspecified, a default name is built by appending
|
||||
a 'log-psyco' extension to the main script name.
|
||||
|
||||
Mode is 'a' to append to a possibly existing file or 'w' to overwrite
|
||||
an existing file. Note that the log file may grow quickly in 'a' mode."""
|
||||
import profiler, logger
|
||||
if not logfile:
|
||||
import os
|
||||
logfile, dummy = os.path.splitext(sys.argv[0])
|
||||
if os.path.basename(logfile):
|
||||
logfile += '.'
|
||||
logfile += 'log-psyco'
|
||||
if hasattr(_psyco, 'VERBOSE_LEVEL'):
|
||||
print >> sys.stderr, 'psyco: logging to', logfile
|
||||
# logger.current should be a real file object; subtle problems
|
||||
# will show up if its write() and flush() methods are written
|
||||
# in Python, as Psyco will invoke them while compiling.
|
||||
logger.current = open(logfile, mode)
|
||||
logger.print_charges = top
|
||||
profiler.logger = logger
|
||||
logger.writedate('Logging started')
|
||||
cannotcompile(logger.psycowrite)
|
||||
_psyco.statwrite(logger=logger.psycowrite)
|
||||
|
||||
|
||||
def bind(x, rec=None):
|
||||
"""Enable compilation of the given function, method, or class object.
|
||||
|
||||
If C is a class (or anything with a '__dict__' attribute), bind(C) will
|
||||
rebind all functions and methods found in C.__dict__ (which means, for
|
||||
classes, all methods defined in the class but not in its parents).
|
||||
|
||||
The optional second argument specifies the number of recursive
|
||||
compilation levels: all functions called by func are compiled
|
||||
up to the given depth of indirection."""
|
||||
if isinstance(x, types.MethodType):
|
||||
x = x.im_func
|
||||
if isinstance(x, types.FunctionType):
|
||||
if rec is None:
|
||||
x.func_code = _psyco.proxycode(x)
|
||||
else:
|
||||
x.func_code = _psyco.proxycode(x, rec)
|
||||
return
|
||||
if hasattr(x, '__dict__'):
|
||||
funcs = [o for o in x.__dict__.values()
|
||||
if isinstance(o, types.MethodType)
|
||||
or isinstance(o, types.FunctionType)]
|
||||
if not funcs:
|
||||
raise error, ("nothing bindable found in %s object" %
|
||||
type(x).__name__)
|
||||
for o in funcs:
|
||||
bind(o, rec)
|
||||
return
|
||||
raise TypeError, "cannot bind %s objects" % type(x).__name__
|
||||
|
||||
|
||||
def unbind(x):
|
||||
"""Reverse of bind()."""
|
||||
if isinstance(x, types.MethodType):
|
||||
x = x.im_func
|
||||
if isinstance(x, types.FunctionType):
|
||||
try:
|
||||
f = _psyco.unproxycode(x.func_code)
|
||||
except error:
|
||||
pass
|
||||
else:
|
||||
x.func_code = f.func_code
|
||||
return
|
||||
if hasattr(x, '__dict__'):
|
||||
for o in x.__dict__.values():
|
||||
if (isinstance(o, types.MethodType)
|
||||
or isinstance(o, types.FunctionType)):
|
||||
unbind(o)
|
||||
return
|
||||
raise TypeError, "cannot unbind %s objects" % type(x).__name__
|
||||
|
||||
|
||||
def proxy(x, rec=None):
|
||||
"""Return a Psyco-enabled copy of the function.
|
||||
|
||||
The original function is still available for non-compiled calls.
|
||||
The optional second argument specifies the number of recursive
|
||||
compilation levels: all functions called by func are compiled
|
||||
up to the given depth of indirection."""
|
||||
if isinstance(x, types.FunctionType):
|
||||
if rec is None:
|
||||
code = _psyco.proxycode(x)
|
||||
else:
|
||||
code = _psyco.proxycode(x, rec)
|
||||
return newfunction(code, x.func_globals, x.func_name)
|
||||
if isinstance(x, types.MethodType):
|
||||
p = proxy(x.im_func, rec)
|
||||
return newinstancemethod(p, x.im_self, x.im_class)
|
||||
raise TypeError, "cannot proxy %s objects" % type(x).__name__
|
||||
|
||||
|
||||
def unproxy(proxy):
|
||||
"""Return a new copy of the original function of method behind a proxy.
|
||||
The result behaves like the original function in that calling it
|
||||
does not trigger compilation nor execution of any compiled code."""
|
||||
if isinstance(proxy, types.FunctionType):
|
||||
return _psyco.unproxycode(proxy.func_code)
|
||||
if isinstance(proxy, types.MethodType):
|
||||
f = unproxy(proxy.im_func)
|
||||
return newinstancemethod(f, proxy.im_self, proxy.im_class)
|
||||
raise TypeError, "%s objects cannot be proxies" % type(proxy).__name__
|
||||
|
||||
|
||||
def cannotcompile(x):
|
||||
"""Instruct Psyco never to compile the given function, method
|
||||
or code object."""
|
||||
if isinstance(x, types.MethodType):
|
||||
x = x.im_func
|
||||
if isinstance(x, types.FunctionType):
|
||||
x = x.func_code
|
||||
if isinstance(x, types.CodeType):
|
||||
_psyco.cannotcompile(x)
|
||||
else:
|
||||
raise TypeError, "unexpected %s object" % type(x).__name__
|
||||
|
||||
|
||||
def dumpcodebuf():
|
||||
"""Write in file psyco.dump a copy of the emitted machine code,
|
||||
provided Psyco was compiled with a non-zero CODE_DUMP.
|
||||
See py-utils/httpxam.py to examine psyco.dump."""
|
||||
if hasattr(_psyco, 'dumpcodebuf'):
|
||||
_psyco.dumpcodebuf()
|
||||
|
||||
|
||||
###########################################################################
|
||||
# Psyco variables
|
||||
# error * the error raised by Psyco
|
||||
# warning * the warning raised by Psyco
|
||||
# __in_psyco__ * a new built-in variable which is always zero, but which
|
||||
# Psyco special-cases by returning 1 instead. So
|
||||
# __in_psyco__ can be used in a function to know if
|
||||
# that function is being executed by Psyco or not.
|
||||
@@ -1,133 +0,0 @@
|
||||
###########################################################################
|
||||
#
|
||||
# Support code for the 'psyco.compact' type.
|
||||
|
||||
from __future__ import generators
|
||||
|
||||
try:
|
||||
from UserDict import DictMixin
|
||||
except ImportError:
|
||||
|
||||
# backported from Python 2.3 to Python 2.2
|
||||
class DictMixin:
|
||||
# Mixin defining all dictionary methods for classes that already have
|
||||
# a minimum dictionary interface including getitem, setitem, delitem,
|
||||
# and keys. Without knowledge of the subclass constructor, the mixin
|
||||
# does not define __init__() or copy(). In addition to the four base
|
||||
# methods, progressively more efficiency comes with defining
|
||||
# __contains__(), __iter__(), and iteritems().
|
||||
|
||||
# second level definitions support higher levels
|
||||
def __iter__(self):
|
||||
for k in self.keys():
|
||||
yield k
|
||||
def has_key(self, key):
|
||||
try:
|
||||
value = self[key]
|
||||
except KeyError:
|
||||
return False
|
||||
return True
|
||||
def __contains__(self, key):
|
||||
return self.has_key(key)
|
||||
|
||||
# third level takes advantage of second level definitions
|
||||
def iteritems(self):
|
||||
for k in self:
|
||||
yield (k, self[k])
|
||||
def iterkeys(self):
|
||||
return self.__iter__()
|
||||
|
||||
# fourth level uses definitions from lower levels
|
||||
def itervalues(self):
|
||||
for _, v in self.iteritems():
|
||||
yield v
|
||||
def values(self):
|
||||
return [v for _, v in self.iteritems()]
|
||||
def items(self):
|
||||
return list(self.iteritems())
|
||||
def clear(self):
|
||||
for key in self.keys():
|
||||
del self[key]
|
||||
def setdefault(self, key, default):
|
||||
try:
|
||||
return self[key]
|
||||
except KeyError:
|
||||
self[key] = default
|
||||
return default
|
||||
def pop(self, key, *args):
|
||||
if len(args) > 1:
|
||||
raise TypeError, "pop expected at most 2 arguments, got "\
|
||||
+ repr(1 + len(args))
|
||||
try:
|
||||
value = self[key]
|
||||
except KeyError:
|
||||
if args:
|
||||
return args[0]
|
||||
raise
|
||||
del self[key]
|
||||
return value
|
||||
def popitem(self):
|
||||
try:
|
||||
k, v = self.iteritems().next()
|
||||
except StopIteration:
|
||||
raise KeyError, 'container is empty'
|
||||
del self[k]
|
||||
return (k, v)
|
||||
def update(self, other):
|
||||
# Make progressively weaker assumptions about "other"
|
||||
if hasattr(other, 'iteritems'): # iteritems saves memory and lookups
|
||||
for k, v in other.iteritems():
|
||||
self[k] = v
|
||||
elif hasattr(other, '__iter__'): # iter saves memory
|
||||
for k in other:
|
||||
self[k] = other[k]
|
||||
else:
|
||||
for k in other.keys():
|
||||
self[k] = other[k]
|
||||
def get(self, key, default=None):
|
||||
try:
|
||||
return self[key]
|
||||
except KeyError:
|
||||
return default
|
||||
def __repr__(self):
|
||||
return repr(dict(self.iteritems()))
|
||||
def __cmp__(self, other):
|
||||
if other is None:
|
||||
return 1
|
||||
if isinstance(other, DictMixin):
|
||||
other = dict(other.iteritems())
|
||||
return cmp(dict(self.iteritems()), other)
|
||||
def __len__(self):
|
||||
return len(self.keys())
|
||||
|
||||
###########################################################################
|
||||
|
||||
from _psyco import compact
|
||||
|
||||
|
||||
class compactdictproxy(DictMixin):
|
||||
|
||||
def __init__(self, ko):
|
||||
self._ko = ko # compact object of which 'self' is the dict
|
||||
|
||||
def __getitem__(self, key):
|
||||
return compact.__getslot__(self._ko, key)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
compact.__setslot__(self._ko, key, value)
|
||||
|
||||
def __delitem__(self, key):
|
||||
compact.__delslot__(self._ko, key)
|
||||
|
||||
def keys(self):
|
||||
return compact.__members__.__get__(self._ko)
|
||||
|
||||
def clear(self):
|
||||
keys = self.keys()
|
||||
keys.reverse()
|
||||
for key in keys:
|
||||
del self[key]
|
||||
|
||||
def __repr__(self):
|
||||
keys = ', '.join(self.keys())
|
||||
return '<compactdictproxy object {%s}>' % (keys,)
|
||||
@@ -1,96 +0,0 @@
|
||||
###########################################################################
|
||||
#
|
||||
# Psyco logger.
|
||||
# Copyright (C) 2001-2002 Armin Rigo et.al.
|
||||
|
||||
"""Psyco logger.
|
||||
|
||||
See log() in core.py.
|
||||
"""
|
||||
###########################################################################
|
||||
|
||||
|
||||
import _psyco
|
||||
from time import time, localtime, strftime
|
||||
|
||||
|
||||
current = None
|
||||
print_charges = 10
|
||||
dump_delay = 0.2
|
||||
dump_last = 0.0
|
||||
|
||||
def write(s, level):
|
||||
t = time()
|
||||
f = t-int(t)
|
||||
try:
|
||||
current.write("%s.%02d %-*s%s\n" % (
|
||||
strftime("%X", localtime(int(t))),
|
||||
int(f*100.0), 63-level, s,
|
||||
"%"*level))
|
||||
current.flush()
|
||||
except (OSError, IOError):
|
||||
pass
|
||||
|
||||
def psycowrite(s):
|
||||
t = time()
|
||||
f = t-int(t)
|
||||
try:
|
||||
current.write("%s.%02d %-*s%s\n" % (
|
||||
strftime("%X", localtime(int(t))),
|
||||
int(f*100.0), 60, s.strip(),
|
||||
"% %"))
|
||||
current.flush()
|
||||
except (OSError, IOError):
|
||||
pass
|
||||
|
||||
##def writelines(lines, level=0):
|
||||
## if lines:
|
||||
## t = time()
|
||||
## f = t-int(t)
|
||||
## timedesc = strftime("%x %X", localtime(int(t)))
|
||||
## print >> current, "%s.%03d %-*s %s" % (
|
||||
## timedesc, int(f*1000),
|
||||
## 50-level, lines[0],
|
||||
## "+"*level)
|
||||
## timedesc = " " * (len(timedesc)+5)
|
||||
## for line in lines[1:]:
|
||||
## print >> current, timedesc, line
|
||||
|
||||
def writememory():
|
||||
write("memory usage: %d+ kb" % _psyco.memory(), 1)
|
||||
|
||||
def dumpcharges():
|
||||
global dump_last
|
||||
if print_charges:
|
||||
t = time()
|
||||
if not (dump_last <= t < dump_last+dump_delay):
|
||||
if t <= dump_last+1.5*dump_delay:
|
||||
dump_last += dump_delay
|
||||
else:
|
||||
dump_last = t
|
||||
#write("%s: charges:" % who, 0)
|
||||
lst = _psyco.stattop(print_charges)
|
||||
if lst:
|
||||
f = t-int(t)
|
||||
lines = ["%s.%02d ______\n" % (
|
||||
strftime("%X", localtime(int(t))),
|
||||
int(f*100.0))]
|
||||
i = 1
|
||||
for co, charge in lst:
|
||||
detail = co.co_filename
|
||||
if len(detail) > 19:
|
||||
detail = '...' + detail[-17:]
|
||||
lines.append(" #%-3d |%4.1f %%| %-26s%20s:%d\n" %
|
||||
(i, charge*100.0, co.co_name, detail,
|
||||
co.co_firstlineno))
|
||||
i += 1
|
||||
current.writelines(lines)
|
||||
current.flush()
|
||||
|
||||
def writefinalstats():
|
||||
dumpcharges()
|
||||
writememory()
|
||||
writedate("program exit")
|
||||
|
||||
def writedate(msg):
|
||||
write('%s, %s' % (msg, strftime("%x")), 20)
|
||||
@@ -1,379 +0,0 @@
|
||||
###########################################################################
|
||||
#
|
||||
# Psyco profiler (Python part).
|
||||
# Copyright (C) 2001-2002 Armin Rigo et.al.
|
||||
|
||||
"""Psyco profiler (Python part).
|
||||
|
||||
The implementation of the non-time-critical parts of the profiler.
|
||||
See profile() and full() in core.py for the easy interface.
|
||||
"""
|
||||
###########################################################################
|
||||
|
||||
import _psyco
|
||||
from support import *
|
||||
import math, time, types, atexit
|
||||
now = time.time
|
||||
try:
|
||||
import thread
|
||||
except ImportError:
|
||||
import dummy_thread as thread
|
||||
|
||||
|
||||
# current profiler instance
|
||||
current = None
|
||||
|
||||
# enabled profilers, in order of priority
|
||||
profilers = []
|
||||
|
||||
# logger module (when enabled by core.log())
|
||||
logger = None
|
||||
|
||||
# a lock for a thread-safe go()
|
||||
go_lock = thread.allocate_lock()
|
||||
|
||||
def go(stop=0):
|
||||
# run the highest-priority profiler in 'profilers'
|
||||
global current
|
||||
go_lock.acquire()
|
||||
try:
|
||||
prev = current
|
||||
if stop:
|
||||
del profilers[:]
|
||||
if prev:
|
||||
if profilers and profilers[0] is prev:
|
||||
return # best profiler already running
|
||||
prev.stop()
|
||||
current = None
|
||||
for p in profilers[:]:
|
||||
if p.start():
|
||||
current = p
|
||||
if logger: # and p is not prev:
|
||||
logger.write("%s: starting" % p.__class__.__name__, 5)
|
||||
return
|
||||
finally:
|
||||
go_lock.release()
|
||||
# no profiler is running now
|
||||
if stop:
|
||||
if logger:
|
||||
logger.writefinalstats()
|
||||
else:
|
||||
tag2bind()
|
||||
|
||||
atexit.register(go, 1)
|
||||
|
||||
|
||||
def buildfncache(globals, cache):
|
||||
if hasattr(types.IntType, '__dict__'):
|
||||
clstypes = (types.ClassType, types.TypeType)
|
||||
else:
|
||||
clstypes = types.ClassType
|
||||
for x in globals.values():
|
||||
if isinstance(x, types.MethodType):
|
||||
x = x.im_func
|
||||
if isinstance(x, types.FunctionType):
|
||||
cache[x.func_code] = x, ''
|
||||
elif isinstance(x, clstypes):
|
||||
for y in x.__dict__.values():
|
||||
if isinstance(y, types.MethodType):
|
||||
y = y.im_func
|
||||
if isinstance(y, types.FunctionType):
|
||||
cache[y.func_code] = y, x.__name__
|
||||
|
||||
# code-to-function mapping (cache)
|
||||
function_cache = {}
|
||||
|
||||
def trytobind(co, globals, log=1):
|
||||
try:
|
||||
f, clsname = function_cache[co]
|
||||
except KeyError:
|
||||
buildfncache(globals, function_cache)
|
||||
try:
|
||||
f, clsname = function_cache[co]
|
||||
except KeyError:
|
||||
if logger:
|
||||
logger.write('warning: cannot find function %s in %s' %
|
||||
(co.co_name, globals.get('__name__', '?')), 3)
|
||||
return # give up
|
||||
if logger and log:
|
||||
modulename = globals.get('__name__', '?')
|
||||
if clsname:
|
||||
modulename += '.' + clsname
|
||||
logger.write('bind function: %s.%s' % (modulename, co.co_name), 1)
|
||||
f.func_code = _psyco.proxycode(f)
|
||||
|
||||
|
||||
# the list of code objects that have been tagged
|
||||
tagged_codes = []
|
||||
|
||||
def tag(co, globals):
|
||||
if logger:
|
||||
try:
|
||||
f, clsname = function_cache[co]
|
||||
except KeyError:
|
||||
buildfncache(globals, function_cache)
|
||||
try:
|
||||
f, clsname = function_cache[co]
|
||||
except KeyError:
|
||||
clsname = '' # give up
|
||||
modulename = globals.get('__name__', '?')
|
||||
if clsname:
|
||||
modulename += '.' + clsname
|
||||
logger.write('tag function: %s.%s' % (modulename, co.co_name), 1)
|
||||
tagged_codes.append((co, globals))
|
||||
_psyco.turbo_frame(co)
|
||||
_psyco.turbo_code(co)
|
||||
|
||||
def tag2bind():
|
||||
if tagged_codes:
|
||||
if logger:
|
||||
logger.write('profiling stopped, binding %d functions' %
|
||||
len(tagged_codes), 2)
|
||||
for co, globals in tagged_codes:
|
||||
trytobind(co, globals, 0)
|
||||
function_cache.clear()
|
||||
del tagged_codes[:]
|
||||
|
||||
|
||||
class Profiler:
|
||||
MemoryTimerResolution = 0.103
|
||||
|
||||
def run(self, memory, time, memorymax, timemax):
|
||||
self.memory = memory
|
||||
self.memorymax = memorymax
|
||||
self.time = time
|
||||
if timemax is None:
|
||||
self.endtime = None
|
||||
else:
|
||||
self.endtime = now() + timemax
|
||||
self.alarms = []
|
||||
profilers.append(self)
|
||||
go()
|
||||
|
||||
def start(self):
|
||||
curmem = _psyco.memory()
|
||||
memlimits = []
|
||||
if self.memorymax is not None:
|
||||
if curmem >= self.memorymax:
|
||||
if logger:
|
||||
logger.writememory()
|
||||
return self.limitreached('memorymax')
|
||||
memlimits.append(self.memorymax)
|
||||
if self.memory is not None:
|
||||
if self.memory <= 0:
|
||||
if logger:
|
||||
logger.writememory()
|
||||
return self.limitreached('memory')
|
||||
memlimits.append(curmem + self.memory)
|
||||
self.memory_at_start = curmem
|
||||
|
||||
curtime = now()
|
||||
timelimits = []
|
||||
if self.endtime is not None:
|
||||
if curtime >= self.endtime:
|
||||
return self.limitreached('timemax')
|
||||
timelimits.append(self.endtime - curtime)
|
||||
if self.time is not None:
|
||||
if self.time <= 0.0:
|
||||
return self.limitreached('time')
|
||||
timelimits.append(self.time)
|
||||
self.time_at_start = curtime
|
||||
|
||||
try:
|
||||
self.do_start()
|
||||
except error, e:
|
||||
if logger:
|
||||
logger.write('%s: disabled by psyco.error:' % (
|
||||
self.__class__.__name__), 4)
|
||||
logger.write(' %s' % str(e), 3)
|
||||
return 0
|
||||
|
||||
if memlimits:
|
||||
self.memlimits_args = (time.sleep, (self.MemoryTimerResolution,),
|
||||
self.check_memory, (min(memlimits),))
|
||||
self.alarms.append(_psyco.alarm(*self.memlimits_args))
|
||||
if timelimits:
|
||||
self.alarms.append(_psyco.alarm(time.sleep, (min(timelimits),),
|
||||
self.time_out))
|
||||
return 1
|
||||
|
||||
def stop(self):
|
||||
for alarm in self.alarms:
|
||||
alarm.stop(0)
|
||||
for alarm in self.alarms:
|
||||
alarm.stop(1) # wait for parallel threads to stop
|
||||
del self.alarms[:]
|
||||
if self.time is not None:
|
||||
self.time -= now() - self.time_at_start
|
||||
if self.memory is not None:
|
||||
self.memory -= _psyco.memory() - self.memory_at_start
|
||||
|
||||
try:
|
||||
self.do_stop()
|
||||
except error:
|
||||
return 0
|
||||
return 1
|
||||
|
||||
def check_memory(self, limit):
|
||||
if _psyco.memory() < limit:
|
||||
return self.memlimits_args
|
||||
go()
|
||||
|
||||
def time_out(self):
|
||||
self.time = 0.0
|
||||
go()
|
||||
|
||||
def limitreached(self, limitname):
|
||||
try:
|
||||
profilers.remove(self)
|
||||
except ValueError:
|
||||
pass
|
||||
if logger:
|
||||
logger.write('%s: disabled (%s limit reached)' % (
|
||||
self.__class__.__name__, limitname), 4)
|
||||
return 0
|
||||
|
||||
|
||||
class FullCompiler(Profiler):
|
||||
|
||||
def do_start(self):
|
||||
_psyco.profiling('f')
|
||||
|
||||
def do_stop(self):
|
||||
_psyco.profiling('.')
|
||||
|
||||
|
||||
class RunOnly(Profiler):
|
||||
|
||||
def do_start(self):
|
||||
_psyco.profiling('n')
|
||||
|
||||
def do_stop(self):
|
||||
_psyco.profiling('.')
|
||||
|
||||
|
||||
class ChargeProfiler(Profiler):
|
||||
|
||||
def __init__(self, watermark, parentframe):
|
||||
self.watermark = watermark
|
||||
self.parent2 = parentframe * 2.0
|
||||
self.lock = thread.allocate_lock()
|
||||
|
||||
def init_charges(self):
|
||||
_psyco.statwrite(watermark = self.watermark,
|
||||
parent2 = self.parent2)
|
||||
|
||||
def do_stop(self):
|
||||
_psyco.profiling('.')
|
||||
_psyco.statwrite(callback = None)
|
||||
|
||||
|
||||
class ActiveProfiler(ChargeProfiler):
|
||||
|
||||
def active_start(self):
|
||||
_psyco.profiling('p')
|
||||
|
||||
def do_start(self):
|
||||
self.init_charges()
|
||||
self.active_start()
|
||||
_psyco.statwrite(callback = self.charge_callback)
|
||||
|
||||
def charge_callback(self, frame, charge):
|
||||
tag(frame.f_code, frame.f_globals)
|
||||
|
||||
|
||||
class PassiveProfiler(ChargeProfiler):
|
||||
|
||||
initial_charge_unit = _psyco.statread('unit')
|
||||
reset_stats_after = 120 # half-lives (maximum 200!)
|
||||
reset_limit = initial_charge_unit * (2.0 ** reset_stats_after)
|
||||
|
||||
def __init__(self, watermark, halflife, pollfreq, parentframe):
|
||||
ChargeProfiler.__init__(self, watermark, parentframe)
|
||||
self.pollfreq = pollfreq
|
||||
# self.progress is slightly more than 1.0, and computed so that
|
||||
# do_profile() will double the change_unit every 'halflife' seconds.
|
||||
self.progress = 2.0 ** (1.0 / (halflife * pollfreq))
|
||||
|
||||
def reset(self):
|
||||
_psyco.statwrite(unit = self.initial_charge_unit, callback = None)
|
||||
_psyco.statreset()
|
||||
if logger:
|
||||
logger.write("%s: resetting stats" % self.__class__.__name__, 1)
|
||||
|
||||
def passive_start(self):
|
||||
self.passivealarm_args = (time.sleep, (1.0 / self.pollfreq,),
|
||||
self.do_profile)
|
||||
self.alarms.append(_psyco.alarm(*self.passivealarm_args))
|
||||
|
||||
def do_start(self):
|
||||
tag2bind()
|
||||
self.init_charges()
|
||||
self.passive_start()
|
||||
|
||||
def do_profile(self):
|
||||
_psyco.statcollect()
|
||||
if logger:
|
||||
logger.dumpcharges()
|
||||
nunit = _psyco.statread('unit') * self.progress
|
||||
if nunit > self.reset_limit:
|
||||
self.reset()
|
||||
else:
|
||||
_psyco.statwrite(unit = nunit, callback = self.charge_callback)
|
||||
return self.passivealarm_args
|
||||
|
||||
def charge_callback(self, frame, charge):
|
||||
trytobind(frame.f_code, frame.f_globals)
|
||||
|
||||
|
||||
class ActivePassiveProfiler(PassiveProfiler, ActiveProfiler):
|
||||
|
||||
def do_start(self):
|
||||
self.init_charges()
|
||||
self.active_start()
|
||||
self.passive_start()
|
||||
|
||||
def charge_callback(self, frame, charge):
|
||||
tag(frame.f_code, frame.f_globals)
|
||||
|
||||
|
||||
|
||||
#
|
||||
# we register our own version of sys.settrace(), sys.setprofile()
|
||||
# and thread.start_new_thread().
|
||||
#
|
||||
|
||||
def psyco_settrace(*args, **kw):
|
||||
"This is the Psyco-aware version of sys.settrace()."
|
||||
result = original_settrace(*args, **kw)
|
||||
go()
|
||||
return result
|
||||
|
||||
def psyco_setprofile(*args, **kw):
|
||||
"This is the Psyco-aware version of sys.setprofile()."
|
||||
result = original_setprofile(*args, **kw)
|
||||
go()
|
||||
return result
|
||||
|
||||
def psyco_thread_stub(callable, args, kw):
|
||||
_psyco.statcollect()
|
||||
if kw is None:
|
||||
return callable(*args)
|
||||
else:
|
||||
return callable(*args, **kw)
|
||||
|
||||
def psyco_start_new_thread(callable, args, kw=None):
|
||||
"This is the Psyco-aware version of thread.start_new_thread()."
|
||||
return original_start_new_thread(psyco_thread_stub, (callable, args, kw))
|
||||
|
||||
original_settrace = sys.settrace
|
||||
original_setprofile = sys.setprofile
|
||||
original_start_new_thread = thread.start_new_thread
|
||||
sys.settrace = psyco_settrace
|
||||
sys.setprofile = psyco_setprofile
|
||||
thread.start_new_thread = psyco_start_new_thread
|
||||
# hack to patch threading._start_new_thread if the module is
|
||||
# already loaded
|
||||
if ('threading' in sys.modules and
|
||||
hasattr(sys.modules['threading'], '_start_new_thread')):
|
||||
sys.modules['threading']._start_new_thread = psyco_start_new_thread
|
||||
@@ -1,191 +0,0 @@
|
||||
###########################################################################
|
||||
#
|
||||
# Psyco general support module.
|
||||
# Copyright (C) 2001-2002 Armin Rigo et.al.
|
||||
|
||||
"""Psyco general support module.
|
||||
|
||||
For internal use.
|
||||
"""
|
||||
###########################################################################
|
||||
|
||||
import sys, _psyco, __builtin__
|
||||
|
||||
error = _psyco.error
|
||||
class warning(Warning):
|
||||
pass
|
||||
|
||||
_psyco.NoLocalsWarning = warning
|
||||
|
||||
def warn(msg):
|
||||
from warnings import warn
|
||||
warn(msg, warning, stacklevel=2)
|
||||
|
||||
#
|
||||
# Version checks
|
||||
#
|
||||
__version__ = 0x010600f0
|
||||
if _psyco.PSYVER != __version__:
|
||||
raise error, "version mismatch between Psyco parts, reinstall it"
|
||||
|
||||
version_info = (__version__ >> 24,
|
||||
(__version__ >> 16) & 0xff,
|
||||
(__version__ >> 8) & 0xff,
|
||||
{0xa0: 'alpha',
|
||||
0xb0: 'beta',
|
||||
0xc0: 'candidate',
|
||||
0xf0: 'final'}[__version__ & 0xf0],
|
||||
__version__ & 0xf)
|
||||
|
||||
|
||||
VERSION_LIMITS = [0x02020200, # 2.2.2
|
||||
0x02030000, # 2.3
|
||||
0x02040000] # 2.4
|
||||
|
||||
if ([v for v in VERSION_LIMITS if v <= sys.hexversion] !=
|
||||
[v for v in VERSION_LIMITS if v <= _psyco.PYVER ]):
|
||||
if sys.hexversion < VERSION_LIMITS[0]:
|
||||
warn("Psyco requires Python version 2.2.2 or later")
|
||||
else:
|
||||
warn("Psyco version does not match Python version. "
|
||||
"Psyco must be updated or recompiled")
|
||||
|
||||
|
||||
if hasattr(_psyco, 'ALL_CHECKS') and hasattr(_psyco, 'VERBOSE_LEVEL'):
|
||||
print >> sys.stderr, ('psyco: running in debugging mode on %s' %
|
||||
_psyco.PROCESSOR)
|
||||
|
||||
|
||||
###########################################################################
|
||||
# sys._getframe() gives strange results on a mixed Psyco- and Python-style
|
||||
# stack frame. Psyco provides a replacement that partially emulates Python
|
||||
# frames from Psyco frames. The new sys._getframe() may return objects of
|
||||
# a custom "Psyco frame" type, which is a subtype of the normal frame type.
|
||||
#
|
||||
# The same problems require some other built-in functions to be replaced
|
||||
# as well. Note that the local variables are not available in any
|
||||
# dictionary with Psyco.
|
||||
|
||||
|
||||
class Frame:
|
||||
pass
|
||||
|
||||
|
||||
class PythonFrame(Frame):
|
||||
|
||||
def __init__(self, frame):
|
||||
self.__dict__.update({
|
||||
'_frame': frame,
|
||||
})
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if attr == 'f_back':
|
||||
try:
|
||||
result = embedframe(_psyco.getframe(self._frame))
|
||||
except ValueError:
|
||||
result = None
|
||||
except error:
|
||||
warn("f_back is skipping dead Psyco frames")
|
||||
result = self._frame.f_back
|
||||
self.__dict__['f_back'] = result
|
||||
return result
|
||||
else:
|
||||
return getattr(self._frame, attr)
|
||||
|
||||
def __setattr__(self, attr, value):
|
||||
setattr(self._frame, attr, value)
|
||||
|
||||
def __delattr__(self, attr):
|
||||
delattr(self._frame, attr)
|
||||
|
||||
|
||||
class PsycoFrame(Frame):
|
||||
|
||||
def __init__(self, tag):
|
||||
self.__dict__.update({
|
||||
'_tag' : tag,
|
||||
'f_code' : tag[0],
|
||||
'f_globals': tag[1],
|
||||
})
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if attr == 'f_back':
|
||||
try:
|
||||
result = embedframe(_psyco.getframe(self._tag))
|
||||
except ValueError:
|
||||
result = None
|
||||
elif attr == 'f_lineno':
|
||||
result = self.f_code.co_firstlineno # better than nothing
|
||||
elif attr == 'f_builtins':
|
||||
result = self.f_globals['__builtins__']
|
||||
elif attr == 'f_restricted':
|
||||
result = self.f_builtins is not __builtins__
|
||||
elif attr == 'f_locals':
|
||||
raise AttributeError, ("local variables of functions run by Psyco "
|
||||
"cannot be accessed in any way, sorry")
|
||||
else:
|
||||
raise AttributeError, ("emulated Psyco frames have "
|
||||
"no '%s' attribute" % attr)
|
||||
self.__dict__[attr] = result
|
||||
return result
|
||||
|
||||
def __setattr__(self, attr, value):
|
||||
raise AttributeError, "Psyco frame objects are read-only"
|
||||
|
||||
def __delattr__(self, attr):
|
||||
if attr == 'f_trace':
|
||||
# for bdb which relies on CPython frames exhibiting a slightly
|
||||
# buggy behavior: you can 'del f.f_trace' as often as you like
|
||||
# even without having set it previously.
|
||||
return
|
||||
raise AttributeError, "Psyco frame objects are read-only"
|
||||
|
||||
|
||||
def embedframe(result):
|
||||
if type(result) is type(()):
|
||||
return PsycoFrame(result)
|
||||
else:
|
||||
return PythonFrame(result)
|
||||
|
||||
def _getframe(depth=0):
|
||||
"""Return a frame object from the call stack. This is a replacement for
|
||||
sys._getframe() which is aware of Psyco frames.
|
||||
|
||||
The returned objects are instances of either PythonFrame or PsycoFrame
|
||||
instead of being real Python-level frame object, so that they can emulate
|
||||
the common attributes of frame objects.
|
||||
|
||||
The original sys._getframe() ignoring Psyco frames altogether is stored in
|
||||
psyco._getrealframe(). See also psyco._getemulframe()."""
|
||||
# 'depth+1' to account for this _getframe() Python function
|
||||
return embedframe(_psyco.getframe(depth+1))
|
||||
|
||||
def _getemulframe(depth=0):
|
||||
"""As _getframe(), but the returned objects are real Python frame objects
|
||||
emulating Psyco frames. Some of their attributes can be wrong or missing,
|
||||
however."""
|
||||
# 'depth+1' to account for this _getemulframe() Python function
|
||||
return _psyco.getframe(depth+1, 1)
|
||||
|
||||
def patch(name, module=__builtin__):
|
||||
f = getattr(_psyco, name)
|
||||
org = getattr(module, name)
|
||||
if org is not f:
|
||||
setattr(module, name, f)
|
||||
setattr(_psyco, 'original_' + name, org)
|
||||
|
||||
_getrealframe = sys._getframe
|
||||
sys._getframe = _getframe
|
||||
patch('globals')
|
||||
patch('eval')
|
||||
patch('execfile')
|
||||
patch('locals')
|
||||
patch('vars')
|
||||
patch('dir')
|
||||
patch('input')
|
||||
_psyco.original_raw_input = raw_input
|
||||
__builtin__.__in_psyco__ = 0==1 # False
|
||||
|
||||
if hasattr(_psyco, 'compact'):
|
||||
import kdictproxy
|
||||
_psyco.compactdictproxy = kdictproxy.compactdictproxy
|
||||
@@ -1,54 +0,0 @@
|
||||
###########################################################################
|
||||
#
|
||||
# Psyco top-level file of the Psyco package.
|
||||
# Copyright (C) 2001-2002 Armin Rigo et.al.
|
||||
|
||||
"""Psyco -- the Python Specializing Compiler.
|
||||
|
||||
Typical usage: add the following lines to your application's main module,
|
||||
preferably after the other imports:
|
||||
|
||||
try:
|
||||
import psyco
|
||||
psyco.full()
|
||||
except ImportError:
|
||||
print 'Psyco not installed, the program will just run slower'
|
||||
"""
|
||||
###########################################################################
|
||||
|
||||
|
||||
#
|
||||
# This module is present to make 'psyco' a package and to
|
||||
# publish the main functions and variables.
|
||||
#
|
||||
# More documentation can be found in core.py.
|
||||
#
|
||||
|
||||
|
||||
# Try to import the dynamic-loading _psyco and report errors
|
||||
try:
|
||||
import _psyco
|
||||
except ImportError, e:
|
||||
extramsg = ''
|
||||
import sys, imp
|
||||
try:
|
||||
file, filename, (suffix, mode, type) = imp.find_module('_psyco', __path__)
|
||||
except ImportError:
|
||||
ext = [suffix for suffix, mode, type in imp.get_suffixes()
|
||||
if type == imp.C_EXTENSION]
|
||||
if ext:
|
||||
extramsg = (" (cannot locate the compiled extension '_psyco%s' "
|
||||
"in the package path '%s')" % (ext[0], '; '.join(__path__)))
|
||||
else:
|
||||
extramsg = (" (check that the compiled extension '%s' is for "
|
||||
"the correct Python version; this is Python %s)" %
|
||||
(filename, sys.version.split()[0]))
|
||||
raise ImportError, str(e) + extramsg
|
||||
|
||||
# Publish important data by importing them in the package
|
||||
from support import __version__, error, warning, _getrealframe, _getemulframe
|
||||
from support import version_info, __version__ as hexversion
|
||||
from core import full, profile, background, runonly, stop, cannotcompile
|
||||
from core import log, bind, unbind, proxy, unproxy, dumpcodebuf
|
||||
from _psyco import setfilter
|
||||
from _psyco import compact, compacttype
|
||||
@@ -1,42 +0,0 @@
|
||||
###########################################################################
|
||||
#
|
||||
# Psyco class support module.
|
||||
# Copyright (C) 2001-2002 Armin Rigo et.al.
|
||||
|
||||
"""Psyco class support module.
|
||||
|
||||
'psyco.classes.psyobj' is an alternate Psyco-optimized root for classes.
|
||||
Any class inheriting from it or using the metaclass '__metaclass__' might
|
||||
get optimized specifically for Psyco. It is equivalent to call
|
||||
psyco.bind() on the class object after its creation.
|
||||
|
||||
Importing everything from psyco.classes in a module will import the
|
||||
'__metaclass__' name, so all classes defined after a
|
||||
|
||||
from psyco.classes import *
|
||||
|
||||
will automatically use the Psyco-optimized metaclass.
|
||||
"""
|
||||
###########################################################################
|
||||
|
||||
__all__ = ['psyobj', 'psymetaclass', '__metaclass__']
|
||||
|
||||
|
||||
from _psyco import compacttype
|
||||
import core
|
||||
from types import FunctionType
|
||||
|
||||
class psymetaclass(compacttype):
|
||||
"Psyco-optimized meta-class. Turns all methods into Psyco proxies."
|
||||
|
||||
def __new__(cls, name, bases, dict):
|
||||
bindlist = dict.get('__psyco__bind__')
|
||||
if bindlist is None:
|
||||
bindlist = [key for key, value in dict.items()
|
||||
if isinstance(value, FunctionType)]
|
||||
for attr in bindlist:
|
||||
dict[attr] = core.proxy(dict[attr])
|
||||
return super(psymetaclass, cls).__new__(cls, name, bases, dict)
|
||||
|
||||
psyobj = psymetaclass("psyobj", (), {})
|
||||
__metaclass__ = psymetaclass
|
||||
@@ -1,231 +0,0 @@
|
||||
###########################################################################
|
||||
#
|
||||
# Psyco main functions.
|
||||
# Copyright (C) 2001-2002 Armin Rigo et.al.
|
||||
|
||||
"""Psyco main functions.
|
||||
|
||||
Here are the routines that you can use from your applications.
|
||||
These are mostly interfaces to the C core, but they depend on
|
||||
the Python version.
|
||||
|
||||
You can use these functions from the 'psyco' module instead of
|
||||
'psyco.core', e.g.
|
||||
|
||||
import psyco
|
||||
psyco.log('/tmp/psyco.log')
|
||||
psyco.profile()
|
||||
"""
|
||||
###########################################################################
|
||||
|
||||
import _psyco
|
||||
import types
|
||||
from support import *
|
||||
|
||||
newfunction = types.FunctionType
|
||||
newinstancemethod = types.MethodType
|
||||
|
||||
|
||||
# Default charge profiler values
|
||||
default_watermark = 0.09 # between 0.0 (0%) and 1.0 (100%)
|
||||
default_halflife = 0.5 # seconds
|
||||
default_pollfreq_profile = 20 # Hz
|
||||
default_pollfreq_background = 100 # Hz -- a maximum for sleep's resolution
|
||||
default_parentframe = 0.25 # should not be more than 0.5 (50%)
|
||||
|
||||
|
||||
def full(memory=None, time=None, memorymax=None, timemax=None):
|
||||
"""Compile as much as possible.
|
||||
|
||||
Typical use is for small scripts performing intensive computations
|
||||
or string handling."""
|
||||
import profiler
|
||||
p = profiler.FullCompiler()
|
||||
p.run(memory, time, memorymax, timemax)
|
||||
|
||||
|
||||
def profile(watermark = default_watermark,
|
||||
halflife = default_halflife,
|
||||
pollfreq = default_pollfreq_profile,
|
||||
parentframe = default_parentframe,
|
||||
memory=None, time=None, memorymax=None, timemax=None):
|
||||
"""Turn on profiling.
|
||||
|
||||
The 'watermark' parameter controls how easily running functions will
|
||||
be compiled. The smaller the value, the more functions are compiled."""
|
||||
import profiler
|
||||
p = profiler.ActivePassiveProfiler(watermark, halflife,
|
||||
pollfreq, parentframe)
|
||||
p.run(memory, time, memorymax, timemax)
|
||||
|
||||
|
||||
def background(watermark = default_watermark,
|
||||
halflife = default_halflife,
|
||||
pollfreq = default_pollfreq_background,
|
||||
parentframe = default_parentframe,
|
||||
memory=None, time=None, memorymax=None, timemax=None):
|
||||
"""Turn on passive profiling.
|
||||
|
||||
This is a very lightweight mode in which only intensively computing
|
||||
functions can be detected. The smaller the 'watermark', the more functions
|
||||
are compiled."""
|
||||
import profiler
|
||||
p = profiler.PassiveProfiler(watermark, halflife, pollfreq, parentframe)
|
||||
p.run(memory, time, memorymax, timemax)
|
||||
|
||||
|
||||
def runonly(memory=None, time=None, memorymax=None, timemax=None):
|
||||
"""Nonprofiler.
|
||||
|
||||
XXX check if this is useful and document."""
|
||||
import profiler
|
||||
p = profiler.RunOnly()
|
||||
p.run(memory, time, memorymax, timemax)
|
||||
|
||||
|
||||
def stop():
|
||||
"""Turn off all automatic compilation. bind() calls remain in effect."""
|
||||
import profiler
|
||||
profiler.go([])
|
||||
|
||||
|
||||
def log(logfile='', mode='w', top=10):
|
||||
"""Enable logging to the given file.
|
||||
|
||||
If the file name is unspecified, a default name is built by appending
|
||||
a 'log-psyco' extension to the main script name.
|
||||
|
||||
Mode is 'a' to append to a possibly existing file or 'w' to overwrite
|
||||
an existing file. Note that the log file may grow quickly in 'a' mode."""
|
||||
import profiler, logger
|
||||
if not logfile:
|
||||
import os
|
||||
logfile, dummy = os.path.splitext(sys.argv[0])
|
||||
if os.path.basename(logfile):
|
||||
logfile += '.'
|
||||
logfile += 'log-psyco'
|
||||
if hasattr(_psyco, 'VERBOSE_LEVEL'):
|
||||
print >> sys.stderr, 'psyco: logging to', logfile
|
||||
# logger.current should be a real file object; subtle problems
|
||||
# will show up if its write() and flush() methods are written
|
||||
# in Python, as Psyco will invoke them while compiling.
|
||||
logger.current = open(logfile, mode)
|
||||
logger.print_charges = top
|
||||
profiler.logger = logger
|
||||
logger.writedate('Logging started')
|
||||
cannotcompile(logger.psycowrite)
|
||||
_psyco.statwrite(logger=logger.psycowrite)
|
||||
|
||||
|
||||
def bind(x, rec=None):
|
||||
"""Enable compilation of the given function, method, or class object.
|
||||
|
||||
If C is a class (or anything with a '__dict__' attribute), bind(C) will
|
||||
rebind all functions and methods found in C.__dict__ (which means, for
|
||||
classes, all methods defined in the class but not in its parents).
|
||||
|
||||
The optional second argument specifies the number of recursive
|
||||
compilation levels: all functions called by func are compiled
|
||||
up to the given depth of indirection."""
|
||||
if isinstance(x, types.MethodType):
|
||||
x = x.im_func
|
||||
if isinstance(x, types.FunctionType):
|
||||
if rec is None:
|
||||
x.func_code = _psyco.proxycode(x)
|
||||
else:
|
||||
x.func_code = _psyco.proxycode(x, rec)
|
||||
return
|
||||
if hasattr(x, '__dict__'):
|
||||
funcs = [o for o in x.__dict__.values()
|
||||
if isinstance(o, types.MethodType)
|
||||
or isinstance(o, types.FunctionType)]
|
||||
if not funcs:
|
||||
raise error, ("nothing bindable found in %s object" %
|
||||
type(x).__name__)
|
||||
for o in funcs:
|
||||
bind(o, rec)
|
||||
return
|
||||
raise TypeError, "cannot bind %s objects" % type(x).__name__
|
||||
|
||||
|
||||
def unbind(x):
|
||||
"""Reverse of bind()."""
|
||||
if isinstance(x, types.MethodType):
|
||||
x = x.im_func
|
||||
if isinstance(x, types.FunctionType):
|
||||
try:
|
||||
f = _psyco.unproxycode(x.func_code)
|
||||
except error:
|
||||
pass
|
||||
else:
|
||||
x.func_code = f.func_code
|
||||
return
|
||||
if hasattr(x, '__dict__'):
|
||||
for o in x.__dict__.values():
|
||||
if (isinstance(o, types.MethodType)
|
||||
or isinstance(o, types.FunctionType)):
|
||||
unbind(o)
|
||||
return
|
||||
raise TypeError, "cannot unbind %s objects" % type(x).__name__
|
||||
|
||||
|
||||
def proxy(x, rec=None):
|
||||
"""Return a Psyco-enabled copy of the function.
|
||||
|
||||
The original function is still available for non-compiled calls.
|
||||
The optional second argument specifies the number of recursive
|
||||
compilation levels: all functions called by func are compiled
|
||||
up to the given depth of indirection."""
|
||||
if isinstance(x, types.FunctionType):
|
||||
if rec is None:
|
||||
code = _psyco.proxycode(x)
|
||||
else:
|
||||
code = _psyco.proxycode(x, rec)
|
||||
return newfunction(code, x.func_globals, x.func_name)
|
||||
if isinstance(x, types.MethodType):
|
||||
p = proxy(x.im_func, rec)
|
||||
return newinstancemethod(p, x.im_self, x.im_class)
|
||||
raise TypeError, "cannot proxy %s objects" % type(x).__name__
|
||||
|
||||
|
||||
def unproxy(proxy):
|
||||
"""Return a new copy of the original function of method behind a proxy.
|
||||
The result behaves like the original function in that calling it
|
||||
does not trigger compilation nor execution of any compiled code."""
|
||||
if isinstance(proxy, types.FunctionType):
|
||||
return _psyco.unproxycode(proxy.func_code)
|
||||
if isinstance(proxy, types.MethodType):
|
||||
f = unproxy(proxy.im_func)
|
||||
return newinstancemethod(f, proxy.im_self, proxy.im_class)
|
||||
raise TypeError, "%s objects cannot be proxies" % type(proxy).__name__
|
||||
|
||||
|
||||
def cannotcompile(x):
|
||||
"""Instruct Psyco never to compile the given function, method
|
||||
or code object."""
|
||||
if isinstance(x, types.MethodType):
|
||||
x = x.im_func
|
||||
if isinstance(x, types.FunctionType):
|
||||
x = x.func_code
|
||||
if isinstance(x, types.CodeType):
|
||||
_psyco.cannotcompile(x)
|
||||
else:
|
||||
raise TypeError, "unexpected %s object" % type(x).__name__
|
||||
|
||||
|
||||
def dumpcodebuf():
|
||||
"""Write in file psyco.dump a copy of the emitted machine code,
|
||||
provided Psyco was compiled with a non-zero CODE_DUMP.
|
||||
See py-utils/httpxam.py to examine psyco.dump."""
|
||||
if hasattr(_psyco, 'dumpcodebuf'):
|
||||
_psyco.dumpcodebuf()
|
||||
|
||||
|
||||
###########################################################################
|
||||
# Psyco variables
|
||||
# error * the error raised by Psyco
|
||||
# warning * the warning raised by Psyco
|
||||
# __in_psyco__ * a new built-in variable which is always zero, but which
|
||||
# Psyco special-cases by returning 1 instead. So
|
||||
# __in_psyco__ can be used in a function to know if
|
||||
# that function is being executed by Psyco or not.
|
||||
@@ -1,133 +0,0 @@
|
||||
###########################################################################
|
||||
#
|
||||
# Support code for the 'psyco.compact' type.
|
||||
|
||||
from __future__ import generators
|
||||
|
||||
try:
|
||||
from UserDict import DictMixin
|
||||
except ImportError:
|
||||
|
||||
# backported from Python 2.3 to Python 2.2
|
||||
class DictMixin:
|
||||
# Mixin defining all dictionary methods for classes that already have
|
||||
# a minimum dictionary interface including getitem, setitem, delitem,
|
||||
# and keys. Without knowledge of the subclass constructor, the mixin
|
||||
# does not define __init__() or copy(). In addition to the four base
|
||||
# methods, progressively more efficiency comes with defining
|
||||
# __contains__(), __iter__(), and iteritems().
|
||||
|
||||
# second level definitions support higher levels
|
||||
def __iter__(self):
|
||||
for k in self.keys():
|
||||
yield k
|
||||
def has_key(self, key):
|
||||
try:
|
||||
value = self[key]
|
||||
except KeyError:
|
||||
return False
|
||||
return True
|
||||
def __contains__(self, key):
|
||||
return self.has_key(key)
|
||||
|
||||
# third level takes advantage of second level definitions
|
||||
def iteritems(self):
|
||||
for k in self:
|
||||
yield (k, self[k])
|
||||
def iterkeys(self):
|
||||
return self.__iter__()
|
||||
|
||||
# fourth level uses definitions from lower levels
|
||||
def itervalues(self):
|
||||
for _, v in self.iteritems():
|
||||
yield v
|
||||
def values(self):
|
||||
return [v for _, v in self.iteritems()]
|
||||
def items(self):
|
||||
return list(self.iteritems())
|
||||
def clear(self):
|
||||
for key in self.keys():
|
||||
del self[key]
|
||||
def setdefault(self, key, default):
|
||||
try:
|
||||
return self[key]
|
||||
except KeyError:
|
||||
self[key] = default
|
||||
return default
|
||||
def pop(self, key, *args):
|
||||
if len(args) > 1:
|
||||
raise TypeError, "pop expected at most 2 arguments, got "\
|
||||
+ repr(1 + len(args))
|
||||
try:
|
||||
value = self[key]
|
||||
except KeyError:
|
||||
if args:
|
||||
return args[0]
|
||||
raise
|
||||
del self[key]
|
||||
return value
|
||||
def popitem(self):
|
||||
try:
|
||||
k, v = self.iteritems().next()
|
||||
except StopIteration:
|
||||
raise KeyError, 'container is empty'
|
||||
del self[k]
|
||||
return (k, v)
|
||||
def update(self, other):
|
||||
# Make progressively weaker assumptions about "other"
|
||||
if hasattr(other, 'iteritems'): # iteritems saves memory and lookups
|
||||
for k, v in other.iteritems():
|
||||
self[k] = v
|
||||
elif hasattr(other, '__iter__'): # iter saves memory
|
||||
for k in other:
|
||||
self[k] = other[k]
|
||||
else:
|
||||
for k in other.keys():
|
||||
self[k] = other[k]
|
||||
def get(self, key, default=None):
|
||||
try:
|
||||
return self[key]
|
||||
except KeyError:
|
||||
return default
|
||||
def __repr__(self):
|
||||
return repr(dict(self.iteritems()))
|
||||
def __cmp__(self, other):
|
||||
if other is None:
|
||||
return 1
|
||||
if isinstance(other, DictMixin):
|
||||
other = dict(other.iteritems())
|
||||
return cmp(dict(self.iteritems()), other)
|
||||
def __len__(self):
|
||||
return len(self.keys())
|
||||
|
||||
###########################################################################
|
||||
|
||||
from _psyco import compact
|
||||
|
||||
|
||||
class compactdictproxy(DictMixin):
|
||||
|
||||
def __init__(self, ko):
|
||||
self._ko = ko # compact object of which 'self' is the dict
|
||||
|
||||
def __getitem__(self, key):
|
||||
return compact.__getslot__(self._ko, key)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
compact.__setslot__(self._ko, key, value)
|
||||
|
||||
def __delitem__(self, key):
|
||||
compact.__delslot__(self._ko, key)
|
||||
|
||||
def keys(self):
|
||||
return compact.__members__.__get__(self._ko)
|
||||
|
||||
def clear(self):
|
||||
keys = self.keys()
|
||||
keys.reverse()
|
||||
for key in keys:
|
||||
del self[key]
|
||||
|
||||
def __repr__(self):
|
||||
keys = ', '.join(self.keys())
|
||||
return '<compactdictproxy object {%s}>' % (keys,)
|
||||
@@ -1,96 +0,0 @@
|
||||
###########################################################################
|
||||
#
|
||||
# Psyco logger.
|
||||
# Copyright (C) 2001-2002 Armin Rigo et.al.
|
||||
|
||||
"""Psyco logger.
|
||||
|
||||
See log() in core.py.
|
||||
"""
|
||||
###########################################################################
|
||||
|
||||
|
||||
import _psyco
|
||||
from time import time, localtime, strftime
|
||||
|
||||
|
||||
current = None
|
||||
print_charges = 10
|
||||
dump_delay = 0.2
|
||||
dump_last = 0.0
|
||||
|
||||
def write(s, level):
|
||||
t = time()
|
||||
f = t-int(t)
|
||||
try:
|
||||
current.write("%s.%02d %-*s%s\n" % (
|
||||
strftime("%X", localtime(int(t))),
|
||||
int(f*100.0), 63-level, s,
|
||||
"%"*level))
|
||||
current.flush()
|
||||
except (OSError, IOError):
|
||||
pass
|
||||
|
||||
def psycowrite(s):
|
||||
t = time()
|
||||
f = t-int(t)
|
||||
try:
|
||||
current.write("%s.%02d %-*s%s\n" % (
|
||||
strftime("%X", localtime(int(t))),
|
||||
int(f*100.0), 60, s.strip(),
|
||||
"% %"))
|
||||
current.flush()
|
||||
except (OSError, IOError):
|
||||
pass
|
||||
|
||||
##def writelines(lines, level=0):
|
||||
## if lines:
|
||||
## t = time()
|
||||
## f = t-int(t)
|
||||
## timedesc = strftime("%x %X", localtime(int(t)))
|
||||
## print >> current, "%s.%03d %-*s %s" % (
|
||||
## timedesc, int(f*1000),
|
||||
## 50-level, lines[0],
|
||||
## "+"*level)
|
||||
## timedesc = " " * (len(timedesc)+5)
|
||||
## for line in lines[1:]:
|
||||
## print >> current, timedesc, line
|
||||
|
||||
def writememory():
|
||||
write("memory usage: %d+ kb" % _psyco.memory(), 1)
|
||||
|
||||
def dumpcharges():
|
||||
global dump_last
|
||||
if print_charges:
|
||||
t = time()
|
||||
if not (dump_last <= t < dump_last+dump_delay):
|
||||
if t <= dump_last+1.5*dump_delay:
|
||||
dump_last += dump_delay
|
||||
else:
|
||||
dump_last = t
|
||||
#write("%s: charges:" % who, 0)
|
||||
lst = _psyco.stattop(print_charges)
|
||||
if lst:
|
||||
f = t-int(t)
|
||||
lines = ["%s.%02d ______\n" % (
|
||||
strftime("%X", localtime(int(t))),
|
||||
int(f*100.0))]
|
||||
i = 1
|
||||
for co, charge in lst:
|
||||
detail = co.co_filename
|
||||
if len(detail) > 19:
|
||||
detail = '...' + detail[-17:]
|
||||
lines.append(" #%-3d |%4.1f %%| %-26s%20s:%d\n" %
|
||||
(i, charge*100.0, co.co_name, detail,
|
||||
co.co_firstlineno))
|
||||
i += 1
|
||||
current.writelines(lines)
|
||||
current.flush()
|
||||
|
||||
def writefinalstats():
|
||||
dumpcharges()
|
||||
writememory()
|
||||
writedate("program exit")
|
||||
|
||||
def writedate(msg):
|
||||
write('%s, %s' % (msg, strftime("%x")), 20)
|
||||
@@ -1,379 +0,0 @@
|
||||
###########################################################################
|
||||
#
|
||||
# Psyco profiler (Python part).
|
||||
# Copyright (C) 2001-2002 Armin Rigo et.al.
|
||||
|
||||
"""Psyco profiler (Python part).
|
||||
|
||||
The implementation of the non-time-critical parts of the profiler.
|
||||
See profile() and full() in core.py for the easy interface.
|
||||
"""
|
||||
###########################################################################
|
||||
|
||||
import _psyco
|
||||
from support import *
|
||||
import math, time, types, atexit
|
||||
now = time.time
|
||||
try:
|
||||
import thread
|
||||
except ImportError:
|
||||
import dummy_thread as thread
|
||||
|
||||
|
||||
# current profiler instance
|
||||
current = None
|
||||
|
||||
# enabled profilers, in order of priority
|
||||
profilers = []
|
||||
|
||||
# logger module (when enabled by core.log())
|
||||
logger = None
|
||||
|
||||
# a lock for a thread-safe go()
|
||||
go_lock = thread.allocate_lock()
|
||||
|
||||
def go(stop=0):
|
||||
# run the highest-priority profiler in 'profilers'
|
||||
global current
|
||||
go_lock.acquire()
|
||||
try:
|
||||
prev = current
|
||||
if stop:
|
||||
del profilers[:]
|
||||
if prev:
|
||||
if profilers and profilers[0] is prev:
|
||||
return # best profiler already running
|
||||
prev.stop()
|
||||
current = None
|
||||
for p in profilers[:]:
|
||||
if p.start():
|
||||
current = p
|
||||
if logger: # and p is not prev:
|
||||
logger.write("%s: starting" % p.__class__.__name__, 5)
|
||||
return
|
||||
finally:
|
||||
go_lock.release()
|
||||
# no profiler is running now
|
||||
if stop:
|
||||
if logger:
|
||||
logger.writefinalstats()
|
||||
else:
|
||||
tag2bind()
|
||||
|
||||
atexit.register(go, 1)
|
||||
|
||||
|
||||
def buildfncache(globals, cache):
|
||||
if hasattr(types.IntType, '__dict__'):
|
||||
clstypes = (types.ClassType, types.TypeType)
|
||||
else:
|
||||
clstypes = types.ClassType
|
||||
for x in globals.values():
|
||||
if isinstance(x, types.MethodType):
|
||||
x = x.im_func
|
||||
if isinstance(x, types.FunctionType):
|
||||
cache[x.func_code] = x, ''
|
||||
elif isinstance(x, clstypes):
|
||||
for y in x.__dict__.values():
|
||||
if isinstance(y, types.MethodType):
|
||||
y = y.im_func
|
||||
if isinstance(y, types.FunctionType):
|
||||
cache[y.func_code] = y, x.__name__
|
||||
|
||||
# code-to-function mapping (cache)
|
||||
function_cache = {}
|
||||
|
||||
def trytobind(co, globals, log=1):
|
||||
try:
|
||||
f, clsname = function_cache[co]
|
||||
except KeyError:
|
||||
buildfncache(globals, function_cache)
|
||||
try:
|
||||
f, clsname = function_cache[co]
|
||||
except KeyError:
|
||||
if logger:
|
||||
logger.write('warning: cannot find function %s in %s' %
|
||||
(co.co_name, globals.get('__name__', '?')), 3)
|
||||
return # give up
|
||||
if logger and log:
|
||||
modulename = globals.get('__name__', '?')
|
||||
if clsname:
|
||||
modulename += '.' + clsname
|
||||
logger.write('bind function: %s.%s' % (modulename, co.co_name), 1)
|
||||
f.func_code = _psyco.proxycode(f)
|
||||
|
||||
|
||||
# the list of code objects that have been tagged
|
||||
tagged_codes = []
|
||||
|
||||
def tag(co, globals):
|
||||
if logger:
|
||||
try:
|
||||
f, clsname = function_cache[co]
|
||||
except KeyError:
|
||||
buildfncache(globals, function_cache)
|
||||
try:
|
||||
f, clsname = function_cache[co]
|
||||
except KeyError:
|
||||
clsname = '' # give up
|
||||
modulename = globals.get('__name__', '?')
|
||||
if clsname:
|
||||
modulename += '.' + clsname
|
||||
logger.write('tag function: %s.%s' % (modulename, co.co_name), 1)
|
||||
tagged_codes.append((co, globals))
|
||||
_psyco.turbo_frame(co)
|
||||
_psyco.turbo_code(co)
|
||||
|
||||
def tag2bind():
|
||||
if tagged_codes:
|
||||
if logger:
|
||||
logger.write('profiling stopped, binding %d functions' %
|
||||
len(tagged_codes), 2)
|
||||
for co, globals in tagged_codes:
|
||||
trytobind(co, globals, 0)
|
||||
function_cache.clear()
|
||||
del tagged_codes[:]
|
||||
|
||||
|
||||
class Profiler:
|
||||
MemoryTimerResolution = 0.103
|
||||
|
||||
def run(self, memory, time, memorymax, timemax):
|
||||
self.memory = memory
|
||||
self.memorymax = memorymax
|
||||
self.time = time
|
||||
if timemax is None:
|
||||
self.endtime = None
|
||||
else:
|
||||
self.endtime = now() + timemax
|
||||
self.alarms = []
|
||||
profilers.append(self)
|
||||
go()
|
||||
|
||||
def start(self):
|
||||
curmem = _psyco.memory()
|
||||
memlimits = []
|
||||
if self.memorymax is not None:
|
||||
if curmem >= self.memorymax:
|
||||
if logger:
|
||||
logger.writememory()
|
||||
return self.limitreached('memorymax')
|
||||
memlimits.append(self.memorymax)
|
||||
if self.memory is not None:
|
||||
if self.memory <= 0:
|
||||
if logger:
|
||||
logger.writememory()
|
||||
return self.limitreached('memory')
|
||||
memlimits.append(curmem + self.memory)
|
||||
self.memory_at_start = curmem
|
||||
|
||||
curtime = now()
|
||||
timelimits = []
|
||||
if self.endtime is not None:
|
||||
if curtime >= self.endtime:
|
||||
return self.limitreached('timemax')
|
||||
timelimits.append(self.endtime - curtime)
|
||||
if self.time is not None:
|
||||
if self.time <= 0.0:
|
||||
return self.limitreached('time')
|
||||
timelimits.append(self.time)
|
||||
self.time_at_start = curtime
|
||||
|
||||
try:
|
||||
self.do_start()
|
||||
except error, e:
|
||||
if logger:
|
||||
logger.write('%s: disabled by psyco.error:' % (
|
||||
self.__class__.__name__), 4)
|
||||
logger.write(' %s' % str(e), 3)
|
||||
return 0
|
||||
|
||||
if memlimits:
|
||||
self.memlimits_args = (time.sleep, (self.MemoryTimerResolution,),
|
||||
self.check_memory, (min(memlimits),))
|
||||
self.alarms.append(_psyco.alarm(*self.memlimits_args))
|
||||
if timelimits:
|
||||
self.alarms.append(_psyco.alarm(time.sleep, (min(timelimits),),
|
||||
self.time_out))
|
||||
return 1
|
||||
|
||||
def stop(self):
|
||||
for alarm in self.alarms:
|
||||
alarm.stop(0)
|
||||
for alarm in self.alarms:
|
||||
alarm.stop(1) # wait for parallel threads to stop
|
||||
del self.alarms[:]
|
||||
if self.time is not None:
|
||||
self.time -= now() - self.time_at_start
|
||||
if self.memory is not None:
|
||||
self.memory -= _psyco.memory() - self.memory_at_start
|
||||
|
||||
try:
|
||||
self.do_stop()
|
||||
except error:
|
||||
return 0
|
||||
return 1
|
||||
|
||||
def check_memory(self, limit):
|
||||
if _psyco.memory() < limit:
|
||||
return self.memlimits_args
|
||||
go()
|
||||
|
||||
def time_out(self):
|
||||
self.time = 0.0
|
||||
go()
|
||||
|
||||
def limitreached(self, limitname):
|
||||
try:
|
||||
profilers.remove(self)
|
||||
except ValueError:
|
||||
pass
|
||||
if logger:
|
||||
logger.write('%s: disabled (%s limit reached)' % (
|
||||
self.__class__.__name__, limitname), 4)
|
||||
return 0
|
||||
|
||||
|
||||
class FullCompiler(Profiler):
|
||||
|
||||
def do_start(self):
|
||||
_psyco.profiling('f')
|
||||
|
||||
def do_stop(self):
|
||||
_psyco.profiling('.')
|
||||
|
||||
|
||||
class RunOnly(Profiler):
|
||||
|
||||
def do_start(self):
|
||||
_psyco.profiling('n')
|
||||
|
||||
def do_stop(self):
|
||||
_psyco.profiling('.')
|
||||
|
||||
|
||||
class ChargeProfiler(Profiler):
|
||||
|
||||
def __init__(self, watermark, parentframe):
|
||||
self.watermark = watermark
|
||||
self.parent2 = parentframe * 2.0
|
||||
self.lock = thread.allocate_lock()
|
||||
|
||||
def init_charges(self):
|
||||
_psyco.statwrite(watermark = self.watermark,
|
||||
parent2 = self.parent2)
|
||||
|
||||
def do_stop(self):
|
||||
_psyco.profiling('.')
|
||||
_psyco.statwrite(callback = None)
|
||||
|
||||
|
||||
class ActiveProfiler(ChargeProfiler):
|
||||
|
||||
def active_start(self):
|
||||
_psyco.profiling('p')
|
||||
|
||||
def do_start(self):
|
||||
self.init_charges()
|
||||
self.active_start()
|
||||
_psyco.statwrite(callback = self.charge_callback)
|
||||
|
||||
def charge_callback(self, frame, charge):
|
||||
tag(frame.f_code, frame.f_globals)
|
||||
|
||||
|
||||
class PassiveProfiler(ChargeProfiler):
|
||||
|
||||
initial_charge_unit = _psyco.statread('unit')
|
||||
reset_stats_after = 120 # half-lives (maximum 200!)
|
||||
reset_limit = initial_charge_unit * (2.0 ** reset_stats_after)
|
||||
|
||||
def __init__(self, watermark, halflife, pollfreq, parentframe):
|
||||
ChargeProfiler.__init__(self, watermark, parentframe)
|
||||
self.pollfreq = pollfreq
|
||||
# self.progress is slightly more than 1.0, and computed so that
|
||||
# do_profile() will double the change_unit every 'halflife' seconds.
|
||||
self.progress = 2.0 ** (1.0 / (halflife * pollfreq))
|
||||
|
||||
def reset(self):
|
||||
_psyco.statwrite(unit = self.initial_charge_unit, callback = None)
|
||||
_psyco.statreset()
|
||||
if logger:
|
||||
logger.write("%s: resetting stats" % self.__class__.__name__, 1)
|
||||
|
||||
def passive_start(self):
|
||||
self.passivealarm_args = (time.sleep, (1.0 / self.pollfreq,),
|
||||
self.do_profile)
|
||||
self.alarms.append(_psyco.alarm(*self.passivealarm_args))
|
||||
|
||||
def do_start(self):
|
||||
tag2bind()
|
||||
self.init_charges()
|
||||
self.passive_start()
|
||||
|
||||
def do_profile(self):
|
||||
_psyco.statcollect()
|
||||
if logger:
|
||||
logger.dumpcharges()
|
||||
nunit = _psyco.statread('unit') * self.progress
|
||||
if nunit > self.reset_limit:
|
||||
self.reset()
|
||||
else:
|
||||
_psyco.statwrite(unit = nunit, callback = self.charge_callback)
|
||||
return self.passivealarm_args
|
||||
|
||||
def charge_callback(self, frame, charge):
|
||||
trytobind(frame.f_code, frame.f_globals)
|
||||
|
||||
|
||||
class ActivePassiveProfiler(PassiveProfiler, ActiveProfiler):
|
||||
|
||||
def do_start(self):
|
||||
self.init_charges()
|
||||
self.active_start()
|
||||
self.passive_start()
|
||||
|
||||
def charge_callback(self, frame, charge):
|
||||
tag(frame.f_code, frame.f_globals)
|
||||
|
||||
|
||||
|
||||
#
|
||||
# we register our own version of sys.settrace(), sys.setprofile()
|
||||
# and thread.start_new_thread().
|
||||
#
|
||||
|
||||
def psyco_settrace(*args, **kw):
|
||||
"This is the Psyco-aware version of sys.settrace()."
|
||||
result = original_settrace(*args, **kw)
|
||||
go()
|
||||
return result
|
||||
|
||||
def psyco_setprofile(*args, **kw):
|
||||
"This is the Psyco-aware version of sys.setprofile()."
|
||||
result = original_setprofile(*args, **kw)
|
||||
go()
|
||||
return result
|
||||
|
||||
def psyco_thread_stub(callable, args, kw):
|
||||
_psyco.statcollect()
|
||||
if kw is None:
|
||||
return callable(*args)
|
||||
else:
|
||||
return callable(*args, **kw)
|
||||
|
||||
def psyco_start_new_thread(callable, args, kw=None):
|
||||
"This is the Psyco-aware version of thread.start_new_thread()."
|
||||
return original_start_new_thread(psyco_thread_stub, (callable, args, kw))
|
||||
|
||||
original_settrace = sys.settrace
|
||||
original_setprofile = sys.setprofile
|
||||
original_start_new_thread = thread.start_new_thread
|
||||
sys.settrace = psyco_settrace
|
||||
sys.setprofile = psyco_setprofile
|
||||
thread.start_new_thread = psyco_start_new_thread
|
||||
# hack to patch threading._start_new_thread if the module is
|
||||
# already loaded
|
||||
if ('threading' in sys.modules and
|
||||
hasattr(sys.modules['threading'], '_start_new_thread')):
|
||||
sys.modules['threading']._start_new_thread = psyco_start_new_thread
|
||||
@@ -1,191 +0,0 @@
|
||||
###########################################################################
|
||||
#
|
||||
# Psyco general support module.
|
||||
# Copyright (C) 2001-2002 Armin Rigo et.al.
|
||||
|
||||
"""Psyco general support module.
|
||||
|
||||
For internal use.
|
||||
"""
|
||||
###########################################################################
|
||||
|
||||
import sys, _psyco, __builtin__
|
||||
|
||||
error = _psyco.error
|
||||
class warning(Warning):
|
||||
pass
|
||||
|
||||
_psyco.NoLocalsWarning = warning
|
||||
|
||||
def warn(msg):
|
||||
from warnings import warn
|
||||
warn(msg, warning, stacklevel=2)
|
||||
|
||||
#
|
||||
# Version checks
|
||||
#
|
||||
__version__ = 0x010600f0
|
||||
if _psyco.PSYVER != __version__:
|
||||
raise error, "version mismatch between Psyco parts, reinstall it"
|
||||
|
||||
version_info = (__version__ >> 24,
|
||||
(__version__ >> 16) & 0xff,
|
||||
(__version__ >> 8) & 0xff,
|
||||
{0xa0: 'alpha',
|
||||
0xb0: 'beta',
|
||||
0xc0: 'candidate',
|
||||
0xf0: 'final'}[__version__ & 0xf0],
|
||||
__version__ & 0xf)
|
||||
|
||||
|
||||
VERSION_LIMITS = [0x02020200, # 2.2.2
|
||||
0x02030000, # 2.3
|
||||
0x02040000] # 2.4
|
||||
|
||||
if ([v for v in VERSION_LIMITS if v <= sys.hexversion] !=
|
||||
[v for v in VERSION_LIMITS if v <= _psyco.PYVER ]):
|
||||
if sys.hexversion < VERSION_LIMITS[0]:
|
||||
warn("Psyco requires Python version 2.2.2 or later")
|
||||
else:
|
||||
warn("Psyco version does not match Python version. "
|
||||
"Psyco must be updated or recompiled")
|
||||
|
||||
|
||||
if hasattr(_psyco, 'ALL_CHECKS') and hasattr(_psyco, 'VERBOSE_LEVEL'):
|
||||
print >> sys.stderr, ('psyco: running in debugging mode on %s' %
|
||||
_psyco.PROCESSOR)
|
||||
|
||||
|
||||
###########################################################################
|
||||
# sys._getframe() gives strange results on a mixed Psyco- and Python-style
|
||||
# stack frame. Psyco provides a replacement that partially emulates Python
|
||||
# frames from Psyco frames. The new sys._getframe() may return objects of
|
||||
# a custom "Psyco frame" type, which is a subtype of the normal frame type.
|
||||
#
|
||||
# The same problems require some other built-in functions to be replaced
|
||||
# as well. Note that the local variables are not available in any
|
||||
# dictionary with Psyco.
|
||||
|
||||
|
||||
class Frame:
|
||||
pass
|
||||
|
||||
|
||||
class PythonFrame(Frame):
|
||||
|
||||
def __init__(self, frame):
|
||||
self.__dict__.update({
|
||||
'_frame': frame,
|
||||
})
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if attr == 'f_back':
|
||||
try:
|
||||
result = embedframe(_psyco.getframe(self._frame))
|
||||
except ValueError:
|
||||
result = None
|
||||
except error:
|
||||
warn("f_back is skipping dead Psyco frames")
|
||||
result = self._frame.f_back
|
||||
self.__dict__['f_back'] = result
|
||||
return result
|
||||
else:
|
||||
return getattr(self._frame, attr)
|
||||
|
||||
def __setattr__(self, attr, value):
|
||||
setattr(self._frame, attr, value)
|
||||
|
||||
def __delattr__(self, attr):
|
||||
delattr(self._frame, attr)
|
||||
|
||||
|
||||
class PsycoFrame(Frame):
|
||||
|
||||
def __init__(self, tag):
|
||||
self.__dict__.update({
|
||||
'_tag' : tag,
|
||||
'f_code' : tag[0],
|
||||
'f_globals': tag[1],
|
||||
})
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if attr == 'f_back':
|
||||
try:
|
||||
result = embedframe(_psyco.getframe(self._tag))
|
||||
except ValueError:
|
||||
result = None
|
||||
elif attr == 'f_lineno':
|
||||
result = self.f_code.co_firstlineno # better than nothing
|
||||
elif attr == 'f_builtins':
|
||||
result = self.f_globals['__builtins__']
|
||||
elif attr == 'f_restricted':
|
||||
result = self.f_builtins is not __builtins__
|
||||
elif attr == 'f_locals':
|
||||
raise AttributeError, ("local variables of functions run by Psyco "
|
||||
"cannot be accessed in any way, sorry")
|
||||
else:
|
||||
raise AttributeError, ("emulated Psyco frames have "
|
||||
"no '%s' attribute" % attr)
|
||||
self.__dict__[attr] = result
|
||||
return result
|
||||
|
||||
def __setattr__(self, attr, value):
|
||||
raise AttributeError, "Psyco frame objects are read-only"
|
||||
|
||||
def __delattr__(self, attr):
|
||||
if attr == 'f_trace':
|
||||
# for bdb which relies on CPython frames exhibiting a slightly
|
||||
# buggy behavior: you can 'del f.f_trace' as often as you like
|
||||
# even without having set it previously.
|
||||
return
|
||||
raise AttributeError, "Psyco frame objects are read-only"
|
||||
|
||||
|
||||
def embedframe(result):
|
||||
if type(result) is type(()):
|
||||
return PsycoFrame(result)
|
||||
else:
|
||||
return PythonFrame(result)
|
||||
|
||||
def _getframe(depth=0):
|
||||
"""Return a frame object from the call stack. This is a replacement for
|
||||
sys._getframe() which is aware of Psyco frames.
|
||||
|
||||
The returned objects are instances of either PythonFrame or PsycoFrame
|
||||
instead of being real Python-level frame object, so that they can emulate
|
||||
the common attributes of frame objects.
|
||||
|
||||
The original sys._getframe() ignoring Psyco frames altogether is stored in
|
||||
psyco._getrealframe(). See also psyco._getemulframe()."""
|
||||
# 'depth+1' to account for this _getframe() Python function
|
||||
return embedframe(_psyco.getframe(depth+1))
|
||||
|
||||
def _getemulframe(depth=0):
|
||||
"""As _getframe(), but the returned objects are real Python frame objects
|
||||
emulating Psyco frames. Some of their attributes can be wrong or missing,
|
||||
however."""
|
||||
# 'depth+1' to account for this _getemulframe() Python function
|
||||
return _psyco.getframe(depth+1, 1)
|
||||
|
||||
def patch(name, module=__builtin__):
|
||||
f = getattr(_psyco, name)
|
||||
org = getattr(module, name)
|
||||
if org is not f:
|
||||
setattr(module, name, f)
|
||||
setattr(_psyco, 'original_' + name, org)
|
||||
|
||||
_getrealframe = sys._getframe
|
||||
sys._getframe = _getframe
|
||||
patch('globals')
|
||||
patch('eval')
|
||||
patch('execfile')
|
||||
patch('locals')
|
||||
patch('vars')
|
||||
patch('dir')
|
||||
patch('input')
|
||||
_psyco.original_raw_input = raw_input
|
||||
__builtin__.__in_psyco__ = 0==1 # False
|
||||
|
||||
if hasattr(_psyco, 'compact'):
|
||||
import kdictproxy
|
||||
_psyco.compactdictproxy = kdictproxy.compactdictproxy
|
||||
218
Calibre_Plugins/eReaderPDB2PML_plugin/python_des.py
Normal file
218
Calibre_Plugins/eReaderPDB2PML_plugin/python_des.py
Normal file
@@ -0,0 +1,218 @@
|
||||
import sys
|
||||
|
||||
ECB = 0
|
||||
CBC = 1
|
||||
class Des(object):
|
||||
__pc1 = [56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
|
||||
9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
|
||||
62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
|
||||
13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3]
|
||||
__left_rotations = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]
|
||||
__pc2 = [13, 16, 10, 23, 0, 4,2, 27, 14, 5, 20, 9,
|
||||
22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
|
||||
40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
|
||||
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31]
|
||||
__ip = [57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
|
||||
61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7,
|
||||
56, 48, 40, 32, 24, 16, 8, 0, 58, 50, 42, 34, 26, 18, 10, 2,
|
||||
60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6]
|
||||
__expansion_table = [31, 0, 1, 2, 3, 4, 3, 4, 5, 6, 7, 8,
|
||||
7, 8, 9, 10, 11, 12,11, 12, 13, 14, 15, 16,
|
||||
15, 16, 17, 18, 19, 20,19, 20, 21, 22, 23, 24,
|
||||
23, 24, 25, 26, 27, 28,27, 28, 29, 30, 31, 0]
|
||||
__sbox = [[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
|
||||
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
|
||||
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
|
||||
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13],
|
||||
[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
|
||||
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
|
||||
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
|
||||
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9],
|
||||
[10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
|
||||
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
|
||||
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
|
||||
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12],
|
||||
[7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
|
||||
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
|
||||
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
|
||||
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14],
|
||||
[2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
|
||||
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
|
||||
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
|
||||
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3],
|
||||
[12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
|
||||
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
|
||||
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
|
||||
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13],
|
||||
[4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
|
||||
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
|
||||
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
|
||||
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12],
|
||||
[13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
|
||||
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
|
||||
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
|
||||
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11],]
|
||||
__p = [15, 6, 19, 20, 28, 11,27, 16, 0, 14, 22, 25,
|
||||
4, 17, 30, 9, 1, 7,23,13, 31, 26, 2, 8,18, 12, 29, 5, 21, 10,3, 24]
|
||||
__fp = [39, 7, 47, 15, 55, 23, 63, 31,38, 6, 46, 14, 54, 22, 62, 30,
|
||||
37, 5, 45, 13, 53, 21, 61, 29,36, 4, 44, 12, 52, 20, 60, 28,
|
||||
35, 3, 43, 11, 51, 19, 59, 27,34, 2, 42, 10, 50, 18, 58, 26,
|
||||
33, 1, 41, 9, 49, 17, 57, 25,32, 0, 40, 8, 48, 16, 56, 24]
|
||||
# Type of crypting being done
|
||||
ENCRYPT = 0x00
|
||||
DECRYPT = 0x01
|
||||
def __init__(self, key, mode=ECB, IV=None):
|
||||
if len(key) != 8:
|
||||
raise ValueError("Invalid DES key size. Key must be exactly 8 bytes long.")
|
||||
self.block_size = 8
|
||||
self.key_size = 8
|
||||
self.__padding = ''
|
||||
self.setMode(mode)
|
||||
if IV:
|
||||
self.setIV(IV)
|
||||
self.L = []
|
||||
self.R = []
|
||||
self.Kn = [ [0] * 48 ] * 16 # 16 48-bit keys (K1 - K16)
|
||||
self.final = []
|
||||
self.setKey(key)
|
||||
def getKey(self):
|
||||
return self.__key
|
||||
def setKey(self, key):
|
||||
self.__key = key
|
||||
self.__create_sub_keys()
|
||||
def getMode(self):
|
||||
return self.__mode
|
||||
def setMode(self, mode):
|
||||
self.__mode = mode
|
||||
def getIV(self):
|
||||
return self.__iv
|
||||
def setIV(self, IV):
|
||||
if not IV or len(IV) != self.block_size:
|
||||
raise ValueError("Invalid Initial Value (IV), must be a multiple of " + str(self.block_size) + " bytes")
|
||||
self.__iv = IV
|
||||
def getPadding(self):
|
||||
return self.__padding
|
||||
def __String_to_BitList(self, data):
|
||||
l = len(data) * 8
|
||||
result = [0] * l
|
||||
pos = 0
|
||||
for c in data:
|
||||
i = 7
|
||||
ch = ord(c)
|
||||
while i >= 0:
|
||||
if ch & (1 << i) != 0:
|
||||
result[pos] = 1
|
||||
else:
|
||||
result[pos] = 0
|
||||
pos += 1
|
||||
i -= 1
|
||||
return result
|
||||
def __BitList_to_String(self, data):
|
||||
result = ''
|
||||
pos = 0
|
||||
c = 0
|
||||
while pos < len(data):
|
||||
c += data[pos] << (7 - (pos % 8))
|
||||
if (pos % 8) == 7:
|
||||
result += chr(c)
|
||||
c = 0
|
||||
pos += 1
|
||||
return result
|
||||
def __permutate(self, table, block):
|
||||
return [block[x] for x in table]
|
||||
def __create_sub_keys(self):
|
||||
key = self.__permutate(Des.__pc1, self.__String_to_BitList(self.getKey()))
|
||||
i = 0
|
||||
self.L = key[:28]
|
||||
self.R = key[28:]
|
||||
while i < 16:
|
||||
j = 0
|
||||
while j < Des.__left_rotations[i]:
|
||||
self.L.append(self.L[0])
|
||||
del self.L[0]
|
||||
self.R.append(self.R[0])
|
||||
del self.R[0]
|
||||
j += 1
|
||||
self.Kn[i] = self.__permutate(Des.__pc2, self.L + self.R)
|
||||
i += 1
|
||||
def __des_crypt(self, block, crypt_type):
|
||||
block = self.__permutate(Des.__ip, block)
|
||||
self.L = block[:32]
|
||||
self.R = block[32:]
|
||||
if crypt_type == Des.ENCRYPT:
|
||||
iteration = 0
|
||||
iteration_adjustment = 1
|
||||
else:
|
||||
iteration = 15
|
||||
iteration_adjustment = -1
|
||||
i = 0
|
||||
while i < 16:
|
||||
tempR = self.R[:]
|
||||
self.R = self.__permutate(Des.__expansion_table, self.R)
|
||||
self.R = [x ^ y for x,y in zip(self.R, self.Kn[iteration])]
|
||||
B = [self.R[:6], self.R[6:12], self.R[12:18], self.R[18:24], self.R[24:30], self.R[30:36], self.R[36:42], self.R[42:]]
|
||||
j = 0
|
||||
Bn = [0] * 32
|
||||
pos = 0
|
||||
while j < 8:
|
||||
m = (B[j][0] << 1) + B[j][5]
|
||||
n = (B[j][1] << 3) + (B[j][2] << 2) + (B[j][3] << 1) + B[j][4]
|
||||
v = Des.__sbox[j][(m << 4) + n]
|
||||
Bn[pos] = (v & 8) >> 3
|
||||
Bn[pos + 1] = (v & 4) >> 2
|
||||
Bn[pos + 2] = (v & 2) >> 1
|
||||
Bn[pos + 3] = v & 1
|
||||
pos += 4
|
||||
j += 1
|
||||
self.R = self.__permutate(Des.__p, Bn)
|
||||
self.R = [x ^ y for x, y in zip(self.R, self.L)]
|
||||
self.L = tempR
|
||||
i += 1
|
||||
iteration += iteration_adjustment
|
||||
self.final = self.__permutate(Des.__fp, self.R + self.L)
|
||||
return self.final
|
||||
def crypt(self, data, crypt_type):
|
||||
if not data:
|
||||
return ''
|
||||
if len(data) % self.block_size != 0:
|
||||
if crypt_type == Des.DECRYPT: # Decryption must work on 8 byte blocks
|
||||
raise ValueError("Invalid data length, data must be a multiple of " + str(self.block_size) + " bytes\n.")
|
||||
if not self.getPadding():
|
||||
raise ValueError("Invalid data length, data must be a multiple of " + str(self.block_size) + " bytes\n. Try setting the optional padding character")
|
||||
else:
|
||||
data += (self.block_size - (len(data) % self.block_size)) * self.getPadding()
|
||||
if self.getMode() == CBC:
|
||||
if self.getIV():
|
||||
iv = self.__String_to_BitList(self.getIV())
|
||||
else:
|
||||
raise ValueError("For CBC mode, you must supply the Initial Value (IV) for ciphering")
|
||||
i = 0
|
||||
dict = {}
|
||||
result = []
|
||||
while i < len(data):
|
||||
block = self.__String_to_BitList(data[i:i+8])
|
||||
if self.getMode() == CBC:
|
||||
if crypt_type == Des.ENCRYPT:
|
||||
block = [x ^ y for x, y in zip(block, iv)]
|
||||
processed_block = self.__des_crypt(block, crypt_type)
|
||||
if crypt_type == Des.DECRYPT:
|
||||
processed_block = [x ^ y for x, y in zip(processed_block, iv)]
|
||||
iv = block
|
||||
else:
|
||||
iv = processed_block
|
||||
else:
|
||||
processed_block = self.__des_crypt(block, crypt_type)
|
||||
result.append(self.__BitList_to_String(processed_block))
|
||||
i += 8
|
||||
if crypt_type == Des.DECRYPT and self.getPadding():
|
||||
s = result[-1]
|
||||
while s[-1] == self.getPadding():
|
||||
s = s[:-1]
|
||||
result[-1] = s
|
||||
return ''.join(result)
|
||||
def encrypt(self, data, pad=''):
|
||||
self.__padding = pad
|
||||
return self.crypt(data, Des.ENCRYPT)
|
||||
def decrypt(self, data, pad=''):
|
||||
self.__padding = pad
|
||||
return self.crypt(data, Des.DECRYPT)
|
||||
BIN
Calibre_Plugins/eReaderPDB2PML_plugin/windows/psyco/__init__.pyo
Normal file
BIN
Calibre_Plugins/eReaderPDB2PML_plugin/windows/psyco/__init__.pyo
Normal file
Binary file not shown.
BIN
Calibre_Plugins/eReaderPDB2PML_plugin/windows/psyco/_psyco.pyd
Normal file
BIN
Calibre_Plugins/eReaderPDB2PML_plugin/windows/psyco/_psyco.pyd
Normal file
Binary file not shown.
BIN
Calibre_Plugins/eReaderPDB2PML_plugin/windows/psyco/builtin.pyo
Normal file
BIN
Calibre_Plugins/eReaderPDB2PML_plugin/windows/psyco/builtin.pyo
Normal file
Binary file not shown.
BIN
Calibre_Plugins/eReaderPDB2PML_plugin/windows/psyco/classes.pyo
Normal file
BIN
Calibre_Plugins/eReaderPDB2PML_plugin/windows/psyco/classes.pyo
Normal file
Binary file not shown.
BIN
Calibre_Plugins/eReaderPDB2PML_plugin/windows/psyco/clibrary.pyo
Normal file
BIN
Calibre_Plugins/eReaderPDB2PML_plugin/windows/psyco/clibrary.pyo
Normal file
Binary file not shown.
BIN
Calibre_Plugins/eReaderPDB2PML_plugin/windows/psyco/core.pyo
Normal file
BIN
Calibre_Plugins/eReaderPDB2PML_plugin/windows/psyco/core.pyo
Normal file
Binary file not shown.
Binary file not shown.
BIN
Calibre_Plugins/eReaderPDB2PML_plugin/windows/psyco/logger.pyo
Normal file
BIN
Calibre_Plugins/eReaderPDB2PML_plugin/windows/psyco/logger.pyo
Normal file
Binary file not shown.
BIN
Calibre_Plugins/eReaderPDB2PML_plugin/windows/psyco/profiler.pyo
Normal file
BIN
Calibre_Plugins/eReaderPDB2PML_plugin/windows/psyco/profiler.pyo
Normal file
Binary file not shown.
BIN
Calibre_Plugins/eReaderPDB2PML_plugin/windows/psyco/support.pyo
Normal file
BIN
Calibre_Plugins/eReaderPDB2PML_plugin/windows/psyco/support.pyo
Normal file
Binary file not shown.
Reference in New Issue
Block a user