commit 0a46f3db4bb8a8fc5183041c93a990cb8f6a8eb8 Author: Damian Johnson atagar@torproject.org Date: Thu Jan 4 00:05:23 2018 -0800
Replace cell_attributes() with a couple class functions --- stem/client.py | 118 +++++++++++++++++++++++++++++----------------------- test/unit/client.py | 25 +++++------ 2 files changed, 79 insertions(+), 64 deletions(-)
diff --git a/stem/client.py b/stem/client.py index 136fc240..8fe2878d 100644 --- a/stem/client.py +++ b/stem/client.py @@ -2,21 +2,21 @@ # See LICENSE for licensing information
""" -Module for interacting with the ORPort provided by Tor relays. The -:class:`~stem.client.Relay` is a wrapper for :class:`~stem.socket.RelaySocket`, -providing higher level functions in much the same way as our -:class:`~stem.control.Controller` wraps :class:`~stem.socket.ControlSocket`. +Interaction with a Tor relay's ORPort. :class:`~stem.client.Relay` is +a wrapper for :class:`~stem.socket.RelaySocket`, much the same way as +:class:`~stem.control.Controller` provides higher level functions for +:class:`~stem.socket.ControlSocket`.
.. versionadded:: 1.7.0
-.. data:: PackType (enum) +.. data:: Pack (enum)
Unsigned `struct.pack format https://docs.python.org/2/library/struct.html#format-characters` for network-order fields.
==================== =========== - PackType Description + Pack Description ==================== =========== CHAR Unsigned char (1 byte) SHORT Unsigned short (2 bytes) @@ -36,17 +36,10 @@ import struct
from stem.util import enum
-PackType = enum.Enum( - ('CHAR', '!B'), # 1 byte - ('SHORT', '!H'), # 2 bytes - ('LONG', '!L'), # 4 bytes - ('LONG_LONG', '!Q'), # 8 bytes -) -
-class CellAttributes(collections.namedtuple('CellAttributes', ['name', 'value', 'fixed_size', 'for_circuit'])): +class Cell(collections.namedtuple('Cell', ['name', 'value', 'fixed_size', 'for_circuit'])): """ - Metadata for cells tor will accept on its ORPort. + Metadata for ORPort cells.
:var str name: name of the cell type :var int value: integer value of the command on the wire @@ -56,52 +49,44 @@ class CellAttributes(collections.namedtuple('CellAttributes', ['name', 'value', **False** otherwise """
+ @staticmethod + def by_name(name): + """ + Provides cell attributes by its name.
-CELL_ATTR = ( - CellAttributes('PADDING', 0, True, False), # Padding (section 7.2) - CellAttributes('CREATE', 1, True, True), # Create a circuit (section 5.1) - CellAttributes('CREATED', 2, True, True), # Acknowledge create (section 5.1) - CellAttributes('RELAY', 3, True, True), # End-to-end data (section 5.5 and 6) - CellAttributes('DESTROY', 4, True, True), # Stop using a circuit (section 5.4) - CellAttributes('CREATE_FAST', 5, True, True), # Create a circuit, no PK (section 5.1) - CellAttributes('CREATED_FAST', 6, True, True), # Circuit created, no PK (section 5.1) - CellAttributes('VERSIONS', 7, False, False), # Negotiate proto version (section 4) - CellAttributes('NETINFO', 8, True, False), # Time and address info (section 4.5) - CellAttributes('RELAY_EARLY', 9, True, True), # End-to-end data; limited (section 5.6) - CellAttributes('CREATE2', 10, True, True), # Extended CREATE cell (section 5.1) - CellAttributes('CREATED2', 11, True, True), # Extended CREATED cell (section 5.1) - CellAttributes('PADDING_NEGOTIATE', 12, True, False), # Padding negotiation (section 7.2) - CellAttributes('VPADDING', 128, False, False), # Variable-length padding (section 7.2) - CellAttributes('CERTS', 129, False, False), # Certificates (section 4.2) - CellAttributes('AUTH_CHALLENGE', 130, False, False), # Challenge value (section 4.3) - CellAttributes('AUTHENTICATE', 131, False, False), # Client authentication (section 4.5) - CellAttributes('AUTHORIZE', 132, False, False), # Client authorization (not yet used) -) + :parm str name: name of the cell type to fetch
+ :raise: **ValueError** if cell type is invalid + """
-class Relay(object): - """ - Connection with a `Tor relay's ORPort - https://gitweb.torproject.org/torspec.git/tree/tor-spec.txt`_. - """ + for cell_type in CELL_TYPES: + if name == cell_type.name: + return cell_type
+ raise ValueError("'%s' isn't a valid cell type" % name)
-def cell_attributes(cell_type): - """ - Provides attributes of the given cell type. + @staticmethod + def by_value(value): + """ + Provides cell attributes by its value.
- :parm str,int cell_type: cell type as either a string or integer + :parm int value: value of the cell type to fetch
- :raise: **ValueError** if cell type is invalid - """ + :raise: **ValueError** if cell type is invalid + """
- param = 'value' if isinstance(cell_type, int) else 'name' + for cell_type in CELL_TYPES: + if value == cell_type.value: + return cell_type
- for attr in CELL_ATTR: - if getattr(attr, param) == cell_type: - return attr + raise ValueError("'%s' isn't a valid cell value" % value)
- raise ValueError("'%s' isn't a valid cell type" % cell_type) + +class Relay(object): + """ + Connection with a `Tor relay's ORPort + https://gitweb.torproject.org/torspec.git/tree/tor-spec.txt`_. + """
def serialize_versions(versions): @@ -113,4 +98,33 @@ def serialize_versions(versions): :returns: **bytes** with a payload for these versions """
- return b''.join([struct.pack(PackType.SHORT, v) for v in versions]) + return b''.join([struct.pack(Pack.SHORT, v) for v in versions]) + + +Pack = enum.Enum( + ('CHAR', '!B'), # 1 byte + ('SHORT', '!H'), # 2 bytes + ('LONG', '!L'), # 4 bytes + ('LONG_LONG', '!Q'), # 8 bytes +) + +CELL_TYPES = ( + Cell('PADDING', 0, True, False), # Padding (section 7.2) + Cell('CREATE', 1, True, True), # Create a circuit (section 5.1) + Cell('CREATED', 2, True, True), # Acknowledge create (section 5.1) + Cell('RELAY', 3, True, True), # End-to-end data (section 5.5 and 6) + Cell('DESTROY', 4, True, True), # Stop using a circuit (section 5.4) + Cell('CREATE_FAST', 5, True, True), # Create a circuit, no PK (section 5.1) + Cell('CREATED_FAST', 6, True, True), # Circuit created, no PK (section 5.1) + Cell('VERSIONS', 7, False, False), # Negotiate proto version (section 4) + Cell('NETINFO', 8, True, False), # Time and address info (section 4.5) + Cell('RELAY_EARLY', 9, True, True), # End-to-end data; limited (section 5.6) + Cell('CREATE2', 10, True, True), # Extended CREATE cell (section 5.1) + Cell('CREATED2', 11, True, True), # Extended CREATED cell (section 5.1) + Cell('PADDING_NEGOTIATE', 12, True, False), # Padding negotiation (section 7.2) + Cell('VPADDING', 128, False, False), # Variable-length padding (section 7.2) + Cell('CERTS', 129, False, False), # Certificates (section 4.2) + Cell('AUTH_CHALLENGE', 130, False, False), # Challenge value (section 4.3) + Cell('AUTHENTICATE', 131, False, False), # Client authentication (section 4.5) + Cell('AUTHORIZE', 132, False, False), # Client authorization (not yet used) +) diff --git a/test/unit/client.py b/test/unit/client.py index 204c55fd..1d2df417 100644 --- a/test/unit/client.py +++ b/test/unit/client.py @@ -4,21 +4,22 @@ Unit tests for the stem.client.
import unittest
-import stem.client +from stem.client import Cell
class TestClient(unittest.TestCase): - def test_cell_attributes(self): - attr = stem.client.cell_attributes('NETINFO') + def test_cell_fetching(self): + cell = Cell.by_name('NETINFO')
- self.assertEqual('NETINFO', attr.name) - self.assertEqual(8, attr.value) - self.assertEqual(True, attr.fixed_size) - self.assertEqual(False, attr.for_circuit) + self.assertEqual('NETINFO', cell.name) + self.assertEqual(8, cell.value) + self.assertEqual(True, cell.fixed_size) + self.assertEqual(False, cell.for_circuit)
- self.assertEqual(10, stem.client.cell_attributes('CREATE2').value) - self.assertEqual('CREATE2', stem.client.cell_attributes(10).name) + self.assertEqual(10, Cell.by_name('CREATE2').value) + self.assertEqual('CREATE2', Cell.by_value(10).name)
- self.assertRaises(ValueError, stem.client.cell_attributes, 'NOPE') - self.assertRaises(ValueError, stem.client.cell_attributes, 85) - self.assertRaises(ValueError, stem.client.cell_attributes, None) + self.assertRaises(ValueError, Cell.by_name, 'NOPE') + self.assertRaises(ValueError, Cell.by_value, 'NOPE') + self.assertRaises(ValueError, Cell.by_name, 85) + self.assertRaises(ValueError, Cell.by_name, None)
tor-commits@lists.torproject.org