Skip to content

Commit 2ec2b79

Browse files
committed
Migrate all Python scripts to Python 3.
Most of them are now _mandatory_ P3 scripts, because I'm tired of maintaining everything to be compatible with both versions. The current exceptions are gdb.py (which has to live with whatever gdb gives it), and kh2reg.py (which is actually designed for other people to use, and some of them might still be stuck on P2 for the moment).
1 parent cdffb99 commit 2ec2b79

File tree

15 files changed

+116
-93
lines changed

15 files changed

+116
-93
lines changed

contrib/encodelib.py

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,21 @@
44
# The idea of this is that you can use it to manually construct key
55
# exchange sequences of interesting kinds, for testing purposes.
66

7-
import struct, random
7+
import sys
8+
import struct
9+
import random
10+
11+
assert sys.version_info[:2] >= (3,0), "This is Python 3 code"
12+
13+
def tobytes(s):
14+
return s if isinstance(s, bytes) else s.encode('ASCII')
815

916
def boolean(b):
10-
return "\1" if b else "\0"
17+
return b"\1" if b else b"\0"
1118

1219
def byte(b):
1320
assert 0 <= b < 0x100
14-
return chr(b)
21+
return bytes([b])
1522

1623
def uint32(u):
1724
assert 0 <= u < 0x100000000
@@ -22,25 +29,24 @@ def uint64(u):
2229
return struct.pack(">L", u)
2330

2431
def string(s):
25-
return uint32(len(s)) + s
32+
return uint32(len(s)) + tobytes(s)
2633

2734
def mpint(m):
28-
s = ""
29-
lastbyte = 0
35+
s = []
3036
while m > 0:
31-
lastbyte = m & 0xFF
32-
s = chr(lastbyte) + s
37+
s.append(m & 0xFF)
3338
m >>= 8
34-
if lastbyte & 0x80:
35-
s = "\0" + s
36-
return string(s)
39+
if len(s) > 0 and (s[-1] & 0x80):
40+
s.append(0)
41+
s.reverse()
42+
return string(bytes(s))
3743

3844
def name_list(ns):
39-
s = ""
40-
for n in ns:
41-
assert "," not in n
42-
if s != "":
43-
s += ","
45+
s = b""
46+
for n in map(tobytes, ns):
47+
assert b"," not in n
48+
if s != b"":
49+
s += b","
4450
s += n
4551
return string(s)
4652

@@ -52,7 +58,7 @@ def ssh_rsa_signature_blob(signature):
5258

5359
def greeting(string):
5460
# Greeting at the start of an SSH connection.
55-
return string + "\r\n"
61+
return tobytes(string) + b"\r\n"
5662

5763
# Packet types.
5864
SSH2_MSG_DISCONNECT = 1
@@ -122,8 +128,5 @@ def decode_uint32(s):
122128
def read_clearpkt(fh):
123129
length_field = fh.read(4)
124130
s = fh.read(decode_uint32(length_field))
125-
import sys
126-
padlen = ord(s[0])
127-
s = s[1:-padlen]
128-
msgtype = ord(s[0])
129-
return msgtype, s[1:]
131+
padlen, msgtype = s[:2]
132+
return msgtype, s[2:-padlen]

contrib/kh2reg.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#! /usr/bin/env python
1+
#!/usr/bin/env python3
22

33
# Convert OpenSSH known_hosts and known_hosts2 files to "new format" PuTTY
44
# host keys.

contrib/make1305.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
#!/usr/bin/env python
1+
#!/usr/bin/env python3
22

33
import sys
44
import string
55
from collections import namedtuple
66

7+
assert sys.version_info[:2] >= (3,0), "This is Python 3 code"
8+
79
class Multiprecision(object):
810
def __init__(self, target, minval, maxval, words):
911
self.target = target
@@ -89,21 +91,21 @@ def extract_bits(self, start, bits=None):
8991
for i in range(nwords):
9092
srcpos = i * self.target.bits + start
9193
maxbits = min(self.target.bits, start + bits - srcpos)
92-
wordindex = srcpos / self.target.bits
94+
wordindex = srcpos // self.target.bits
9395
if srcpos % self.target.bits == 0:
94-
word = self.getword(srcpos / self.target.bits)
96+
word = self.getword(srcpos // self.target.bits)
9597
elif (wordindex+1 >= len(self.words) or
9698
srcpos % self.target.bits + maxbits < self.target.bits):
9799
word = self.target.new_value(
98100
"(%%s) >> %d" % (srcpos % self.target.bits),
99-
self.getword(srcpos / self.target.bits))
101+
self.getword(srcpos // self.target.bits))
100102
else:
101103
word = self.target.new_value(
102104
"((%%s) >> %d) | ((%%s) << %d)" % (
103105
srcpos % self.target.bits,
104106
self.target.bits - (srcpos % self.target.bits)),
105-
self.getword(srcpos / self.target.bits),
106-
self.getword(srcpos / self.target.bits + 1))
107+
self.getword(srcpos // self.target.bits),
108+
self.getword(srcpos // self.target.bits + 1))
107109
if maxbits < self.target.bits and maxbits < bits:
108110
word = self.target.new_value(
109111
"(%%s) & ((((BignumInt)1) << %d)-1)" % maxbits,
@@ -127,11 +129,11 @@ def __init__(self, bits):
127129
self.valindex = 0
128130
self.stmts = []
129131
self.generators = {}
130-
self.bv_words = (130 + self.bits - 1) / self.bits
132+
self.bv_words = (130 + self.bits - 1) // self.bits
131133
self.carry_index = 0
132134

133135
def nwords(self, maxval):
134-
return (maxval.bit_length() + self.bits - 1) / self.bits
136+
return (maxval.bit_length() + self.bits - 1) // self.bits
135137

136138
def stmt(self, stmt, needed=False):
137139
index = len(self.stmts)
@@ -149,7 +151,7 @@ def new_value(self, formatstr=None, *deps):
149151
return name
150152

151153
def bigval_input(self, name, bits):
152-
words = (bits + self.bits - 1) / self.bits
154+
words = (bits + self.bits - 1) // self.bits
153155
# Expect not to require an entire extra word
154156
assert words == self.bv_words
155157

contrib/samplekex.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/usr/bin/env python
1+
#!/usr/bin/env python3
22

33
# Example Python script to synthesise the server end of an SSH key exchange.
44

@@ -27,6 +27,8 @@
2727
import sys, random
2828
from encodelib import *
2929

30+
assert sys.version_info[:2] >= (3,0), "This is Python 3 code"
31+
3032
# A random Diffie-Hellman group, taken from an SSH server I made a
3133
# test connection to.
3234
groupgen = 5
@@ -37,7 +39,7 @@
3739
rsamod = 0xB98FE0C0BEE1E05B35FDDF5517B3E29D8A9A6A7834378B6783A19536968968F755E341B5822CAE15B465DECB80EE4116CF8D22DB5A6C85444A68D0D45D9D42008329619BE3CAC3B192EF83DD2B75C4BB6B567E11B841073BACE92108DA7E97E543ED7F032F454F7AC3C6D3F27DB34BC9974A85C7963C546662AE300A61CBABEE274481FD041C41D0145704F5FA9C77A5A442CD7A64827BB0F21FB56FDE388B596A20D7A7D1C5F22DA96C6C2171D90A673DABC66596CD99499D75AD82FEFDBE04DEC2CC7E1414A95388F668591B3F4D58249F80489646ED2C318E77D4F4E37EE8A588E79F2960620E6D28BF53653F1C974C91845F0BABFE5D167E1CA7044EE20D
3840

3941
# 16 bytes of random data for the start of KEXINIT.
40-
cookie = "".join([chr(random.randint(0,255)) for i in range(16)])
42+
cookie = bytes(random.randint(0,255) for i in range(16))
4143

4244
def expect(var, expr):
4345
expected_val = eval(expr)
@@ -46,12 +48,12 @@ def expect(var, expr):
4648
expr, repr(expected_val), repr(var)))
4749
sys.exit(1)
4850

49-
sys.stdout.write(greeting("SSH-2.0-Example KEX synthesis"))
51+
sys.stdout.buffer.write(greeting("SSH-2.0-Example KEX synthesis"))
5052

51-
greeting = sys.stdin.readline()
52-
expect(greeting[:8], '"SSH-2.0-"')
53+
greeting = sys.stdin.buffer.readline()
54+
expect(greeting[:8].decode("ASCII"), '"SSH-2.0-"')
5355

54-
sys.stdout.write(
56+
sys.stdout.buffer.write(
5557
clearpkt(SSH2_MSG_KEXINIT,
5658
cookie,
5759
name_list(("diffie-hellman-group-exchange-sha256",)), # kex
@@ -66,27 +68,27 @@ def expect(var, expr):
6668
name_list(()), # server->client languages
6769
boolean(False), # first kex packet does not follow
6870
uint32(0)))
69-
sys.stdout.flush()
71+
sys.stdout.buffer.flush()
7072

71-
intype, inpkt = read_clearpkt(sys.stdin)
73+
intype, inpkt = read_clearpkt(sys.stdin.buffer)
7274
expect(intype, "SSH2_MSG_KEXINIT")
7375

74-
intype, inpkt = read_clearpkt(sys.stdin)
76+
intype, inpkt = read_clearpkt(sys.stdin.buffer)
7577
expect(intype, "SSH2_MSG_KEX_DH_GEX_REQUEST")
7678
expect(inpkt, "uint32(0x400) + uint32(0x400) + uint32(0x2000)")
7779

78-
sys.stdout.write(
80+
sys.stdout.buffer.write(
7981
clearpkt(SSH2_MSG_KEX_DH_GEX_GROUP,
8082
mpint(group),
8183
mpint(groupgen)))
82-
sys.stdout.flush()
84+
sys.stdout.buffer.flush()
8385

84-
intype, inpkt = read_clearpkt(sys.stdin)
86+
intype, inpkt = read_clearpkt(sys.stdin.buffer)
8587
expect(intype, "SSH2_MSG_KEX_DH_GEX_INIT")
8688

87-
sys.stdout.write(
89+
sys.stdout.buffer.write(
8890
clearpkt(SSH2_MSG_KEX_DH_GEX_REPLY,
8991
ssh_rsa_key_blob(rsaexp, rsamod),
9092
mpint(random.randint(2, group-2)),
9193
ssh_rsa_signature_blob(random.randint(2, rsamod-2))))
92-
sys.stdout.flush()
94+
sys.stdout.buffer.flush()

icons/macicon.py

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/usr/bin/env python
1+
#!/usr/bin/env python3
22

33
# Generate Mac OS X .icns files, or at least the simple subformats
44
# that don't involve JPEG encoding and the like.
@@ -10,6 +10,8 @@
1010
import struct
1111
import subprocess
1212

13+
assert sys.version_info[:2] >= (3,0), "This is Python 3 code"
14+
1315
# The file format has a typical IFF-style (type, length, data) chunk
1416
# structure, with one outer chunk containing subchunks for various
1517
# different icon sizes and formats.
@@ -33,28 +35,28 @@ def make_mono_icon(size, rgba):
3335
for index in range(len(rgba))]
3436

3537
# Encode in 1-bit big-endian format.
36-
data = ""
38+
data = b''
3739
for i in range(0, len(pixels), 8):
3840
byte = 0
3941
for j in range(8):
4042
if pixels[i+j] >= 0x80:
4143
byte |= 0x80 >> j
42-
data += chr(byte)
44+
data += bytes(byte)
4345

4446
# This size-32 chunk id is an anomaly in what would otherwise be a
4547
# consistent system of using {s,l,h,t} for {16,32,48,128}-pixel
4648
# icon sizes.
47-
chunkid = { 16: "ics#", 32: "ICN#", 48: "ich#" }[size]
49+
chunkid = { 16: b"ics#", 32: b"ICN#", 48: b"ich#" }[size]
4850
return make_chunk(chunkid, data)
4951

5052
# Mask for full-colour icons: a chunk containing an 8 bpp alpha
5153
# bitmap, uncompressed. The RGB data appears in a separate chunk.
5254
def make_colour_mask(size, rgba):
5355
assert len(rgba) == size * size
5456

55-
data = "".join(map(lambda pix: chr(pix[3]), rgba))
57+
data = bytes(map(lambda pix: pix[3], rgba))
5658

57-
chunkid = { 16: "s8mk", 32: "l8mk", 48: "h8mk", 128: "t8mk" }[size]
59+
chunkid = { 16: b"s8mk", 32: b"l8mk", 48: b"h8mk", 128: b"t8mk" }[size]
5860
return make_chunk(chunkid, data)
5961

6062
# Helper routine for deciding when to start and stop run-length
@@ -69,19 +71,18 @@ def runof3(string, position):
6971
def make_colour_icon(size, rgba):
7072
assert len(rgba) == size * size
7173

72-
data = ""
74+
data = b""
7375

7476
# Mysterious extra zero header word appearing only in the size-128
7577
# icon chunk. libicns doesn't know what it's for, and neither do
7678
# I.
7779
if size == 128:
78-
data += "\0\0\0\0"
80+
data += b"\0\0\0\0"
7981

8082
# Handle R,G,B channels in sequence. (Ignore the alpha channel; it
8183
# goes into the separate mask chunk constructed above.)
8284
for chan in range(3):
83-
pixels = "".join([chr(rgba[index][chan])
84-
for index in range(len(rgba))])
85+
pixels = bytes([rgba[index][chan] for index in range(len(rgba))])
8586

8687
# Run-length encode each channel using the following format:
8788
# * byte 0x80-0xFF followed by one literal byte means repeat
@@ -98,15 +99,15 @@ def make_colour_icon(size, rgba):
9899
pos < len(pixels) and
99100
pixels[pos] == pixval):
100101
pos += 1
101-
data += chr(0x80 + pos-start - 3) + pixval
102+
data += bytes(0x80 + pos-start - 3) + pixval
102103
else:
103104
while (pos - start < 128 and
104105
pos < len(pixels) and
105106
not runof3(pixels, pos)):
106107
pos += 1
107-
data += chr(0x00 + pos-start - 1) + pixels[start:pos]
108+
data += bytes(0x00 + pos-start - 1) + pixels[start:pos]
108109

109-
chunkid = { 16: "is32", 32: "il32", 48: "ih32", 128: "it32" }[size]
110+
chunkid = { 16: b"is32", 32: b"il32", 48: b"ih32", 128: b"it32" }[size]
110111
return make_chunk(chunkid, data)
111112

112113
# Load an image file from disk and turn it into a simple list of
@@ -117,10 +118,10 @@ def make_colour_icon(size, rgba):
117118
# here that the file is in RGBA .pam format (as mkicon.py will have
118119
# generated it).
119120
def load_rgba(filename):
120-
with open(filename) as f:
121-
assert f.readline() == "P7\n"
121+
with open(filename, "rb") as f:
122+
assert f.readline() == b"P7\n"
122123
for line in iter(f.readline, ''):
123-
words = line.rstrip("\n").split()
124+
words = line.decode("ASCII").rstrip("\n").split()
124125
if words[0] == "WIDTH":
125126
width = int(words[1])
126127
elif words[0] == "HEIGHT":
@@ -135,10 +136,10 @@ def load_rgba(filename):
135136
assert width == height
136137
data = f.read()
137138
assert len(data) == width*height*4
138-
rgba = [map(ord, data[i:i+4]) for i in range(0, len(data), 4)]
139+
rgba = [list(data[i:i+4]) for i in range(0, len(data), 4)]
139140
return width, rgba
140141

141-
data = ""
142+
data = b""
142143

143144
# Trivial argument format: each argument is a filename prefixed with
144145
# "mono:", "colour:" or "output:". The first two indicate image files
@@ -157,7 +158,7 @@ def load_rgba(filename):
157158
else:
158159
assert False, "bad argument '%s'" % arg
159160

160-
data = make_chunk("icns", data)
161+
data = make_chunk(b"icns", data)
161162

162-
with open(outfile, "w") as f:
163+
with open(outfile, "wb") as f:
163164
f.write(data)

icons/mkicon.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
from __future__ import division
44

5+
import sys
56
import decimal
67
import math
78

9+
assert sys.version_info[:2] >= (3,0), "This is Python 3 code"
10+
811
# Python code which draws the PuTTY icon components at a range of
912
# sizes.
1013

test/agenttest.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
from ssh import *
1111
import agenttestdata
1212

13+
assert sys.version_info[:2] >= (3,0), "This is Python 3 code"
14+
1315
test_session_id = b'Test16ByteSessId'
1416
assert len(test_session_id) == 16
1517
test_message_to_sign = b'test message to sign'

test/agenttestgen.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
#!/usr/bin/env python3
22

3+
import sys
4+
5+
assert sys.version_info[:2] >= (3,0), "This is Python 3 code"
6+
37
def generate():
48
import hashlib
59

0 commit comments

Comments
 (0)