]>
git.proxmox.com Git - ovs.git/blob - tests/test-ovsdb.py
1 # Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at:
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 from __future__
import print_function
23 from ovs
.db
import error
26 from ovs
.db
import data
31 from ovs
.fatal_signal
import signal_alarm
36 if type(json
) == list and len(json
) == 1:
42 def do_default_atoms():
43 for type_
in ovs
.db
.types
.ATOMIC_TYPES
:
44 if type_
== ovs
.db
.types
.VoidType
:
47 sys
.stdout
.write("%s: " % type_
.to_string())
49 atom
= data
.Atom
.default(type_
)
50 if atom
!= data
.Atom
.default(type_
):
51 sys
.stdout
.write("wrong\n")
54 sys
.stdout
.write("OK\n")
57 def do_default_data():
60 for key
in ovs
.db
.types
.ATOMIC_TYPES
:
61 if key
== ovs
.db
.types
.VoidType
:
63 for value
in ovs
.db
.types
.ATOMIC_TYPES
:
64 if value
== ovs
.db
.types
.VoidType
:
67 valueBase
= ovs
.db
.types
.BaseType(value
)
68 type_
= ovs
.db
.types
.Type(ovs
.db
.types
.BaseType(key
),
70 assert type_
.is_valid()
72 sys
.stdout
.write("key %s, value %s, n_min %d: "
73 % (key
.to_string(), value
.to_string(), n_min
))
75 datum
= data
.Datum
.default(type_
)
76 if datum
!= data
.Datum
.default(type_
):
77 sys
.stdout
.write("wrong\n")
80 sys
.stdout
.write("OK\n")
85 def do_parse_atomic_type(type_string
):
86 type_json
= unbox_json(ovs
.json
.from_string(type_string
))
87 atomic_type
= ovs
.db
.types
.AtomicType
.from_json(type_json
)
88 print(ovs
.json
.to_string(atomic_type
.to_json(), sort_keys
=True))
91 def do_parse_base_type(type_string
):
92 type_json
= unbox_json(ovs
.json
.from_string(type_string
))
93 base_type
= ovs
.db
.types
.BaseType
.from_json(type_json
)
94 print(ovs
.json
.to_string(base_type
.to_json(), sort_keys
=True))
97 def do_parse_type(type_string
):
98 type_json
= unbox_json(ovs
.json
.from_string(type_string
))
99 type_
= ovs
.db
.types
.Type
.from_json(type_json
)
100 print(ovs
.json
.to_string(type_
.to_json(), sort_keys
=True))
103 def do_parse_atoms(type_string
, *atom_strings
):
104 type_json
= unbox_json(ovs
.json
.from_string(type_string
))
105 base
= ovs
.db
.types
.BaseType
.from_json(type_json
)
106 for atom_string
in atom_strings
:
107 atom_json
= unbox_json(ovs
.json
.from_string(atom_string
))
109 atom
= data
.Atom
.from_json(base
, atom_json
)
110 print(ovs
.json
.to_string(atom
.to_json()))
111 except error
.Error
as e
:
115 def do_parse_data(type_string
, *data_strings
):
116 type_json
= unbox_json(ovs
.json
.from_string(type_string
))
117 type_
= ovs
.db
.types
.Type
.from_json(type_json
)
118 for datum_string
in data_strings
:
119 datum_json
= unbox_json(ovs
.json
.from_string(datum_string
))
120 datum
= data
.Datum
.from_json(type_
, datum_json
)
121 print(ovs
.json
.to_string(datum
.to_json()))
124 def do_sort_atoms(type_string
, atom_strings
):
125 type_json
= unbox_json(ovs
.json
.from_string(type_string
))
126 base
= ovs
.db
.types
.BaseType
.from_json(type_json
)
127 atoms
= [data
.Atom
.from_json(base
, atom_json
)
128 for atom_json
in unbox_json(ovs
.json
.from_string(atom_strings
))]
129 print(ovs
.json
.to_string([data
.Atom
.to_json(atom
)
130 for atom
in sorted(atoms
)]))
133 def do_parse_column(name
, column_string
):
134 column_json
= unbox_json(ovs
.json
.from_string(column_string
))
135 column
= ovs
.db
.schema
.ColumnSchema
.from_json(column_json
, name
)
136 print(ovs
.json
.to_string(column
.to_json(), sort_keys
=True))
139 def do_parse_table(name
, table_string
, default_is_root_string
='false'):
140 default_is_root
= default_is_root_string
== 'true'
141 table_json
= unbox_json(ovs
.json
.from_string(table_string
))
142 table
= ovs
.db
.schema
.TableSchema
.from_json(table_json
, name
)
143 print(ovs
.json
.to_string(table
.to_json(default_is_root
), sort_keys
=True))
146 def do_parse_schema(schema_string
):
147 schema_json
= unbox_json(ovs
.json
.from_string(schema_string
))
148 schema
= ovs
.db
.schema
.DbSchema
.from_json(schema_json
)
149 print(ovs
.json
.to_string(schema
.to_json(), sort_keys
=True))
152 def get_simple_table_printable_row(row
):
153 simple_columns
= ["i", "r", "b", "s", "u", "ia",
154 "ra", "ba", "sa", "ua", "uuid"]
156 for column
in simple_columns
:
157 if hasattr(row
, column
) and not (type(getattr(row
, column
))
158 is ovs
.db
.data
.Atom
):
159 s
+= "%s=%s " % (column
, getattr(row
, column
))
161 s
= re
.sub('""|,|u?\'', "", s
)
162 s
= re
.sub('UUID\(([^)]+)\)', r
'\1', s
)
163 s
= re
.sub('False', 'false', s
)
164 s
= re
.sub('True', 'true', s
)
165 s
= re
.sub(r
'(ba)=([^[][^ ]*) ', r
'\1=[\2] ', s
)
169 def get_simple2_table_printable_row(row
):
170 simple2_columns
= ["name", "smap", "imap"]
172 for column
in simple2_columns
:
173 if hasattr(row
, column
) and not (type(getattr(row
, column
))
174 is ovs
.db
.data
.Atom
):
175 s
+= "%s=%s " % (column
, getattr(row
, column
))
177 s
= re
.sub('""|,|u?\'', "", s
)
178 s
= re
.sub('UUID\(([^)]+)\)', r
'\1', s
)
179 s
= re
.sub('False', 'false', s
)
180 s
= re
.sub('True', 'true', s
)
181 s
= re
.sub(r
'(ba)=([^[][^ ]*) ', r
'\1=[\2] ', s
)
185 def get_simple3_table_printable_row(row
):
186 simple3_columns
= ["name", "uset"]
188 for column
in simple3_columns
:
189 if hasattr(row
, column
) and not (type(getattr(row
, column
))
190 is ovs
.db
.data
.Atom
):
191 s
+= "%s=%s " % (column
, getattr(row
, column
))
193 s
= re
.sub('""|,|u?\'', "", s
)
194 s
= re
.sub('UUID\(([^)]+)\)', r
'\1', s
)
195 s
= re
.sub('False', 'false', s
)
196 s
= re
.sub('True', 'true', s
)
197 s
= re
.sub(r
'(ba)=([^[][^ ]*) ', r
'\1=[\2] ', s
)
201 def print_idl(idl
, step
):
203 if "simple" in idl
.tables
:
204 simple
= idl
.tables
["simple"].rows
205 for row
in six
.itervalues(simple
):
207 s
+= get_simple_table_printable_row(row
)
211 if "simple2" in idl
.tables
:
212 simple2
= idl
.tables
["simple2"].rows
213 for row
in six
.itervalues(simple2
):
215 s
+= get_simple2_table_printable_row(row
)
219 if "simple3" in idl
.tables
:
220 simple3
= idl
.tables
["simple3"].rows
221 for row
in six
.itervalues(simple3
):
223 s
+= get_simple3_table_printable_row(row
)
227 if "link1" in idl
.tables
:
228 l1
= idl
.tables
["link1"].rows
229 for row
in six
.itervalues(l1
):
230 s
= ["%03d: i=%s k=" % (step
, row
.i
)]
231 if hasattr(row
, "k") and row
.k
:
232 s
.append(str(row
.k
.i
))
233 if hasattr(row
, "ka"):
235 s
.append(' '.join(sorted(str(ka
.i
) for ka
in row
.ka
)))
237 if hasattr(row
, "l2") and row
.l2
:
238 s
.append(str(row
.l2
[0].i
))
239 if hasattr(row
, "uuid"):
240 s
.append(" uuid=%s" % row
.uuid
)
244 if "link2" in idl
.tables
:
245 l2
= idl
.tables
["link2"].rows
246 for row
in six
.itervalues(l2
):
248 s
.append(" i=%s l1=" % row
.i
)
249 if hasattr(row
, "l1") and row
.l1
:
250 s
.append(str(row
.l1
[0].i
))
251 if hasattr(row
, "uuid"):
252 s
.append(" uuid=%s" % row
.uuid
)
257 print("%03d: empty" % step
)
261 def substitute_uuids(json
, symtab
):
262 if isinstance(json
, six
.string_types
):
263 symbol
= symtab
.get(json
)
266 elif type(json
) == list:
267 return [substitute_uuids(element
, symtab
) for element
in json
]
268 elif type(json
) == dict:
270 for key
, value
in six
.iteritems(json
):
271 d
[key
] = substitute_uuids(value
, symtab
)
276 def parse_uuids(json
, symtab
):
277 if (isinstance(json
, six
.string_types
)
278 and ovs
.ovsuuid
.is_valid_string(json
)):
279 name
= "#%d#" % len(symtab
)
280 sys
.stderr
.write("%s = %s\n" % (name
, json
))
282 elif type(json
) == list:
284 parse_uuids(element
, symtab
)
285 elif type(json
) == dict:
286 for value
in six
.itervalues(json
):
287 parse_uuids(value
, symtab
)
290 def idltest_find_simple(idl
, i
):
291 for row
in six
.itervalues(idl
.tables
["simple"].rows
):
297 def idltest_find_simple2(idl
, i
):
298 for row
in six
.itervalues(idl
.tables
["simple2"].rows
):
304 def idltest_find_simple3(idl
, i
):
305 for row
in six
.itervalues(idl
.tables
["simple3"].rows
):
311 def idl_set(idl
, commands
, step
):
312 txn
= ovs
.db
.idl
.Transaction(idl
)
316 for command
in commands
.split(','):
317 words
= command
.split()
321 if name
== "notifytest":
324 old_notify
= idl
.notify
326 def notify(event
, row
, updates
=None):
328 upcol
= list(updates
._data
.keys())[0]
331 events
.append("%s|%s|%s" % (event
, row
.i
, upcol
))
332 idl
.notify
= old_notify
338 sys
.stderr
.write('"set" command requires 3 arguments\n')
341 s
= idltest_find_simple(idl
, int(args
[0]))
343 sys
.stderr
.write('"set" command asks for nonexistent i=%d\n'
352 s
.u
= uuid
.UUID(args
[2])
356 sys
.stderr
.write('"set" comamnd asks for unknown column %s\n'
359 elif name
== "insert":
361 sys
.stderr
.write('"set" command requires 1 argument\n')
364 s
= txn
.insert(idl
.tables
["simple"])
366 elif name
== "delete":
368 sys
.stderr
.write('"delete" command requires 1 argument\n')
371 s
= idltest_find_simple(idl
, int(args
[0]))
373 sys
.stderr
.write('"delete" command asks for nonexistent i=%d\n'
377 elif name
== "verify":
379 sys
.stderr
.write('"verify" command requires 2 arguments\n')
382 s
= idltest_find_simple(idl
, int(args
[0]))
384 sys
.stderr
.write('"verify" command asks for nonexistent i=%d\n'
388 if args
[1] in ("i", "b", "s", "u", "r"):
391 sys
.stderr
.write('"verify" command asks for unknown column '
394 elif name
== "fetch":
396 sys
.stderr
.write('"fetch" command requires 2 argument\n')
399 row
= idltest_find_simple(idl
, int(args
[0]))
401 sys
.stderr
.write('"fetch" command asks for nonexistent i=%d\n'
407 fetch_cmds
.append([row
, column
])
408 elif name
== "increment":
410 sys
.stderr
.write('"increment" command requires 1 argument\n')
413 s
= idltest_find_simple(idl
, int(args
[0]))
415 sys
.stderr
.write('"set" command asks for nonexistent i=%d\n'
421 elif name
== "abort":
424 elif name
== "destroy":
425 print("%03d: destroy" % step
)
429 elif name
== "linktest":
430 l1_0
= txn
.insert(idl
.tables
["link1"])
434 l1_1
= txn
.insert(idl
.tables
["link1"])
437 l1_1
.ka
= [l1_0
, l1_1
]
438 elif name
== 'getattrtest':
439 l1
= txn
.insert(idl
.tables
["link1"])
440 i
= getattr(l1
, 'i', 1)
443 i
= getattr(l1
, 'i', 1)
446 elif name
== 'partialmapinsertelement':
447 row
= idltest_find_simple2(idl
, 'myString1')
448 row
.setkey('smap', 'key1', 'myList1')
449 row
.setkey('imap', 3, 'myids2')
450 row
.__setattr
__('name', 'String2')
451 elif name
== 'partialmapdelelement':
452 row
= idltest_find_simple2(idl
, 'String2')
453 row
.delkey('smap', 'key2', 'value2')
454 elif name
== 'partialrenamesetadd':
455 row
= idltest_find_simple3(idl
, 'mySet1')
457 uuid
.UUID("001e43d2-dd3f-4616-ab6a-83a490bb0991"))
458 row
.__setattr
__('name', 'String2')
459 elif name
== 'partialsetadd2':
460 row
= idltest_find_simple3(idl
, 'String2')
462 uuid
.UUID("0026b3ba-571b-4729-8227-d860a5210ab8"))
463 elif name
== 'partialsetdel':
464 row
= idltest_find_simple3(idl
, 'String2')
466 uuid
.UUID("001e43d2-dd3f-4616-ab6a-83a490bb0991"))
467 elif name
== 'partialsetref':
468 new_row
= txn
.insert(idl
.tables
["simple4"])
469 new_row
.__setattr
__('name', 'test')
470 row
= idltest_find_simple3(idl
, 'String2')
471 row
.addvalue('uref', new_row
.uuid
)
473 sys
.stderr
.write("unknown command %s\n" % name
)
476 status
= txn
.commit_block()
477 sys
.stdout
.write("%03d: commit, status=%s"
478 % (step
, ovs
.db
.idl
.Transaction
.status_to_string(status
)))
479 if increment
and status
== ovs
.db
.idl
.Transaction
.SUCCESS
:
480 sys
.stdout
.write(", increment=%d" % txn
.get_increment_new_value())
482 # Event notifications from operations in a single transaction are
483 # not in a gauranteed order due to update messages being dicts
484 sys
.stdout
.write(", events=" + ", ".join(sorted(events
)))
485 sys
.stdout
.write("\n")
489 def update_condition(idl
, commands
):
490 commands
= commands
.split(";")
491 for command
in commands
:
492 command
= command
[len("condition "):]
495 command
= command
[len("add "):]
498 command
= command
[len("remove "):]
500 command
= command
.split(" ")
501 if(len(command
) != 2):
502 sys
.stderr
.write("Error parsong condition %s\n" % command
)
506 cond
= ovs
.json
.from_string(command
[1])
508 idl
.cond_change(table
, add_cmd
, cond
)
511 def do_idl(schema_file
, remote
, *commands
):
512 schema_helper
= ovs
.db
.idl
.SchemaHelper(schema_file
)
515 if commands
and commands
[0] == "track-notify":
516 commands
= commands
[1:]
519 if commands
and commands
[0].startswith("?"):
521 for x
in commands
[0][1:].split("?"):
523 table
, columns
= x
.split(":")
524 columns
= columns
.split(",")
525 for index
, column
in enumerate(columns
):
526 if column
[-1] == '!':
527 columns
[index
] = columns
[index
][:-1]
528 readonly
.append(columns
[index
])
529 schema_helper
.register_columns(table
, columns
, readonly
)
530 commands
= commands
[1:]
532 schema_helper
.register_all()
533 idl
= ovs
.db
.idl
.Idl(remote
, schema_helper
)
536 error
, stream
= ovs
.stream
.Stream
.open_block(
537 ovs
.stream
.Stream
.open(remote
))
539 sys
.stderr
.write("failed to connect to \"%s\"" % remote
)
541 rpc
= ovs
.jsonrpc
.Connection(stream
)
549 def mock_notify(event
, row
, updates
=None):
550 output
= "%03d: " % step
551 output
+= "event:" + str(event
) + ", row={"
552 output
+= get_simple_table_printable_row(row
) + "}, updates="
556 output
+= "{" + get_simple_table_printable_row(updates
) + "}"
559 sys
.stdout
.write(output
)
562 if track_notify
and "simple" in idl
.tables
:
563 idl
.notify
= mock_notify
565 commands
= list(commands
)
566 if len(commands
) >= 1 and "condition" in commands
[0]:
567 update_condition(idl
, commands
.pop(0))
568 sys
.stdout
.write("%03d: change conditions\n" % step
)
572 for command
in commands
:
573 if command
.startswith("+"):
574 # The previous transaction didn't change anything.
575 command
= command
[1:]
578 while idl
.change_seqno
== seqno
and not idl
.run():
581 poller
= ovs
.poller
.Poller()
589 seqno
= idl
.change_seqno
591 if command
== "reconnect":
592 print("%03d: reconnect" % step
)
595 idl
.force_reconnect()
596 elif "condition" in command
:
597 update_condition(idl
, command
)
598 sys
.stdout
.write("%03d: change conditions\n" % step
)
601 elif not command
.startswith("["):
602 idl_set(idl
, command
, step
)
605 json
= ovs
.json
.from_string(command
)
606 if isinstance(json
, six
.string_types
):
607 sys
.stderr
.write("\"%s\": %s\n" % (command
, json
))
609 json
= substitute_uuids(json
, symtab
)
610 request
= ovs
.jsonrpc
.Message
.create_request("transact", json
)
611 error
, reply
= rpc
.transact_block(request
)
613 sys
.stderr
.write("jsonrpc transaction failed: %s"
614 % os
.strerror(error
))
616 elif reply
.error
is not None:
617 sys
.stderr
.write("jsonrpc transaction failed: %s"
621 sys
.stdout
.write("%03d: " % step
)
624 if reply
.result
is not None:
625 parse_uuids(reply
.result
, symtab
)
627 sys
.stdout
.write("%s\n" % ovs
.json
.to_string(reply
.to_json()))
632 while idl
.change_seqno
== seqno
and not idl
.run():
633 poller
= ovs
.poller
.Poller()
639 print("%03d: done" % step
)
642 def do_idl_passive(schema_file
, remote
, *commands
):
645 schema_helper
= ovs
.db
.idl
.SchemaHelper(schema_file
)
646 schema_helper
.register_all()
647 idl
= ovs
.db
.idl
.Idl(remote
, schema_helper
)
649 while idl
._session
.rpc
is None:
652 rpc
= idl
._session
.rpc
657 for command
in commands
:
658 json
= ovs
.json
.from_string(command
)
659 if isinstance(json
, six
.string_types
):
660 sys
.stderr
.write("\"%s\": %s\n" % (command
, json
))
662 json
= substitute_uuids(json
, symtab
)
663 request
= ovs
.jsonrpc
.Message
.create_request("transact", json
)
664 error
, reply
= rpc
.transact_block(request
)
666 sys
.stderr
.write("jsonrpc transaction failed: %s"
667 % os
.strerror(error
))
669 elif reply
.error
is not None:
670 sys
.stderr
.write("jsonrpc transaction failed: %s"
674 sys
.stdout
.write("%03d: " % step
)
677 if reply
.result
is not None:
678 parse_uuids(reply
.result
, symtab
)
680 sys
.stdout
.write("%s\n" % ovs
.json
.to_string(reply
.to_json()))
684 print("%03d: done" % step
)
689 %(program_name)s: test utility for Open vSwitch database Python bindings
690 usage: %(program_name)s [OPTIONS] COMMAND ARG...
692 The following commands are supported:
694 test ovsdb_atom_default()
696 test ovsdb_datum_default()
697 parse-atomic-type TYPE
698 parse TYPE as OVSDB atomic type, and re-serialize
700 parse TYPE as OVSDB base type, and re-serialize
702 parse JSON as OVSDB type, and re-serialize
703 parse-atoms TYPE ATOM...
704 parse JSON ATOMs as atoms of TYPE, and re-serialize
705 parse-atom-strings TYPE ATOM...
706 parse string ATOMs as atoms of given TYPE, and re-serialize
707 sort-atoms TYPE ATOM...
708 print JSON ATOMs in sorted order
709 parse-data TYPE DATUM...
710 parse JSON DATUMs as data of given TYPE, and re-serialize
711 parse-column NAME OBJECT
712 parse column NAME with info OBJECT, and re-serialize
713 parse-table NAME OBJECT [DEFAULT-IS-ROOT]
714 parse table NAME with info OBJECT
716 parse JSON as an OVSDB schema, and re-serialize
717 idl SCHEMA SERVER [?T1:C1,C2...[?T2:C1,C2,...]...] [TRANSACTION...]
718 connect to SERVER (which has the specified SCHEMA) and dump the
719 contents of the database as seen initially by the IDL implementation
720 and after executing each TRANSACTION. (Each TRANSACTION must modify
721 the database or this command will hang.)
722 By default, all columns of all tables are monitored. The "?" option
723 can be used to monitor specific Table:Column(s). The table and their
724 columns are listed as a string of the form starting with "?":
725 ?<table-name>:<column-name>,<column-name>,...
727 ?simple:b - Monitor column "b" in table "simple"
728 Entries for multiple tables are seperated by "?":
729 ?<table-name>:<column-name>,...?<table-name>:<column-name>,...
731 ?simple:b?link1:i,k - Monitor column "b" in table "simple",
732 and column "i", "k" in table "link1"
733 Readonly columns: Suffixing a "!" after a column indicates that the
734 column is to be registered "readonly".
736 ?simple:i,b! - Register interest in column "i" (monitoring) and
737 column "b" (readonly).
740 The following options are also available:
741 -t, --timeout=SECS give up after SECS seconds
742 -h, --help display this help message\
743 """ % {'program_name': ovs
.util
.PROGRAM_NAME
})
749 options
, args
= getopt
.gnu_getopt(argv
[1:], 't:h',
752 except getopt
.GetoptError
as geo
:
753 sys
.stderr
.write("%s: %s\n" % (ovs
.util
.PROGRAM_NAME
, geo
.msg
))
756 for key
, value
in options
:
757 if key
in ['-h', '--help']:
759 elif key
in ['-t', '--timeout']:
765 raise error
.Error("value %s on -t or --timeout is not at "
767 signal_alarm(timeout
)
772 sys
.stderr
.write("%s: missing command argument "
773 "(use --help for help)\n" % ovs
.util
.PROGRAM_NAME
)
776 commands
= {"default-atoms": (do_default_atoms
, 0),
777 "default-data": (do_default_data
, 0),
778 "parse-atomic-type": (do_parse_atomic_type
, 1),
779 "parse-base-type": (do_parse_base_type
, 1),
780 "parse-type": (do_parse_type
, 1),
781 "parse-atoms": (do_parse_atoms
, (2,)),
782 "parse-data": (do_parse_data
, (2,)),
783 "sort-atoms": (do_sort_atoms
, 2),
784 "parse-column": (do_parse_column
, 2),
785 "parse-table": (do_parse_table
, (2, 3)),
786 "parse-schema": (do_parse_schema
, 1),
787 "idl": (do_idl
, (2,)),
788 "idl_passive": (do_idl_passive
, (2,))}
790 command_name
= args
[0]
792 if command_name
not in commands
:
793 sys
.stderr
.write("%s: unknown command \"%s\" "
794 "(use --help for help)\n" % (ovs
.util
.PROGRAM_NAME
,
798 func
, n_args
= commands
[command_name
]
799 if type(n_args
) == tuple:
800 if len(args
) < n_args
[0]:
801 sys
.stderr
.write("%s: \"%s\" requires at least %d arguments but "
803 % (ovs
.util
.PROGRAM_NAME
, command_name
,
806 elif type(n_args
) == int:
807 if len(args
) != n_args
:
808 sys
.stderr
.write("%s: \"%s\" requires %d arguments but %d "
810 % (ovs
.util
.PROGRAM_NAME
, command_name
,
819 if __name__
== '__main__':
822 except error
.Error
as e
:
823 sys
.stderr
.write("%s\n" % e
)