pax_global_header00006660000000000000000000000064122674625430014525gustar00rootroot0000000000000052 comment=715b54436837e6425e599e243c42e49670092cd4 txtorcon-0.9.1/000077500000000000000000000000001226746254300134145ustar00rootroot00000000000000txtorcon-0.9.1/INSTALL000066400000000000000000000017371226746254300144550ustar00rootroot00000000000000 See README for more information. To just install this as quickly as possible, using a Debian or Ubuntu system, run the following as root: apt-get install python-setuptools python-twisted python-ipaddr python-geoip python-psutil graphviz python setup.py install Or, instead of installing locally, simply: export PYTHONPATH=. If you want to take slightly more time, but only install temporarily, use virtualenv: apt-get install python-setuptools python-pip python setup.py build mkdir tmp virtualenv --never-download --extra-search-dir=/usr/lib/python2.7/dist-packages/ tmp/txtorcon_env cd tmp/txtorcon_env source bin/activate pip install Twisted ipaddr pygeoip # this will download from internets: export PYTHONPATH=../../build/lib.linux-x86_64-2.7/ (Or you can type "make virtualenv" which creates tmp/txtorcon_env, up to the "activate" step above) Now, this should work (where "work" means "prints nothing"): python -c "import txtorcon" txtorcon-0.9.1/LICENSE000066400000000000000000000020401226746254300144150ustar00rootroot00000000000000Copyright (c) 2012, 2013 meejah Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. txtorcon-0.9.1/MANIFEST.in000066400000000000000000000005461226746254300151570ustar00rootroot00000000000000include Makefile include README.rst include INSTALL include TODO include LICENSE include meejah.asc include scripts/*.py include docs/Makefile include docs/apilinks_sphinxext.py include docs/conf.py include docs/*.rst include docs/_static/* exclude docs/_static/*~ include examples/* exclude examples/*~ include requirements.txt include dev-requirements.txt txtorcon-0.9.1/Makefile000066400000000000000000000057741226746254300150710ustar00rootroot00000000000000.PHONY: test html counts coverage sdist clean install doc integration default: test test: trial --reporter=text test # see also http://docs.docker.io/en/latest/use/baseimages/ dockerbase-wheezy: @echo 'Building a minimal "wheezy" system.' @echo "This may take a while...and will consume about 240MB when done." debootstrap wheezy dockerbase-wheezy dockerbase-wheezy-image: dockerbase-wheezy @echo 'Importing dockerbase-wheezy into docker' tar -C dockerbase-wheezy -c . | docker import - dockerbase-wheezy docker run dockerbase-wheezy cat /etc/issue txtorcon-tester: Dockerfile dockerbase-wheezy-image @echo "Creating a Docker.io container" docker build -rm -q -t txtorcon-tester ./ integration: ## txtorcon-tester python integration/run.py install: python setup.py install doc: docs/*.rst cd docs && make html -cp dist/txtorcon-0.9.1.tar.gz docs/_build/html coverage: coverage run --source=txtorcon `which trial` test coverage -a -d annotated_coverage coverage report # dang, this is a little annoying. maybe add a shell-script which # looks for "coverage" or "python-coverage"?? coverage-debian: python-coverage run --source=txtorcon `which trial` test python-coverage -a -d annotated_coverage python-coverage report pep8: find txtorcon/*.py test/*.py examples/*.py | xargs pep8 --ignore=E501 pep8count: find txtorcon/*.py test/*.py examples/*.py | xargs pep8 --ignore=E501 | wc -l pyflakes: pyflakes txtorcon/ examples/ test/ pyflakescount: pyflakes txtorcon/ examples/ | wc -l clean: -rm -rf _trial_temp -rm -rf build -rm -rf dist -rm -rf html -rm MANIFEST -rm `find . -name \*.py[co]` -cd docs && make clean -rm -rf dockerbase-wheezy -docker rmi txtorcon-tester -docker rmi dockerbase-wheezy counts: ohcount -s txtorcon/*.py dist: dist/txtorcon-0.9.1-py27-none-any.whl.asc dist/txtorcon-0.9.1.tar.gz.asc sdist: setup.py python setup.py sdist dist/txtorcon-0.9.1-py27-none-any.whl: python setup.py bdist_wheel dist/txtorcon-0.9.1-py27-none-any.whl.asc: dist/txtorcon-0.9.1-py27-none-any.whl gpg --verify dist/txtorcon-0.9.1-py27-none-any.whl.asc || gpg --no-version --detach-sign --armor --local-user meejah@meejah.ca dist/txtorcon-0.9.1-py27-none-any.whl dist/txtorcon-0.9.1.tar.gz: sdist dist/txtorcon-0.9.1.tar.gz.asc: dist/txtorcon-0.9.1.tar.gz gpg --verify dist/txtorcon-0.9.1.tar.gz.asc || gpg --no-version --detach-sign --armor --local-user meejah@meejah.ca dist/txtorcon-0.9.1.tar.gz release: twine upload -r pypi -c "txtorcon v0.9.1 tarball" dist/txtorcon-0.9.1.tar.gz dist/txtorcon-0.9.1.tar.gz.asc twine upload -r pypi -c "txtorcon v0.9.1 wheel" dist/txtorcon-0.9.1-py27-none-any.whl dist/txtorcon-0.9.1-py27-none-any.whl.asc venv: virtualenv --never-download --extra-search-dir=/usr/lib/python2.7/dist-packages/ venv @echo "created venv" @echo "see INSTALL for more information; to use:" @echo ". ./venv/bin/activate" @echo "pip install -r requirements.txt" @echo "pip install -r dev-requirements.txt" @echo "python examples/monitor.py" html: docs/README.rst cd docs && make html txtorcon-0.9.1/PKG-INFO000066400000000000000000000247131226746254300145200ustar00rootroot00000000000000Metadata-Version: 1.1 Name: txtorcon Version: 0.9.1 Summary: Twisted-based Tor controller client, with state-tracking and configuration abstractions. Home-page: https://github.com/meejah/txtorcon Author: meejah Author-email: meejah@meejah.ca License: MIT Description: txtorcon README =============== Full, built **documentation at ReadTheDocs https://txtorcon.readthedocs.org** .. image:: https://travis-ci.org/meejah/txtorcon.png?branch=master :target: https://www.travis-ci.org/meejah/txtorcon .. image:: https://coveralls.io/repos/meejah/txtorcon/badge.png :target: https://coveralls.io/r/meejah/txtorcon quick start ----------- For the impatient, there are two quick ways to install this:: $ pip install txtorcon or, if you checked out or downloaded the source:: $ python setup.py install To avoid installing, you can just add the base of the source to your PYTHONPATH:: $ export PYTHONPATH=`pwd`:$PYTHONPATH Then, you will want to explore the examples. Try "python examples/stream\_circuit\_logger.py" for instance. On Debian testing (jessie), or with wheezy-backports you can install version 0.8.2:: $ apt-get install python-txtorcon You may also like `this asciinema demo `_ for an overview. overview -------- txtorcon is a Twisted-based asynchronous Tor control protocol implementation. Twisted is an event-driven networking engine written in Python and Tor is an onion-routing network designed to improve people's privacy and anonymity on the Internet. The main abstraction of this library is txtorcon.TorControlProtocol which presents an asynchronous API to speak the Tor client protocol in Python. txtorcon also provides abstractions to track and get updates about Tor's state (txtorcon.TorState) and current configuration (including writing it to Tor or disk) in txtorcon.TorConfig, along with helpers to asynchronously launch slave instances of Tor including Twisted endpoint support. txtorcon runs all tests cleanly on: - Debian "squeeze", "wheezy" and "jessie" - OS X 10.4 (naif) - OS X 10.8 (lukas lueg) - Fedora 18 (lukas lueg) - Reports from other OSes appreciated. If instead you want a synchronous (threaded) Python controller library, check out Stem at https://stem.torproject.org/ quick implementation overview ----------------------------- txtorcon provides a class to track Tor's current state -- such as details about routers, circuits and streams -- called txtorcon.TorState and an abstraction to the configuration values via txtorcon.TorConfig which provides attribute-style accessors to Tor's state (including making changes). txtorcon.TorState provides txtorcon.Router, txtorcon.Circuit and txtorcon.Stream objects which implement a listener interface so client code may receive updates (in real time) including Tor events. txtorcon uses **trial for unit-tests** and has 96% test-coverage -- which is not to say I've covered all the cases, but nearly all of the code is at least exercised somehow by the unit tests. Tor itself is not required to be running for any of the tests. There are no integration tests. ohcount claims around 2000 lines of code for the core bit; around 4000 including tests. About 37% comments in the not-test code. dependencies / requirements --------------------------- - `twisted `_: I am working against Twisted 11.1.0 on Debian with Python 2.7.2. Twisted 12 works fine as well. Twisted does not yet support Python 3. - `GeoIP `_: **optional** provides location information for ip addresses; you will want to download GeoLite City from `MaxMind `_ or pay them for more accuracy. Or use tor-geoip, which makes this sort-of optional, in that we'll query Tor for the if the GeoIP database doesn't have an answer but I haven't bothered removing the dependency yet. It also does ASN lookups if you installed that MaxMind database. - `python-ipaddr `_: **optional**. Google's IP address manipulation code. - development: `Sphinx `_ if you want to build the documentation. In that case you'll also need something called ``python-repoze.sphinx.autointerface`` (at least in Debian) to build the Interface-derived docs properly. - development: `coverage `_ to run the code-coverage metrics - optional: GraphViz is used in the tests (and to generate state-machine diagrams, if you like) but those tests are skipped if "dot" isn't in your path In any case, on a `Debian `_ wheezy, squeeze or Ubuntu system, this should work:: apt-get install python-setuptools python-twisted python-ipaddr python-geoip graphviz apt-get install python-sphinx python-repoze.sphinx.autointerface python-coverage # for develoment Using pip this would be:: pip install Twisted ipaddr pygeoip pip install GeoIP Sphinx repoze.sphinx.autointerface coverage # for development or:: pip install -r requirements.txt pip install -r dev-requirements.txt or for the bare minimum:: pip install Twisted # will install zope.interface too documentation ------------- It is likely that you will need to read at least some of `control-spec.txt `_ from the torspec git repository so you know what's being abstracted by this library. Run "make doc" to build the Sphinx documentation locally, or rely on ReadTheDocs https://txtorcon.readthedocs.org which builds each tagged release and the latest master. There is also a directory of examples/ scripts, which have inline documentation explaining their use. You may also use pydoc:: pydoc txtorcon.TorControlProtocol pydoc txtorcon.TorState pydoc txtorcon.TorConfig ...for the main classes. If you're using TorState, you will also be interested in the support classes for it:: pydoc txtorcon.Circuit pydoc txtorcon.Stream pydoc txtorcon.Router pydoc txtorcon.AddrMap There are also Zope interfaces for some things, if you wish to listen for events for your own purposes (the best example of the use of these being TorState itself):: txtorcon.ITorControlProtocol txtorcon.IStreamAttacher txtorcon.ICircuitListener txtorcon.IStreamListener For launching Tor and Twisted integration, you will want to look at:: txtorcon.launch_tor (in torconfig.py) txtorcon.TCPHiddenServiceEndpoint (in torconfig.py) txtorcon.TorProtocolFactory (in torcontrolprotocol.py) txtorcon.build_tor_connection (in torstate.py) txtorcon.build_local_tor_connection (in torstate.py) IStreamAttacher affects Tor's behaviour, allowing one to customize how circuits for particular streams are selected. You can build your own circuits via ITorControlProtocol.build\_circuit(). There is an example of this called custom\_stream\_attacher.py which builds (or uses) circuits exiting in the same country as the address to which the stream is connecting. contact information ------------------- For novelty value, the Web site (with built documentation and so forth) can be viewed via Tor at https://timaq4ygg2iegci7.onion although the code itself is hosted via git:: torsocks git clone git://timaq4ygg2iegci7.onion/txtorcon.git or:: git clone git://github.com/meejah/txtorcon.git You may contact me via ``meejah at meejah dot ca`` with GPG key `0xC2602803128069A7 `_ or see ``meejah.asc`` in the repository. The fingerprint is ``9D5A 2BD5 688E CB88 9DEB CD3F C260 2803 1280 69A7``. It is often possible to contact me as ``meejah`` in #tor-dev on `OFTC `_ but be patient for replies (I do look at scrollback, so putting "meejah: " in front will alert my client). More conventionally, you may get the code at GitHub and documentation via ReadTheDocs: - https://github.com/meejah/txtorcon - https://txtorcon.readthedocs.org Please do **use the GitHub issue-tracker** to report bugs. Patches, pull-requests, comments and criticisms are all welcomed and appreciated. Keywords: python,twisted,tor,tor controller Platform: UNKNOWN Classifier: Framework :: Twisted Classifier: Development Status :: 4 - Beta Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Natural Language :: English Classifier: Operating System :: POSIX :: Linux Classifier: Operating System :: Unix Classifier: Programming Language :: Python Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: Internet :: Proxy Servers Classifier: Topic :: Internet Classifier: Topic :: Security Requires: Twisted (>=11.1.0) Requires: ipaddr (>=2.1.10) Requires: zope.interface (>=3.6.1) txtorcon-0.9.1/README.rst000066400000000000000000000174561226746254300151200ustar00rootroot00000000000000txtorcon README =============== Full, built **documentation at ReadTheDocs https://txtorcon.readthedocs.org** .. image:: https://travis-ci.org/meejah/txtorcon.png?branch=master :target: https://www.travis-ci.org/meejah/txtorcon .. image:: https://coveralls.io/repos/meejah/txtorcon/badge.png :target: https://coveralls.io/r/meejah/txtorcon quick start ----------- For the impatient, there are two quick ways to install this:: $ pip install txtorcon or, if you checked out or downloaded the source:: $ python setup.py install To avoid installing, you can just add the base of the source to your PYTHONPATH:: $ export PYTHONPATH=`pwd`:$PYTHONPATH Then, you will want to explore the examples. Try "python examples/stream\_circuit\_logger.py" for instance. On Debian testing (jessie), or with wheezy-backports you can install version 0.8.2:: $ apt-get install python-txtorcon You may also like `this asciinema demo `_ for an overview. overview -------- txtorcon is a Twisted-based asynchronous Tor control protocol implementation. Twisted is an event-driven networking engine written in Python and Tor is an onion-routing network designed to improve people's privacy and anonymity on the Internet. The main abstraction of this library is txtorcon.TorControlProtocol which presents an asynchronous API to speak the Tor client protocol in Python. txtorcon also provides abstractions to track and get updates about Tor's state (txtorcon.TorState) and current configuration (including writing it to Tor or disk) in txtorcon.TorConfig, along with helpers to asynchronously launch slave instances of Tor including Twisted endpoint support. txtorcon runs all tests cleanly on: - Debian "squeeze", "wheezy" and "jessie" - OS X 10.4 (naif) - OS X 10.8 (lukas lueg) - Fedora 18 (lukas lueg) - Reports from other OSes appreciated. If instead you want a synchronous (threaded) Python controller library, check out Stem at https://stem.torproject.org/ quick implementation overview ----------------------------- txtorcon provides a class to track Tor's current state -- such as details about routers, circuits and streams -- called txtorcon.TorState and an abstraction to the configuration values via txtorcon.TorConfig which provides attribute-style accessors to Tor's state (including making changes). txtorcon.TorState provides txtorcon.Router, txtorcon.Circuit and txtorcon.Stream objects which implement a listener interface so client code may receive updates (in real time) including Tor events. txtorcon uses **trial for unit-tests** and has 96% test-coverage -- which is not to say I've covered all the cases, but nearly all of the code is at least exercised somehow by the unit tests. Tor itself is not required to be running for any of the tests. There are no integration tests. ohcount claims around 2000 lines of code for the core bit; around 4000 including tests. About 37% comments in the not-test code. dependencies / requirements --------------------------- - `twisted `_: I am working against Twisted 11.1.0 on Debian with Python 2.7.2. Twisted 12 works fine as well. Twisted does not yet support Python 3. - `GeoIP `_: **optional** provides location information for ip addresses; you will want to download GeoLite City from `MaxMind `_ or pay them for more accuracy. Or use tor-geoip, which makes this sort-of optional, in that we'll query Tor for the if the GeoIP database doesn't have an answer but I haven't bothered removing the dependency yet. It also does ASN lookups if you installed that MaxMind database. - `python-ipaddr `_: **optional**. Google's IP address manipulation code. - development: `Sphinx `_ if you want to build the documentation. In that case you'll also need something called ``python-repoze.sphinx.autointerface`` (at least in Debian) to build the Interface-derived docs properly. - development: `coverage `_ to run the code-coverage metrics - optional: GraphViz is used in the tests (and to generate state-machine diagrams, if you like) but those tests are skipped if "dot" isn't in your path In any case, on a `Debian `_ wheezy, squeeze or Ubuntu system, this should work:: apt-get install python-setuptools python-twisted python-ipaddr python-geoip graphviz apt-get install python-sphinx python-repoze.sphinx.autointerface python-coverage # for develoment Using pip this would be:: pip install Twisted ipaddr pygeoip pip install GeoIP Sphinx repoze.sphinx.autointerface coverage # for development or:: pip install -r requirements.txt pip install -r dev-requirements.txt or for the bare minimum:: pip install Twisted # will install zope.interface too documentation ------------- It is likely that you will need to read at least some of `control-spec.txt `_ from the torspec git repository so you know what's being abstracted by this library. Run "make doc" to build the Sphinx documentation locally, or rely on ReadTheDocs https://txtorcon.readthedocs.org which builds each tagged release and the latest master. There is also a directory of examples/ scripts, which have inline documentation explaining their use. You may also use pydoc:: pydoc txtorcon.TorControlProtocol pydoc txtorcon.TorState pydoc txtorcon.TorConfig ...for the main classes. If you're using TorState, you will also be interested in the support classes for it:: pydoc txtorcon.Circuit pydoc txtorcon.Stream pydoc txtorcon.Router pydoc txtorcon.AddrMap There are also Zope interfaces for some things, if you wish to listen for events for your own purposes (the best example of the use of these being TorState itself):: txtorcon.ITorControlProtocol txtorcon.IStreamAttacher txtorcon.ICircuitListener txtorcon.IStreamListener For launching Tor and Twisted integration, you will want to look at:: txtorcon.launch_tor (in torconfig.py) txtorcon.TCPHiddenServiceEndpoint (in torconfig.py) txtorcon.TorProtocolFactory (in torcontrolprotocol.py) txtorcon.build_tor_connection (in torstate.py) txtorcon.build_local_tor_connection (in torstate.py) IStreamAttacher affects Tor's behaviour, allowing one to customize how circuits for particular streams are selected. You can build your own circuits via ITorControlProtocol.build\_circuit(). There is an example of this called custom\_stream\_attacher.py which builds (or uses) circuits exiting in the same country as the address to which the stream is connecting. contact information ------------------- For novelty value, the Web site (with built documentation and so forth) can be viewed via Tor at https://timaq4ygg2iegci7.onion although the code itself is hosted via git:: torsocks git clone git://timaq4ygg2iegci7.onion/txtorcon.git or:: git clone git://github.com/meejah/txtorcon.git You may contact me via ``meejah at meejah dot ca`` with GPG key `0xC2602803128069A7 `_ or see ``meejah.asc`` in the repository. The fingerprint is ``9D5A 2BD5 688E CB88 9DEB CD3F C260 2803 1280 69A7``. It is often possible to contact me as ``meejah`` in #tor-dev on `OFTC `_ but be patient for replies (I do look at scrollback, so putting "meejah: " in front will alert my client). More conventionally, you may get the code at GitHub and documentation via ReadTheDocs: - https://github.com/meejah/txtorcon - https://txtorcon.readthedocs.org Please do **use the GitHub issue-tracker** to report bugs. Patches, pull-requests, comments and criticisms are all welcomed and appreciated. txtorcon-0.9.1/TODO000066400000000000000000000126241226746254300141110ustar00rootroot00000000000000 . strip OKs off the end of responses in TorControlProtocol -- should simplify the rest, and testing. See FIXME in at least torinfo.py:89 or so . look at get_info versus get_info_raw for entry_guards: parse keywords needs to be more smarterer . looks like ~41 hours to do full scan of 850321 combinations, at 3.5 seconds per combo and 20 outstanding requests (i.e. 20 in parallel at 3.5 seconds each). . should handle the case when routers are added/delete in exit-scanning thing. Maybe/probably add an IRouterListener that has callbacks for new and removed routers? . need test for authentication (and other) bootstrap errors -- does the Deferred from build_tor_connection get the errbacks properly? . If I want to depend on sphinx-contrib's programoutput then I can add this to README to get live results from the tests/coverage things: .. command-output:: make test :ellipsis: 0,-5 :shell: :nostderr: .. command-output:: make coverage :ellipsis: 0,-5 :shell: :nostderr: This also needs a couple changes to doc, in Makefile: test: cd .. && make test coverage: cd .. && make coverage and to conf.py, adding to extensions: 'sphinxcontrib.programoutput' . if we're going with "attribute-style access for everything" then also basically everything should be audited for this: . TorControlProtocol needs some things marked read-only? . TorState.set_attacher . put the nginx config for the hidden service somewhere in git; need to remember to change the redirect for "-latest" if releasing a new version... . Looking briefly at "chutney" (tor test-network setup thing) it seems to me an improvement on the templates would be: use txtor.TorConfig in a mode that allows one to set objects by keys (including hidden services, lists-of-strings, etc) and somewhere else is code which can start Tor based on a TorConfig -- *after* it connects, it does validation on the TorConfig by going through all the now-valid Parser objects asking them to validate the options. Then, instead of templates which "inherit" from each other and have an environment to set up, you have Python types (following Builder pattern) which represent the Tors you want to set up so you have a Relay class that has a subclass Authority whith the bonus it can override anything in Relay. They'd all implement a method in something like ITorConfigBuilder that asks it to return a config give a Node object (for example, FIXME: look up Builder again). For example: class ITorConfigBuilder(Interface): def build_config_for(self, node): """return a TorConfig object for the given Node instance""" class Relay: implements(ITorConfigBuilder) def build_config_for(self, node): config = txtor.TorConfig() config.SocksPort = 0 config.OrPort = node.or_port config.Address = node.ip config.DirPort = node.dir_port return config class Authority(Relay): implements(ITorConfigBuilder) def build_config_for(self, node): config = super(self, Relay).build_config_for(node) config.AuthoritativeDirectory 1 config.V3AuthoritativeDirectory 1 config.ContactInfo = '%d@test.test' % node.number config.ExitPolicy = 'reject *:*' return config . double-double check that i have a utest covering the case of multi-line 650 in the midst of a multi-line response OR re-verify that this can never happen -- the FSM is right now accumulating in only one buffer I believe (after simplifying in commit a62dfe0a1511eae717788732de54269920206015) . should support CIRC_MINOR event, too (in TorState) . $B56F17701DC248F8C42150942BDF7A7FAD6C6FC6~Thaolia is in one of my circuits, but not showing up in ns/all (nor via ns/id/XX). talked about it in #tor a little, but no conclusion. also tried starting up a separate Tor and that one also failed to find the key. (And possibly triggered my main Tor failing to COOKIE authenticate -- probably had the cookie file overwritten?) - it seems that streams aren't getting set up right if there is exactly one right now in tor? via telnet (url changed): getinfo stream-status 250-stream-status=123 SUCCEEDED 496 www.example.com:6667 250 OK fixed, but is this the same for circuits? Probably but hard to have precisely one circuit (still, should utest + fix) . ICircuitListener and IStreamListener are pretty complicated interfaces; might be better to make a simpler interface that is more like "pull" Observer pattern with "stateChanged(newstate, **kwargs)" or something and an interface on TorController to listen for newly created streams and circuits. Could still provide the complicated-interface via a multiplex that implemented IStreamListener and fanned out to the complicated states. This would ease live for clients merely wanting to know, e.g., when there are new circuits (or streams). (Instead, or as a stopgap, I've provided StreamListenerMixin and CircuitListenerMixin with empty default methods). . need to interrogate Tor for its bootstrap state when connection, as per control-spec.txt (e.g. post_boostrap callback shouldn't be issued until both the TorController are up and running AND Tor is fully bootstrapped, if we connected while it was still starting up). What to do if Tor starts bootstrapping (again) while we're running? txtorcon-0.9.1/dev-requirements.txt000066400000000000000000000001201226746254300174450ustar00rootroot00000000000000setuptools>=0.8.0 Sphinx repoze.sphinx.autointerface>=0.4 coveralls wheel twine txtorcon-0.9.1/docs/000077500000000000000000000000001226746254300143445ustar00rootroot00000000000000txtorcon-0.9.1/docs/Makefile000066400000000000000000000107551226746254300160140ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/txtor.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/txtor.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/txtor" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/txtor" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." txtorcon-0.9.1/docs/README.rst000077700000000000000000000000001226746254300177302../README.rstustar00rootroot00000000000000txtorcon-0.9.1/docs/_static/000077500000000000000000000000001226746254300157725ustar00rootroot00000000000000txtorcon-0.9.1/docs/_static/avatar.png000066400000000000000000000467561226746254300200000ustar00rootroot00000000000000PNG  IHDRW,gAMA asRGB cHRMz&u0`:pQ<bKGD pHYs B(xLIDATxy|$y}ߪh\3`)rHDJ")d:l9ıl'Yo*k7DvN|ȗ,ɢ,(K$ER$k8}]UGu7c }>`zs?Zp]W !$"D 0B\S\Zf)JcYւZBCXԃA8F^&UAA]]XL& ~w^&H $|՟e ht:IL22N  1-FzOe I )L%HiBTHe&I9*ղ1Ցd(J $K BA  bK˘+XE]]lb`H$ ⺮DzLj5ByeYדm{AdIdpp4ͪZZ?5L$S(IA X@Cec0 )  kJ%Gt:aVE|)Q"aql۾$YRqG j5bXRVIrԭ%EL& hȋ Tަx *W&/|>M[5J)fi$兿l\72߾J`z>;oBz$N#dp=*Ǖr2/w3Dg?L`y=4Y ZJ9/7fɨXt 4Fl\(90 0${MAŽԼO   d3Alb0!ˡry2mF!q!Ѯ7DBYIHT>tIRx0çgHI|d1cmyޜuOut.4kk<&?[.uTJ@E$7I) ryfLu/?IJ1iRNd$ T_?;8 PJy6( 1 o` a DH! HCb4g%J]r" AEJٶ]i1g7麖 |)!1b3q9D"| yMk'7r/Ź= psE#ڶqw| y;"n8ҡ9Q<>\9͂,۶ H)g]ź2R4* X?&0$檕}C=*lZ3~CDD`@¯(Rp#^uLPnB[0Rs(8GCXQIpz·݀7¹3p*"|M{( A X&d2_JyURrQeret;(")>)Uj'Dȝ7!뢔J%RB9-A vKY;폙>|~kϿa]lk# TlT4(1W40Fre֮"}#|`0is"=`d`KvPv yED ܱ se3nwo.rs8) oKf0щr 2ƾ1d]u xc2=|/Ul`Qq׍a^R,]\RL7FD87@e#G*x #0uQB7oc(3۵-+kN@H i_Ey?ZJçEF”J%cdQFt@`~o!1 sD529ѿ+_wRGkK~+oS %khs3Cp禉3o=E9O|ui IkD8DzpTU# Kf{>Z~ARHgΞh5e\G~HjgP.\SKJaտ3^ڇ}巉_5(߾q넹XPw?*P5JQ?&9<P:I}_yRU%O u'K];ԕq৿Iq.UF?}J8w? ߠoK j.gC.^뾝1Ƒ&RL"a&8RG4֘T8a"΂8Z {ig_ې^&QD8Hm}xw_$kxéZ#,~}ԏhp1%3(ͻ` yrB-ku[/q#Kujq]Z"M8 40N_+<J#Hó889v0+4GE+Xr;n727ֳ~W#Fӯ~seӨeY ØL^XQJb&ϑ!Lm$D[ (T$M暝Q[7DEd2Xx ci1#(_!ME-,k~)cgH?X7֘m-}oEZ{q8z1W }EEZk)Q(( 8N oʉI łZV*F4MF^}*Lӏc })oܵܢ j:6ӐHͰ^ c*N˲*~=$BpGx՜2!]?!U#?;>SDwT*E44ͅGv=e+/;Z<"V$ٻZS:Iϑ{r.l^K?B=V}$}ws0iDk=.JhR8j} @&PuGI؇Ou(r40uKSc4B=ts0)U.ml{'!*s9$- P"šN0r(;0L̶bZQ]S:d:KHGcծ J/~G="JЀ2 *okb*G4PGpAt8,!G&6U0$gٰ^P%$p{p.\L9(9~"ib4ʼnwO=r"3~wTx0ru]rx|NN *ӹ"ur_Y&"hG6Ǒ+1ZMx"FC`i@Mi MalQ"^";Oo/Fm(G+63^{JRrȿ~׿OQ XOۗ-~wŹn[ &}ky#C:>:'OQ0j lR2DChbc z:d} #BYe*Wt\Ѕه?JgŒWV"R^9@mӴ[D"z D[ϐ+x)yo(ex7/&@ɿϏzPoО0vqŚ?ǫ7}00ZZ0Z0[vuQ]̲Z6P<`Lnnr9m]*U w6КjT0hGn^|n2M;khkNk rmX֐{M_w0Q}|IQ=KfJWwzQ.( ! YhiZӊa5kִb47LتfѠqlޟ;R/nw"%3(W$ j~+!p A$0d aAp(2ع%;V~H(e۸=~46`3۴tHA̓#]) %Q p o(7K%lv 8h'Qe\J˘/>^,T, Y\ٌ~6j_GA{.2زaܞܮ~mWT$Qc3~B6Cǀ1dxdMg0-9p(#BiE(cî[}~gt~hMaakZi_Q|>?,RD碋`򶿓TerL- T|2<FZ)}>`!,WCQ%zjI#%"'^I`[Xߎڌ^qU+0?77KQ.GYHj*Y.eP$KNj!=4h5V5MQ^*GJ';(ut %vFWڕ%1[֭ڴ'LS\#C"d(\ы."*W*G:o$<:W@l .:QKjU% 8ZQ#ːpC%-=lQR`X&i%gy|]Ds{ßd 3}2 4IzuEЮ4J:(Ѕ7DmF{_FfX&2kYk+50s+ ]+`VࢱGZx$p>R#/5 H  lRd7|=W>m}`(4T쏹N1^ۅFˡ=OTwYt".Z_RyxQ&mboB "K!0, BQEٵBh]MC&%e\pnBZv^/L[J% ¼2ZkU({CQIH JzfQ{BPH  2%S&&RA  ̚uشm+V^?{4NF7h4?n)M,RJ"ȼ9B !#!߭{Na lFh´0 Jq4VC ڣ=C Ȋ0E"466Һjk֭}ZZZW@)КxgNpkEHWA,uM%]67_!'ݷLx>`b-fعc1@r@N/ZSW+oUmn]>zEJ(E(OkUGJnȢF!AMͬlkUhln&asBON<6q>3O-\ӌ)%Oԟܯ;1@'ȍwݍ1Kz8uw$Uc{bJ̚8(@kA =KM4LcS 446d1qch̭'yv= tgMtdy_dw }BXA b6t "Lf( 8zԢKlieIU=vV0H8+iikcEk+ &!,2Bexء,YZ)ZV硟"[nHMRd29 *@o%ZFWbB>O!'ˑsryB۶)J%S f2euIôE $f}P__O$&`sM $o~'Oc.bڍ|;n$"P(.uuuq@\;6kDkE0>ʺMp ץ8sR!{5Ro'~?7͛Yq {OB$O~+t9~$JQ߼|ꗸ=%/!q{K@/_{oDΏxִG~?ELkS .b )%A xs]ؼ\6H&B;4l=49BDxs_dۦmCghY/*To9/bK*K%F5-cJPP,1Lsg8sKԓ"^'eyaT:5fjNy)h[ODMs8nQC!V@{atxǼ \Q^h|f`8^NĩN.He)g! hlMѹW\Sbh\F&9 gWO sFO2D8" +t!OgvR\o0K=?{;$R*qFRr.N+~֚X A425ѥ"2 G=%7x;?+ژ! Ai AE{e RD隺W?r "Q+\WQr |t&O2%0ʐHgIery],>i<4XRYZk2yN?BۊFfQJ.BD:K0z8~zIf%]V*|rcqM׵au+m-cQ|N#]e[?!=IR՛q{۾R:X ZssCͺ(ƛO|3okSͥHKa[CAC$P6'\態/G"V! 碔e(b0f8&͓.$Q SoH8D( v`uY|vJ~_`E}K!ԊBO]GpOln ͓HeN7wp$TL@q|i#FzaQH9nX5m6X_G(MwRIAX Iҟjۛ~KZ`Zqw_H))9R\({GJ9оM 7[SAl05p'P2s\A)!MD*rQdf̴gC1 zK޿:\sWs9`"aHm^իJUaW6Wi7sJWm5XOB4V?YB@8eYUI 0I !ĺ$p(u98O}@04kEAwi@PYf`p(Ė"4Q,xٟptC V޲@ <ۿQ݉,)R픪O2eV{孪:Wk/6'R~X -7,:EףqwZcY`&%~Nypuvw_D : Ok!&uQ}` GҬh?i:p]U:r†`+xq 5l߼x,B2c8qDJIoŲzUۤ+sol Na=stb/!L>YT Mf}%62 ?bkͣg>>^zTq W9xʝlZkVlx,BkCrQCi!1)Hf  ɔ:ʗkZ]\S Ia i_aC!nݵVIЀ!%?޲~Zk"غaۇ5d3)N?4aȰWT" '="'0ܩ)o]cv Ab|oVB&vMqU5g<ҙ̼DJ-imۤf!YU4\8fx6LK>;=I^*9v ALpt:=*yq*PZS`N2SkM4f;( !FTgN0sWʠ~,FcƤ6'$D:ɉw^vG'!玼C&14+j֢#@$RJUE)Z t5=ps2\<zbhz_yO.#&<0MxiGDž uuĬ\EIJ#c=5IcX֔k$P)禌՛sK@'saxeS -pn;+ !l=?uouX8wdBxNH$m{u_*QҴH!ɤ 9or8%赺))&i=}XD/7ΦSˍDža+w]^\ '`Wf-8ȸAQWW8:R(t(ޠJu]4р5muƲ,Z@ 0T (6P J){Z!1k*B)8ě߻r\%▊sǃy٫+}]o~UaQ˲Dcc#RIsJׇ3:~(@ A:1L & VG]]EsqlZA̲0JsH^!}\)L A6C!p]RR u\G=7;Zk\ǹc\Z-h8N)td<!H<ߒ}c<̡. =ejBPH& )\"Oot]M{T2|!H%Ȥ&zb2|7ͱ1x*:%; g!ܯR)VAg׺!.S$2f <:/R|s])VSJqI6Slq:dEDƴfSxGuc,*}Z*B˦tqJچ7JpɹtZu$0-!"1+ViEPPگ1 렴2-X4WM\ϥ4L!ݝ~B|.K>]R+nΞ<2 B0<_6:\< AeLS_#14)%'cΞ:: 7'<Q { !ȦSv_W*V b+AjϤ~/#Ρ=ie/?rmhSy<,R!Q{|FKgK:14+38Rm7"R v-{iZ۹OhiS>%E1r7F.>*(,\>;cxM!NȏRǵNgxI qQoQ,u;[粃T00 dKװKɦg_e뎛0 cԀѹQq-~uڟ}iȡ&Vgۮ[\J RȦAףX7ILI[r)!9Uk{>LFQܕzT0"BFBP`ɔRocÖ8PFω%$J֫cmO}t+@d^B<#]wO>>!,AB᨟yX~36nNmo;4 !  yʣǃRP(­ヌ;nȁ7yĥӳfI)qJ%N8O^>:Δ fWQ`Λm uwՙsq_oum|%HUX NH&<'>E#b$XbsST"X=w. }'XٶzN)%pI<'Xn3j֚x7m{B4 ,zy|ٲ-7[r,a4ZC}c ݗRr1x{G1-lPQo]gez7N:RX-*ARȥ $ ֚UдbBEXrÃyǜ;uw:Xkhm.Cb M45uZZW%،iZl V.KB\6ù8t9NG#F۴@`z6TbJKkg`({pDX}>Ƌ T*ٜ=yJdܴ,㍬][vҶz=֔2;:1$I p~ݝ8N 9Ĩ z Q`ab#uK k$R*7Tz>*uÃ}zuV^F|HVG@o`Kk*֚h]=-!gҔl{CcZQP4An w;/%])BJ"у{I%/1j~vbu_3tE `hT/%M37>}8Ѵlu ax6P d/OH% Bn>z5&gRsv}M(zIjC JZk ͬYyRBF{ǡϐJ oDwgk+w$PxB 5HR4E!sK얍ZBdeH&.Cd3)vaVJagZkn|]<'&%G0LoËZڨMf\p<%iŨۯr`߫$ɦS,ReaCj|+KO7GȧS *k*du[\W_7!#Bin[Csݺ<Ϥȅ9{mϟ$N`sRJqÝs#?`,i4azy"2* J) qZ<֭̆7qrW,JDsG>EaZ{śśظ~9{c{_sGRkc~XlơH?-Ԉ@%u~灇u1MbҴ8yoRe'J)ZV0gU_c3ʙư}'%O\:w.:;a&wӼ  ھݷ[k]fkI4s|Dkͦn_5Vo1i!'~>E:1cv+~'<?;0MS%eG46}oA Dbu~ӼY\´[}Ur~!>_iżmLJgS V^R |)wp؁ڪfPJohce\z #D"1B(u`77~?폣pG>E ^>eq͗NZ,cf.s%?o]Jmɏ_|h}p=1 )u>{}(M<}  jV 쓬޴7޾Q=e`K{-RH4ƞ{>D8[p1ZViMoXX&e8k[wgvOpclq5XuH!o  Zk~g(]PE?cZJI6n}zǽJZe7 BaNs,HxB=>ײ6\kT9n!AپVﺅš.LYG@.|#gY\:_~k|YRw I) "44}znuhji% -HƐuq4ǜ-d,dhtg_~oPo'yWYPiX XXq+k6ҴH$描F^{vH:5 2hurSľ>\*9N1a"1Wܶ41-0hiV߷ 402V;bTLi)@E.:…:{D}4hXƚ-;XF7mH,^%eQup6B #2!4s%tEXtdate:create2012-03-02T14:03:56-07:00%tEXtdate:modify2012-03-02T14:03:56-07:00׽] IENDB`txtorcon-0.9.1/docs/_static/haiku.css000066400000000000000000000147151226746254300176150ustar00rootroot00000000000000/* custom stuff I put in FIXME where is it "supposed" to go? */ div.admonition-todo { border: 1px solid red; background-color: #Fdd; } div.admonition-todo p.admonition-title { margin: 0; color: red; text-transform: lowercase; } p.admonition-title { font-size: 120%; font-weight: bold; } dl.class>dt, dl.interface>dt, dl.function>dt, dl.staticmethod>dt { font-size: 150%; background-color:#ddd; } dl.method>dt { background-color: #eee; border-bottom: 2px solid #ddd; } dl.method:hover { background-color:#ffd; } /** end custom */ html { margin: 0px; padding: 0px; background: #FFF url(bg-page.png) top left repeat-x; } body { line-height: 1.5; margin: auto; padding: 0px; font-family: "DejaVu Sans", Arial, Helvetica, sans-serif; min-width: 59em; max-width: 70em; color: #333333; } div.footer { padding: 8px; font-size: 11px; text-align: center; letter-spacing: 0.5px; } /* link colors and text decoration */ a:link { font-weight: bold; text-decoration: none; color: #dc3c01; } a:visited { font-weight: bold; text-decoration: none; color: #892601; } a:hover, a:active { text-decoration: underline; color: #ff4500; } /* Some headers act as anchors, don't give them a hover effect */ h1 a:hover, a:active { text-decoration: none; color: #0c3762; } h2 a:hover, a:active { text-decoration: none; color: #0c3762; } h3 a:hover, a:active { text-decoration: none; color: #0c3762; } h4 a:hover, a:active { text-decoration: none; color: #0c3762; } a.headerlink { color: #a7ce38; padding-left: 5px; } a.headerlink:hover { color: #a7ce38; } /* basic text elements */ div.content { margin-top: 20px; margin-left: 40px; margin-right: 40px; margin-bottom: 50px; font-size: 0.9em; } /* heading and navigation */ div.header { position: relative; left: 0px; top: 0px; height: 85px; /* background: #eeeeee; */ padding: 0 40px; } div.header h1 { font-size: 1.6em; font-weight: normal; letter-spacing: 1px; color: #0c3762; border: 0; margin: 0; padding-top: 15px; } div.header h1 a { font-weight: normal; color: #0c3762; } div.header h2 { font-size: 1.3em; font-weight: normal; letter-spacing: 1px; text-transform: uppercase; color: #aaa; border: 0; margin-top: -3px; padding: 0; } div.header img.rightlogo { float: right; } div.title { font-size: 1.3em; font-weight: bold; color: #0c3762; border-bottom: dotted thin #e0e0e0; margin-bottom: 25px; } div.topnav { /* background: #e0e0e0; */ } div.topnav p { margin-top: 0; margin-left: 40px; margin-right: 40px; margin-bottom: 0px; text-align: right; font-size: 0.8em; } div.bottomnav { background: #eeeeee; } div.bottomnav p { margin-right: 40px; text-align: right; font-size: 0.8em; } a.uplink { font-weight: normal; } /* contents box */ table.index { margin: 0px 0px 30px 30px; padding: 1px; border-width: 1px; border-style: dotted; border-color: #e0e0e0; } table.index tr.heading { background-color: #e0e0e0; text-align: center; font-weight: bold; font-size: 1.1em; } table.index tr.index { background-color: #eeeeee; } table.index td { padding: 5px 20px; } table.index a:link, table.index a:visited { font-weight: normal; text-decoration: none; color: #dc3c01; } table.index a:hover, table.index a:active { text-decoration: underline; color: #ff4500; } /* Haiku User Guide styles and layout */ /* Rounded corner boxes */ /* Common declarations */ div.admonition { -webkit-border-radius: 10px; -khtml-border-radius: 10px; -moz-border-radius: 10px; border-radius: 10px; border-style: dotted; border-width: thin; border-color: #dcdcdc; padding: 10px 15px 10px 15px; margin-bottom: 15px; margin-top: 15px; } div.note { padding: 10px 15px 10px 80px; background: #e4ffde url(alert_info_32.png) 15px 15px no-repeat; min-height: 42px; } div.warning { padding: 10px 15px 10px 80px; background: #fffbc6 url(alert_warning_32.png) 15px 15px no-repeat; min-height: 42px; } div.seealso { background: #e4ffde; } /* More layout and styles */ h1 { font-size: 1.3em; font-weight: bold; color: #0c3762; border-bottom: dotted thin #e0e0e0; margin-top: 30px; } h2 { font-size: 1.2em; font-weight: normal; color: #0c3762; border-bottom: dotted thin #e0e0e0; margin-top: 30px; } h3 { font-size: 1.1em; font-weight: normal; color: #0c3762; margin-top: 30px; } h4 { font-size: 1.0em; font-weight: normal; color: #0c3762; margin-top: 30px; } p { text-align: justify; } p.last { margin-bottom: 0; } ol { padding-left: 20px; } ul { padding-left: 5px; margin-top: 3px; } li { line-height: 1.3; } div.content ul > li { -moz-background-clip:border; -moz-background-inline-policy:continuous; -moz-background-origin:padding; background: transparent url(bullet_orange.png) no-repeat scroll left 0.45em; list-style-image: none; list-style-type: none; padding: 0 0 0 1.666em; margin-bottom: 3px; } td { vertical-align: top; } tt { background-color: #e2e2e2; font-size: 1.0em; font-family: monospace; } pre { border-color: #0c3762; border-style: dotted; border-width: thin; margin: 0 0 12px 0; padding: 0.8em; background-color: #f0f0f0; } hr { border-top: 1px solid #ccc; border-bottom: 0; border-right: 0; border-left: 0; margin-bottom: 10px; margin-top: 20px; } /* printer only pretty stuff */ @media print { .noprint { display: none; } /* for acronyms we want their definitions inlined at print time */ acronym[title]:after { font-size: small; content: " (" attr(title) ")"; font-style: italic; } /* and not have mozilla dotted underline */ acronym { border: none; } div.topnav, div.bottomnav, div.header, table.index { display: none; } div.content { margin: 0px; padding: 0px; } html { background: #FFF; } } .viewcode-back { font-family: "DejaVu Sans", Arial, Helvetica, sans-serif; } div.viewcode-block:target { background-color: #f4debf; border-top: 1px solid #ac9; border-bottom: 1px solid #ac9; margin: -1px -12px; padding: 0 12px; } txtorcon-0.9.1/docs/_static/logo.png000066400000000000000000000417661226746254300174560ustar00rootroot00000000000000PNG  IHDR<qbKGD pHYs 4tIME '"< IDATxwxTLO B7QQ,(EE^^ꇀ^J" H9c3sr2iyɔs޳ʻ޵ګ\RJ2lx)e60Lf_ku'Yr>p//mo%!R9xέxDu6R-f8,/\kuqS8Q $N(( c^FDG1? 0|^B?1+gsaCD! 7R|> <Rb۟ͻ1naCJޝ-W~_ZŻ: 8.ph0y#q_C"1N0HRl\2 ) }WaH !SPϓB]懆AbiI,8+SߤQ\p#lhI?ep$ BHQg|y1(+@B )x Cq!8qZ"v ۀXP ! F%>BkRqq<3>|H0͈e+dX*oK<.4g23ʘ#JKļtFC&HTl?'rZ* L`Р:c)X+d=RDODXnzR>s{\ x@˲9R>:! !,KxeIY2CmE`=`/m*r<y`}6`h0u\+`@kmN2:+Hb`w:xŽ@,*, ].|bhDiD`QԩX8hסm8zeb.0/.t\ۣ㵇 > ̏XJygJS]v dRENgO8,a` | |`wZI +/+hU. \XwLmCFp@,? irt'Hc DI1/?Ѽ4RP27p3 0$݉VCD$?G ?k_Wx(C= 4+ zfa\i [HTU]Ƚ߁Aw;{*Zx a%bf(0էPj7{<͌_ ۩Dס|=T EY )S)*ө/[T | ƃX:<ɦST@iY)>wsBmM2%e'Ta``(FP2Q ¦4/>{VmZ!5Oe,'g;?%4lҌ1cfutkx$!3pQ7)90eXbM@kd@^#@} H#h(53"؆6OޭSPdb/}>e1`P!BJK.rr(,,~l6m~KFGq)!şF,Ι*FN:*T@o{ 2 [!"-X+d-Ru,`rK9շQ{ΩPisŦM[G@qpU&Ȓ-s#]a3Lz:5)6j^Js_@אR˶*< F3`Xg侑i ([ ,XJf+ ٸq 4')%իVԩtkC50٩Hb"{֮w@$*oHvhPMjBT,zZ"GCo5-Vˣ:#Nk<͸\ RCbV.䙧$/[`H$=}"I熽n$O#xA}$Jq  XeTy( K CpBU?x|@XŇ6͛5qsi!M3SE,_ˠal'!1Eӧ  ygܻl|4>w8ם%[犲- x Ax بh6&ˀ^\$@=Drj[xn enjPXuuj\wlEAkTOPM(  kh>η9Zu R4[$ Wǔ)Ҩq- !|-na^|QZZFÆչ2ݏٿϦYf/z%[QzUdxp F C6=)%,/Oj ,'%PcfjU_ 8`/rr>xirCx*2fהr k`yHJJ`t!"8X^z=歛J^qoF݉/8Փ.Nӧ Kj0K]u n`;'^P]Iڰ^{f,-0]z `9&=n._ࢋƮ MZlʕP[(ˇ; +M*JS< j}< A^HF-d IZiVJXX63e\zy_bf?HAAaun~[O`ԧ_[4Y]́wB‘ճ˿ A W.^VL~2g i8~c Ui*xP'| (m'^焓.dٲݧ!h i k U5td: $ŵQ.E(JJg EZZx{a蘨&R" @pE8^#gv|5>RnTė#˽,Ml= wFE):SFs՚n?,C_OWM\ʂ| >:֯ G{Pd":1ZC)&qԤk~~UZj:QF3tԀ+$D%D}Z#X C'9PEYaTsϫ!J`Պ|% v#~f]d#C!뮿Ϲ;~zq۵ 5;q/0\t'pU9.+B(eUF^gTFYݡM舿b]ً!+[aPEBeb/< >Z22Y0 C?&`t1?L4MUyGf8Ϋ]4;t.J acG%;`&"9+Fiv&Iejb Q@QW Gkb_S \}o2TT ݊;_1tM wy-,I ʕ| :*rr)2Ooѓ"PҺ\*'^iǠfhmp}kt'D"$"h\`\߮Guň+D Xv$GݓOG<ː5pOp͵^'~]p&Uq().aȰy)..QK+ xX;nRC֊Y(zeqWeECGP0X4d9M:bƪvp?P=c1I\5s{FNz, .wTY+C|e&^F劵upf̘ gi3g-6hс)-܊7H&ohҡ#HB$:0^˝ىb$¢ѥ!:-t\ +75Rj{A[SII LYԕr~.c\F}&0K2¼({۷TN8VF&e4IUGiQfIb?p$* Ym:QBklbI[507rͨbX(k[gkU:N׻5'kH-.b{/PX%"Ixv09M[ѬN;_CE+#XueًDNw J=JF,G A8r Y#m\ߊزNAbnYrtty h߮%o^O 7>=w]˻d+…е -C9ڐ'9b XR4!\dC*qzKBQp zl`oJDdN"Yc.|CVbI[~z{=ćnP쀲6vvX1Vc͐"J_%鯩[o>B]fjqqg+!-qq0ayUl3X-5K 0˷/eiс{KaՄr>r^NW` (}U (I_gJu1l- 5GڊFX*⦆"j Яo7ϜVwK'di̚9}vӌƝtm#Peg"5-Ī Զjhފݮ`3ž|ui_jc}F%H>׍X${^rqf ۫Z.ξiz1-KV˲nbQQ@"IHn@p$"r&??5V{njM .['%$Q[<Э$%%TAz9|>>y;ᦇ' êx(jܲ8,,M|()*-sH$.@ IDATmu&x;; *JXlaq@[",kT∭bYXk=0\ gRu=bۡq +ҋλcҭ +W#/z6(5x[g},;sT!?Ǝt>Y=pܬfH^^bSt^d%Bt'[ne[(Ьݥ]_HC# Z*sNeРf0f%dgNn[oSNݻ T@{YԬEi_z_G<Uu6ZMִI/y+A4YC`9JR2G|U,(5Vkb@r jDC*Nvݷ| ]CH3DFgc^檫ng!R {AŵLh~(-h;˷/$9F0vpr45wArdirQ)Sl*s` *KIFNPrgwϛ%{up8.ڱ)>/_CAf oԄYYq_8"FT~'[Mf'S,b·YC'(7gnز9P-_[bMG\UeɾR4Hԥ䚈|j׮%fPl,Yɼy+P5fj4uҰs$tNJ߽a&-.l6d+OsðKDP rEM OY_FJ\ ^,,_ŽZzy&JZɑUuy 7uB ](u"]%}:]ŐF?rvcՎL렾5p2@;쎌lRI{0 1tE.9~eЫ!FDw4i^nTӐ.^^O^mBvƵJ 2\!8I_{{-c}o_/M+f˗^K3~u9(vv:٠p{y78y T^THN*$ZP'/(\C7iet~u؞s/UoTK(P@F\'];\kԆNnG0G&/BTҗi~(C2Z3Th!?/:7USqZBVU^S5^L(eEO]>w3;](!j箜VOjgX BD{O_9БбXB~J.VPL4ӻ+'~H)S[`-ۥA?˹KN: j,cFZ}Q\.ްZn;U$НXЀɺ+݄'y YhӚvVD@49$''*9P[?kM}mߨ~DB *ncuWfb}l>P1U3}5!:詶[C_Dh |}4Rݬ*^G ]Kב|_̲bU\IIq _t.GHft*^oҟ8XB󁮐ϠA85j =uUDvVf tԉ~~ q,Y2[YR-:AݼN{g l) *SOX=Wg_F,u4e7oxKT,wL@Fxu@] "2zؑGyGή$J^,kjUɓ'3vXnݚ[owy'wqǩJff27nPާK/DCtKVz3N@ +|kjofV#y%6Ai|r-:.;? SHWzeŃ%6B,$%E}deewsT9Q;饔oDj~ͮ]McqCh>@\Ӎȭ!kItG@=4M0bhg:,=<Dv074bY*g_OL]^1ULYXVeffi43Z*i߾%ե\IϽ17;>, vra'5qD ԛ0{luힿsD;d&5ufg<.RJ R$CѮJqSŨ#LQ^Uv1~6lJ8XokEO(+!%U뗿kl2eַOW>5ҢBlބ'~mv(Z45Lܢ~~sKsq .d…-VI AUjXNiJ̎hM!_T˷/Z<RB}d.h9[!Z$X`L`㭬jJ]g MOnC;c8C #{,]]*\ |7YIyu/!>[P]ԭJ\ηفf"nr$O'=I/ς3-̉ibļJ:xI5uk,. Rq_Le/X1 \6x5xH}k/[+:u*jL}zO b$qL,lZPMEG5qBuKߚ-d.4Sq̫~c4B2< $SIeKS*!h[;j/㺰NGR ñK`*#εmƝ}ejw3EzCcd:X||[mPg3}<ډEbbz4oֈbэ{﹞:uR26M5C(`Bb]ˑU'&ɗ  K&-!,R 7"F7$KΚu끛Y|j/vi9ϷbM8;tjJ\aT)(͖2/#Itvkԩs+~gpBez0` 2sGp7гޞqx-?3-1_4g BSɾ4uI%ɛ% W6m[ ."O4OŖ PEK'D%\ոbB)=\ӑ4 ]} 2U%JIݬLƏ)%'Я?a.<^7m۴vdɛqľTzPnAVu;45BkmH$_o7 ݾM5# 5{$A4bP~lTNr̆ C'c3H#b/ N'1^5e 6nڊ0 ;C`xHxSBP9y 7ko-%+;Ӯ] .9np3},RZp5R[CDJ : uI !ImXCR$0Q뢯_$IXۭU2,KtbSۭK'TٵרtΥ3 }+{vi f\pIOW?~V]zb;g&OFqѠA=ڷkM[OЛbYQ5$$ܠ/4$a\& -A/ ۏp#H[6݊/Dw (TT2+G X"=!ǑWT`bZNx d% =˖;z`ݚ|5ѝ x}^ҹ-EEŬZ^ Au׉qM6d6"JItj Rb.n?I2T(N-+.Rz-+{fzڱBx|~ڷ"==%KVRn9aSErPɻ@,-muĉ.Ã'ɟJZ TI]^ *"zc͛6[n`ߑm|WLq&]r>2\FvXfYĠаIH"TkTl?X͂hѼ1y[v+p݊˭Pezun'A鍄 ;@?tx] a НDqQQ^8XX|3fe/"YBdAFųTY{Mb 60Ruf^r/LFT{=5ɢ{N[`ƌ̘9뮻!,`.|> 6mq [@Z>1ypެ mHinDRIO & e's)%ɏ+be앆j}$]SWBdҌ5YԂ*c>V%0S_%aͬ=v)df3f7leltiWnchܥMLLwҬY#~f̍kt!ci<@AlɍVTLi Cvg)þd&-|b֓H~@ 4gW6汴,,Q[-ƍ[ČY1rY.BvڱǬ\sCu57,]KVrE+:xBРQ#ƌ@N6>ZR?+%KWRW"@7֭X灷ԯM4Xm߃O ^%K dM){MYٌ[naB,-xX iWp}My Pj^Wm%{'=$[_]ȰqDGhP?^zr֠cyؾ}'p)6v%$@&dfӳG'.\R';?!T;ctږKW!$IuΤz__/B.o9_,|iCQ"ln/WTPmoG,1ҌWRE'*P\:z蘫6־\4oֈ&~@#W=4oq,={vbQP#̙ѩS~q1w8roW^}%ϳݑO0$܏?1`i_N$?7q;LgӘ>c#F'yhղ +VLu ն^7Nhu&0lh%BIlQ|iHD,8Y/#*@Ex>RKbuKBJW&z2vd(̹C17y7xIIIf̘yL13κ0xڷ?c9r7L&))<;wgOlݖKaaq< l~~01UWXSSnaښ( "ۣ$˛܆dsqSQ$ETԣ;fAcŋVЀھۧ+r)~\q|fIzy9.[6oKIIIS>fOA+W匳梑g3li :*Z4o̦[)--߼wVKܠާtb Ee{Xc 7NeՎ%uNF#9˴*a txN@ib & i]u#/'zY1vKADF^r KϑGvg7ӻ9|5{; iƔ)3yrM$ QT=C~6uikYw*[QPNq T#-Y*{<4qں9wFZjXX}Sl@M_LtVJpjѝ1UXvpa. \noLm}D.F5?ҧ뤳]bv`UB-ni8V^p}UgLѦgc\.z9ݤ'p< ԖM"醠n 삡uHD-h9~g,U}"> 2Y XK&"#\Ec6x ȰWQӆKrd}U ,;#̓TjVE¶}ӡ=5B}?FԴ|*2m^)CxwSv͗@MzYnQJml젒;vW/wKX,n(csKx:}`աfiBJd2-Ot5䥜y(P\"|l؂x*吱R>DTR9]v9kXaʬ0*W,B՞X+舣; ʭPu>7NƲR,"b&7<]Y}muZ(Pa`U\.W0ܼyI/^zZ& IENDB`txtorcon-0.9.1/docs/apilinks_sphinxext.py000066400000000000000000000031361226746254300206450ustar00rootroot00000000000000''' Sphinx/docutils extension to create links to pyDoctor documentation using a RestructuredText interpreted text role that looks like this: :api:`python_object_to_link_to