
commit 1a26c5f654e783b649611b457149168105593e9a Author: Sambuddha Basu <sambuddhabasu1@gmail.com> Date: Mon May 25 08:31:59 2015 +0400 Added downloadable tutorial examples --- docs/_static/example/compare_flags.py | 41 +++++++++++++++++ docs/_static/example/exit_used.py | 35 +++++++++++++++ docs/_static/example/list_circuits.py | 21 +++++++++ docs/_static/example/outdated_relays.py | 19 ++++++++ docs/_static/example/persisting_a_consensus.py | 8 ++++ .../persisting_a_consensus_with_parse_file.py | 10 +++++ .../example/votes_by_bandwidth_authorities.py | 29 ++++++++++++ docs/tutorials/examples/compare_flags.rst | 46 ++------------------ docs/tutorials/examples/exit_used.rst | 40 ++--------------- docs/tutorials/examples/list_circuits.rst | 26 ++--------- docs/tutorials/examples/outdated_relays.rst | 24 ++-------- docs/tutorials/examples/persisting_a_consensus.rst | 28 +++--------- .../examples/votes_by_bandwidth_authorities.rst | 34 ++------------- 13 files changed, 184 insertions(+), 177 deletions(-) diff --git a/docs/_static/example/compare_flags.py b/docs/_static/example/compare_flags.py new file mode 100644 index 0000000..a668e11 --- /dev/null +++ b/docs/_static/example/compare_flags.py @@ -0,0 +1,41 @@ +from stem.descriptor import DocumentHandler, remote + +# Query all authority votes asynchronously. + +downloader = remote.DescriptorDownloader(document_handler = DocumentHandler.DOCUMENT) +queries = {} + +for name, authority in remote.get_authorities().items(): + if authority.v3ident is None: + continue # authority doens't vote if it lacks a v3ident + + queries[name] = downloader.get_vote(authority) + +# Wait for the votes to finish being downloaded, this produces a dictionary of +# authority nicknames to their vote. + +votes = dict((name, query.run()[0]) for (name, query) in queries.items()) + +# Get a superset of all the fingerprints in all the votes. + +all_fingerprints = set() + +for vote in votes.values(): + all_fingerprints.update(vote.routers.keys()) + +# Finally, compare moria1's votes to maatuska. + +for fingerprint in all_fingerprints: + moria1_vote = votes['moria1'].routers.get(fingerprint) + maatuska_vote = votes['maatuska'].routers.get(fingerprint) + + if not moria1_vote and not maatuska_vote: + print "both moria1 and maatuska haven't voted about %s" % fingerprint + elif not moria1_vote: + print "moria1 hasn't voted about %s" % fingerprint + elif not maatuska_vote: + print "maatuska hasn't voted about %s" % fingerprint + elif 'Running' in moria1_vote.flags and 'Running' not in maatuska_vote.flags: + print "moria1 has the Running flag but maatuska doesn't: %s" % fingerprint + elif 'Running' in maatuska_vote.flags and 'Running' not in moria1_vote.flags: + print "maatuska has the Running flag but moria1 doesn't: %s" % fingerprint diff --git a/docs/_static/example/exit_used.py b/docs/_static/example/exit_used.py new file mode 100644 index 0000000..7ecd19a --- /dev/null +++ b/docs/_static/example/exit_used.py @@ -0,0 +1,35 @@ +import functools + +from stem import StreamStatus +from stem.control import EventType, Controller + +def main(): + print "Tracking requests for tor exits. Press 'enter' to end." + print + + with Controller.from_port() as controller: + controller.authenticate() + + stream_listener = functools.partial(stream_event, controller) + controller.add_event_listener(stream_listener, EventType.STREAM) + + raw_input() # wait for user to press enter + + +def stream_event(controller, event): + if event.status == StreamStatus.SUCCEEDED and event.circ_id: + circ = controller.get_circuit(event.circ_id) + + exit_fingerprint = circ.path[-1][0] + exit_relay = controller.get_network_status(exit_fingerprint) + + print "Exit relay for our connection to %s" % (event.target) + print " address: %s:%i" % (exit_relay.address, exit_relay.or_port) + print " fingerprint: %s" % exit_relay.fingerprint + print " nickname: %s" % exit_relay.nickname + print " locale: %s" % controller.get_info("ip-to-country/%s" % exit_relay.address, 'unknown') + print + + +if __name__ == '__main__': + main() diff --git a/docs/_static/example/list_circuits.py b/docs/_static/example/list_circuits.py new file mode 100644 index 0000000..61fdd5e --- /dev/null +++ b/docs/_static/example/list_circuits.py @@ -0,0 +1,21 @@ +from stem import CircStatus +from stem.control import Controller + +with Controller.from_port(port = 9051) as controller: + controller.authenticate() + + for circ in sorted(controller.get_circuits()): + if circ.status != CircStatus.BUILT: + continue + + print + print "Circuit %s (%s)" % (circ.id, circ.purpose) + + for i, entry in enumerate(circ.path): + div = '+' if (i == len(circ.path) - 1) else '|' + fingerprint, nickname = entry + + desc = controller.get_network_status(fingerprint, None) + address = desc.address if desc else 'unknown' + + print " %s- %s (%s, %s)" % (div, fingerprint, nickname, address) diff --git a/docs/_static/example/outdated_relays.py b/docs/_static/example/outdated_relays.py new file mode 100644 index 0000000..a78c6ee --- /dev/null +++ b/docs/_static/example/outdated_relays.py @@ -0,0 +1,19 @@ +from stem.descriptor.remote import DescriptorDownloader +from stem.version import Version + +downloader = DescriptorDownloader() +count, with_contact = 0, 0 + +print "Checking for outdated relays..." +print + +for desc in downloader.get_server_descriptors(): + if desc.tor_version < Version('0.2.3.0'): + count += 1 + + if desc.contact: + print ' %-15s %s' % (desc.tor_version, desc.contact.decode("utf-8", "replace")) + with_contact += 1 + +print +print "%i outdated relays found, %i had contact information" % (count, with_contact) diff --git a/docs/_static/example/persisting_a_consensus.py b/docs/_static/example/persisting_a_consensus.py new file mode 100644 index 0000000..55b17bd --- /dev/null +++ b/docs/_static/example/persisting_a_consensus.py @@ -0,0 +1,8 @@ +from stem.descriptor import DocumentHandler +from stem.descriptor.remote import DescriptorDownloader + +downloader = DescriptorDownloader() +consensus = downloader.get_consensus(document_handler = DocumentHandler.DOCUMENT).run()[0] + +with open('/tmp/descriptor_dump', 'w') as descriptor_file: + descriptor_file.write(str(consensus)) diff --git a/docs/_static/example/persisting_a_consensus_with_parse_file.py b/docs/_static/example/persisting_a_consensus_with_parse_file.py new file mode 100644 index 0000000..bbec73a --- /dev/null +++ b/docs/_static/example/persisting_a_consensus_with_parse_file.py @@ -0,0 +1,10 @@ +from stem.descriptor import DocumentHandler, parse_file + +consensus = next(parse_file( + '/tmp/descriptor_dump', + descriptor_type = 'network-status-consensus-3 1.0', + document_handler = DocumentHandler.DOCUMENT, +)) + +for fingerprint, relay in consensus.routers.items(): + print "%s: %s" % (fingerprint, relay.nickname) diff --git a/docs/_static/example/votes_by_bandwidth_authorities.py b/docs/_static/example/votes_by_bandwidth_authorities.py new file mode 100644 index 0000000..e957be5 --- /dev/null +++ b/docs/_static/example/votes_by_bandwidth_authorities.py @@ -0,0 +1,29 @@ +from stem.descriptor import remote + +# request votes from all the bandwidth authorities + +queries = {} +downloader = remote.DescriptorDownloader() + +for authority in remote.get_authorities().values(): + if authority.is_bandwidth_authority: + queries[authority.nickname] = downloader.query( + '/tor/status-vote/current/authority', + endpoints = [(authority.address, authority.dir_port)], + ) + +for authority_name, query in queries.items(): + try: + print "Getting %s's vote from %s:" % (authority_name, query.download_url) + + measured, unmeasured = 0, 0 + + for desc in query.run(): + if desc.measured: + measured += 1 + else: + unmeasured += 1 + + print ' %i measured entries and %i unmeasured' % (measured, unmeasured) + except Exception as exc: + print " failed to get the vote (%s)" % exc diff --git a/docs/tutorials/examples/compare_flags.rst b/docs/tutorials/examples/compare_flags.rst index 07a4126..3ea6143 100644 --- a/docs/tutorials/examples/compare_flags.rst +++ b/docs/tutorials/examples/compare_flags.rst @@ -7,49 +7,9 @@ Comparing Directory Authority Flags Compares the votes of two directory authorities, in this case moria1 and maatuska, with a special interest in the 'Running' flag. -:: - - from stem.descriptor import DocumentHandler, remote - - # Query all authority votes asynchronously. - - downloader = remote.DescriptorDownloader(document_handler = DocumentHandler.DOCUMENT) - queries = {} - - for name, authority in remote.get_authorities().items(): - if authority.v3ident is None: - continue # authority doens't vote if it lacks a v3ident - - queries[name] = downloader.get_vote(authority) - - # Wait for the votes to finish being downloaded, this produces a dictionary of - # authority nicknames to their vote. - - votes = dict((name, query.run()[0]) for (name, query) in queries.items()) - - # Get a superset of all the fingerprints in all the votes. - - all_fingerprints = set() - - for vote in votes.values(): - all_fingerprints.update(vote.routers.keys()) - - # Finally, compare moria1's votes to maatuska. - - for fingerprint in all_fingerprints: - moria1_vote = votes['moria1'].routers.get(fingerprint) - maatuska_vote = votes['maatuska'].routers.get(fingerprint) - - if not moria1_vote and not maatuska_vote: - print "both moria1 and maatuska haven't voted about %s" % fingerprint - elif not moria1_vote: - print "moria1 hasn't voted about %s" % fingerprint - elif not maatuska_vote: - print "maatuska hasn't voted about %s" % fingerprint - elif 'Running' in moria1_vote.flags and 'Running' not in maatuska_vote.flags: - print "moria1 has the Running flag but maatuska doesn't: %s" % fingerprint - elif 'Running' in maatuska_vote.flags and 'Running' not in moria1_vote.flags: - print "maatuska has the Running flag but moria1 doesn't: %s" % fingerprint +.. literalinclude:: /_static/example/compare_flags.py + :caption: `[Download] <../../_static/example/compare_flags.py>`__ + :language: python :: diff --git a/docs/tutorials/examples/exit_used.rst b/docs/tutorials/examples/exit_used.rst index 26a9a63..095cd3c 100644 --- a/docs/tutorials/examples/exit_used.rst +++ b/docs/tutorials/examples/exit_used.rst @@ -11,43 +11,9 @@ out what exit you're using? Here's a simple script that prints information about the exits used to service the requests going through Tor... -:: - - import functools - - from stem import StreamStatus - from stem.control import EventType, Controller - - def main(): - print "Tracking requests for tor exits. Press 'enter' to end." - print - - with Controller.from_port() as controller: - controller.authenticate() - - stream_listener = functools.partial(stream_event, controller) - controller.add_event_listener(stream_listener, EventType.STREAM) - - raw_input() # wait for user to press enter - - - def stream_event(controller, event): - if event.status == StreamStatus.SUCCEEDED and event.circ_id: - circ = controller.get_circuit(event.circ_id) - - exit_fingerprint = circ.path[-1][0] - exit_relay = controller.get_network_status(exit_fingerprint) - - print "Exit relay for our connection to %s" % (event.target) - print " address: %s:%i" % (exit_relay.address, exit_relay.or_port) - print " fingerprint: %s" % exit_relay.fingerprint - print " nickname: %s" % exit_relay.nickname - print " locale: %s" % controller.get_info("ip-to-country/%s" % exit_relay.address, 'unknown') - print - - - if __name__ == '__main__': - main() +.. literalinclude:: /_static/example/exit_used.py + :caption: `[Download] <../../_static/example/exit_used.py>`__ + :language: python Now if you make a request over Tor... diff --git a/docs/tutorials/examples/list_circuits.rst b/docs/tutorials/examples/list_circuits.rst index 800b945..298089b 100644 --- a/docs/tutorials/examples/list_circuits.rst +++ b/docs/tutorials/examples/list_circuits.rst @@ -7,29 +7,9 @@ List Circuits Tor creates new circuits and tears down old ones on your behalf, so how can you get information about circuits Tor currently has available? -:: - - from stem import CircStatus - from stem.control import Controller - - with Controller.from_port(port = 9051) as controller: - controller.authenticate() - - for circ in sorted(controller.get_circuits()): - if circ.status != CircStatus.BUILT: - continue - - print - print "Circuit %s (%s)" % (circ.id, circ.purpose) - - for i, entry in enumerate(circ.path): - div = '+' if (i == len(circ.path) - 1) else '|' - fingerprint, nickname = entry - - desc = controller.get_network_status(fingerprint, None) - address = desc.address if desc else 'unknown' - - print " %s- %s (%s, %s)" % (div, fingerprint, nickname, address) +.. literalinclude:: /_static/example/list_circuits.py + :caption: `[Download] <../../_static/example/list_circuits.py>`__ + :language: python :: diff --git a/docs/tutorials/examples/outdated_relays.rst b/docs/tutorials/examples/outdated_relays.rst index 283b94f..e7d4cb2 100644 --- a/docs/tutorials/examples/outdated_relays.rst +++ b/docs/tutorials/examples/outdated_relays.rst @@ -8,27 +8,9 @@ Time marches on. Tor makes new releases, and at some point needs to drop support for old ones. Below is the script we used on :trac:`9476` to reach out to relay operators that needed to upgrade. -:: - - from stem.descriptor.remote import DescriptorDownloader - from stem.version import Version - - downloader = DescriptorDownloader() - count, with_contact = 0, 0 - - print "Checking for outdated relays..." - print - - for desc in downloader.get_server_descriptors(): - if desc.tor_version < Version('0.2.3.0'): - count += 1 - - if desc.contact: - print ' %-15s %s' % (desc.tor_version, desc.contact.decode("utf-8", "replace")) - with_contact += 1 - - print - print "%i outdated relays found, %i had contact information" % (count, with_contact) +.. literalinclude:: /_static/example/outdated_relays.py + :caption: `[Download] <../../_static/example/outdated_relays.py>`__ + :language: python :: diff --git a/docs/tutorials/examples/persisting_a_consensus.rst b/docs/tutorials/examples/persisting_a_consensus.rst index d9c681b..6e51fe7 100644 --- a/docs/tutorials/examples/persisting_a_consensus.rst +++ b/docs/tutorials/examples/persisting_a_consensus.rst @@ -30,16 +30,9 @@ So how do we get it? Just tell Stem that's what you want. The :class:`~stem.descriptor.__init__.DocumentHandler` tells Stem how to read the consensus. For example, to write the consensus simply do the following... -:: - - from stem.descriptor import DocumentHandler - from stem.descriptor.remote import DescriptorDownloader - - downloader = DescriptorDownloader() - consensus = downloader.get_consensus(document_handler = DocumentHandler.DOCUMENT).run()[0] - - with open('/tmp/descriptor_dump', 'w') as descriptor_file: - descriptor_file.write(str(consensus)) +.. literalinclude:: /_static/example/persisting_a_consensus.py + :caption: `[Download] <../../_static/example/persisting_a_consensus.py>`__ + :language: python Our *consensus* here is the current :class:`~stem.descriptor.networkstatus.NetworkStatusDocumentV3`. The @@ -58,15 +51,6 @@ Our *consensus* here is the current You can then read it back with :func:`~stem.descriptor.__init__.parse_file`... -:: - - from stem.descriptor import DocumentHandler, parse_file - - consensus = next(parse_file( - '/tmp/descriptor_dump', - descriptor_type = 'network-status-consensus-3 1.0', - document_handler = DocumentHandler.DOCUMENT, - )) - - for fingerprint, relay in consensus.routers.items(): - print "%s: %s" % (fingerprint, relay.nickname) +.. literalinclude:: /_static/example/persisting_a_consensus_with_parse_file.py + :caption: `[Download] <../../_static/example/persisting_a_consensus_with_parse_file.py>`__ + :language: python diff --git a/docs/tutorials/examples/votes_by_bandwidth_authorities.rst b/docs/tutorials/examples/votes_by_bandwidth_authorities.rst index c413c96..df78ca2 100644 --- a/docs/tutorials/examples/votes_by_bandwidth_authorities.rst +++ b/docs/tutorials/examples/votes_by_bandwidth_authorities.rst @@ -16,37 +16,9 @@ more complicated than that, but that's the general idea. Bandwidth authorities include their measurements in their votes. The following gets their current votes then prints how many relays it had a measurement for. -:: - - from stem.descriptor import remote - - # request votes from all the bandwidth authorities - - queries = {} - downloader = remote.DescriptorDownloader() - - for authority in remote.get_authorities().values(): - if authority.is_bandwidth_authority: - queries[authority.nickname] = downloader.query( - '/tor/status-vote/current/authority', - endpoints = [(authority.address, authority.dir_port)], - ) - - for authority_name, query in queries.items(): - try: - print "Getting %s's vote from %s:" % (authority_name, query.download_url) - - measured, unmeasured = 0, 0 - - for desc in query.run(): - if desc.measured: - measured += 1 - else: - unmeasured += 1 - - print ' %i measured entries and %i unmeasured' % (measured, unmeasured) - except Exception as exc: - print " failed to get the vote (%s)" % exc +.. literalinclude:: /_static/example/votes_by_bandwidth_authorities.py + :caption: `[Download] <../../_static/example/votes_by_bandwidth_authorities.py>`__ + :language: python ::