forked from LBRYCommunity/lbry-sdk
pylint: fix trailing-whitespace
This commit is contained in:
parent
32fa2460ff
commit
14ac2bac39
17 changed files with 123 additions and 122 deletions
|
@ -214,7 +214,7 @@ class ApplicationSettings(Settings):
|
||||||
self.BLOBFILES_DIR = "blobfiles"
|
self.BLOBFILES_DIR = "blobfiles"
|
||||||
self.BLOB_SIZE = 2*MB
|
self.BLOB_SIZE = 2*MB
|
||||||
self.LOG_FILE_NAME = "lbrynet.log"
|
self.LOG_FILE_NAME = "lbrynet.log"
|
||||||
self.LOG_POST_URL = "https://lbry.io/log-upload"
|
self.LOG_POST_URL = "https://lbry.io/log-upload"
|
||||||
self.CRYPTSD_FILE_EXTENSION = ".cryptsd"
|
self.CRYPTSD_FILE_EXTENSION = ".cryptsd"
|
||||||
self.API_ADDRESS = "lbryapi"
|
self.API_ADDRESS = "lbryapi"
|
||||||
self.ICON_PATH = "icons" if platform is WINDOWS else "app.icns"
|
self.ICON_PATH = "icons" if platform is WINDOWS else "app.icns"
|
||||||
|
@ -230,7 +230,7 @@ class ApplicationSettings(Settings):
|
||||||
self.LOGGLY_TOKEN = 'LJEzATH4AzRgAwxjAP00LwZ2YGx3MwVgZTMuBQZ3MQuxLmOv'
|
self.LOGGLY_TOKEN = 'LJEzATH4AzRgAwxjAP00LwZ2YGx3MwVgZTMuBQZ3MQuxLmOv'
|
||||||
self.ANALYTICS_ENDPOINT = 'https://api.segment.io/v1'
|
self.ANALYTICS_ENDPOINT = 'https://api.segment.io/v1'
|
||||||
self.ANALYTICS_TOKEN = 'Ax5LZzR1o3q3Z3WjATASDwR5rKyHH0qOIRIbLmMXn2H='
|
self.ANALYTICS_TOKEN = 'Ax5LZzR1o3q3Z3WjATASDwR5rKyHH0qOIRIbLmMXn2H='
|
||||||
self.DB_REVISION_FILE_NAME = 'db_revision'
|
self.DB_REVISION_FILE_NAME = 'db_revision'
|
||||||
Settings.__init__(self)
|
Settings.__init__(self)
|
||||||
|
|
||||||
|
|
||||||
|
@ -299,7 +299,7 @@ class Config(DefaultSettings):
|
||||||
return os.path.join(self.ensure_data_dir(), self.LOG_FILE_NAME)
|
return os.path.join(self.ensure_data_dir(), self.LOG_FILE_NAME)
|
||||||
|
|
||||||
def get_db_revision_filename(self):
|
def get_db_revision_filename(self):
|
||||||
return os.path.join(self.ensure_data_dir(), self.DB_REVISION_FILE_NAME)
|
return os.path.join(self.ensure_data_dir(), self.DB_REVISION_FILE_NAME)
|
||||||
|
|
||||||
def get_conf_filename(self):
|
def get_conf_filename(self):
|
||||||
return get_settings_file_ext(self.ensure_data_dir())
|
return get_settings_file_ext(self.ensure_data_dir())
|
||||||
|
|
|
@ -361,7 +361,7 @@ class Wallet(object):
|
||||||
except (TypeError, ValueError, ValidationError):
|
except (TypeError, ValueError, ValidationError):
|
||||||
return Failure(InvalidStreamInfoError(name, result['value']))
|
return Failure(InvalidStreamInfoError(name, result['value']))
|
||||||
sd_hash = metadata['sources']['lbry_sd_hash']
|
sd_hash = metadata['sources']['lbry_sd_hash']
|
||||||
claim_outpoint = ClaimOutpoint(result['txid'], result['n'])
|
claim_outpoint = ClaimOutpoint(result['txid'], result['n'])
|
||||||
d = self._save_name_metadata(name, claim_outpoint, sd_hash)
|
d = self._save_name_metadata(name, claim_outpoint, sd_hash)
|
||||||
d.addCallback(lambda _: self.get_claimid(name, result['txid'], result['n']))
|
d.addCallback(lambda _: self.get_claimid(name, result['txid'], result['n']))
|
||||||
d.addCallback(lambda cid: _log_success(cid))
|
d.addCallback(lambda cid: _log_success(cid))
|
||||||
|
@ -382,7 +382,7 @@ class Wallet(object):
|
||||||
d.addCallback(lambda claims: next(c for c in claims if c['name'] == name and c['nOut'] == claim_outpoint['nout']))
|
d.addCallback(lambda claims: next(c for c in claims if c['name'] == name and c['nOut'] == claim_outpoint['nout']))
|
||||||
d.addCallback(lambda claim: self._update_claimid(claim['claimId'], name, ClaimOutpoint(txid, claim['nOut'])))
|
d.addCallback(lambda claim: self._update_claimid(claim['claimId'], name, ClaimOutpoint(txid, claim['nOut'])))
|
||||||
return d
|
return d
|
||||||
claim_outpoint = ClaimOutpoint(txid, nout)
|
claim_outpoint = ClaimOutpoint(txid, nout)
|
||||||
d = self._get_claimid_for_tx(name, claim_outpoint)
|
d = self._get_claimid_for_tx(name, claim_outpoint)
|
||||||
d.addCallback(_get_id_for_return)
|
d.addCallback(_get_id_for_return)
|
||||||
return d
|
return d
|
||||||
|
@ -583,7 +583,7 @@ class Wallet(object):
|
||||||
for claim in claims:
|
for claim in claims:
|
||||||
if 'in claim trie' in claim:
|
if 'in claim trie' in claim:
|
||||||
name_is_equal = 'name' in claim and str(claim['name']) == name
|
name_is_equal = 'name' in claim and str(claim['name']) == name
|
||||||
nout_is_equal = 'nOut' in claim and claim['nOut'] == claim_outpoint['nout']
|
nout_is_equal = 'nOut' in claim and claim['nOut'] == claim_outpoint['nout']
|
||||||
if name_is_equal and nout_is_equal and 'value' in claim:
|
if name_is_equal and nout_is_equal and 'value' in claim:
|
||||||
try:
|
try:
|
||||||
value_dict = json.loads(claim['value'])
|
value_dict = json.loads(claim['value'])
|
||||||
|
@ -682,7 +682,7 @@ class Wallet(object):
|
||||||
d.addCallback(
|
d.addCallback(
|
||||||
lambda _: self.db.runQuery("delete from name_metadata where name=? and txid=? and n=? and sd_hash=?",
|
lambda _: self.db.runQuery("delete from name_metadata where name=? and txid=? and n=? and sd_hash=?",
|
||||||
(name, claim_outpoint['txid'], UNSET_NOUT, sd_hash)))
|
(name, claim_outpoint['txid'], UNSET_NOUT, sd_hash)))
|
||||||
|
|
||||||
d.addCallback(lambda _: self.db.runQuery("insert into name_metadata values (?, ?, ?, ?)",
|
d.addCallback(lambda _: self.db.runQuery("insert into name_metadata values (?, ?, ?, ?)",
|
||||||
(name, claim_outpoint['txid'], claim_outpoint['nout'], sd_hash)))
|
(name, claim_outpoint['txid'], claim_outpoint['nout'], sd_hash)))
|
||||||
return d
|
return d
|
||||||
|
@ -698,7 +698,7 @@ class Wallet(object):
|
||||||
d.addCallback(
|
d.addCallback(
|
||||||
lambda _: self.db.runQuery("delete from claim_ids where claimId=? and name=? and txid=? and n=?",
|
lambda _: self.db.runQuery("delete from claim_ids where claimId=? and name=? and txid=? and n=?",
|
||||||
(claim_id, name, claim_outpoint['txid'], UNSET_NOUT)))
|
(claim_id, name, claim_outpoint['txid'], UNSET_NOUT)))
|
||||||
|
|
||||||
d.addCallback(lambda r: self.db.runQuery("insert into claim_ids values (?, ?, ?, ?)",
|
d.addCallback(lambda r: self.db.runQuery("insert into claim_ids values (?, ?, ?, ?)",
|
||||||
(claim_id, name, claim_outpoint['txid'], claim_outpoint['nout'])))
|
(claim_id, name, claim_outpoint['txid'], claim_outpoint['nout'])))
|
||||||
d.addCallback(lambda _: claim_id)
|
d.addCallback(lambda _: claim_id)
|
||||||
|
@ -997,7 +997,7 @@ class LBRYumWallet(Wallet):
|
||||||
|
|
||||||
def _send_name_claim_update(self, name, claim_id, claim_outpoint, value, amount):
|
def _send_name_claim_update(self, name, claim_id, claim_outpoint, value, amount):
|
||||||
metadata = json.dumps(value)
|
metadata = json.dumps(value)
|
||||||
log.debug("Update %s %d %f %s %s '%s'", claim_outpoint['txid'], claim_outpoint['nout'],
|
log.debug("Update %s %d %f %s %s '%s'", claim_outpoint['txid'], claim_outpoint['nout'],
|
||||||
amount, name, claim_id, metadata)
|
amount, name, claim_id, metadata)
|
||||||
cmd = known_commands['update']
|
cmd = known_commands['update']
|
||||||
func = getattr(self.cmd_runner, cmd.name)
|
func = getattr(self.cmd_runner, cmd.name)
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
the terms and conditions of version 3 of the GNU General Public
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
License, supplemented by the additional permissions listed below.
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
0. Additional Definitions.
|
0. Additional Definitions.
|
||||||
|
|
||||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
@ -111,7 +111,7 @@ the following:
|
||||||
a copy of the Library already present on the user's computer
|
a copy of the Library already present on the user's computer
|
||||||
system, and (b) will operate properly with a modified version
|
system, and (b) will operate properly with a modified version
|
||||||
of the Library that is interface-compatible with the Linked
|
of the Library that is interface-compatible with the Linked
|
||||||
Version.
|
Version.
|
||||||
|
|
||||||
e) Provide Installation Information, but only if you would otherwise
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
be required to provide such information under section 6 of the
|
be required to provide such information under section 6 of the
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
""" This module defines the charaterizing constants of the Kademlia network
|
""" This module defines the charaterizing constants of the Kademlia network
|
||||||
|
|
||||||
C{checkRefreshInterval} and C{udpDatagramMaxSize} are implementation-specific
|
C{checkRefreshInterval} and C{udpDatagramMaxSize} are implementation-specific
|
||||||
constants, and do not affect general Kademlia operation.
|
constants, and do not affect general Kademlia operation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
######### KADEMLIA CONSTANTS ###########
|
######### KADEMLIA CONSTANTS ###########
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
class Contact(object):
|
class Contact(object):
|
||||||
""" Encapsulation for remote contact
|
""" Encapsulation for remote contact
|
||||||
|
|
||||||
This class contains information on a single remote contact, and also
|
This class contains information on a single remote contact, and also
|
||||||
provides a direct RPC API to the remote node which it represents
|
provides a direct RPC API to the remote node which it represents
|
||||||
"""
|
"""
|
||||||
|
@ -20,7 +20,7 @@ class Contact(object):
|
||||||
self.port = udpPort
|
self.port = udpPort
|
||||||
self._networkProtocol = networkProtocol
|
self._networkProtocol = networkProtocol
|
||||||
self.commTime = firstComm
|
self.commTime = firstComm
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if isinstance(other, Contact):
|
if isinstance(other, Contact):
|
||||||
return self.id == other.id
|
return self.id == other.id
|
||||||
|
@ -28,7 +28,7 @@ class Contact(object):
|
||||||
return self.id == other
|
return self.id == other
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __ne__(self, other):
|
def __ne__(self, other):
|
||||||
if isinstance(other, Contact):
|
if isinstance(other, Contact):
|
||||||
return self.id != other.id
|
return self.id != other.id
|
||||||
|
@ -41,20 +41,20 @@ class Contact(object):
|
||||||
compact_ip = reduce(
|
compact_ip = reduce(
|
||||||
lambda buff, x: buff + bytearray([int(x)]), self.address.split('.'), bytearray())
|
lambda buff, x: buff + bytearray([int(x)]), self.address.split('.'), bytearray())
|
||||||
return str(compact_ip)
|
return str(compact_ip)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '<%s.%s object; IP address: %s, UDP port: %d>' % (
|
return '<%s.%s object; IP address: %s, UDP port: %d>' % (
|
||||||
self.__module__, self.__class__.__name__, self.address, self.port)
|
self.__module__, self.__class__.__name__, self.address, self.port)
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
""" This override allows the host node to call a method of the remote
|
""" This override allows the host node to call a method of the remote
|
||||||
node (i.e. this contact) as if it was a local function.
|
node (i.e. this contact) as if it was a local function.
|
||||||
|
|
||||||
For instance, if C{remoteNode} is a instance of C{Contact}, the
|
For instance, if C{remoteNode} is a instance of C{Contact}, the
|
||||||
following will result in C{remoteNode}'s C{test()} method to be
|
following will result in C{remoteNode}'s C{test()} method to be
|
||||||
called with argument C{123}::
|
called with argument C{123}::
|
||||||
remoteNode.test(123)
|
remoteNode.test(123)
|
||||||
|
|
||||||
Such a RPC method call will return a Deferred, which will callback
|
Such a RPC method call will return a Deferred, which will callback
|
||||||
when the contact responds with the result (or an error occurs).
|
when the contact responds with the result (or an error occurs).
|
||||||
This happens via this contact's C{_networkProtocol} object (i.e. the
|
This happens via this contact's C{_networkProtocol} object (i.e. the
|
||||||
|
|
|
@ -16,7 +16,7 @@ import constants
|
||||||
class DataStore(UserDict.DictMixin):
|
class DataStore(UserDict.DictMixin):
|
||||||
""" Interface for classes implementing physical storage (for data
|
""" Interface for classes implementing physical storage (for data
|
||||||
published via the "STORE" RPC) for the Kademlia DHT
|
published via the "STORE" RPC) for the Kademlia DHT
|
||||||
|
|
||||||
@note: This provides an interface for a dict-like object
|
@note: This provides an interface for a dict-like object
|
||||||
"""
|
"""
|
||||||
def keys(self):
|
def keys(self):
|
||||||
|
|
|
@ -14,47 +14,47 @@ class DecodeError(Exception):
|
||||||
|
|
||||||
class Encoding(object):
|
class Encoding(object):
|
||||||
""" Interface for RPC message encoders/decoders
|
""" Interface for RPC message encoders/decoders
|
||||||
|
|
||||||
All encoding implementations used with this library should inherit and
|
All encoding implementations used with this library should inherit and
|
||||||
implement this.
|
implement this.
|
||||||
"""
|
"""
|
||||||
def encode(self, data):
|
def encode(self, data):
|
||||||
""" Encode the specified data
|
""" Encode the specified data
|
||||||
|
|
||||||
@param data: The data to encode
|
@param data: The data to encode
|
||||||
This method has to support encoding of the following
|
This method has to support encoding of the following
|
||||||
types: C{str}, C{int} and C{long}
|
types: C{str}, C{int} and C{long}
|
||||||
Any additional data types may be supported as long as the
|
Any additional data types may be supported as long as the
|
||||||
implementing class's C{decode()} method can successfully
|
implementing class's C{decode()} method can successfully
|
||||||
decode them.
|
decode them.
|
||||||
|
|
||||||
@return: The encoded data
|
@return: The encoded data
|
||||||
@rtype: str
|
@rtype: str
|
||||||
"""
|
"""
|
||||||
def decode(self, data):
|
def decode(self, data):
|
||||||
""" Decode the specified data string
|
""" Decode the specified data string
|
||||||
|
|
||||||
@param data: The data (byte string) to decode.
|
@param data: The data (byte string) to decode.
|
||||||
@type data: str
|
@type data: str
|
||||||
|
|
||||||
@return: The decoded data (in its correct type)
|
@return: The decoded data (in its correct type)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class Bencode(Encoding):
|
class Bencode(Encoding):
|
||||||
""" Implementation of a Bencode-based algorithm (Bencode is the encoding
|
""" Implementation of a Bencode-based algorithm (Bencode is the encoding
|
||||||
algorithm used by Bittorrent).
|
algorithm used by Bittorrent).
|
||||||
|
|
||||||
@note: This algorithm differs from the "official" Bencode algorithm in
|
@note: This algorithm differs from the "official" Bencode algorithm in
|
||||||
that it can encode/decode floating point values in addition to
|
that it can encode/decode floating point values in addition to
|
||||||
integers.
|
integers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def encode(self, data):
|
def encode(self, data):
|
||||||
""" Encoder implementation of the Bencode algorithm
|
""" Encoder implementation of the Bencode algorithm
|
||||||
|
|
||||||
@param data: The data to encode
|
@param data: The data to encode
|
||||||
@type data: int, long, tuple, list, dict or str
|
@type data: int, long, tuple, list, dict or str
|
||||||
|
|
||||||
@return: The encoded data
|
@return: The encoded data
|
||||||
@rtype: str
|
@rtype: str
|
||||||
"""
|
"""
|
||||||
|
@ -76,7 +76,7 @@ class Bencode(Encoding):
|
||||||
encodedDictItems += self.encode(data[key])
|
encodedDictItems += self.encode(data[key])
|
||||||
return 'd%se' % encodedDictItems
|
return 'd%se' % encodedDictItems
|
||||||
elif type(data) == float:
|
elif type(data) == float:
|
||||||
# This (float data type) is a non-standard extension to the original Bencode algorithm
|
# This (float data type) is a non-standard extension to the original Bencode algorithm
|
||||||
return 'f%fe' % data
|
return 'f%fe' % data
|
||||||
elif data == None:
|
elif data == None:
|
||||||
# This (None/NULL data type) is a non-standard extension
|
# This (None/NULL data type) is a non-standard extension
|
||||||
|
@ -85,16 +85,16 @@ class Bencode(Encoding):
|
||||||
else:
|
else:
|
||||||
print data
|
print data
|
||||||
raise TypeError, "Cannot bencode '%s' object" % type(data)
|
raise TypeError, "Cannot bencode '%s' object" % type(data)
|
||||||
|
|
||||||
def decode(self, data):
|
def decode(self, data):
|
||||||
""" Decoder implementation of the Bencode algorithm
|
""" Decoder implementation of the Bencode algorithm
|
||||||
|
|
||||||
@param data: The encoded data
|
@param data: The encoded data
|
||||||
@type data: str
|
@type data: str
|
||||||
|
|
||||||
@note: This is a convenience wrapper for the recursive decoding
|
@note: This is a convenience wrapper for the recursive decoding
|
||||||
algorithm, C{_decodeRecursive}
|
algorithm, C{_decodeRecursive}
|
||||||
|
|
||||||
@return: The decoded data, as a native Python type
|
@return: The decoded data, as a native Python type
|
||||||
@rtype: int, list, dict or str
|
@rtype: int, list, dict or str
|
||||||
"""
|
"""
|
||||||
|
@ -104,11 +104,11 @@ class Bencode(Encoding):
|
||||||
return self._decodeRecursive(data)[0]
|
return self._decodeRecursive(data)[0]
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise DecodeError, e.message
|
raise DecodeError, e.message
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _decodeRecursive(data, startIndex=0):
|
def _decodeRecursive(data, startIndex=0):
|
||||||
""" Actual implementation of the recursive Bencode algorithm
|
""" Actual implementation of the recursive Bencode algorithm
|
||||||
|
|
||||||
Do not call this; use C{decode()} instead
|
Do not call this; use C{decode()} instead
|
||||||
"""
|
"""
|
||||||
if data[startIndex] == 'i':
|
if data[startIndex] == 'i':
|
||||||
|
|
|
@ -31,11 +31,11 @@ class KBucket(object):
|
||||||
def addContact(self, contact):
|
def addContact(self, contact):
|
||||||
""" Add contact to _contact list in the right order. This will move the
|
""" Add contact to _contact list in the right order. This will move the
|
||||||
contact to the end of the k-bucket if it is already present.
|
contact to the end of the k-bucket if it is already present.
|
||||||
|
|
||||||
@raise kademlia.kbucket.BucketFull: Raised when the bucket is full and
|
@raise kademlia.kbucket.BucketFull: Raised when the bucket is full and
|
||||||
the contact isn't in the bucket
|
the contact isn't in the bucket
|
||||||
already
|
already
|
||||||
|
|
||||||
@param contact: The contact to add
|
@param contact: The contact to add
|
||||||
@type contact: kademlia.contact.Contact
|
@type contact: kademlia.contact.Contact
|
||||||
"""
|
"""
|
||||||
|
@ -57,7 +57,7 @@ class KBucket(object):
|
||||||
|
|
||||||
def getContacts(self, count=-1, excludeContact=None):
|
def getContacts(self, count=-1, excludeContact=None):
|
||||||
""" Returns a list containing up to the first count number of contacts
|
""" Returns a list containing up to the first count number of contacts
|
||||||
|
|
||||||
@param count: The amount of contacts to return (if 0 or less, return
|
@param count: The amount of contacts to return (if 0 or less, return
|
||||||
all contacts)
|
all contacts)
|
||||||
@type count: int
|
@type count: int
|
||||||
|
@ -65,12 +65,12 @@ class KBucket(object):
|
||||||
the list of returned values, it will be
|
the list of returned values, it will be
|
||||||
discarded before returning. If a C{str} is
|
discarded before returning. If a C{str} is
|
||||||
passed as this argument, it must be the
|
passed as this argument, it must be the
|
||||||
contact's ID.
|
contact's ID.
|
||||||
@type excludeContact: kademlia.contact.Contact or str
|
@type excludeContact: kademlia.contact.Contact or str
|
||||||
|
|
||||||
|
|
||||||
@raise IndexError: If the number of requested contacts is too large
|
@raise IndexError: If the number of requested contacts is too large
|
||||||
|
|
||||||
@return: Return up to the first count number of contacts in a list
|
@return: Return up to the first count number of contacts in a list
|
||||||
If no contacts are present an empty is returned
|
If no contacts are present an empty is returned
|
||||||
@rtype: list
|
@rtype: list
|
||||||
|
@ -97,7 +97,7 @@ class KBucket(object):
|
||||||
# enough contacts in list
|
# enough contacts in list
|
||||||
else:
|
else:
|
||||||
contactList = self._contacts[0:count]
|
contactList = self._contacts[0:count]
|
||||||
|
|
||||||
if excludeContact in contactList:
|
if excludeContact in contactList:
|
||||||
contactList.remove(excludeContact)
|
contactList.remove(excludeContact)
|
||||||
|
|
||||||
|
@ -105,24 +105,24 @@ class KBucket(object):
|
||||||
|
|
||||||
def removeContact(self, contact):
|
def removeContact(self, contact):
|
||||||
""" Remove given contact from list
|
""" Remove given contact from list
|
||||||
|
|
||||||
@param contact: The contact to remove, or a string containing the
|
@param contact: The contact to remove, or a string containing the
|
||||||
contact's node ID
|
contact's node ID
|
||||||
@type contact: kademlia.contact.Contact or str
|
@type contact: kademlia.contact.Contact or str
|
||||||
|
|
||||||
@raise ValueError: The specified contact is not in this bucket
|
@raise ValueError: The specified contact is not in this bucket
|
||||||
"""
|
"""
|
||||||
self._contacts.remove(contact)
|
self._contacts.remove(contact)
|
||||||
|
|
||||||
def keyInRange(self, key):
|
def keyInRange(self, key):
|
||||||
""" Tests whether the specified key (i.e. node ID) is in the range
|
""" Tests whether the specified key (i.e. node ID) is in the range
|
||||||
of the n-bit ID space covered by this k-bucket (in otherwords, it
|
of the n-bit ID space covered by this k-bucket (in otherwords, it
|
||||||
returns whether or not the specified key should be placed in this
|
returns whether or not the specified key should be placed in this
|
||||||
k-bucket)
|
k-bucket)
|
||||||
|
|
||||||
@param key: The key to test
|
@param key: The key to test
|
||||||
@type key: str or int
|
@type key: str or int
|
||||||
|
|
||||||
@return: C{True} if the key is in this k-bucket's range, or C{False}
|
@return: C{True} if the key is in this k-bucket's range, or C{False}
|
||||||
if not.
|
if not.
|
||||||
@rtype: bool
|
@rtype: bool
|
||||||
|
|
|
@ -11,37 +11,37 @@ import msgtypes
|
||||||
|
|
||||||
class MessageTranslator(object):
|
class MessageTranslator(object):
|
||||||
""" Interface for RPC message translators/formatters
|
""" Interface for RPC message translators/formatters
|
||||||
|
|
||||||
Classes inheriting from this should provide a translation services between
|
Classes inheriting from this should provide a translation services between
|
||||||
the classes used internally by this Kademlia implementation and the actual
|
the classes used internally by this Kademlia implementation and the actual
|
||||||
data that is transmitted between nodes.
|
data that is transmitted between nodes.
|
||||||
"""
|
"""
|
||||||
def fromPrimitive(self, msgPrimitive):
|
def fromPrimitive(self, msgPrimitive):
|
||||||
""" Create an RPC Message from a message's string representation
|
""" Create an RPC Message from a message's string representation
|
||||||
|
|
||||||
@param msgPrimitive: The unencoded primitive representation of a message
|
@param msgPrimitive: The unencoded primitive representation of a message
|
||||||
@type msgPrimitive: str, int, list or dict
|
@type msgPrimitive: str, int, list or dict
|
||||||
|
|
||||||
@return: The translated message object
|
@return: The translated message object
|
||||||
@rtype: entangled.kademlia.msgtypes.Message
|
@rtype: entangled.kademlia.msgtypes.Message
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def toPrimitive(self, message):
|
def toPrimitive(self, message):
|
||||||
""" Create a string representation of a message
|
""" Create a string representation of a message
|
||||||
|
|
||||||
@param message: The message object
|
@param message: The message object
|
||||||
@type message: msgtypes.Message
|
@type message: msgtypes.Message
|
||||||
|
|
||||||
@return: The message's primitive representation in a particular
|
@return: The message's primitive representation in a particular
|
||||||
messaging format
|
messaging format
|
||||||
@rtype: str, int, list or dict
|
@rtype: str, int, list or dict
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class DefaultFormat(MessageTranslator):
|
class DefaultFormat(MessageTranslator):
|
||||||
""" The default on-the-wire message format for this library """
|
""" The default on-the-wire message format for this library """
|
||||||
typeRequest, typeResponse, typeError = range(3)
|
typeRequest, typeResponse, typeError = range(3)
|
||||||
headerType, headerMsgID, headerNodeID, headerPayload, headerArgs = range(5)
|
headerType, headerMsgID, headerNodeID, headerPayload, headerArgs = range(5)
|
||||||
|
|
||||||
def fromPrimitive(self, msgPrimitive):
|
def fromPrimitive(self, msgPrimitive):
|
||||||
msgType = msgPrimitive[self.headerType]
|
msgType = msgPrimitive[self.headerType]
|
||||||
if msgType == self.typeRequest:
|
if msgType == self.typeRequest:
|
||||||
|
@ -62,8 +62,8 @@ class DefaultFormat(MessageTranslator):
|
||||||
# Unknown message, no payload
|
# Unknown message, no payload
|
||||||
msg = msgtypes.Message(msgPrimitive[self.headerMsgID], msgPrimitive[self.headerNodeID])
|
msg = msgtypes.Message(msgPrimitive[self.headerMsgID], msgPrimitive[self.headerNodeID])
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
def toPrimitive(self, message):
|
def toPrimitive(self, message):
|
||||||
msg = {self.headerMsgID: message.id,
|
msg = {self.headerMsgID: message.id,
|
||||||
self.headerNodeID: message.nodeID}
|
self.headerNodeID: message.nodeID}
|
||||||
if isinstance(message, msgtypes.RequestMessage):
|
if isinstance(message, msgtypes.RequestMessage):
|
||||||
|
|
|
@ -22,7 +22,7 @@ class RequestMessage(Message):
|
||||||
def __init__(self, nodeID, method, methodArgs, rpcID=None):
|
def __init__(self, nodeID, method, methodArgs, rpcID=None):
|
||||||
if rpcID == None:
|
if rpcID == None:
|
||||||
hash = hashlib.sha384()
|
hash = hashlib.sha384()
|
||||||
hash.update(str(random.getrandbits(255)))
|
hash.update(str(random.getrandbits(255)))
|
||||||
rpcID = hash.digest()
|
rpcID = hash.digest()
|
||||||
Message.__init__(self, rpcID, nodeID)
|
Message.__init__(self, rpcID, nodeID)
|
||||||
self.request = method
|
self.request = method
|
||||||
|
|
|
@ -27,7 +27,7 @@ log = logging.getLogger(__name__)
|
||||||
|
|
||||||
def rpcmethod(func):
|
def rpcmethod(func):
|
||||||
""" Decorator to expose Node methods as remote procedure calls
|
""" Decorator to expose Node methods as remote procedure calls
|
||||||
|
|
||||||
Apply this decorator to methods in the Node class (or a subclass) in order
|
Apply this decorator to methods in the Node class (or a subclass) in order
|
||||||
to make them remotely callable via the DHT's RPC mechanism.
|
to make them remotely callable via the DHT's RPC mechanism.
|
||||||
"""
|
"""
|
||||||
|
@ -36,13 +36,13 @@ def rpcmethod(func):
|
||||||
|
|
||||||
class Node(object):
|
class Node(object):
|
||||||
""" Local node in the Kademlia network
|
""" Local node in the Kademlia network
|
||||||
|
|
||||||
This class represents a single local node in a Kademlia network; in other
|
This class represents a single local node in a Kademlia network; in other
|
||||||
words, this class encapsulates an Entangled-using application's "presence"
|
words, this class encapsulates an Entangled-using application's "presence"
|
||||||
in a Kademlia network.
|
in a Kademlia network.
|
||||||
|
|
||||||
In Entangled, all interactions with the Kademlia network by a client
|
In Entangled, all interactions with the Kademlia network by a client
|
||||||
application is performed via this class (or a subclass).
|
application is performed via this class (or a subclass).
|
||||||
"""
|
"""
|
||||||
def __init__(self, id=None, udpPort=4000, dataStore=None,
|
def __init__(self, id=None, udpPort=4000, dataStore=None,
|
||||||
routingTableClass=None, networkProtocol=None, lbryid=None,
|
routingTableClass=None, networkProtocol=None, lbryid=None,
|
||||||
|
@ -61,7 +61,7 @@ class Node(object):
|
||||||
exposed. This should be a class, not an object,
|
exposed. This should be a class, not an object,
|
||||||
in order to allow the Node to pass an
|
in order to allow the Node to pass an
|
||||||
auto-generated node ID to the routingtable object
|
auto-generated node ID to the routingtable object
|
||||||
upon instantiation (if necessary).
|
upon instantiation (if necessary).
|
||||||
@type routingTable: entangled.kademlia.routingtable.RoutingTable
|
@type routingTable: entangled.kademlia.routingtable.RoutingTable
|
||||||
@param networkProtocol: The network protocol to use. This can be
|
@param networkProtocol: The network protocol to use. This can be
|
||||||
overridden from the default to (for example)
|
overridden from the default to (for example)
|
||||||
|
@ -138,7 +138,7 @@ class Node(object):
|
||||||
def joinNetwork(self, knownNodeAddresses=None):
|
def joinNetwork(self, knownNodeAddresses=None):
|
||||||
""" Causes the Node to join the Kademlia network; normally, this
|
""" Causes the Node to join the Kademlia network; normally, this
|
||||||
should be called before any other DHT operations.
|
should be called before any other DHT operations.
|
||||||
|
|
||||||
@param knownNodeAddresses: A sequence of tuples containing IP address
|
@param knownNodeAddresses: A sequence of tuples containing IP address
|
||||||
information for existing nodes on the
|
information for existing nodes on the
|
||||||
Kademlia network, in the format:
|
Kademlia network, in the format:
|
||||||
|
@ -329,12 +329,12 @@ class Node(object):
|
||||||
|
|
||||||
def iterativeFindNode(self, key):
|
def iterativeFindNode(self, key):
|
||||||
""" The basic Kademlia node lookup operation
|
""" The basic Kademlia node lookup operation
|
||||||
|
|
||||||
Call this to find a remote node in the P2P overlay network.
|
Call this to find a remote node in the P2P overlay network.
|
||||||
|
|
||||||
@param key: the n-bit key (i.e. the node or value ID) to search for
|
@param key: the n-bit key (i.e. the node or value ID) to search for
|
||||||
@type key: str
|
@type key: str
|
||||||
|
|
||||||
@return: This immediately returns a deferred object, which will return
|
@return: This immediately returns a deferred object, which will return
|
||||||
a list of k "closest" contacts (C{kademlia.contact.Contact}
|
a list of k "closest" contacts (C{kademlia.contact.Contact}
|
||||||
objects) to the specified key as soon as the operation is
|
objects) to the specified key as soon as the operation is
|
||||||
|
@ -345,12 +345,12 @@ class Node(object):
|
||||||
|
|
||||||
def iterativeFindValue(self, key):
|
def iterativeFindValue(self, key):
|
||||||
""" The Kademlia search operation (deterministic)
|
""" The Kademlia search operation (deterministic)
|
||||||
|
|
||||||
Call this to retrieve data from the DHT.
|
Call this to retrieve data from the DHT.
|
||||||
|
|
||||||
@param key: the n-bit key (i.e. the value ID) to search for
|
@param key: the n-bit key (i.e. the value ID) to search for
|
||||||
@type key: str
|
@type key: str
|
||||||
|
|
||||||
@return: This immediately returns a deferred object, which will return
|
@return: This immediately returns a deferred object, which will return
|
||||||
either one of two things:
|
either one of two things:
|
||||||
- If the value was found, it will return a Python
|
- If the value was found, it will return a Python
|
||||||
|
@ -409,7 +409,7 @@ class Node(object):
|
||||||
""" Remove the contact with the specified node ID from this node's
|
""" Remove the contact with the specified node ID from this node's
|
||||||
table of known nodes. This is a simple wrapper for the same method
|
table of known nodes. This is a simple wrapper for the same method
|
||||||
in this object's RoutingTable object
|
in this object's RoutingTable object
|
||||||
|
|
||||||
@param contactID: The node ID of the contact to remove
|
@param contactID: The node ID of the contact to remove
|
||||||
@type contactID: str
|
@type contactID: str
|
||||||
"""
|
"""
|
||||||
|
@ -418,10 +418,10 @@ class Node(object):
|
||||||
def findContact(self, contactID):
|
def findContact(self, contactID):
|
||||||
""" Find a entangled.kademlia.contact.Contact object for the specified
|
""" Find a entangled.kademlia.contact.Contact object for the specified
|
||||||
cotact ID
|
cotact ID
|
||||||
|
|
||||||
@param contactID: The contact ID of the required Contact object
|
@param contactID: The contact ID of the required Contact object
|
||||||
@type contactID: str
|
@type contactID: str
|
||||||
|
|
||||||
@return: Contact object of remote node with the specified node ID,
|
@return: Contact object of remote node with the specified node ID,
|
||||||
or None if the contact was not found
|
or None if the contact was not found
|
||||||
@rtype: twisted.internet.defer.Deferred
|
@rtype: twisted.internet.defer.Deferred
|
||||||
|
@ -444,7 +444,7 @@ class Node(object):
|
||||||
@rpcmethod
|
@rpcmethod
|
||||||
def ping(self):
|
def ping(self):
|
||||||
""" Used to verify contact between two Kademlia nodes
|
""" Used to verify contact between two Kademlia nodes
|
||||||
|
|
||||||
@rtype: str
|
@rtype: str
|
||||||
"""
|
"""
|
||||||
return 'pong'
|
return 'pong'
|
||||||
|
@ -452,7 +452,7 @@ class Node(object):
|
||||||
@rpcmethod
|
@rpcmethod
|
||||||
def store(self, key, value, originalPublisherID=None, self_store=False, **kwargs):
|
def store(self, key, value, originalPublisherID=None, self_store=False, **kwargs):
|
||||||
""" Store the received data in this node's local hash table
|
""" Store the received data in this node's local hash table
|
||||||
|
|
||||||
@param key: The hashtable key of the data
|
@param key: The hashtable key of the data
|
||||||
@type key: str
|
@type key: str
|
||||||
@param value: The actual data (the value associated with C{key})
|
@param value: The actual data (the value associated with C{key})
|
||||||
|
@ -467,7 +467,7 @@ class Node(object):
|
||||||
@type age: int
|
@type age: int
|
||||||
|
|
||||||
@rtype: str
|
@rtype: str
|
||||||
|
|
||||||
@todo: Since the data (value) may be large, passing it around as a buffer
|
@todo: Since the data (value) may be large, passing it around as a buffer
|
||||||
(which is the case currently) might not be a good idea... will have
|
(which is the case currently) might not be a good idea... will have
|
||||||
to fix this (perhaps use a stream from the Protocol class?)
|
to fix this (perhaps use a stream from the Protocol class?)
|
||||||
|
@ -576,7 +576,7 @@ class Node(object):
|
||||||
|
|
||||||
def _generateID(self):
|
def _generateID(self):
|
||||||
""" Generates an n-bit pseudo-random identifier
|
""" Generates an n-bit pseudo-random identifier
|
||||||
|
|
||||||
@return: A globally unique n-bit pseudo-random identifier
|
@return: A globally unique n-bit pseudo-random identifier
|
||||||
@rtype: str
|
@rtype: str
|
||||||
"""
|
"""
|
||||||
|
@ -586,12 +586,12 @@ class Node(object):
|
||||||
|
|
||||||
def _iterativeFind(self, key, startupShortlist=None, rpc='findNode'):
|
def _iterativeFind(self, key, startupShortlist=None, rpc='findNode'):
|
||||||
""" The basic Kademlia iterative lookup operation (for nodes/values)
|
""" The basic Kademlia iterative lookup operation (for nodes/values)
|
||||||
|
|
||||||
This builds a list of k "closest" contacts through iterative use of
|
This builds a list of k "closest" contacts through iterative use of
|
||||||
the "FIND_NODE" RPC, or if C{findValue} is set to C{True}, using the
|
the "FIND_NODE" RPC, or if C{findValue} is set to C{True}, using the
|
||||||
"FIND_VALUE" RPC, in which case the value (if found) may be returned
|
"FIND_VALUE" RPC, in which case the value (if found) may be returned
|
||||||
instead of a list of contacts
|
instead of a list of contacts
|
||||||
|
|
||||||
@param key: the n-bit key (i.e. the node or value ID) to search for
|
@param key: the n-bit key (i.e. the node or value ID) to search for
|
||||||
@type key: str
|
@type key: str
|
||||||
@param startupShortlist: A list of contacts to use as the starting
|
@param startupShortlist: A list of contacts to use as the starting
|
||||||
|
@ -605,7 +605,7 @@ class Node(object):
|
||||||
other operations that piggy-back on the basic Kademlia
|
other operations that piggy-back on the basic Kademlia
|
||||||
lookup operation (Entangled's "delete" RPC, for instance).
|
lookup operation (Entangled's "delete" RPC, for instance).
|
||||||
@type rpc: str
|
@type rpc: str
|
||||||
|
|
||||||
@return: If C{findValue} is C{True}, the algorithm will stop as soon
|
@return: If C{findValue} is C{True}, the algorithm will stop as soon
|
||||||
as a data value for C{key} is found, and return a dictionary
|
as a data value for C{key} is found, and return a dictionary
|
||||||
containing the key and the found value. Otherwise, it will
|
containing the key and the found value. Otherwise, it will
|
||||||
|
|
|
@ -192,7 +192,7 @@ class KademliaProtocol(protocol.DatagramProtocol):
|
||||||
@note: The header used for breaking up large data segments will
|
@note: The header used for breaking up large data segments will
|
||||||
possibly be moved out of the KademliaProtocol class in the
|
possibly be moved out of the KademliaProtocol class in the
|
||||||
future, into something similar to a message translator/encoder
|
future, into something similar to a message translator/encoder
|
||||||
class (see C{kademlia.msgformat} and C{kademlia.encoding}).
|
class (see C{kademlia.msgformat} and C{kademlia.encoding}).
|
||||||
"""
|
"""
|
||||||
if len(data) > self.msgSizeLimit:
|
if len(data) > self.msgSizeLimit:
|
||||||
# We have to spread the data over multiple UDP datagrams,
|
# We have to spread the data over multiple UDP datagrams,
|
||||||
|
|
|
@ -30,10 +30,10 @@ class RoutingTable(object):
|
||||||
@param contact: The contact to add to this node's k-buckets
|
@param contact: The contact to add to this node's k-buckets
|
||||||
@type contact: kademlia.contact.Contact
|
@type contact: kademlia.contact.Contact
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def distance(self, keyOne, keyTwo):
|
def distance(self, keyOne, keyTwo):
|
||||||
""" Calculate the XOR result between two string variables
|
""" Calculate the XOR result between two string variables
|
||||||
|
|
||||||
@return: XOR result of two long variables
|
@return: XOR result of two long variables
|
||||||
@rtype: long
|
@rtype: long
|
||||||
"""
|
"""
|
||||||
|
@ -44,7 +44,7 @@ class RoutingTable(object):
|
||||||
def findCloseNodes(self, key, count, _rpcNodeID=None):
|
def findCloseNodes(self, key, count, _rpcNodeID=None):
|
||||||
""" Finds a number of known nodes closest to the node/value with the
|
""" Finds a number of known nodes closest to the node/value with the
|
||||||
specified key.
|
specified key.
|
||||||
|
|
||||||
@param key: the n-bit key (i.e. the node or value ID) to search for
|
@param key: the n-bit key (i.e. the node or value ID) to search for
|
||||||
@type key: str
|
@type key: str
|
||||||
@param count: the amount of contacts to return
|
@param count: the amount of contacts to return
|
||||||
|
@ -53,9 +53,9 @@ class RoutingTable(object):
|
||||||
Whatever ID is passed in the paramater will get
|
Whatever ID is passed in the paramater will get
|
||||||
excluded from the list of returned contacts.
|
excluded from the list of returned contacts.
|
||||||
@type _rpcNodeID: str
|
@type _rpcNodeID: str
|
||||||
|
|
||||||
@return: A list of node contacts (C{kademlia.contact.Contact instances})
|
@return: A list of node contacts (C{kademlia.contact.Contact instances})
|
||||||
closest to the specified key.
|
closest to the specified key.
|
||||||
This method will return C{k} (or C{count}, if specified)
|
This method will return C{k} (or C{count}, if specified)
|
||||||
contacts if at all possible; it will only return fewer if the
|
contacts if at all possible; it will only return fewer if the
|
||||||
node is returning all of the contacts that it knows of.
|
node is returning all of the contacts that it knows of.
|
||||||
|
@ -63,7 +63,7 @@ class RoutingTable(object):
|
||||||
"""
|
"""
|
||||||
def getContact(self, contactID):
|
def getContact(self, contactID):
|
||||||
""" Returns the (known) contact with the specified node ID
|
""" Returns the (known) contact with the specified node ID
|
||||||
|
|
||||||
@raise ValueError: No contact with the specified contact ID is known
|
@raise ValueError: No contact with the specified contact ID is known
|
||||||
by this node
|
by this node
|
||||||
"""
|
"""
|
||||||
|
@ -83,7 +83,7 @@ class RoutingTable(object):
|
||||||
will be refreshed, regardless of the time they were last
|
will be refreshed, regardless of the time they were last
|
||||||
accessed.
|
accessed.
|
||||||
@type force: bool
|
@type force: bool
|
||||||
|
|
||||||
@return: A list of node ID's that the parent node should search for
|
@return: A list of node ID's that the parent node should search for
|
||||||
in order to refresh the routing Table
|
in order to refresh the routing Table
|
||||||
@rtype: list
|
@rtype: list
|
||||||
|
@ -91,14 +91,14 @@ class RoutingTable(object):
|
||||||
def removeContact(self, contactID):
|
def removeContact(self, contactID):
|
||||||
""" Remove the contact with the specified node ID from the routing
|
""" Remove the contact with the specified node ID from the routing
|
||||||
table
|
table
|
||||||
|
|
||||||
@param contactID: The node ID of the contact to remove
|
@param contactID: The node ID of the contact to remove
|
||||||
@type contactID: str
|
@type contactID: str
|
||||||
"""
|
"""
|
||||||
def touchKBucket(self, key):
|
def touchKBucket(self, key):
|
||||||
""" Update the "last accessed" timestamp of the k-bucket which covers
|
""" Update the "last accessed" timestamp of the k-bucket which covers
|
||||||
the range containing the specified key in the key/ID space
|
the range containing the specified key in the key/ID space
|
||||||
|
|
||||||
@param key: A key in the range of the target k-bucket
|
@param key: A key in the range of the target k-bucket
|
||||||
@type key: str
|
@type key: str
|
||||||
"""
|
"""
|
||||||
|
@ -106,13 +106,13 @@ class RoutingTable(object):
|
||||||
|
|
||||||
class TreeRoutingTable(RoutingTable):
|
class TreeRoutingTable(RoutingTable):
|
||||||
""" This class implements a routing table used by a Node class.
|
""" This class implements a routing table used by a Node class.
|
||||||
|
|
||||||
The Kademlia routing table is a binary tree whose leaves are k-buckets,
|
The Kademlia routing table is a binary tree whose leaves are k-buckets,
|
||||||
where each k-bucket contains nodes with some common prefix of their IDs.
|
where each k-bucket contains nodes with some common prefix of their IDs.
|
||||||
This prefix is the k-bucket's position in the binary tree; it therefore
|
This prefix is the k-bucket's position in the binary tree; it therefore
|
||||||
covers some range of ID values, and together all of the k-buckets cover
|
covers some range of ID values, and together all of the k-buckets cover
|
||||||
the entire n-bit ID (or key) space (with no overlap).
|
the entire n-bit ID (or key) space (with no overlap).
|
||||||
|
|
||||||
@note: In this implementation, nodes in the tree (the k-buckets) are
|
@note: In this implementation, nodes in the tree (the k-buckets) are
|
||||||
added dynamically, as needed; this technique is described in the 13-page
|
added dynamically, as needed; this technique is described in the 13-page
|
||||||
version of the Kademlia paper, in section 2.4. It does, however, use the
|
version of the Kademlia paper, in section 2.4. It does, however, use the
|
||||||
|
@ -162,11 +162,11 @@ class TreeRoutingTable(RoutingTable):
|
||||||
# the k-bucket. This implementation follows section
|
# the k-bucket. This implementation follows section
|
||||||
# 2.2 regarding this point.
|
# 2.2 regarding this point.
|
||||||
headContact = self._buckets[bucketIndex]._contacts[0]
|
headContact = self._buckets[bucketIndex]._contacts[0]
|
||||||
|
|
||||||
def replaceContact(failure):
|
def replaceContact(failure):
|
||||||
""" Callback for the deferred PING RPC to see if the head
|
""" Callback for the deferred PING RPC to see if the head
|
||||||
node in the k-bucket is still responding
|
node in the k-bucket is still responding
|
||||||
|
|
||||||
@type failure: twisted.python.failure.Failure
|
@type failure: twisted.python.failure.Failure
|
||||||
"""
|
"""
|
||||||
failure.trap(TimeoutError)
|
failure.trap(TimeoutError)
|
||||||
|
@ -180,18 +180,18 @@ class TreeRoutingTable(RoutingTable):
|
||||||
pass
|
pass
|
||||||
# ...and add the new one at the tail of the bucket
|
# ...and add the new one at the tail of the bucket
|
||||||
self.addContact(contact)
|
self.addContact(contact)
|
||||||
|
|
||||||
# Ping the least-recently seen contact in this k-bucket
|
# Ping the least-recently seen contact in this k-bucket
|
||||||
headContact = self._buckets[bucketIndex]._contacts[0]
|
headContact = self._buckets[bucketIndex]._contacts[0]
|
||||||
df = headContact.ping()
|
df = headContact.ping()
|
||||||
# If there's an error (i.e. timeout), remove the head
|
# If there's an error (i.e. timeout), remove the head
|
||||||
# contact, and append the new one
|
# contact, and append the new one
|
||||||
df.addErrback(replaceContact)
|
df.addErrback(replaceContact)
|
||||||
|
|
||||||
def findCloseNodes(self, key, count, _rpcNodeID=None):
|
def findCloseNodes(self, key, count, _rpcNodeID=None):
|
||||||
""" Finds a number of known nodes closest to the node/value with the
|
""" Finds a number of known nodes closest to the node/value with the
|
||||||
specified key.
|
specified key.
|
||||||
|
|
||||||
@param key: the n-bit key (i.e. the node or value ID) to search for
|
@param key: the n-bit key (i.e. the node or value ID) to search for
|
||||||
@type key: str
|
@type key: str
|
||||||
@param count: the amount of contacts to return
|
@param count: the amount of contacts to return
|
||||||
|
@ -200,9 +200,9 @@ class TreeRoutingTable(RoutingTable):
|
||||||
Whatever ID is passed in the paramater will get
|
Whatever ID is passed in the paramater will get
|
||||||
excluded from the list of returned contacts.
|
excluded from the list of returned contacts.
|
||||||
@type _rpcNodeID: str
|
@type _rpcNodeID: str
|
||||||
|
|
||||||
@return: A list of node contacts (C{kademlia.contact.Contact instances})
|
@return: A list of node contacts (C{kademlia.contact.Contact instances})
|
||||||
closest to the specified key.
|
closest to the specified key.
|
||||||
This method will return C{k} (or C{count}, if specified)
|
This method will return C{k} (or C{count}, if specified)
|
||||||
contacts if at all possible; it will only return fewer if the
|
contacts if at all possible; it will only return fewer if the
|
||||||
node is returning all of the contacts that it knows of.
|
node is returning all of the contacts that it knows of.
|
||||||
|
@ -219,7 +219,7 @@ class TreeRoutingTable(RoutingTable):
|
||||||
i = 1
|
i = 1
|
||||||
canGoLower = bucketIndex-i >= 0
|
canGoLower = bucketIndex-i >= 0
|
||||||
canGoHigher = bucketIndex+i < len(self._buckets)
|
canGoHigher = bucketIndex+i < len(self._buckets)
|
||||||
# Fill up the node list to k nodes, starting with the closest neighbouring nodes known
|
# Fill up the node list to k nodes, starting with the closest neighbouring nodes known
|
||||||
while len(closestNodes) < constants.k and (canGoLower or canGoHigher):
|
while len(closestNodes) < constants.k and (canGoLower or canGoHigher):
|
||||||
#TODO: this may need to be optimized
|
#TODO: this may need to be optimized
|
||||||
if canGoLower:
|
if canGoLower:
|
||||||
|
@ -237,7 +237,7 @@ class TreeRoutingTable(RoutingTable):
|
||||||
|
|
||||||
def getContact(self, contactID):
|
def getContact(self, contactID):
|
||||||
""" Returns the (known) contact with the specified node ID
|
""" Returns the (known) contact with the specified node ID
|
||||||
|
|
||||||
@raise ValueError: No contact with the specified contact ID is known
|
@raise ValueError: No contact with the specified contact ID is known
|
||||||
by this node
|
by this node
|
||||||
"""
|
"""
|
||||||
|
@ -265,7 +265,7 @@ class TreeRoutingTable(RoutingTable):
|
||||||
will be refreshed, regardless of the time they were last
|
will be refreshed, regardless of the time they were last
|
||||||
accessed.
|
accessed.
|
||||||
@type force: bool
|
@type force: bool
|
||||||
|
|
||||||
@return: A list of node ID's that the parent node should search for
|
@return: A list of node ID's that the parent node should search for
|
||||||
in order to refresh the routing Table
|
in order to refresh the routing Table
|
||||||
@rtype: list
|
@rtype: list
|
||||||
|
@ -282,7 +282,7 @@ class TreeRoutingTable(RoutingTable):
|
||||||
def removeContact(self, contactID):
|
def removeContact(self, contactID):
|
||||||
""" Remove the contact with the specified node ID from the routing
|
""" Remove the contact with the specified node ID from the routing
|
||||||
table
|
table
|
||||||
|
|
||||||
@param contactID: The node ID of the contact to remove
|
@param contactID: The node ID of the contact to remove
|
||||||
@type contactID: str
|
@type contactID: str
|
||||||
"""
|
"""
|
||||||
|
@ -296,7 +296,7 @@ class TreeRoutingTable(RoutingTable):
|
||||||
def touchKBucket(self, key):
|
def touchKBucket(self, key):
|
||||||
""" Update the "last accessed" timestamp of the k-bucket which covers
|
""" Update the "last accessed" timestamp of the k-bucket which covers
|
||||||
the range containing the specified key in the key/ID space
|
the range containing the specified key in the key/ID space
|
||||||
|
|
||||||
@param key: A key in the range of the target k-bucket
|
@param key: A key in the range of the target k-bucket
|
||||||
@type key: str
|
@type key: str
|
||||||
"""
|
"""
|
||||||
|
@ -306,10 +306,10 @@ class TreeRoutingTable(RoutingTable):
|
||||||
def _kbucketIndex(self, key):
|
def _kbucketIndex(self, key):
|
||||||
""" Calculate the index of the k-bucket which is responsible for the
|
""" Calculate the index of the k-bucket which is responsible for the
|
||||||
specified key (or ID)
|
specified key (or ID)
|
||||||
|
|
||||||
@param key: The key for which to find the appropriate k-bucket index
|
@param key: The key for which to find the appropriate k-bucket index
|
||||||
@type key: str
|
@type key: str
|
||||||
|
|
||||||
@return: The index of the k-bucket responsible for the specified key
|
@return: The index of the k-bucket responsible for the specified key
|
||||||
@rtype: int
|
@rtype: int
|
||||||
"""
|
"""
|
||||||
|
@ -324,7 +324,7 @@ class TreeRoutingTable(RoutingTable):
|
||||||
|
|
||||||
def _randomIDInBucketRange(self, bucketIndex):
|
def _randomIDInBucketRange(self, bucketIndex):
|
||||||
""" Returns a random ID in the specified k-bucket's range
|
""" Returns a random ID in the specified k-bucket's range
|
||||||
|
|
||||||
@param bucketIndex: The index of the k-bucket to use
|
@param bucketIndex: The index of the k-bucket to use
|
||||||
@type bucketIndex: int
|
@type bucketIndex: int
|
||||||
"""
|
"""
|
||||||
|
@ -342,7 +342,7 @@ class TreeRoutingTable(RoutingTable):
|
||||||
def _splitBucket(self, oldBucketIndex):
|
def _splitBucket(self, oldBucketIndex):
|
||||||
""" Splits the specified k-bucket into two new buckets which together
|
""" Splits the specified k-bucket into two new buckets which together
|
||||||
cover the same range in the key/ID space
|
cover the same range in the key/ID space
|
||||||
|
|
||||||
@param oldBucketIndex: The index of k-bucket to split (in this table's
|
@param oldBucketIndex: The index of k-bucket to split (in this table's
|
||||||
list of k-buckets)
|
list of k-buckets)
|
||||||
@type oldBucketIndex: int
|
@type oldBucketIndex: int
|
||||||
|
@ -372,7 +372,7 @@ class OptimizedTreeRoutingTable(TreeRoutingTable):
|
||||||
TreeRoutingTable.__init__(self, parentNodeID)
|
TreeRoutingTable.__init__(self, parentNodeID)
|
||||||
# Cache containing nodes eligible to replace stale k-bucket entries
|
# Cache containing nodes eligible to replace stale k-bucket entries
|
||||||
self._replacementCache = {}
|
self._replacementCache = {}
|
||||||
|
|
||||||
def addContact(self, contact):
|
def addContact(self, contact):
|
||||||
""" Add the given contact to the correct k-bucket; if it already
|
""" Add the given contact to the correct k-bucket; if it already
|
||||||
exists, its status will be updated
|
exists, its status will be updated
|
||||||
|
@ -415,11 +415,11 @@ class OptimizedTreeRoutingTable(TreeRoutingTable):
|
||||||
elif len(self._replacementCache) >= constants.k:
|
elif len(self._replacementCache) >= constants.k:
|
||||||
self._replacementCache.pop(0)
|
self._replacementCache.pop(0)
|
||||||
self._replacementCache[bucketIndex].append(contact)
|
self._replacementCache[bucketIndex].append(contact)
|
||||||
|
|
||||||
def removeContact(self, contactID):
|
def removeContact(self, contactID):
|
||||||
""" Remove the contact with the specified node ID from the routing
|
""" Remove the contact with the specified node ID from the routing
|
||||||
table
|
table
|
||||||
|
|
||||||
@param contactID: The node ID of the contact to remove
|
@param contactID: The node ID of the contact to remove
|
||||||
@type contactID: str
|
@type contactID: str
|
||||||
"""
|
"""
|
||||||
|
@ -430,7 +430,7 @@ class OptimizedTreeRoutingTable(TreeRoutingTable):
|
||||||
#print 'removeContact(): Contact not in routing table'
|
#print 'removeContact(): Contact not in routing table'
|
||||||
return
|
return
|
||||||
contact.failedRPCs += 1
|
contact.failedRPCs += 1
|
||||||
if contact.failedRPCs >= 5:
|
if contact.failedRPCs >= 5:
|
||||||
self._buckets[bucketIndex].removeContact(contactID)
|
self._buckets[bucketIndex].removeContact(contactID)
|
||||||
# Replace this stale contact with one from our replacemnent cache, if we have any
|
# Replace this stale contact with one from our replacemnent cache, if we have any
|
||||||
if self._replacementCache.has_key(bucketIndex):
|
if self._replacementCache.has_key(bucketIndex):
|
||||||
|
|
|
@ -407,7 +407,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
# claim_out is dictionary containing 'txid' and 'nout'
|
# claim_out is dictionary containing 'txid' and 'nout'
|
||||||
def _add_to_pending_claims(self, name, claim_out):
|
def _add_to_pending_claims(self, name, claim_out):
|
||||||
txid = claim_out['txid']
|
txid = claim_out['txid']
|
||||||
nout = claim_out['nout']
|
nout = claim_out['nout']
|
||||||
log.info("Adding lbry://%s to pending claims, txid %s nout %d" % (name, txid, nout))
|
log.info("Adding lbry://%s to pending claims, txid %s nout %d" % (name, txid, nout))
|
||||||
self.pending_claims[name] = (txid, nout)
|
self.pending_claims[name] = (txid, nout)
|
||||||
return claim_out
|
return claim_out
|
||||||
|
@ -1498,7 +1498,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
'name': name to look up, string, do not include lbry:// prefix
|
'name': name to look up, string, do not include lbry:// prefix
|
||||||
'txid': optional, if specified, look for claim with this txid
|
'txid': optional, if specified, look for claim with this txid
|
||||||
'nout': optional, if specified, look for claim with this nout
|
'nout': optional, if specified, look for claim with this nout
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
txid, amount, value, n, height
|
txid, amount, value, n, height
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -40,11 +40,11 @@ class Publisher(object):
|
||||||
def start(self, name, file_path, bid, metadata):
|
def start(self, name, file_path, bid, metadata):
|
||||||
log.info('Starting publish for %s', name)
|
log.info('Starting publish for %s', name)
|
||||||
def _show_result():
|
def _show_result():
|
||||||
log.info("Success! Published %s --> lbry://%s txid: %s nout: %d",
|
log.info("Success! Published %s --> lbry://%s txid: %s nout: %d",
|
||||||
self.file_name, self.publish_name, self.txid, self.nout)
|
self.file_name, self.publish_name, self.txid, self.nout)
|
||||||
out = {}
|
out = {}
|
||||||
out['nout'] = self.nout
|
out['nout'] = self.nout
|
||||||
out['txid'] = self.txid
|
out['txid'] = self.txid
|
||||||
return defer.succeed(out)
|
return defer.succeed(out)
|
||||||
|
|
||||||
self.publish_name = name
|
self.publish_name = name
|
||||||
|
@ -137,10 +137,10 @@ class Publisher(object):
|
||||||
msg = 'Failed to claim name:{}'.format(claim_out['reason'])
|
msg = 'Failed to claim name:{}'.format(claim_out['reason'])
|
||||||
defer.fail(Exception(msg))
|
defer.fail(Exception(msg))
|
||||||
txid = claim_out['txid']
|
txid = claim_out['txid']
|
||||||
nout = claim_out['nout']
|
nout = claim_out['nout']
|
||||||
log.debug('Name claimed using txid: %s, nout: %d', txid, nout)
|
log.debug('Name claimed using txid: %s, nout: %d', txid, nout)
|
||||||
self.txid = txid
|
self.txid = txid
|
||||||
self.nout = nout
|
self.nout = nout
|
||||||
|
|
||||||
d = self.wallet.claim_name(self.publish_name, self.bid_amount, m)
|
d = self.wallet.claim_name(self.publish_name, self.bid_amount, m)
|
||||||
d.addCallback(set_txid_nout)
|
d.addCallback(set_txid_nout)
|
||||||
|
|
|
@ -38,7 +38,7 @@ class Metadata(StructuredDict):
|
||||||
|
|
||||||
def __init__(self, metadata, migrate=True, target_version=None):
|
def __init__(self, metadata, migrate=True, target_version=None):
|
||||||
if not isinstance(metadata, dict):
|
if not isinstance(metadata, dict):
|
||||||
raise TypeError("metadata is not a dictionary")
|
raise TypeError("metadata is not a dictionary")
|
||||||
starting_version = metadata.get('ver', '0.0.1')
|
starting_version = metadata.get('ver', '0.0.1')
|
||||||
|
|
||||||
StructuredDict.__init__(self, metadata, starting_version, migrate, target_version)
|
StructuredDict.__init__(self, metadata, starting_version, migrate, target_version)
|
||||||
|
|
|
@ -8,4 +8,5 @@ pylint -E --disable=inherit-non-class --disable=no-member \
|
||||||
--enable=unused-import \
|
--enable=unused-import \
|
||||||
--enable=bad-whitespace \
|
--enable=bad-whitespace \
|
||||||
--enable=line-too-long \
|
--enable=line-too-long \
|
||||||
|
--enable=trailing-whitespace \
|
||||||
lbrynet $@
|
lbrynet $@
|
||||||
|
|
Loading…
Reference in a new issue