Damn this was long overdue. I’m delighted to announce Stem 1.5.2, the accumulation of seventeen months of improvements.
What is Stem, you ask? For those who aren’t familiar with it Stem is a Python library for interacting with Tor. With it you can script against your relay, descriptor data, or even write applications similar to Nyx and Vidalia.
So what’s new in this release? Short answer: a lot.
Improved Python 3.x Performance
Reading from tor’s control port 800x faster, Python 3.x users will find this release a dramatic improvement. By ‘dramatic’ I mean multiple orders of magnitude.
Tor Manual Information
Stem’s new stem.manual module provides programmatic access for Tor manual information. For example, say we want a little script that told us what our torrc options do…
from stem.manual import Manual
from stem.util import term
print("Downloading tor's manual information, please wait...")
manual = Manual.from_remote()
except IOError as exc:
print(" unsuccessful (%s), using information provided with stem\n" % exc)
manual = Manual.from_cache() # fall back to our bundled manual information
print('Which tor configuration would you like to learn about? (press ctrl+c to quit)\n')
requested_option = raw_input('> ').strip()
if requested_option in manual.config_options:
option = manual.config_options[requested_option]
print(term.format('%s %s' % (option.name, option.usage), term.Color.GREEN, term.Attr.BOLD))
print(term.format(option.summary, term.Color.GREEN)) # brief description provided by stem
print(term.format('\nFull Description:\n', term.Color.GREEN, term.Attr.BOLD))
print(term.format(option.description + '\n', term.Color.GREEN))
print(term.format("Sorry, we don't have any information about %s. Are you sure it's an option?" % requested_option, term.Color.RED))
pass # user pressed ctrl+c
Fallback Directory Information
Relieving load fromt the directory authority, Stem can retrieve information about and use tor’s fallback directory mirrors…
from stem.descriptor.remote import DescriptorDownloader, FallbackDirectory
downloader = DescriptorDownloader()
for fallback_directory in FallbackDirectory.from_cache().values():
start = time.time()
downloader.get_consensus(endpoints = [(fallback_directory.address, fallback_directory.dir_port)]).run()
print('Downloading the consensus took %0.2f from %s' % (time.time() - start, fallback_directory.fingerprint))
As always this is just the tip of the iceberg. For a full rundown on the myriad of improvements and fixes in this release see our changelog.