Skip to content

Commit 55f2fbd

Browse files
committed
more examples
1 parent cc487e3 commit 55f2fbd

28 files changed

+765
-3
lines changed

Pyro5/compatibility/Pyro4.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def __init__(self, namespace):
5353
self.namespace = namespace
5454

5555
def __getattr__(self, item):
56-
raise NotImplementedError("The Pyro4 compatibility layer doesn't provide the Pyro4.{0} namespace, "
56+
raise NotImplementedError("The Pyro4 compatibility layer doesn't provide the Pyro4.{0} module, "
5757
"first make sure the code only uses symbols from the Pyro4 package directly"
5858
.format(self.namespace))
5959

Pyro5/protocol.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ def add_payload(self, payload):
159159
while i < self.annotations_size:
160160
annotation_id = bytes(payload[i:i+4]).decode("ascii")
161161
length = int.from_bytes(payload[i+4:i+8], "big")
162-
self.annotations[annotation_id] = payload[i+8:i+8+length]
162+
self.annotations[annotation_id] = payload[i+8:i+8+length] # note: it stores a memoryview!
163163
i += 8 + length
164164
assert i == self.annotations_size
165165
self.data = payload[self.annotations_size:]

Readme.rst

+3
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ changes done based on original Pyro4
5959
A single thread is the sole "owner" of a proxy. Another thread can use proxy._pyroClaimOwnership to take over.
6060
- simplified serializers by moving the task of compressing data to the protocol module instead (where it belonged)
6161
- optimized wire messages (less code, sometimes less data copying by using memoryviews)
62+
- annotations on the protocol message are stored as no-copy memoryviews now. A memoryview doesn't support all
63+
methods you might expect so sometimes it may be required now to convert it to bytes or bytearray in your
64+
own code first, before further processing. Note that this will create a copy again, so it's best avoided.
6265
- for now, requires ``msgpack`` to be installed as well as ``serpent``.
6366

6467

certs/client_cert.pem

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIID3DCCAsSgAwIBAgIJANw+/bUr6dNQMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD
3+
VQQGEwJOTDETMBEGA1UECAwKU29tZS1TdGF0ZTEWMBQGA1UECgwNUmF6b3J2aW5l
4+
Lm5ldDEOMAwGA1UECwwFUHlybzUxEjAQBgNVBAMMCWxvY2FsaG9zdDEiMCAGCSqG
5+
SIb3DQEJARYTaXJtZW5AcmF6b3J2aW5lLm5ldDAeFw0xODA2MTMyMjQ2MTRaFw0y
6+
MDExMjkyMjQ2MTRaMIGCMQswCQYDVQQGEwJOTDETMBEGA1UECAwKU29tZS1TdGF0
7+
ZTEWMBQGA1UECgwNUmF6b3J2aW5lLm5ldDEOMAwGA1UECwwFUHlybzUxEjAQBgNV
8+
BAMMCWxvY2FsaG9zdDEiMCAGCSqGSIb3DQEJARYTaXJtZW5AcmF6b3J2aW5lLm5l
9+
dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALkoq/1zaZwjMn76HLTz
10+
XJkz8FBz74fydwyentCtH4k6fRa83Oc73qtpBw8p/vNxWrQb5mO7D5JW2sxAQBhL
11+
sjq5KT/JC5zFJbutTXjGmYX9hqe14ts8rNbfCIBHYhZHTPKVTAvJZda2sG+KrOa8
12+
ojQf8D57T2nQ2TggYPetTPX0JLjEXXe8FRZcjdQm2j0pVptiErj2nLkCFaRV0/WO
13+
lrHEI9J3N2PV8FEClLhqgGmzmvDFrGwul3nPw7Z2Z4B0iAdoBK4X7mm+DlFPGQD+
14+
QBcxSfsDCoNjqt4mUeitdyqG8XvOARWNma19S/KF4fEh19MN8bJQwsh/N6JJw5G3
15+
n2MCAwEAAaNTMFEwHQYDVR0OBBYEFBUythr0ngdQ6e11uqlbX99a71tJMB8GA1Ud
16+
IwQYMBaAFBUythr0ngdQ6e11uqlbX99a71tJMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
17+
KoZIhvcNAQELBQADggEBACCBDVBY5ba1SRcoKBYCJaT6bEWbIMetXaNvRqLEwrwC
18+
QntNlaoyCYt7nY6p3Kc/OxujAJse7FovACLpCiXqAn1YIv2hixKodVwRvNEdOQOD
19+
ohBmtOdxcjzs4MRCo87ZyoJwgphmai3uYcwcEr6sMVmTURl91PQJuM3+B9tx5aGF
20+
VWuXFHahJ0tHmblp02Imq0je8536REb+rQyuRsFIAUmgTqn30WEay36sh+JYG4tK
21+
EwEhpG+/OjSghB3doqUqMu7bYi2W6/EVsjNhmTv5pv6E7azG32ebb6fiz6Bne0Ub
22+
dehUNY0kMoBM53UG1QjOxBNVsNWelEM/OU39/sVwi2k=
23+
-----END CERTIFICATE-----

certs/client_key.pem

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC5KKv9c2mcIzJ+
3+
+hy081yZM/BQc++H8ncMnp7QrR+JOn0WvNznO96raQcPKf7zcVq0G+Zjuw+SVtrM
4+
QEAYS7I6uSk/yQucxSW7rU14xpmF/YanteLbPKzW3wiAR2IWR0zylUwLyWXWtrBv
5+
iqzmvKI0H/A+e09p0Nk4IGD3rUz19CS4xF13vBUWXI3UJto9KVabYhK49py5AhWk
6+
VdP1jpaxxCPSdzdj1fBRApS4aoBps5rwxaxsLpd5z8O2dmeAdIgHaASuF+5pvg5R
7+
TxkA/kAXMUn7AwqDY6reJlHorXcqhvF7zgEVjZmtfUvyheHxIdfTDfGyUMLIfzei
8+
ScORt59jAgMBAAECggEBALJI91KUTpyJR5X8Pqf9rKvX1w2glIPSc88y7LkB+duo
9+
9clvEUWV4FIsTx/K0DKYcz35n11oQRYni4YgV5cNTBA/OfixHP1W135e4LnqgOkD
10+
tSTHfiibw9Eh8I2ULl5FSVJLb23p/qVAQ6MjZFjISWbnWezPzyeUcZQZmUTjGbe4
11+
Olw+7T/DIKASuWzyxjEwYEHmCp6sBAN2E4BjkaH40oOo4h2movgpEL5wqMJf2zG1
12+
z8vzpXRT8OXqyClX4o/9yaVgA3VWMZPYp0FSu3gd99uZ8o+EekD0EVaA1cCCvN3J
13+
qBkkWdf+4fqOyU8XSxE95YgKnPWPUO36/03/tlslDAECgYEA2qYNZHBeZm+66cEM
14+
WlMcv1qp3U2utpotNo7Iz8lp4hVhCaFVhMuhRbNe6RpxHBoOsDTBSBWy/Urg+hWv
15+
MZTDk9dfS/5oYLosQ9gftq+wgzKtpfUSQU9lYVbapCPyQiXhq+fqU1aCX47Qpesa
16+
6NrjrhG28YtFT8trMOhFKO+bcHUCgYEA2MoLUMpqReAP4d56W2tiuAXBw64Lhdzo
17+
grFeNXsHrFEclofQbe0OuUE0IMPYjtHpdFVyiU2umW3paHFlBTUJYqZCMdliBj7Y
18+
sOx8xKzaAXZbVwDIwzWfcj+QCvjRi90nlanoZ6jf5HeIBjt44xz0+8aYzDmPDsfO
19+
ADMDB0+x1XcCgYBVMd6GBELEJ0TtUAtAJqJM7UbCtEIfZHO5jmkwjYp0TWBCIFry
20+
I2XzgrC4o1TvXjfa8LNfIxVbHJIM3+Yjq5OJR6IaOkbxaZlV1iCFTm+4r0Z6I8O5
21+
LvaRtwX6bwc2Pwxvry3eyxaBpWQnQjR6BtAwQzbFZz7amKhrphVMnhAzAQKBgQCo
22+
bLBF4DyYdO9h59rf05oqpi5XvIwvP+VURECRBDh947Z2LKX+AUKDIulA22cP7n2V
23+
aB1IFxYjFYVVI2P8m6vi/JBI8j5547GuIsz8b94fbLih63YOU0bBGCjsnUsPgo4S
24+
dKKehlELyuHfFa1hpUmfojdr0vwV251sAjXEJGJhGQKBgQCBK1ZtedBCuyuavKcI
25+
Na/bYC84nHnKSEfGhx8lUG2ugX3lXIlrElqSpoUFSCRdKadHRBKYS6mg02Y48B1N
26+
XrJ3sNMS6k6xq/57y1LlnOjzdnP9gqYQ9xMbvkvxzJjI+i0yOJRufYREb6DD7g50
27+
w80R2Deyap2JbcdBOlLdAYC/Uw==
28+
-----END PRIVATE KEY-----

certs/readme.txt

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
These SSL/TLS certificates are self-signed and have no CA trust chain.
2+
They contain some info to see that they're for Pyro5 (O=Razorvine.net, OU=Pyro5, CN=localhost)
3+
They're meant to be used for testing purposes. There is no key password.
4+
5+
It's easy to make your own certs by the way, it's mentioned in the docs of the ssl module:
6+
https://docs.python.org/3/library/ssl.html#self-signed-certificates
7+
8+
For instance:
9+
10+
$ openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout key.pem
11+
12+
13+
It's also possible to make your own CA certs and sign your client and server certs
14+
with them, but that is a lot more elaborate.

certs/server_cert.pem

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIID3DCCAsSgAwIBAgIJAIw60qiKBlfvMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD
3+
VQQGEwJOTDETMBEGA1UECAwKU29tZS1TdGF0ZTEWMBQGA1UECgwNUmF6b3J2aW5l
4+
Lm5ldDEOMAwGA1UECwwFUHlybzUxEjAQBgNVBAMMCWxvY2FsaG9zdDEiMCAGCSqG
5+
SIb3DQEJARYTaXJtZW5AcmF6b3J2aW5lLm5ldDAeFw0xODA2MTMyMjQ3MTBaFw0y
6+
MDExMjkyMjQ3MTBaMIGCMQswCQYDVQQGEwJOTDETMBEGA1UECAwKU29tZS1TdGF0
7+
ZTEWMBQGA1UECgwNUmF6b3J2aW5lLm5ldDEOMAwGA1UECwwFUHlybzUxEjAQBgNV
8+
BAMMCWxvY2FsaG9zdDEiMCAGCSqGSIb3DQEJARYTaXJtZW5AcmF6b3J2aW5lLm5l
9+
dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMJTxdAgMnOFaDKYt+EW
10+
FqNRqlH26WttK8eWqlBoeX0fRVdAxxyl4IUsCq46FSQqEipWYW9pfQyuNTXyK49y
11+
ELhuxPC4gHz6+bPkspqchwGLkon9MiLFRklXGPNAVpI7evbR3zY3+jw6eT0+6xck
12+
I8yedT6eJ61bIKQ/4jsZl3SIqwRA93XHf1ouXR6F6rBA0UnG6mxhVyudpN3sd0uQ
13+
Z4NFKQNJmqVrYeUh+4+xKQe2FYueyuCpbqX/XpE3ZHkx+X9R4upIeJDZNuzxtE0V
14+
3iguClgrMwGriRECjNUDqnHdP79SgI+iW44cmZJQEehkyjtjMBkUL/c/GXreov6f
15+
e0ECAwEAAaNTMFEwHQYDVR0OBBYEFBvuzbXIjlbpqekKSKSAlTEoM16eMB8GA1Ud
16+
IwQYMBaAFBvuzbXIjlbpqekKSKSAlTEoM16eMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
17+
KoZIhvcNAQELBQADggEBABGU3AsGeFGqBoc24oNmTx2ksacgW6YUIMupXSnL/CNv
18+
klBLbB/WDYWJxwqgfAY3EB0DtneLxBQTPiE2VmuC9aPOHjyYGKyCMrD/sHKwUmFr
19+
KO1SBdhSTxcHMw3D8byN90ZPNOCefHhUXLj+lVq019w36xU1CRDjBEJ2nSO/zpB5
20+
nGD2tsJ1WFsQ2XXzP6bR8/CqyB1mVZK3FA+qI+tH9sX16GdPlGIY/2HXmVGt7QFu
21+
Cd/LQp9tBcZ0DpthoZCTZwdMILEDUxFSw1WjBUGQKcm+GH4ofaFdI7d73I/nei6a
22+
RdgMl8btfLRYXvUcwtH/NGw0LC+YKBm2DmmCasP41Ko=
23+
-----END CERTIFICATE-----

certs/server_key.pem

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDCU8XQIDJzhWgy
3+
mLfhFhajUapR9ulrbSvHlqpQaHl9H0VXQMccpeCFLAquOhUkKhIqVmFvaX0MrjU1
4+
8iuPchC4bsTwuIB8+vmz5LKanIcBi5KJ/TIixUZJVxjzQFaSO3r20d82N/o8Onk9
5+
PusXJCPMnnU+nietWyCkP+I7GZd0iKsEQPd1x39aLl0eheqwQNFJxupsYVcrnaTd
6+
7HdLkGeDRSkDSZqla2HlIfuPsSkHthWLnsrgqW6l/16RN2R5Mfl/UeLqSHiQ2Tbs
7+
8bRNFd4oLgpYKzMBq4kRAozVA6px3T+/UoCPoluOHJmSUBHoZMo7YzAZFC/3Pxl6
8+
3qL+n3tBAgMBAAECggEBAIm/yGEX8athzdLP3sh3V+S9ZvZjCGNWJ8p7So9k/3lq
9+
SUTobjwoeVbtOUT3dzUDfYz1XmwTYskyVBXBbI9qU9/o5UGeB7aQUaDrZI+klS7L
10+
OT0HdhqfrIsgaldELBnMgAWmD4vnckJvULHRf+QPgjDxwjp48bc4+ZJ0lnE+WtYH
11+
Lrnao/P2Al2hGEcnYSWyGphdqmOnCy7pplETN7cyLiDarZjde5BM/lcAH001LIpW
12+
yoJftm/gl4MjEW5v82L9tadzOgRJyybhHG5k34bzaBpV63p3jp0FsBX587C4NIP4
13+
BmnIhfEMpq9RjS9L7vYSKbzMge/Prj0L8g5r90pZAeECgYEA4Odx7fMEZlVgQHU6
14+
5ZgdJKLJ8lYQ3pcy+3pgPj7HlT/N6REbn8OOO91vEalpHi8I1hOERRzjIWQGH5oR
15+
tzNdFf9BsuIs7Ur6tCYoYcy2pz25zwh58xOtqAvScE2aGVvBP1iTpKGEXkwv0Nn7
16+
zWcbwh22BIckCzYK2RQaXY/irV8CgYEA3TIMz9sNkOi/iAzh4Ey26nIKfOg852A8
17+
33c+wvpNcWSGYR9OLnk/a8AGjT+HQA8w8kU3s79T0S7IVLDeVnQomh1lklfhRGGH
18+
6QL/u/miAhIY2ykOtBFS7zICyH0egXUWQea6t3aiHNgqFMLyipa0SngamG9/vP9O
19+
tRSl0j+b+18CgYABUVnZixL7hoSJ3CX8Mmf5Tvrf8KEorLofvxfRRYzl0vnh47fF
20+
t9+dei6sa9Gx25SxrGuZ/BFYoL1ocf6olCR3fIdmBO0+drIBXDfgWtK3KCVukR4l
21+
zne2BFu3TL0aaO8478vtqwSbiNa+4ogXLAN9n67xV9leN3LY0sVUxwMNAQKBgQCO
22+
cnX3wc0JviniVtF73kuJzeldKT5Xjw2Ep8l+TS1kUeWMVFnH6gNiw6Y0fm3+Xgoa
23+
a2ME2bkDpIoUqFZ2/JVNMpM/3GJQ5DJfZ7QDfS7NAJSLRvSWF/X93ooWTSVBH4M2
24+
63zhO4AI7VikSCtj/suajaAq/NsZfp1UVji3nok4JwKBgFoeRO1ezkq3J7igkIBr
25+
d6D8u6z1/3sAgnYJLbSKjgdpewcedRV9uVC1g0tFRPRjTG7X0F7+ZPLaVjDM8UvO
26+
2zhPOL6S0+fYg2bUPHexuEf2ec0PqIF6rAS+0cR85AohAXqyYGydmyDCQFDNvOvW
27+
ygLQbLsx9AyZzrqsRoEJ7Yo6
28+
-----END PRIVATE KEY-----

examples/old_pyro4/hugetransfer/Readme.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ Performance numbers with the various serializers on my local network:
2222

2323
serializer | performance (string) | performance (bytes)
2424
-----------+---------------------------------------------
25-
pickle | ? kb/sec | ? kb/sec
2625
marshal | ? kb/sec | ? kb/sec
2726
json | ? kb/sec | not supported
2827
serpent | ? kb/sec | ? kb/sec
28+
msgpack | ? kb/sec | ? kb/sec
2929

3030

3131
Performance of the download via iterator is almost identical to

examples/old_pyro4/ssl/Readme.txt

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
SSL example showing how to configure 2-way-SSL with custom certificate validation.
2+
3+
What this means is that the server has a certificate, and the client as well.
4+
The server only accepts connections from clients that provide the proper certificate
5+
(and ofcourse, clients only connect to servers having a proper certificate).
6+
7+
By using Pyro's handshake mechanism you can easily add custom certificate verification steps
8+
in both the client (proxy) and server (daemon). This is more or less required, because
9+
you should be checking if the certificate is indeed from the party you expected...
10+
11+
This example uses the self-signed demo certs that come with Pyro, so in the code
12+
you'll also see that we configure the SSL_CACERTS so that SSL will accept the self-signed
13+
certificate as a valid cert.
14+
15+
16+
17+
If the connection is successfully established, all communication is then encrypted and secure.

examples/old_pyro4/ssl/client.py

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from Pyro5.compatibility import Pyro4
2+
import Pyro4.core
3+
import Pyro4.errors
4+
5+
6+
Pyro4.config.SSL = True
7+
Pyro4.config.SSL_CACERTS = "../../certs/server_cert.pem" # to make ssl accept the self-signed server cert
8+
Pyro4.config.SSL_CLIENTCERT = "../../certs/client_cert.pem"
9+
Pyro4.config.SSL_CLIENTKEY = "../../certs/client_key.pem"
10+
print("SSL enabled (2-way).")
11+
12+
13+
def verify_cert(cert):
14+
if not cert:
15+
raise Pyro4.errors.CommunicationError("cert missing")
16+
# note: hostname and expiry date validation is already successfully performed by the SSL layer itself
17+
# not_before = datetime.datetime.utcfromtimestamp(ssl.cert_time_to_seconds(cert["notBefore"]))
18+
# print("not before:", not_before)
19+
# not_after = datetime.datetime.utcfromtimestamp(ssl.cert_time_to_seconds(cert["notAfter"]))
20+
# print("not after:", not_after)
21+
# today = datetime.datetime.now()
22+
# if today > not_after or today < not_before:
23+
# raise Pyro4.errors.CommunicationError("cert not yet valid or expired")
24+
if cert["serialNumber"] != "8C3AD2A88A0657EF":
25+
raise Pyro4.errors.CommunicationError("cert serial number incorrect", cert["serialNumber"])
26+
issuer = dict(p[0] for p in cert["issuer"])
27+
subject = dict(p[0] for p in cert["subject"])
28+
if issuer["organizationName"] != "Razorvine.net":
29+
# issuer is not often relevant I guess, but just to show that you have the data
30+
raise Pyro4.errors.CommunicationError("cert not issued by Razorvine.net")
31+
if subject["countryName"] != "NL":
32+
raise Pyro4.errors.CommunicationError("cert not for country NL")
33+
if subject["organizationName"] != "Razorvine.net":
34+
raise Pyro4.errors.CommunicationError("cert not for Razorvine.net")
35+
print("(SSL server cert is ok: serial={ser}, subject={subj})"
36+
.format(ser=cert["serialNumber"], subj=subject["organizationName"]))
37+
38+
39+
# to make Pyro verify the certificate on new connections, use the handshake mechanism:
40+
class CertCheckingProxy(Pyro4.Proxy):
41+
def _pyroValidateHandshake(self, response):
42+
cert = self._pyroConnection.getpeercert()
43+
verify_cert(cert)
44+
45+
46+
# Note: to automatically enforce certificate verification for all proxy objects you create,
47+
# you can also monkey-patch the method in the Proxy class itself.
48+
# Then you don't have to make sure that you're using CertCheckingProxy every time.
49+
# However some other Proxy subclass can (will) override this again!
50+
#
51+
# def certverifier(self, response):
52+
# cert = self._pyroConnection.getpeercert()
53+
# verify_cert(cert)
54+
# Pyro4.core.Proxy._pyroValidateHandshake = certverifier
55+
56+
57+
uri = input("Server uri: ").strip()
58+
with CertCheckingProxy(uri) as p:
59+
response = p.echo("client speaking")
60+
print("response:", response)

examples/old_pyro4/ssl/server.py

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from Pyro5.compatibility import Pyro4
2+
import Pyro4.core
3+
4+
5+
class Safe(object):
6+
@Pyro4.expose
7+
def echo(self, message):
8+
print("got message:", message)
9+
return "hi!"
10+
11+
12+
Pyro4.config.SSL = True
13+
Pyro4.config.SSL_REQUIRECLIENTCERT = True # enable 2-way ssl
14+
Pyro4.config.SSL_SERVERCERT = "../../certs/server_cert.pem"
15+
Pyro4.config.SSL_SERVERKEY = "../../certs/server_key.pem"
16+
Pyro4.config.SSL_CACERTS = "../../certs/client_cert.pem" # to make ssl accept the self-signed client cert
17+
print("SSL enabled (2-way).")
18+
19+
20+
class CertValidatingDaemon(Pyro4.Daemon):
21+
def validateHandshake(self, conn, data):
22+
cert = conn.getpeercert()
23+
if not cert:
24+
raise Pyro4.errors.CommunicationError("client cert missing")
25+
# note: hostname and expiry date validation is already successfully performed by the SSL layer itself
26+
# not_before = datetime.datetime.utcfromtimestamp(ssl.cert_time_to_seconds(cert["notBefore"]))
27+
# print("not before:", not_before)
28+
# not_after = datetime.datetime.utcfromtimestamp(ssl.cert_time_to_seconds(cert["notAfter"]))
29+
# print("not after:", not_after)
30+
# today = datetime.datetime.now()
31+
# if today > not_after or today < not_before:
32+
# raise Pyro4.errors.CommunicationError("cert not yet valid or expired")
33+
if cert["serialNumber"] != "DC3EFDB52BE9D350":
34+
raise Pyro4.errors.CommunicationError("cert serial number incorrect", cert["serialNumber"])
35+
issuer = dict(p[0] for p in cert["issuer"])
36+
subject = dict(p[0] for p in cert["subject"])
37+
if issuer["organizationName"] != "Razorvine.net":
38+
# issuer is not often relevant I guess, but just to show that you have the data
39+
raise Pyro4.errors.CommunicationError("cert not issued by Razorvine.net")
40+
if subject["countryName"] != "NL":
41+
raise Pyro4.errors.CommunicationError("cert not for country NL")
42+
if subject["organizationName"] != "Razorvine.net":
43+
raise Pyro4.errors.CommunicationError("cert not for Razorvine.net")
44+
print("(SSL client cert is ok: serial={ser}, subject={subj})"
45+
.format(ser=cert["serialNumber"], subj=subject["organizationName"]))
46+
return super(CertValidatingDaemon, self).validateHandshake(conn, data)
47+
48+
49+
d = CertValidatingDaemon()
50+
uri = d.register(Safe)
51+
print("server uri:", uri)
52+
d.requestLoop()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
This example shows two ways of dealing with a third party library whose
2+
source code you cannot or don't want to change, and still use its classes directly in Pyro.
3+
4+
The first server uses the @expose decorator but applies it as a regular function to create a wrapped,
5+
eposed class from the library class. That wrapped class is then registered instead.
6+
There are a couple of caveats when using this approach, see the relevant paragraph
7+
in the server chapter in the documentation for details.
8+
9+
The second server2 shows the approach that I personally prefer: creating explicit adapter classes
10+
that call out to the library. You then have full control over what is happening.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# This is an AWESOME LIBRARY.
2+
# You can use its AWESOME CLASSES to do Great Things.
3+
# The author however DOESN'T allow you to CHANGE the source code and taint it with Pyro decorators!
4+
5+
6+
class WeirdReturnType(object):
7+
def __init__(self, value):
8+
self.value = value
9+
10+
11+
class AwesomeClass(object):
12+
def method(self, arg):
13+
print("Awesome object is called with: ", arg)
14+
return "awesome"
15+
16+
def private(self):
17+
print("This should be a private method...")
18+
return "boo"
19+
20+
def weird(self):
21+
print("Weird!")
22+
return WeirdReturnType("awesome")
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from Pyro5.compatibility import Pyro4
2+
import Pyro4
3+
import Pyro4.errors
4+
5+
6+
uri = input("Enter the URI of the thirdparty library object: ").strip()
7+
with Pyro4.Proxy(uri) as remote:
8+
print(remote.method("how are you?"))
9+
10+
try:
11+
print(remote.weird())
12+
except Pyro4.errors.SerializeError:
13+
print("couldn't call weird() due to serialization error of the result value! (is ok)")
14+
15+
try:
16+
print(remote.private()) # we can call this if full class is exposed...
17+
except AttributeError:
18+
print("couldn't call private(), it doesn't seem to be exposed! (is ok)")
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from awesome_thirdparty_library import AwesomeClass
2+
from Pyro5.compatibility import Pyro4
3+
import Pyro4
4+
5+
6+
# expose the class from the library using @expose as wrapper function:
7+
ExposedClass = Pyro4.expose(AwesomeClass)
8+
9+
10+
with Pyro4.Daemon() as daemon:
11+
# register the wrapped class instead of the library class itself:
12+
uri = daemon.register(ExposedClass, "example.thirdpartylib")
13+
print("wrapped class registered, uri: ", uri)
14+
daemon.requestLoop()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from awesome_thirdparty_library import AwesomeClass
2+
from Pyro5.compatibility import Pyro4
3+
import Pyro4
4+
5+
6+
# create adapter class that only exposes what should be accessible,
7+
# and calls into the library class from there:
8+
9+
class AwesomeAdapterClass(AwesomeClass):
10+
@Pyro4.expose
11+
def method(self, arg):
12+
print("Adapter class is called...")
13+
return super(AwesomeAdapterClass, self).method(arg)
14+
15+
@Pyro4.expose
16+
def weird(self):
17+
result = super(AwesomeAdapterClass, self).weird()
18+
# we have full control over what is returned and can turn the custom
19+
# result class into a normal string value that has no issues traveling over the wire
20+
return "weird " + result.value
21+
22+
23+
with Pyro4.Daemon() as daemon:
24+
# register the adapter class instead of the library class itself:
25+
uri = daemon.register(AwesomeAdapterClass, "example.thirdpartylib")
26+
print("adapter class registered, uri: ", uri)
27+
daemon.requestLoop()
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
This example exercises the support for pytz/dateutil timezones in the serializers.
2+
You'll see that this is quite problematic as the tz info is not really a standard
3+
extension, or some serializers may fail to serialize a datetime object at all.
4+
5+
The only solution is to convert back to a datetime without tz info (so perhaps
6+
normalize them all to UTC) before transferring, or avoiding datetime objects entirely...
7+
8+
9+
PREREQUISITES:
10+
install the 'pytz' and 'python-dateutil' libraries

0 commit comments

Comments
 (0)