Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
0c5e049c
Commit
0c5e049c
authored
Apr 16, 1997
by
Guido van Rossum
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Reindented with 4 spaces.
parent
7cfd31ee
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
813 additions
and
816 deletions
+813
-816
Lib/mhlib.py
Lib/mhlib.py
+813
-816
No files found.
Lib/mhlib.py
View file @
0c5e049c
...
@@ -94,648 +94,646 @@ Error = 'mhlib.Error'
...
@@ -94,648 +94,646 @@ Error = 'mhlib.Error'
class
MH
:
class
MH
:
# Constructor
# Constructor
def
__init__
(
self
,
path
=
None
,
profile
=
None
):
def
__init__
(
self
,
path
=
None
,
profile
=
None
):
if
not
profile
:
profile
=
MH_PROFILE
if
not
profile
:
profile
=
MH_PROFILE
self
.
profile
=
os
.
path
.
expanduser
(
profile
)
self
.
profile
=
os
.
path
.
expanduser
(
profile
)
if
not
path
:
path
=
self
.
getprofile
(
'Path'
)
if
not
path
:
path
=
self
.
getprofile
(
'Path'
)
if
not
path
:
path
=
PATH
if
not
path
:
path
=
PATH
if
not
os
.
path
.
isabs
(
path
)
and
path
[
0
]
!=
'~'
:
if
not
os
.
path
.
isabs
(
path
)
and
path
[
0
]
!=
'~'
:
path
=
os
.
path
.
join
(
'~'
,
path
)
path
=
os
.
path
.
join
(
'~'
,
path
)
path
=
os
.
path
.
expanduser
(
path
)
path
=
os
.
path
.
expanduser
(
path
)
if
not
os
.
path
.
isdir
(
path
):
raise
Error
,
'MH() path not found'
if
not
os
.
path
.
isdir
(
path
):
raise
Error
,
'MH() path not found'
self
.
path
=
path
self
.
path
=
path
# String representation
# String representation
def
__repr__
(
self
):
def
__repr__
(
self
):
return
'MH(%s, %s)'
%
(
`self.path`
,
`self.profile`
)
return
'MH(%s, %s)'
%
(
`self.path`
,
`self.profile`
)
# Routine to print an error. May be overridden by a derived class
# Routine to print an error. May be overridden by a derived class
def
error
(
self
,
msg
,
*
args
):
def
error
(
self
,
msg
,
*
args
):
sys
.
stderr
.
write
(
'MH error: %s
\
n
'
%
(
msg
%
args
))
sys
.
stderr
.
write
(
'MH error: %s
\
n
'
%
(
msg
%
args
))
# Return a profile entry, None if not found
# Return a profile entry, None if not found
def
getprofile
(
self
,
key
):
def
getprofile
(
self
,
key
):
return
pickline
(
self
.
profile
,
key
)
return
pickline
(
self
.
profile
,
key
)
# Return the path (the name of the collection's directory)
# Return the path (the name of the collection's directory)
def
getpath
(
self
):
def
getpath
(
self
):
return
self
.
path
return
self
.
path
# Return the name of the current folder
# Return the name of the current folder
def
getcontext
(
self
):
def
getcontext
(
self
):
context
=
pickline
(
os
.
path
.
join
(
self
.
getpath
(),
'context'
),
context
=
pickline
(
os
.
path
.
join
(
self
.
getpath
(),
'context'
),
'Current-Folder'
)
'Current-Folder'
)
if
not
context
:
context
=
'inbox'
if
not
context
:
context
=
'inbox'
return
context
return
context
# Set the name of the current folder
# Set the name of the current folder
def
setcontext
(
self
,
context
):
def
setcontext
(
self
,
context
):
fn
=
os
.
path
.
join
(
self
.
getpath
(),
'context'
)
fn
=
os
.
path
.
join
(
self
.
getpath
(),
'context'
)
f
=
open
(
fn
,
"w"
)
f
=
open
(
fn
,
"w"
)
f
.
write
(
"Current-Folder: %s
\
n
"
%
context
)
f
.
write
(
"Current-Folder: %s
\
n
"
%
context
)
f
.
close
()
f
.
close
()
# Return the names of the top-level folders
# Return the names of the top-level folders
def
listfolders
(
self
):
def
listfolders
(
self
):
folders
=
[]
folders
=
[]
path
=
self
.
getpath
()
path
=
self
.
getpath
()
for
name
in
os
.
listdir
(
path
):
for
name
in
os
.
listdir
(
path
):
fullname
=
os
.
path
.
join
(
path
,
name
)
fullname
=
os
.
path
.
join
(
path
,
name
)
if
os
.
path
.
isdir
(
fullname
):
if
os
.
path
.
isdir
(
fullname
):
folders
.
append
(
name
)
folders
.
append
(
name
)
folders
.
sort
()
folders
.
sort
()
return
folders
return
folders
# Return the names of the subfolders in a given folder
# Return the names of the subfolders in a given folder
# (prefixed with the given folder name)
# (prefixed with the given folder name)
def
listsubfolders
(
self
,
name
):
def
listsubfolders
(
self
,
name
):
fullname
=
os
.
path
.
join
(
self
.
path
,
name
)
fullname
=
os
.
path
.
join
(
self
.
path
,
name
)
# Get the link count so we can avoid listing folders
# Get the link count so we can avoid listing folders
# that have no subfolders.
# that have no subfolders.
st
=
os
.
stat
(
fullname
)
st
=
os
.
stat
(
fullname
)
nlinks
=
st
[
ST_NLINK
]
nlinks
=
st
[
ST_NLINK
]
if
nlinks
<=
2
:
return
[]
subfolders
=
[]
subnames
=
os
.
listdir
(
fullname
)
for
subname
in
subnames
:
fullsubname
=
os
.
path
.
join
(
fullname
,
subname
)
if
os
.
path
.
isdir
(
fullsubname
):
name_subname
=
os
.
path
.
join
(
name
,
subname
)
subfolders
.
append
(
name_subname
)
# Stop looking for subfolders when
# we've seen them all
nlinks
=
nlinks
-
1
if
nlinks
<=
2
:
if
nlinks
<=
2
:
return
[]
break
subfolders
=
[]
subfolders
.
sort
()
subnames
=
os
.
listdir
(
fullname
)
return
subfolders
for
subname
in
subnames
:
fullsubname
=
os
.
path
.
join
(
fullname
,
subname
)
# Return the names of all folders, including subfolders, recursively
if
os
.
path
.
isdir
(
fullsubname
):
def
listallfolders
(
self
):
name_subname
=
os
.
path
.
join
(
name
,
subname
)
return
self
.
listallsubfolders
(
''
)
subfolders
.
append
(
name_subname
)
# Stop looking for subfolders when
# Return the names of subfolders in a given folder, recursively
# we've seen them all
def
listallsubfolders
(
self
,
name
):
nlinks
=
nlinks
-
1
fullname
=
os
.
path
.
join
(
self
.
path
,
name
)
if
nlinks
<=
2
:
# Get the link count so we can avoid listing folders
break
# that have no subfolders.
subfolders
.
sort
()
st
=
os
.
stat
(
fullname
)
return
subfolders
nlinks
=
st
[
ST_NLINK
]
if
nlinks
<=
2
:
# Return the names of all folders, including subfolders, recursively
return
[]
def
listallfolders
(
self
):
subfolders
=
[]
return
self
.
listallsubfolders
(
''
)
subnames
=
os
.
listdir
(
fullname
)
for
subname
in
subnames
:
# Return the names of subfolders in a given folder, recursively
if
subname
[
0
]
==
','
or
isnumeric
(
subname
):
continue
def
listallsubfolders
(
self
,
name
):
fullsubname
=
os
.
path
.
join
(
fullname
,
subname
)
fullname
=
os
.
path
.
join
(
self
.
path
,
name
)
if
os
.
path
.
isdir
(
fullsubname
):
# Get the link count so we can avoid listing folders
name_subname
=
os
.
path
.
join
(
name
,
subname
)
# that have no subfolders.
subfolders
.
append
(
name_subname
)
st
=
os
.
stat
(
fullname
)
if
not
os
.
path
.
islink
(
fullsubname
):
nlinks
=
st
[
ST_NLINK
]
subsubfolders
=
self
.
listallsubfolders
(
name_subname
)
subfolders
=
subfolders
+
subsubfolders
# Stop looking for subfolders when
# we've seen them all
nlinks
=
nlinks
-
1
if
nlinks
<=
2
:
if
nlinks
<=
2
:
return
[]
break
subfolders
=
[]
subfolders
.
sort
()
subnames
=
os
.
listdir
(
fullname
)
return
subfolders
for
subname
in
subnames
:
if
subname
[
0
]
==
','
or
isnumeric
(
subname
):
continue
# Return a new Folder object for the named folder
fullsubname
=
os
.
path
.
join
(
fullname
,
subname
)
def
openfolder
(
self
,
name
):
if
os
.
path
.
isdir
(
fullsubname
):
return
Folder
(
self
,
name
)
name_subname
=
os
.
path
.
join
(
name
,
subname
)
subfolders
.
append
(
name_subname
)
# Create a new folder. This raises os.error if the folder
if
not
os
.
path
.
islink
(
fullsubname
):
# cannot be created
subsubfolders
=
self
.
listallsubfolders
(
def
makefolder
(
self
,
name
):
name_subname
)
protect
=
pickline
(
self
.
profile
,
'Folder-Protect'
)
subfolders
=
subfolders
+
subsubfolders
if
protect
and
isnumeric
(
protect
):
# Stop looking for subfolders when
mode
=
string
.
atoi
(
protect
,
8
)
# we've seen them all
else
:
nlinks
=
nlinks
-
1
mode
=
FOLDER_PROTECT
if
nlinks
<=
2
:
os
.
mkdir
(
os
.
path
.
join
(
self
.
getpath
(),
name
),
mode
)
break
subfolders
.
sort
()
# Delete a folder. This removes files in the folder but not
return
subfolders
# subdirectories. If deleting the folder itself fails it
# raises os.error
# Return a new Folder object for the named folder
def
deletefolder
(
self
,
name
):
def
openfolder
(
self
,
name
):
fullname
=
os
.
path
.
join
(
self
.
getpath
(),
name
)
return
Folder
(
self
,
name
)
for
subname
in
os
.
listdir
(
fullname
):
fullsubname
=
os
.
path
.
join
(
fullname
,
subname
)
# Create a new folder. This raises os.error if the folder
try
:
# cannot be created
os
.
unlink
(
fullsubname
)
def
makefolder
(
self
,
name
):
except
os
.
error
:
protect
=
pickline
(
self
.
profile
,
'Folder-Protect'
)
self
.
error
(
'%s not deleted, continuing...'
%
if
protect
and
isnumeric
(
protect
):
fullsubname
)
mode
=
string
.
atoi
(
protect
,
8
)
os
.
rmdir
(
fullname
)
else
:
mode
=
FOLDER_PROTECT
os
.
mkdir
(
os
.
path
.
join
(
self
.
getpath
(),
name
),
mode
)
# Delete a folder. This removes files in the folder but not
# subdirectories. If deleting the folder itself fails it
# raises os.error
def
deletefolder
(
self
,
name
):
fullname
=
os
.
path
.
join
(
self
.
getpath
(),
name
)
for
subname
in
os
.
listdir
(
fullname
):
fullsubname
=
os
.
path
.
join
(
fullname
,
subname
)
try
:
os
.
unlink
(
fullsubname
)
except
os
.
error
:
self
.
error
(
'%s not deleted, continuing...'
%
fullsubname
)
os
.
rmdir
(
fullname
)
# Class representing a particular folder
# Class representing a particular folder
numericprog
=
regex
.
compile
(
'^[1-9][0-9]*$'
)
numericprog
=
regex
.
compile
(
'^[1-9][0-9]*$'
)
def
isnumeric
(
str
):
def
isnumeric
(
str
):
return
numericprog
.
match
(
str
)
>=
0
return
numericprog
.
match
(
str
)
>=
0
class
Folder
:
class
Folder
:
# Constructor
# Constructor
def
__init__
(
self
,
mh
,
name
):
def
__init__
(
self
,
mh
,
name
):
self
.
mh
=
mh
self
.
mh
=
mh
self
.
name
=
name
self
.
name
=
name
if
not
os
.
path
.
isdir
(
self
.
getfullname
()):
if
not
os
.
path
.
isdir
(
self
.
getfullname
()):
raise
Error
,
'no folder %s'
%
name
raise
Error
,
'no folder %s'
%
name
# String representation
# String representation
def
__repr__
(
self
):
def
__repr__
(
self
):
return
'Folder(%s, %s)'
%
(
`self.mh`
,
`self.name`
)
return
'Folder(%s, %s)'
%
(
`self.mh`
,
`self.name`
)
# Error message handler
# Error message handler
def
error
(
self
,
*
args
):
def
error
(
self
,
*
args
):
apply
(
self
.
mh
.
error
,
args
)
apply
(
self
.
mh
.
error
,
args
)
# Return the full pathname of the folder
# Return the full pathname of the folder
def
getfullname
(
self
):
def
getfullname
(
self
):
return
os
.
path
.
join
(
self
.
mh
.
path
,
self
.
name
)
return
os
.
path
.
join
(
self
.
mh
.
path
,
self
.
name
)
# Return the full pathname of the folder's sequences file
# Return the full pathname of the folder's sequences file
def
getsequencesfilename
(
self
):
def
getsequencesfilename
(
self
):
return
os
.
path
.
join
(
self
.
getfullname
(),
MH_SEQUENCES
)
return
os
.
path
.
join
(
self
.
getfullname
(),
MH_SEQUENCES
)
# Return the full pathname of a message in the folder
# Return the full pathname of a message in the folder
def
getmessagefilename
(
self
,
n
):
def
getmessagefilename
(
self
,
n
):
return
os
.
path
.
join
(
self
.
getfullname
(),
str
(
n
))
return
os
.
path
.
join
(
self
.
getfullname
(),
str
(
n
))
# Return list of direct subfolders
# Return list of direct subfolders
def
listsubfolders
(
self
):
def
listsubfolders
(
self
):
return
self
.
mh
.
listsubfolders
(
self
.
name
)
return
self
.
mh
.
listsubfolders
(
self
.
name
)
# Return list of all subfolders
# Return list of all subfolders
def
listallsubfolders
(
self
):
def
listallsubfolders
(
self
):
return
self
.
mh
.
listallsubfolders
(
self
.
name
)
return
self
.
mh
.
listallsubfolders
(
self
.
name
)
# Return the list of messages currently present in the folder.
# Return the list of messages currently present in the folder.
# As a side effect, set self.last to the last message (or 0)
# As a side effect, set self.last to the last message (or 0)
def
listmessages
(
self
):
def
listmessages
(
self
):
messages
=
[]
messages
=
[]
match
=
numericprog
.
match
match
=
numericprog
.
match
append
=
messages
.
append
append
=
messages
.
append
for
name
in
os
.
listdir
(
self
.
getfullname
()):
for
name
in
os
.
listdir
(
self
.
getfullname
()):
if
match
(
name
)
>=
0
:
if
match
(
name
)
>=
0
:
append
(
name
)
append
(
name
)
messages
=
map
(
string
.
atoi
,
messages
)
messages
=
map
(
string
.
atoi
,
messages
)
messages
.
sort
()
messages
.
sort
()
if
messages
:
if
messages
:
self
.
last
=
messages
[
-
1
]
self
.
last
=
messages
[
-
1
]
else
:
else
:
self
.
last
=
0
self
.
last
=
0
return
messages
return
messages
# Return the set of sequences for the folder
# Return the set of sequences for the folder
def
getsequences
(
self
):
def
getsequences
(
self
):
sequences
=
{}
sequences
=
{}
fullname
=
self
.
getsequencesfilename
()
fullname
=
self
.
getsequencesfilename
()
try
:
try
:
f
=
open
(
fullname
,
'r'
)
f
=
open
(
fullname
,
'r'
)
except
IOError
:
except
IOError
:
return
sequences
return
sequences
while
1
:
while
1
:
line
=
f
.
readline
()
line
=
f
.
readline
()
if
not
line
:
break
if
not
line
:
break
fields
=
string
.
splitfields
(
line
,
':'
)
fields
=
string
.
splitfields
(
line
,
':'
)
if
len
(
fields
)
<>
2
:
if
len
(
fields
)
<>
2
:
self
.
error
(
'bad sequence in %s: %s'
%
self
.
error
(
'bad sequence in %s: %s'
%
(
fullname
,
string
.
strip
(
line
)))
(
fullname
,
string
.
strip
(
line
)))
key
=
string
.
strip
(
fields
[
0
])
key
=
string
.
strip
(
fields
[
0
])
value
=
IntSet
(
string
.
strip
(
fields
[
1
]),
' '
).
tolist
()
value
=
IntSet
(
string
.
strip
(
fields
[
1
]),
' '
).
tolist
()
sequences
[
key
]
=
value
sequences
[
key
]
=
value
return
sequences
return
sequences
# Write the set of sequences back to the folder
# Write the set of sequences back to the folder
def
putsequences
(
self
,
sequences
):
def
putsequences
(
self
,
sequences
):
fullname
=
self
.
getsequencesfilename
()
fullname
=
self
.
getsequencesfilename
()
f
=
None
f
=
None
for
key
in
sequences
.
keys
():
for
key
in
sequences
.
keys
():
s
=
IntSet
(
''
,
' '
)
s
=
IntSet
(
''
,
' '
)
s
.
fromlist
(
sequences
[
key
])
s
.
fromlist
(
sequences
[
key
])
if
not
f
:
f
=
open
(
fullname
,
'w'
)
if
not
f
:
f
=
open
(
fullname
,
'w'
)
f
.
write
(
'%s: %s
\
n
'
%
(
key
,
s
.
tostring
()))
f
.
write
(
'%s: %s
\
n
'
%
(
key
,
s
.
tostring
()))
if
not
f
:
if
not
f
:
try
:
try
:
os
.
unlink
(
fullname
)
os
.
unlink
(
fullname
)
except
os
.
error
:
except
os
.
error
:
pass
pass
else
:
else
:
f
.
close
()
f
.
close
()
# Return the current message. Raise KeyError when there is none
# Return the current message. Raise KeyError when there is none
def
getcurrent
(
self
):
def
getcurrent
(
self
):
seqs
=
self
.
getsequences
()
try
:
return
max
(
seqs
[
'cur'
])
except
(
ValueError
,
KeyError
):
raise
Error
,
"no cur message"
# Set the current message
def
setcurrent
(
self
,
n
):
updateline
(
self
.
getsequencesfilename
(),
'cur'
,
str
(
n
),
0
)
# Parse an MH sequence specification into a message list.
# Attempt to mimic mh-sequence(5) as close as possible.
# Also attempt to mimic observed behavior regarding which
# conditions cause which error messages
def
parsesequence
(
self
,
seq
):
# XXX Still not complete (see mh-format(5)).
# Missing are:
# - 'prev', 'next' as count
# - Sequence-Negation option
all
=
self
.
listmessages
()
# Observed behavior: test for empty folder is done first
if
not
all
:
raise
Error
,
"no messages in %s"
%
self
.
name
# Common case first: all is frequently the default
if
seq
==
'all'
:
return
all
# Test for X:Y before X-Y because 'seq:-n' matches both
i
=
string
.
find
(
seq
,
':'
)
if
i
>=
0
:
head
,
dir
,
tail
=
seq
[:
i
],
''
,
seq
[
i
+
1
:]
if
tail
[:
1
]
in
'-+'
:
dir
,
tail
=
tail
[:
1
],
tail
[
1
:]
if
not
isnumeric
(
tail
):
raise
Error
,
"bad message list %s"
%
seq
try
:
count
=
string
.
atoi
(
tail
)
except
(
ValueError
,
OverflowError
):
# Can't use sys.maxint because of i+count below
count
=
len
(
all
)
try
:
anchor
=
self
.
_parseindex
(
head
,
all
)
except
Error
,
msg
:
seqs
=
self
.
getsequences
()
seqs
=
self
.
getsequences
()
try
:
if
not
seqs
.
has_key
(
head
):
return
max
(
seqs
[
'cur'
])
if
not
msg
:
except
(
ValueError
,
KeyError
):
msg
=
"bad message list %s"
%
seq
raise
Error
,
"no cur message"
raise
Error
,
msg
,
sys
.
exc_traceback
msgs
=
seqs
[
head
]
# Set the current message
if
not
msgs
:
def
setcurrent
(
self
,
n
):
raise
Error
,
"sequence %s empty"
%
head
updateline
(
self
.
getsequencesfilename
(),
'cur'
,
str
(
n
),
0
)
if
dir
==
'-'
:
return
msgs
[
-
count
:]
# Parse an MH sequence specification into a message list.
# Attempt to mimic mh-sequence(5) as close as possible.
# Also attempt to mimic observed behavior regarding which
# conditions cause which error messages
def
parsesequence
(
self
,
seq
):
# XXX Still not complete (see mh-format(5)).
# Missing are:
# - 'prev', 'next' as count
# - Sequence-Negation option
all
=
self
.
listmessages
()
# Observed behavior: test for empty folder is done first
if
not
all
:
raise
Error
,
"no messages in %s"
%
self
.
name
# Common case first: all is frequently the default
if
seq
==
'all'
:
return
all
# Test for X:Y before X-Y because 'seq:-n' matches both
i
=
string
.
find
(
seq
,
':'
)
if
i
>=
0
:
head
,
dir
,
tail
=
seq
[:
i
],
''
,
seq
[
i
+
1
:]
if
tail
[:
1
]
in
'-+'
:
dir
,
tail
=
tail
[:
1
],
tail
[
1
:]
if
not
isnumeric
(
tail
):
raise
Error
,
"bad message list %s"
%
seq
try
:
count
=
string
.
atoi
(
tail
)
except
(
ValueError
,
OverflowError
):
# Can't use sys.maxint because of i+count below
count
=
len
(
all
)
try
:
anchor
=
self
.
_parseindex
(
head
,
all
)
except
Error
,
msg
:
seqs
=
self
.
getsequences
()
if
not
seqs
.
has_key
(
head
):
if
not
msg
:
msg
=
"bad message list %s"
%
seq
raise
Error
,
msg
,
sys
.
exc_traceback
msgs
=
seqs
[
head
]
if
not
msgs
:
raise
Error
,
"sequence %s empty"
%
head
if
dir
==
'-'
:
return
msgs
[
-
count
:]
else
:
return
msgs
[:
count
]
else
:
if
not
dir
:
if
head
in
(
'prev'
,
'last'
):
dir
=
'-'
if
dir
==
'-'
:
i
=
bisect
(
all
,
anchor
)
return
all
[
max
(
0
,
i
-
count
):
i
]
else
:
i
=
bisect
(
all
,
anchor
-
1
)
return
all
[
i
:
i
+
count
]
# Test for X-Y next
i
=
string
.
find
(
seq
,
'-'
)
if
i
>=
0
:
begin
=
self
.
_parseindex
(
seq
[:
i
],
all
)
end
=
self
.
_parseindex
(
seq
[
i
+
1
:],
all
)
i
=
bisect
(
all
,
begin
-
1
)
j
=
bisect
(
all
,
end
)
r
=
all
[
i
:
j
]
if
not
r
:
raise
Error
,
"bad message list %s"
%
seq
return
r
# Neither X:Y nor X-Y; must be a number or a (pseudo-)sequence
try
:
n
=
self
.
_parseindex
(
seq
,
all
)
except
Error
,
msg
:
seqs
=
self
.
getsequences
()
if
not
seqs
.
has_key
(
seq
):
if
not
msg
:
msg
=
"bad message list %s"
%
seq
raise
Error
,
msg
return
seqs
[
seq
]
else
:
else
:
if
n
not
in
all
:
return
msgs
[:
count
]
if
isnumeric
(
seq
):
else
:
raise
Error
,
\
if
not
dir
:
"message %d doesn't exist"
%
n
if
head
in
(
'prev'
,
'last'
):
else
:
dir
=
'-'
raise
Error
,
"no %s message"
%
seq
if
dir
==
'-'
:
else
:
i
=
bisect
(
all
,
anchor
)
return
[
n
]
return
all
[
max
(
0
,
i
-
count
):
i
]
else
:
# Internal: parse a message number (or cur, first, etc.)
i
=
bisect
(
all
,
anchor
-
1
)
def
_parseindex
(
self
,
seq
,
all
):
return
all
[
i
:
i
+
count
]
# Test for X-Y next
i
=
string
.
find
(
seq
,
'-'
)
if
i
>=
0
:
begin
=
self
.
_parseindex
(
seq
[:
i
],
all
)
end
=
self
.
_parseindex
(
seq
[
i
+
1
:],
all
)
i
=
bisect
(
all
,
begin
-
1
)
j
=
bisect
(
all
,
end
)
r
=
all
[
i
:
j
]
if
not
r
:
raise
Error
,
"bad message list %s"
%
seq
return
r
# Neither X:Y nor X-Y; must be a number or a (pseudo-)sequence
try
:
n
=
self
.
_parseindex
(
seq
,
all
)
except
Error
,
msg
:
seqs
=
self
.
getsequences
()
if
not
seqs
.
has_key
(
seq
):
if
not
msg
:
msg
=
"bad message list %s"
%
seq
raise
Error
,
msg
return
seqs
[
seq
]
else
:
if
n
not
in
all
:
if
isnumeric
(
seq
):
if
isnumeric
(
seq
):
try
:
raise
Error
,
"message %d doesn't exist"
%
n
return
string
.
atoi
(
seq
)
else
:
except
(
OverflowError
,
ValueError
):
raise
Error
,
"no %s message"
%
seq
return
sys
.
maxint
else
:
if
seq
in
(
'cur'
,
'.'
):
return
[
n
]
return
self
.
getcurrent
()
if
seq
==
'first'
:
# Internal: parse a message number (or cur, first, etc.)
return
all
[
0
]
def
_parseindex
(
self
,
seq
,
all
):
if
seq
==
'last'
:
if
isnumeric
(
seq
):
return
all
[
-
1
]
try
:
if
seq
==
'next'
:
return
string
.
atoi
(
seq
)
n
=
self
.
getcurrent
()
except
(
OverflowError
,
ValueError
):
i
=
bisect
(
all
,
n
)
return
sys
.
maxint
try
:
if
seq
in
(
'cur'
,
'.'
):
return
all
[
i
]
return
self
.
getcurrent
()
except
IndexError
:
if
seq
==
'first'
:
raise
Error
,
"no next message"
return
all
[
0
]
if
seq
==
'prev'
:
if
seq
==
'last'
:
n
=
self
.
getcurrent
()
return
all
[
-
1
]
i
=
bisect
(
all
,
n
-
1
)
if
seq
==
'next'
:
if
i
==
0
:
n
=
self
.
getcurrent
()
raise
Error
,
"no prev message"
i
=
bisect
(
all
,
n
)
try
:
try
:
return
all
[
i
-
1
]
return
all
[
i
]
except
IndexError
:
except
IndexError
:
raise
Error
,
"no prev message"
raise
Error
,
"no next message"
raise
Error
,
None
if
seq
==
'prev'
:
n
=
self
.
getcurrent
()
# Open a message -- returns a Message object
i
=
bisect
(
all
,
n
-
1
)
def
openmessage
(
self
,
n
):
if
i
==
0
:
return
Message
(
self
,
n
)
raise
Error
,
"no prev message"
try
:
# Remove one or more messages -- may raise os.error
return
all
[
i
-
1
]
def
removemessages
(
self
,
list
):
except
IndexError
:
errors
=
[]
raise
Error
,
"no prev message"
deleted
=
[]
raise
Error
,
None
for
n
in
list
:
path
=
self
.
getmessagefilename
(
n
)
# Open a message -- returns a Message object
commapath
=
self
.
getmessagefilename
(
','
+
str
(
n
))
def
openmessage
(
self
,
n
):
try
:
return
Message
(
self
,
n
)
os
.
unlink
(
commapath
)
except
os
.
error
:
# Remove one or more messages -- may raise os.error
pass
def
removemessages
(
self
,
list
):
try
:
errors
=
[]
os
.
rename
(
path
,
commapath
)
deleted
=
[]
except
os
.
error
,
msg
:
for
n
in
list
:
errors
.
append
(
msg
)
path
=
self
.
getmessagefilename
(
n
)
else
:
commapath
=
self
.
getmessagefilename
(
','
+
str
(
n
))
deleted
.
append
(
n
)
try
:
if
deleted
:
os
.
unlink
(
commapath
)
self
.
removefromallsequences
(
deleted
)
except
os
.
error
:
if
errors
:
pass
if
len
(
errors
)
==
1
:
try
:
raise
os
.
error
,
errors
[
0
]
os
.
rename
(
path
,
commapath
)
else
:
except
os
.
error
,
msg
:
raise
os
.
error
,
(
'multiple errors:'
,
errors
)
errors
.
append
(
msg
)
else
:
# Refile one or more messages -- may raise os.error.
deleted
.
append
(
n
)
# 'tofolder' is an open folder object
if
deleted
:
def
refilemessages
(
self
,
list
,
tofolder
,
keepsequences
=
0
):
self
.
removefromallsequences
(
deleted
)
errors
=
[]
if
errors
:
refiled
=
{}
if
len
(
errors
)
==
1
:
for
n
in
list
:
raise
os
.
error
,
errors
[
0
]
ton
=
tofolder
.
getlast
()
+
1
else
:
path
=
self
.
getmessagefilename
(
n
)
raise
os
.
error
,
(
'multiple errors:'
,
errors
)
topath
=
tofolder
.
getmessagefilename
(
ton
)
try
:
# Refile one or more messages -- may raise os.error.
os
.
rename
(
path
,
topath
)
# 'tofolder' is an open folder object
except
os
.
error
:
def
refilemessages
(
self
,
list
,
tofolder
,
keepsequences
=
0
):
# Try copying
errors
=
[]
try
:
refiled
=
{}
shutil
.
copy2
(
path
,
topath
)
for
n
in
list
:
os
.
unlink
(
path
)
ton
=
tofolder
.
getlast
()
+
1
except
(
IOError
,
os
.
error
),
msg
:
path
=
self
.
getmessagefilename
(
n
)
errors
.
append
(
msg
)
topath
=
tofolder
.
getmessagefilename
(
ton
)
try
:
try
:
os
.
unlink
(
topath
)
os
.
rename
(
path
,
topath
)
except
os
.
error
:
except
os
.
error
:
pass
# Try copying
continue
tofolder
.
setlast
(
ton
)
refiled
[
n
]
=
ton
if
refiled
:
if
keepsequences
:
tofolder
.
_copysequences
(
self
,
refiled
.
items
())
self
.
removefromallsequences
(
refiled
.
keys
())
if
errors
:
if
len
(
errors
)
==
1
:
raise
os
.
error
,
errors
[
0
]
else
:
raise
os
.
error
,
(
'multiple errors:'
,
errors
)
# Helper for refilemessages() to copy sequences
def
_copysequences
(
self
,
fromfolder
,
refileditems
):
fromsequences
=
fromfolder
.
getsequences
()
tosequences
=
self
.
getsequences
()
changed
=
0
for
name
,
seq
in
fromsequences
.
items
():
try
:
toseq
=
tosequences
[
name
]
new
=
0
except
:
toseq
=
[]
new
=
1
for
fromn
,
ton
in
refileditems
:
if
fromn
in
seq
:
toseq
.
append
(
ton
)
changed
=
1
if
new
and
toseq
:
tosequences
[
name
]
=
toseq
if
changed
:
self
.
putsequences
(
tosequences
)
# Move one message over a specific destination message,
# which may or may not already exist.
def
movemessage
(
self
,
n
,
tofolder
,
ton
):
path
=
self
.
getmessagefilename
(
n
)
# Open it to check that it exists
f
=
open
(
path
)
f
.
close
()
del
f
topath
=
tofolder
.
getmessagefilename
(
ton
)
backuptopath
=
tofolder
.
getmessagefilename
(
',%d'
%
ton
)
try
:
try
:
os
.
rename
(
topath
,
backuptopath
)
shutil
.
copy2
(
path
,
topath
)
except
os
.
error
:
os
.
unlink
(
path
)
except
(
IOError
,
os
.
error
),
msg
:
errors
.
append
(
msg
)
try
:
os
.
unlink
(
topath
)
except
os
.
error
:
pass
pass
try
:
continue
os
.
rename
(
path
,
topath
)
tofolder
.
setlast
(
ton
)
except
os
.
error
:
refiled
[
n
]
=
ton
# Try copying
if
refiled
:
ok
=
0
if
keepsequences
:
try
:
tofolder
.
_copysequences
(
self
,
refiled
.
items
())
tofolder
.
setlast
(
None
)
self
.
removefromallsequences
(
refiled
.
keys
())
shutil
.
copy2
(
path
,
topath
)
if
errors
:
ok
=
1
if
len
(
errors
)
==
1
:
finally
:
raise
os
.
error
,
errors
[
0
]
if
not
ok
:
else
:
try
:
raise
os
.
error
,
(
'multiple errors:'
,
errors
)
os
.
unlink
(
topath
)
except
os
.
error
:
# Helper for refilemessages() to copy sequences
pass
def
_copysequences
(
self
,
fromfolder
,
refileditems
):
os
.
unlink
(
path
)
fromsequences
=
fromfolder
.
getsequences
()
self
.
removefromallsequences
([
n
])
tosequences
=
self
.
getsequences
()
changed
=
0
# Copy one message over a specific destination message,
for
name
,
seq
in
fromsequences
.
items
():
# which may or may not already exist.
try
:
def
copymessage
(
self
,
n
,
tofolder
,
ton
):
toseq
=
tosequences
[
name
]
path
=
self
.
getmessagefilename
(
n
)
new
=
0
# Open it to check that it exists
except
:
f
=
open
(
path
)
toseq
=
[]
f
.
close
()
new
=
1
del
f
for
fromn
,
ton
in
refileditems
:
topath
=
tofolder
.
getmessagefilename
(
ton
)
if
fromn
in
seq
:
backuptopath
=
tofolder
.
getmessagefilename
(
',%d'
%
ton
)
toseq
.
append
(
ton
)
try
:
changed
=
1
os
.
rename
(
topath
,
backuptopath
)
if
new
and
toseq
:
except
os
.
error
:
tosequences
[
name
]
=
toseq
if
changed
:
self
.
putsequences
(
tosequences
)
# Move one message over a specific destination message,
# which may or may not already exist.
def
movemessage
(
self
,
n
,
tofolder
,
ton
):
path
=
self
.
getmessagefilename
(
n
)
# Open it to check that it exists
f
=
open
(
path
)
f
.
close
()
del
f
topath
=
tofolder
.
getmessagefilename
(
ton
)
backuptopath
=
tofolder
.
getmessagefilename
(
',%d'
%
ton
)
try
:
os
.
rename
(
topath
,
backuptopath
)
except
os
.
error
:
pass
try
:
os
.
rename
(
path
,
topath
)
except
os
.
error
:
# Try copying
ok
=
0
try
:
tofolder
.
setlast
(
None
)
shutil
.
copy2
(
path
,
topath
)
ok
=
1
finally
:
if
not
ok
:
try
:
os
.
unlink
(
topath
)
except
os
.
error
:
pass
pass
ok
=
0
os
.
unlink
(
path
)
self
.
removefromallsequences
([
n
])
# Copy one message over a specific destination message,
# which may or may not already exist.
def
copymessage
(
self
,
n
,
tofolder
,
ton
):
path
=
self
.
getmessagefilename
(
n
)
# Open it to check that it exists
f
=
open
(
path
)
f
.
close
()
del
f
topath
=
tofolder
.
getmessagefilename
(
ton
)
backuptopath
=
tofolder
.
getmessagefilename
(
',%d'
%
ton
)
try
:
os
.
rename
(
topath
,
backuptopath
)
except
os
.
error
:
pass
ok
=
0
try
:
tofolder
.
setlast
(
None
)
shutil
.
copy2
(
path
,
topath
)
ok
=
1
finally
:
if
not
ok
:
try
:
try
:
tofolder
.
setlast
(
None
)
os
.
unlink
(
topath
)
shutil
.
copy2
(
path
,
topath
)
except
os
.
error
:
ok
=
1
pass
finally
:
if
not
ok
:
# Remove one or more messages from all sequeuces (including last)
try
:
# -- but not from 'cur'!!!
os
.
unlink
(
topath
)
def
removefromallsequences
(
self
,
list
):
except
os
.
error
:
if
hasattr
(
self
,
'last'
)
and
self
.
last
in
list
:
pass
del
self
.
last
sequences
=
self
.
getsequences
()
# Remove one or more messages from all sequeuces (including last)
changed
=
0
# -- but not from 'cur'!!!
for
name
,
seq
in
sequences
.
items
():
def
removefromallsequences
(
self
,
list
):
if
name
==
'cur'
:
if
hasattr
(
self
,
'last'
)
and
self
.
last
in
list
:
continue
del
self
.
last
for
n
in
list
:
sequences
=
self
.
getsequences
()
if
n
in
seq
:
changed
=
0
seq
.
remove
(
n
)
for
name
,
seq
in
sequences
.
items
():
changed
=
1
if
name
==
'cur'
:
if
not
seq
:
continue
del
sequences
[
name
]
for
n
in
list
:
if
changed
:
if
n
in
seq
:
self
.
putsequences
(
sequences
)
seq
.
remove
(
n
)
changed
=
1
# Return the last message number
if
not
seq
:
def
getlast
(
self
):
del
sequences
[
name
]
if
not
hasattr
(
self
,
'last'
):
if
changed
:
messages
=
self
.
listmessages
()
self
.
putsequences
(
sequences
)
return
self
.
last
# Return the last message number
# Set the last message number
def
getlast
(
self
):
def
setlast
(
self
,
last
):
if
not
hasattr
(
self
,
'last'
):
if
last
is
None
:
messages
=
self
.
listmessages
()
if
hasattr
(
self
,
'last'
):
return
self
.
last
del
self
.
last
else
:
# Set the last message number
self
.
last
=
last
def
setlast
(
self
,
last
):
if
last
is
None
:
if
hasattr
(
self
,
'last'
):
del
self
.
last
else
:
self
.
last
=
last
class
Message
(
mimetools
.
Message
):
class
Message
(
mimetools
.
Message
):
# Constructor
# Constructor
def
__init__
(
self
,
f
,
n
,
fp
=
None
):
def
__init__
(
self
,
f
,
n
,
fp
=
None
):
self
.
folder
=
f
self
.
folder
=
f
self
.
number
=
n
self
.
number
=
n
if
not
fp
:
if
not
fp
:
path
=
f
.
getmessagefilename
(
n
)
path
=
f
.
getmessagefilename
(
n
)
fp
=
open
(
path
,
'r'
)
fp
=
open
(
path
,
'r'
)
mimetools
.
Message
.
__init__
(
self
,
fp
)
mimetools
.
Message
.
__init__
(
self
,
fp
)
# String representation
# String representation
def
__repr__
(
self
):
def
__repr__
(
self
):
return
'Message(%s, %s)'
%
(
repr
(
self
.
folder
),
self
.
number
)
return
'Message(%s, %s)'
%
(
repr
(
self
.
folder
),
self
.
number
)
# Return the message's header text as a string. If an
# Return the message's header text as a string. If an
# argument is specified, it is used as a filter predicate to
# argument is specified, it is used as a filter predicate to
# decide which headers to return (its argument is the header
# decide which headers to return (its argument is the header
# name converted to lower case).
# name converted to lower case).
def
getheadertext
(
self
,
pred
=
None
):
def
getheadertext
(
self
,
pred
=
None
):
if
not
pred
:
if
not
pred
:
return
string
.
joinfields
(
self
.
headers
,
''
)
return
string
.
joinfields
(
self
.
headers
,
''
)
headers
=
[]
headers
=
[]
hit
=
0
hit
=
0
for
line
in
self
.
headers
:
for
line
in
self
.
headers
:
if
line
[
0
]
not
in
string
.
whitespace
:
if
line
[
0
]
not
in
string
.
whitespace
:
i
=
string
.
find
(
line
,
':'
)
i
=
string
.
find
(
line
,
':'
)
if
i
>
0
:
if
i
>
0
:
hit
=
pred
(
string
.
lower
(
line
[:
i
]))
hit
=
pred
(
string
.
lower
(
line
[:
i
]))
if
hit
:
headers
.
append
(
line
)
if
hit
:
headers
.
append
(
line
)
return
string
.
joinfields
(
headers
,
''
)
return
string
.
joinfields
(
headers
,
''
)
# Return the message's body text as string. This undoes a
# Return the message's body text as string. This undoes a
# Content-Transfer-Encoding, but does not interpret other MIME
# Content-Transfer-Encoding, but does not interpret other MIME
# features (e.g. multipart messages). To suppress to
# features (e.g. multipart messages). To suppress to
# decoding, pass a 0 as argument
# decoding, pass a 0 as argument
def
getbodytext
(
self
,
decode
=
1
):
def
getbodytext
(
self
,
decode
=
1
):
self
.
fp
.
seek
(
self
.
startofbody
)
self
.
fp
.
seek
(
self
.
startofbody
)
encoding
=
self
.
getencoding
()
encoding
=
self
.
getencoding
()
if
not
decode
or
encoding
in
(
'7bit'
,
'8bit'
,
'binary'
):
if
not
decode
or
encoding
in
(
'7bit'
,
'8bit'
,
'binary'
):
return
self
.
fp
.
read
()
return
self
.
fp
.
read
()
from
StringIO
import
StringIO
from
StringIO
import
StringIO
output
=
StringIO
()
output
=
StringIO
()
mimetools
.
decode
(
self
.
fp
,
output
,
encoding
)
mimetools
.
decode
(
self
.
fp
,
output
,
encoding
)
return
output
.
getvalue
()
return
output
.
getvalue
()
# Only for multipart messages: return the message's body as a
# Only for multipart messages: return the message's body as a
# list of SubMessage objects. Each submessage object behaves
# list of SubMessage objects. Each submessage object behaves
# (almost) as a Message object.
# (almost) as a Message object.
def
getbodyparts
(
self
):
def
getbodyparts
(
self
):
if
self
.
getmaintype
()
!=
'multipart'
:
if
self
.
getmaintype
()
!=
'multipart'
:
raise
Error
,
\
raise
Error
,
'Content-Type is not multipart/*'
'Content-Type is not multipart/*'
bdry
=
self
.
getparam
(
'boundary'
)
bdry
=
self
.
getparam
(
'boundary'
)
if
not
bdry
:
if
not
bdry
:
raise
Error
,
'multipart/* without boundary param'
raise
Error
,
'multipart/* without boundary param'
self
.
fp
.
seek
(
self
.
startofbody
)
self
.
fp
.
seek
(
self
.
startofbody
)
mf
=
multifile
.
MultiFile
(
self
.
fp
)
mf
=
multifile
.
MultiFile
(
self
.
fp
)
mf
.
push
(
bdry
)
mf
.
push
(
bdry
)
parts
=
[]
parts
=
[]
while
mf
.
next
():
while
mf
.
next
():
n
=
str
(
self
.
number
)
+
'.'
+
`1 + len(parts)`
n
=
str
(
self
.
number
)
+
'.'
+
`1 + len(parts)`
part
=
SubMessage
(
self
.
folder
,
n
,
mf
)
part
=
SubMessage
(
self
.
folder
,
n
,
mf
)
parts
.
append
(
part
)
parts
.
append
(
part
)
mf
.
pop
()
mf
.
pop
()
return
parts
return
parts
# Return body, either a string or a list of messages
# Return body, either a string or a list of messages
def
getbody
(
self
):
def
getbody
(
self
):
if
self
.
getmaintype
()
==
'multipart'
:
if
self
.
getmaintype
()
==
'multipart'
:
return
self
.
getbodyparts
()
return
self
.
getbodyparts
()
else
:
else
:
return
self
.
getbodytext
()
return
self
.
getbodytext
()
class
SubMessage
(
Message
):
class
SubMessage
(
Message
):
# Constructor
# Constructor
def
__init__
(
self
,
f
,
n
,
fp
):
def
__init__
(
self
,
f
,
n
,
fp
):
Message
.
__init__
(
self
,
f
,
n
,
fp
)
Message
.
__init__
(
self
,
f
,
n
,
fp
)
if
self
.
getmaintype
()
==
'multipart'
:
if
self
.
getmaintype
()
==
'multipart'
:
self
.
body
=
Message
.
getbodyparts
(
self
)
self
.
body
=
Message
.
getbodyparts
(
self
)
else
:
else
:
self
.
body
=
Message
.
getbodytext
(
self
)
self
.
body
=
Message
.
getbodytext
(
self
)
# XXX If this is big, should remember file pointers
# XXX If this is big, should remember file pointers
# String representation
# String representation
def
__repr__
(
self
):
def
__repr__
(
self
):
f
,
n
,
fp
=
self
.
folder
,
self
.
number
,
self
.
fp
f
,
n
,
fp
=
self
.
folder
,
self
.
number
,
self
.
fp
return
'SubMessage(%s, %s, %s)'
%
(
f
,
n
,
fp
)
return
'SubMessage(%s, %s, %s)'
%
(
f
,
n
,
fp
)
def
getbodytext
(
self
):
def
getbodytext
(
self
):
if
type
(
self
.
body
)
==
type
(
''
):
if
type
(
self
.
body
)
==
type
(
''
):
return
self
.
body
return
self
.
body
def
getbodyparts
(
self
):
def
getbodyparts
(
self
):
if
type
(
self
.
body
)
==
type
([]):
if
type
(
self
.
body
)
==
type
([]):
return
self
.
body
return
self
.
body
def
getbody
(
self
):
def
getbody
(
self
):
return
self
.
body
return
self
.
body
# Class implementing sets of integers.
# Class implementing sets of integers.
...
@@ -761,225 +759,224 @@ class SubMessage(Message):
...
@@ -761,225 +759,224 @@ class SubMessage(Message):
class
IntSet
:
class
IntSet
:
def
__init__
(
self
,
data
=
None
,
sep
=
','
,
rng
=
'-'
):
def
__init__
(
self
,
data
=
None
,
sep
=
','
,
rng
=
'-'
):
self
.
pairs
=
[]
self
.
pairs
=
[]
self
.
sep
=
sep
self
.
sep
=
sep
self
.
rng
=
rng
self
.
rng
=
rng
if
data
:
self
.
fromstring
(
data
)
if
data
:
self
.
fromstring
(
data
)
def
reset
(
self
):
def
reset
(
self
):
self
.
pairs
=
[]
self
.
pairs
=
[]
def
__cmp__
(
self
,
other
):
def
__cmp__
(
self
,
other
):
return
cmp
(
self
.
pairs
,
other
.
pairs
)
return
cmp
(
self
.
pairs
,
other
.
pairs
)
def
__hash__
(
self
):
def
__hash__
(
self
):
return
hash
(
self
.
pairs
)
return
hash
(
self
.
pairs
)
def
__repr__
(
self
):
def
__repr__
(
self
):
return
'IntSet(%s, %s, %s)'
%
(
`self.tostring()`
,
return
'IntSet(%s, %s, %s)'
%
(
`self.tostring()`
,
`self.sep`
,
`self.rng`
)
`self.sep`
,
`self.rng`
)
def
normalize
(
self
):
def
normalize
(
self
):
self
.
pairs
.
sort
()
self
.
pairs
.
sort
()
i
=
1
i
=
1
while
i
<
len
(
self
.
pairs
):
while
i
<
len
(
self
.
pairs
):
alo
,
ahi
=
self
.
pairs
[
i
-
1
]
alo
,
ahi
=
self
.
pairs
[
i
-
1
]
blo
,
bhi
=
self
.
pairs
[
i
]
blo
,
bhi
=
self
.
pairs
[
i
]
if
ahi
>=
blo
-
1
:
if
ahi
>=
blo
-
1
:
self
.
pairs
[
i
-
1
:
i
+
1
]
=
[(
alo
,
max
(
ahi
,
bhi
))]
self
.
pairs
[
i
-
1
:
i
+
1
]
=
[(
alo
,
max
(
ahi
,
bhi
))]
else
:
else
:
i
=
i
+
1
i
=
i
+
1
def
tostring
(
self
):
def
tostring
(
self
):
s
=
''
s
=
''
for
lo
,
hi
in
self
.
pairs
:
for
lo
,
hi
in
self
.
pairs
:
if
lo
==
hi
:
t
=
`lo`
if
lo
==
hi
:
t
=
`lo`
else
:
t
=
`lo`
+
self
.
rng
+
`hi`
else
:
t
=
`lo`
+
self
.
rng
+
`hi`
if
s
:
s
=
s
+
(
self
.
sep
+
t
)
if
s
:
s
=
s
+
(
self
.
sep
+
t
)
else
:
s
=
t
else
:
s
=
t
return
s
return
s
def
tolist
(
self
):
def
tolist
(
self
):
l
=
[]
l
=
[]
for
lo
,
hi
in
self
.
pairs
:
for
lo
,
hi
in
self
.
pairs
:
m
=
range
(
lo
,
hi
+
1
)
m
=
range
(
lo
,
hi
+
1
)
l
=
l
+
m
l
=
l
+
m
return
l
return
l
def
fromlist
(
self
,
list
):
def
fromlist
(
self
,
list
):
for
i
in
list
:
for
i
in
list
:
self
.
append
(
i
)
self
.
append
(
i
)
def
clone
(
self
):
def
clone
(
self
):
new
=
IntSet
()
new
=
IntSet
()
new
.
pairs
=
self
.
pairs
[:]
new
.
pairs
=
self
.
pairs
[:]
return
new
return
new
def
min
(
self
):
def
min
(
self
):
return
self
.
pairs
[
0
][
0
]
return
self
.
pairs
[
0
][
0
]
def
max
(
self
):
def
max
(
self
):
return
self
.
pairs
[
-
1
][
-
1
]
return
self
.
pairs
[
-
1
][
-
1
]
def
contains
(
self
,
x
):
def
contains
(
self
,
x
):
for
lo
,
hi
in
self
.
pairs
:
for
lo
,
hi
in
self
.
pairs
:
if
lo
<=
x
<=
hi
:
return
1
if
lo
<=
x
<=
hi
:
return
1
return
0
return
0
def
append
(
self
,
x
):
def
append
(
self
,
x
):
for
i
in
range
(
len
(
self
.
pairs
)):
for
i
in
range
(
len
(
self
.
pairs
)):
lo
,
hi
=
self
.
pairs
[
i
]
lo
,
hi
=
self
.
pairs
[
i
]
if
x
<
lo
:
# Need to insert before
if
x
<
lo
:
# Need to insert before
if
x
+
1
==
lo
:
if
x
+
1
==
lo
:
self
.
pairs
[
i
]
=
(
x
,
hi
)
self
.
pairs
[
i
]
=
(
x
,
hi
)
else
:
else
:
self
.
pairs
.
insert
(
i
,
(
x
,
x
))
self
.
pairs
.
insert
(
i
,
(
x
,
x
))
if
i
>
0
and
x
-
1
==
self
.
pairs
[
i
-
1
][
1
]:
if
i
>
0
and
x
-
1
==
self
.
pairs
[
i
-
1
][
1
]:
# Merge with previous
# Merge with previous
self
.
pairs
[
i
-
1
:
i
+
1
]
=
[
self
.
pairs
[
i
-
1
:
i
+
1
]
=
[
(
self
.
pairs
[
i
-
1
][
0
],
(
self
.
pairs
[
i
-
1
][
0
],
self
.
pairs
[
i
][
1
])
self
.
pairs
[
i
][
1
])
]
]
return
return
if
x
<=
hi
:
# Already in set
if
x
<=
hi
:
# Already in set
return
return
i
=
len
(
self
.
pairs
)
-
1
i
=
len
(
self
.
pairs
)
-
1
if
i
>=
0
:
if
i
>=
0
:
lo
,
hi
=
self
.
pairs
[
i
]
lo
,
hi
=
self
.
pairs
[
i
]
if
x
-
1
==
hi
:
if
x
-
1
==
hi
:
self
.
pairs
[
i
]
=
lo
,
x
self
.
pairs
[
i
]
=
lo
,
x
return
return
self
.
pairs
.
append
((
x
,
x
))
self
.
pairs
.
append
((
x
,
x
))
def
addpair
(
self
,
xlo
,
xhi
):
def
addpair
(
self
,
xlo
,
xhi
):
if
xlo
>
xhi
:
return
if
xlo
>
xhi
:
return
self
.
pairs
.
append
((
xlo
,
xhi
))
self
.
pairs
.
append
((
xlo
,
xhi
))
self
.
normalize
()
self
.
normalize
()
def
fromstring
(
self
,
data
):
def
fromstring
(
self
,
data
):
import
string
,
regsub
import
string
,
regsub
new
=
[]
new
=
[]
for
part
in
regsub
.
split
(
data
,
self
.
sep
):
for
part
in
regsub
.
split
(
data
,
self
.
sep
):
list
=
[]
list
=
[]
for
subp
in
regsub
.
split
(
part
,
self
.
rng
):
for
subp
in
regsub
.
split
(
part
,
self
.
rng
):
s
=
string
.
strip
(
subp
)
s
=
string
.
strip
(
subp
)
list
.
append
(
string
.
atoi
(
s
))
list
.
append
(
string
.
atoi
(
s
))
if
len
(
list
)
==
1
:
if
len
(
list
)
==
1
:
new
.
append
((
list
[
0
],
list
[
0
]))
new
.
append
((
list
[
0
],
list
[
0
]))
elif
len
(
list
)
==
2
and
list
[
0
]
<=
list
[
1
]:
elif
len
(
list
)
==
2
and
list
[
0
]
<=
list
[
1
]:
new
.
append
((
list
[
0
],
list
[
1
]))
new
.
append
((
list
[
0
],
list
[
1
]))
else
:
else
:
raise
ValueError
,
'bad data passed to IntSet'
raise
ValueError
,
'bad data passed to IntSet'
self
.
pairs
=
self
.
pairs
+
new
self
.
pairs
=
self
.
pairs
+
new
self
.
normalize
()
self
.
normalize
()
# Subroutines to read/write entries in .mh_profile and .mh_sequences
# Subroutines to read/write entries in .mh_profile and .mh_sequences
def
pickline
(
file
,
key
,
casefold
=
1
):
def
pickline
(
file
,
key
,
casefold
=
1
):
try
:
try
:
f
=
open
(
file
,
'r'
)
f
=
open
(
file
,
'r'
)
except
IOError
:
except
IOError
:
return
None
pat
=
key
+
':'
if
casefold
:
prog
=
regex
.
compile
(
pat
,
regex
.
casefold
)
else
:
prog
=
regex
.
compile
(
pat
)
while
1
:
line
=
f
.
readline
()
if
not
line
:
break
if
prog
.
match
(
line
)
>=
0
:
text
=
line
[
len
(
key
)
+
1
:]
while
1
:
line
=
f
.
readline
()
if
not
line
or
\
line
[
0
]
not
in
string
.
whitespace
:
break
text
=
text
+
line
return
string
.
strip
(
text
)
return
None
return
None
pat
=
key
+
':'
if
casefold
:
prog
=
regex
.
compile
(
pat
,
regex
.
casefold
)
else
:
prog
=
regex
.
compile
(
pat
)
while
1
:
line
=
f
.
readline
()
if
not
line
:
break
if
prog
.
match
(
line
)
>=
0
:
text
=
line
[
len
(
key
)
+
1
:]
while
1
:
line
=
f
.
readline
()
if
not
line
or
line
[
0
]
not
in
string
.
whitespace
:
break
text
=
text
+
line
return
string
.
strip
(
text
)
return
None
def
updateline
(
file
,
key
,
value
,
casefold
=
1
):
def
updateline
(
file
,
key
,
value
,
casefold
=
1
):
try
:
try
:
f
=
open
(
file
,
'r'
)
f
=
open
(
file
,
'r'
)
lines
=
f
.
readlines
()
lines
=
f
.
readlines
()
f
.
close
()
except
IOError
:
lines
=
[]
pat
=
key
+
':
\
(.*
\
)
\
n
'
if
casefold
:
prog
=
regex
.
compile
(
pat
,
regex
.
casefold
)
else
:
prog
=
regex
.
compile
(
pat
)
if
value
is
None
:
newline
=
None
else
:
newline
=
'%s: %s
\
n
'
%
(
key
,
value
)
for
i
in
range
(
len
(
lines
)):
line
=
lines
[
i
]
if
prog
.
match
(
line
)
==
len
(
line
):
if
newline
is
None
:
del
lines
[
i
]
else
:
lines
[
i
]
=
newline
break
else
:
if
newline
is
not
None
:
lines
.
append
(
newline
)
tempfile
=
file
+
"~"
f
=
open
(
tempfile
,
'w'
)
for
line
in
lines
:
f
.
write
(
line
)
f
.
close
()
f
.
close
()
os
.
rename
(
tempfile
,
file
)
except
IOError
:
lines
=
[]
pat
=
key
+
':
\
(.*
\
)
\
n
'
if
casefold
:
prog
=
regex
.
compile
(
pat
,
regex
.
casefold
)
else
:
prog
=
regex
.
compile
(
pat
)
if
value
is
None
:
newline
=
None
else
:
newline
=
'%s: %s
\
n
'
%
(
key
,
value
)
for
i
in
range
(
len
(
lines
)):
line
=
lines
[
i
]
if
prog
.
match
(
line
)
==
len
(
line
):
if
newline
is
None
:
del
lines
[
i
]
else
:
lines
[
i
]
=
newline
break
else
:
if
newline
is
not
None
:
lines
.
append
(
newline
)
tempfile
=
file
+
"~"
f
=
open
(
tempfile
,
'w'
)
for
line
in
lines
:
f
.
write
(
line
)
f
.
close
()
os
.
rename
(
tempfile
,
file
)
# Test program
# Test program
def
test
():
def
test
():
global
mh
,
f
global
mh
,
f
os
.
system
(
'rm -rf $HOME/Mail/@test'
)
os
.
system
(
'rm -rf $HOME/Mail/@test'
)
mh
=
MH
()
mh
=
MH
()
def
do
(
s
):
print
s
;
print
eval
(
s
)
def
do
(
s
):
print
s
;
print
eval
(
s
)
do
(
'mh.listfolders()'
)
do
(
'mh.listfolders()'
)
do
(
'mh.listallfolders()'
)
do
(
'mh.listallfolders()'
)
testfolders
=
[
'@test'
,
'@test/test1'
,
'@test/test2'
,
testfolders
=
[
'@test'
,
'@test/test1'
,
'@test/test2'
,
'@test/test1/test11'
,
'@test/test1/test12'
,
'@test/test1/test11'
,
'@test/test1/test12'
,
'@test/test1/test11/test111'
]
'@test/test1/test11/test111'
]
for
t
in
testfolders
:
do
(
'mh.makefolder(%s)'
%
`t`
)
for
t
in
testfolders
:
do
(
'mh.makefolder(%s)'
%
`t`
)
do
(
'mh.listsubfolders(
\
'
@test
\
'
)'
)
do
(
'mh.listsubfolders(
\
'
@test
\
'
)'
)
do
(
'mh.listallsubfolders(
\
'
@test
\
'
)'
)
do
(
'mh.listallsubfolders(
\
'
@test
\
'
)'
)
f
=
mh
.
openfolder
(
'@test'
)
f
=
mh
.
openfolder
(
'@test'
)
do
(
'f.listsubfolders()'
)
do
(
'f.listsubfolders()'
)
do
(
'f.listallsubfolders()'
)
do
(
'f.listallsubfolders()'
)
do
(
'f.getsequences()'
)
do
(
'f.getsequences()'
)
seqs
=
f
.
getsequences
()
seqs
=
f
.
getsequences
()
seqs
[
'foo'
]
=
IntSet
(
'1-10 12-20'
,
' '
).
tolist
()
seqs
[
'foo'
]
=
IntSet
(
'1-10 12-20'
,
' '
).
tolist
()
print
seqs
print
seqs
f
.
putsequences
(
seqs
)
f
.
putsequences
(
seqs
)
do
(
'f.getsequences()'
)
do
(
'f.getsequences()'
)
testfolders
.
reverse
()
testfolders
.
reverse
()
for
t
in
testfolders
:
do
(
'mh.deletefolder(%s)'
%
`t`
)
for
t
in
testfolders
:
do
(
'mh.deletefolder(%s)'
%
`t`
)
do
(
'mh.getcontext()'
)
do
(
'mh.getcontext()'
)
context
=
mh
.
getcontext
()
context
=
mh
.
getcontext
()
f
=
mh
.
openfolder
(
context
)
f
=
mh
.
openfolder
(
context
)
do
(
'f.getcurrent()'
)
do
(
'f.getcurrent()'
)
for
seq
in
[
'first'
,
'last'
,
'cur'
,
'.'
,
'prev'
,
'next'
,
for
seq
in
[
'first'
,
'last'
,
'cur'
,
'.'
,
'prev'
,
'next'
,
'first:3'
,
'last:3'
,
'cur:3'
,
'cur:-3'
,
'first:3'
,
'last:3'
,
'cur:3'
,
'cur:-3'
,
'prev:3'
,
'next:3'
,
'prev:3'
,
'next:3'
,
'1:3'
,
'1:-3'
,
'100:3'
,
'100:-3'
,
'10000:3'
,
'10000:-3'
,
'1:3'
,
'1:-3'
,
'100:3'
,
'100:-3'
,
'10000:3'
,
'10000:-3'
,
'all'
]:
'all'
]:
try
:
try
:
do
(
'f.parsesequence(%s)'
%
`seq`
)
do
(
'f.parsesequence(%s)'
%
`seq`
)
except
Error
,
msg
:
except
Error
,
msg
:
print
"Error:"
,
msg
print
"Error:"
,
msg
stuff
=
os
.
popen
(
"pick %s 2>/dev/null"
%
`seq`
).
read
()
stuff
=
os
.
popen
(
"pick %s 2>/dev/null"
%
`seq`
).
read
()
list
=
map
(
string
.
atoi
,
string
.
split
(
stuff
))
list
=
map
(
string
.
atoi
,
string
.
split
(
stuff
))
print
list
,
"<-- pick"
print
list
,
"<-- pick"
do
(
'f.listmessages()'
)
do
(
'f.listmessages()'
)
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
test
()
test
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment