diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 09b5d04..74a05f5 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,6 +1,25 @@
Change Log
==========
+2024-04-14 Veselin Penev [penev.veselin@gmail.com](mailto:penev.veselin@gmail.com)
+
+* added HMTL WEB template
+* updated id_server.py
+* built new service_blockchain_explorer()
+* updated bitdust/customer/payment.py
+* Bump cryptography from 39.0.0 to 41.0.6
+* disabled and removed few un-used services
+* updated api.services_list()
+* updated api.suppliers_list()
+* introducing storage contracts
+* bug fix in bitdust/storage/accounting.py
+* bug fixes in bitdust/supplier/storage_contract.py
+* bug fix in supplier_connector()
+* IDURL fix in contacts/contactsdb.py
+* small fix in main/config.py
+
+
+
2023-11-12 Veselin Penev [penev.veselin@gmail.com](mailto:penev.veselin@gmail.com)
* bug fix in bitdust/system/deploy.py related to python3.11
diff --git a/bitdust/automats/automat.py b/bitdust/automats/automat.py
index b08bd05..606548d 100644
--- a/bitdust/automats/automat.py
+++ b/bitdust/automats/automat.py
@@ -765,10 +765,7 @@ def addStateChangedCallback(self, cb, oldstate=None, newstate=None, callback_id=
if key not in self._state_callbacks:
self._state_callbacks[key] = []
if cb not in self._state_callbacks[key]:
- self._state_callbacks[key].append((
- callback_id,
- cb,
- ))
+ self._state_callbacks[key].append((callback_id, cb))
return True
def removeStateChangedCallback(self, cb=None, callback_id=None):
diff --git a/bitdust/blockchain/bismuth_miner.py b/bitdust/blockchain/bismuth_miner.py
index 7288e1d..fbbd854 100644
--- a/bitdust/blockchain/bismuth_miner.py
+++ b/bitdust/blockchain/bismuth_miner.py
@@ -5,7 +5,6 @@
import socks
import hashlib
import random
-import traceback
#------------------------------------------------------------------------------
@@ -95,11 +94,8 @@ def check_start_mining():
global _OwnCoinsLastTime
global _WantMoreCoins
global _MiningIsOn
- try:
- cur_balance = bismuth_wallet.my_balance()
- except:
- traceback.print_exc()
- cur_balance = 'N/A'
+
+ cur_balance = bismuth_wallet.my_balance()
lg.info('my wallet address is %s and current balance is %s' % (bismuth_wallet.my_wallet_address(), cur_balance))
if _Debug:
@@ -108,11 +104,7 @@ def check_start_mining():
if cur_balance == 'N/A':
reactor.callLater(10, check_start_mining) # @UndefinedVariable
return
- try:
- cur_balance = float(cur_balance)
- except:
- reactor.callLater(10, check_start_mining) # @UndefinedVariable
- return
+
if _WantMoreCoins and (not _OwnCoinsLastTime or (time.time() - _OwnCoinsLastTime > 60)):
_OwnCoinsLastTime = time.time()
_WantMoreCoins = False
diff --git a/bitdust/blockchain/bismuth_node.py b/bitdust/blockchain/bismuth_node.py
index 6561e57..6beaafc 100644
--- a/bitdust/blockchain/bismuth_node.py
+++ b/bitdust/blockchain/bismuth_node.py
@@ -521,6 +521,7 @@ def check_db_for_bootstrap(node):
class CustomLogHandler(logging.Handler):
+
def emit(self, record):
try:
if _Debug:
diff --git a/bitdust/blockchain/bismuth_wallet.py b/bitdust/blockchain/bismuth_wallet.py
index 35eeb0b..8e13cdf 100644
--- a/bitdust/blockchain/bismuth_wallet.py
+++ b/bitdust/blockchain/bismuth_wallet.py
@@ -3,8 +3,8 @@
#------------------------------------------------------------------------------
-from twisted.internet import reactor
-from twisted.internet.defer import Deferred
+from twisted.internet import reactor # @UnresolvedImport
+from twisted.internet.defer import Deferred # @UnresolvedImport
#------------------------------------------------------------------------------
@@ -125,17 +125,24 @@ def my_wallet_address():
def my_balance():
- return client().balance()
+ try:
+ _balance = float(client().balance())
+ except:
+ lg.exc()
+ return 'N/A'
+ return _balance
def latest_transactions(num, offset, for_display, mempool_included):
return client().latest_transactions(num, offset, for_display, mempool_included)
-def send_transaction(recipient, amount, operation='', data=''):
+def send_transaction(recipient, amount, operation='', data='', raise_errors=False):
error_reply = []
ret = client().send(recipient=recipient, amount=amount, operation=operation, data=data, error_reply=error_reply)
if not ret:
+ if raise_errors:
+ raise Exception(error_reply)
return error_reply
return ret
diff --git a/bitdust/blockchain/blockchain_explorer.py b/bitdust/blockchain/blockchain_explorer.py
new file mode 100644
index 0000000..03b845b
--- /dev/null
+++ b/bitdust/blockchain/blockchain_explorer.py
@@ -0,0 +1,430 @@
+"""
+Apache2 config
+
+
+ ServerName blockchain.bitdust.io
+ ServerAlias www.blockchain.bitdust.io
+ Redirect / https://blockchain.bitdust.io/
+ RewriteEngine on
+ RewriteCond %{SERVER_NAME} =blockchain.bitdust.io [OR]
+ RewriteCond %{SERVER_NAME} =www.blockchain.bitdust.io
+ RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
+
+
+
+ ServerName blockchain.bitdust.io
+ ServerAlias www.blockchain.bitdust.io
+ ServerAdmin bitdust.io@gmail.com
+ DocumentRoot /var/www
+ SSLEngine on
+ RewriteEngine on
+ RewriteRule ^/([a-zA-Z0-9]*)$ http://localhost:19080/$1 [P,L]
+ SSLCertificateFile /ssl/domain.cert.pem
+ SSLCertificateKeyFile /ssl/private.key.pem
+
+"""
+
+import sys
+import time
+import sqlite3
+import base64
+
+#------------------------------------------------------------------------------
+
+if __name__ == '__main__':
+ import os.path as _p
+ sys.path.insert(0, _p.abspath(_p.join(_p.dirname(_p.abspath(sys.argv[0])), '..')))
+ src_dir_path = _p.dirname(_p.dirname(_p.dirname(_p.abspath(sys.argv[0]))))
+ sys.path.insert(0, src_dir_path)
+ sys.path.insert(0, _p.join(src_dir_path, 'bitdust_forks', 'Bismuth'))
+
+#------------------------------------------------------------------------------
+
+from twisted.internet import reactor
+from twisted.web import server, resource
+
+#------------------------------------------------------------------------------
+
+from bitdust.logs import lg
+
+from bitdust.lib import strng
+
+from bitdust.main import settings
+from bitdust.main import config
+
+from bitdust.interface import web_html_template
+
+from bitdust.blockchain import bismuth_node
+
+#------------------------------------------------------------------------------
+
+_Debug = False
+_DebugLevel = 10
+
+#------------------------------------------------------------------------------
+
+_DataDirPath = None
+_ExplorerHost = None
+_ExplorerPort = None
+_WebListener = None
+
+#------------------------------------------------------------------------------
+
+
+def init():
+ global _DataDirPath
+ global _ExplorerHost
+ global _ExplorerPort
+ global _WebListener
+
+ _DataDirPath = settings.ServiceDir('bismuth_blockchain')
+ _ExplorerHost = config.conf().getString('services/blockchain-explorer/host', '127.0.0.1')
+ _ExplorerPort = config.conf().getInt('services/blockchain-explorer/web-port', 19080)
+
+ root = BlockchainRootPage()
+ root.putChild(b'', BlockchainMainPage())
+ try:
+ _WebListener = reactor.listenTCP(_ExplorerPort, server.Site(root)) # @UndefinedVariable
+ if _Debug:
+ lg.out(_DebugLevel, ' have started web server at port %d hostname=%s' % (_ExplorerPort, strng.to_text(_ExplorerHost)))
+ except:
+ if _Debug:
+ lg.err('exception while trying to listen port ' + str(self.web_port))
+ lg.exc()
+ if _Debug:
+ lg.args(_DebugLevel, data_dir_path=_DataDirPath)
+ return True
+
+
+def shutdown():
+ global _WebListener
+ if _Debug:
+ lg.dbg(_DebugLevel, '')
+ if _WebListener:
+ _WebListener.stopListening()
+ if _Debug:
+ lg.out(_DebugLevel, ' stopped web listener')
+ _WebListener = None
+ return True
+
+
+#------------------------------------------------------------------------------
+
+
+def execute(cursor, query, param):
+ while True:
+ try:
+ cursor.execute(query, param)
+ break
+ except Exception as e:
+ print('Database query: {} {}'.format(cursor, query))
+ print('Database retry reason: {}'.format(e))
+ time.sleep(0.2)
+ return cursor
+
+
+#------------------------------------------------------------------------------
+
+
+class BlockchainMainPage(resource.Resource):
+
+ def render_GET(self, request):
+ global _ExplorerHost
+
+ page_size = 500
+
+ page_num = request.args.get(b'page', [])
+ if page_num:
+ try:
+ page_num = int(strng.to_text(page_num[0]))
+ except:
+ lg.exc()
+ page_num = 0
+ else:
+ page_num = 0
+
+ page_max = page_num + 1
+
+ src = ''
+
+ conn = sqlite3.connect(bismuth_node.nod().ledger_path, timeout=60.0)
+ c = conn.cursor()
+ execute(c, 'SELECT * FROM transactions ORDER BY block_height DESC, timestamp DESC LIMIT ? OFFSET ?;', (
+ page_size,
+ page_size*page_num,
+ ))
+ _all = c.fetchall()
+ c.close()
+ conn.close()
+ conn = None
+ c = None
+
+ if len(_all) < page_size:
+ page_max = page_num
+
+ view = []
+ b = -1
+ x_old = 'init'
+
+ for x in _all:
+ if x[0] != x_old:
+ color_cell = '#F8F8F8'
+ if b >= 0:
+ view.append('
-
Identities on %(hostname)s
-''' % {
- 'hostname': strng.to_text(A().hostname),
- }
+ src = ''
+
+ src += '
\n'
+ src += '
\n'
+ src += '
\n'
+ src += '
\n'
+
+ src += '
\n'
+ src += '
Identities on %s
' % strng.to_text(A().hostname)
+ src += '\n'
+
+ src += '
\n'
src += '
\n'
src += '\n'
HTDOCS_DIR = settings.IdentityServerDir()
@@ -440,8 +464,9 @@ def render_GET(self, request):
url = '/' + filename
name = filename[:-4]
src += ' %s \n' % (strng.to_text(url), strng.to_text(name))
- src += ' | \n
\n
\n\n\n
'
+ src += ' | \n
\n\n'
src += '
Total identities on "%s": %d
\n' % (strng.to_text(A().hostname), len(files))
+ del files
src += '
Other known identity servers:\n'
for idhost in sorted(known_servers.by_host().keys()):
idport = known_servers.by_host()[idhost][0]
@@ -450,15 +475,32 @@ def render_GET(self, request):
src += '%s \n' % (strng.to_text(idhost), strng.to_text(idhost))
src += '
'
src += '\n' % (request.client.host, request.client.port)
- src += '\n'
- del files
- return strng.to_bin(src)
+ src += '
\n'
+ src += '
\n'
+ src += '
\n'
+ src += '
\n'
+ src += '
\n'
+
+ html_src = web_html_template.WEB_ROOT_TEMPLATE % dict(
+ title='Identities on %s' % strng.to_text(A().hostname),
+ site_url='https://bitdust.io',
+ basepath='https://identities.bitdust.io/',
+ wikipath='https://bitdust.io/wiki/',
+ idserverspath='https://identities.bitdust.io/',
+ blockchainpath='https://blockchain.bitdust.io/',
+ div_main_class='main idservers',
+ div_main_body=src,
+ google_analytics='',
+ pre_footer='',
+ )
+ return strng.to_bin(html_src)
#------------------------------------------------------------------------------
class WebRoot(resource.Resource):
+
def getChild(self, path, request):
if not path:
return self
@@ -481,27 +523,103 @@ def getChild(self, path, request):
#------------------------------------------------------------------------------
+class KnownIDServersWebRoot(resource.Resource):
+
+ def getChild(self, path, request):
+ if not path:
+ return self
+ return resource.NoResource('Not found')
+
+
+class KnownIDServersWebMainPage(resource.Resource):
+
+ def render_GET(self, request):
+ src = ''
+ src += '
\n'
+ src += '
\n'
+ src += '
\n'
+ src += '
\n'
+
+ src += '
\n'
+ src += '
BitDust identity servers
\n'
+ src += '\n'
+
+ src += '
\n'
+ for idhost in sorted(known_servers.by_host().keys()):
+ idport = known_servers.by_host()[idhost][0]
+ if idport != 80:
+ idhost += ':%d' % idport
+ src += '
\n'
+ src += '
\n' % strng.to_text(idhost)
+ src += '
\n'
+ src += '
\n' % (strng.to_text(idhost), strng.to_text(idhost))
+ src += '
\n'
+ src += '
\n'
+ src += '
\n'
+ src += '
\n'
+
+ src += '
\n'
+ src += '
\n'
+ src += '
\n'
+ src += '
\n'
+
+ html_src = web_html_template.WEB_ROOT_TEMPLATE % dict(
+ title='BitDust identity servers',
+ site_url='https://bitdust.io',
+ basepath='https://identities.bitdust.io/',
+ wikipath='https://bitdust.io/wiki/',
+ idserverspath='https://identities.bitdust.io/',
+ blockchainpath='https://blockchain.bitdust.io/',
+ div_main_class='main idservers',
+ div_main_body=src,
+ google_analytics='',
+ pre_footer=web_html_template.pre_footer % dict(basepath='https://identities.bitdust.io/'),
+ )
+ return strng.to_bin(html_src)
+
+
+def render_known_id_servers(web_port):
+ root = KnownIDServersWebRoot()
+ root.putChild(b'', KnownIDServersWebMainPage())
+ reactor.listenTCP(web_port, server.Site(root)) # @UndefinedVariable
+
+
+#------------------------------------------------------------------------------
+
+
def main():
bpio.init()
settings.init()
+ lg.set_debug_level(_DebugLevel)
+
+ serve_known_id_servers = False
if len(sys.argv) > 1:
- web_port = int(sys.argv[1])
+ if sys.argv[1].strip() == 'known_id_servers':
+ serve_known_id_servers = True
+ web_port = settings.getIdServerWebPort()
+ else:
+ web_port = int(sys.argv[1])
else:
web_port = settings.getIdServerWebPort()
if len(sys.argv) > 2:
tcp_port = int(sys.argv[2])
else:
tcp_port = settings.getIdServerTCPPort()
- lg.set_debug_level(20)
- lg.out(2, 'starting ID server ...')
- reactor.addSystemEventTrigger( # @UndefinedVariable
- 'before',
- 'shutdown',
- A().automat,
- 'shutdown',
- )
- reactor.callWhenRunning(A, 'init', (web_port, tcp_port)) # @UndefinedVariable
- reactor.callLater(0, A, 'start') # @UndefinedVariable
+
+ if serve_known_id_servers:
+ web_port = int(sys.argv[2])
+ lg.out(2, 'serving known ID servers web_port=%d' % web_port)
+ reactor.callWhenRunning(render_known_id_servers, web_port) # @UndefinedVariable
+
+ else:
+ lg.out(2, 'starting ID server web_port=%d tcp_port=%d' % (
+ web_port,
+ tcp_port,
+ ))
+ reactor.addSystemEventTrigger('before', 'shutdown', A().automat, 'shutdown') # @UndefinedVariable
+ reactor.callWhenRunning(A, 'init', (web_port, tcp_port)) # @UndefinedVariable
+ reactor.callLater(0, A, 'start') # @UndefinedVariable
+
reactor.run() # @UndefinedVariable
settings.shutdown()
lg.out(2, 'reactor stopped, EXIT')
diff --git a/bitdust/userid/id_url.py b/bitdust/userid/id_url.py
index 075b0f0..833094c 100644
--- a/bitdust/userid/id_url.py
+++ b/bitdust/userid/id_url.py
@@ -741,7 +741,7 @@ def idurl_to_id(idurl_text, by_parts=False):
class ID_URL_FIELD(object):
"""
A class represents a valid, verified and synced IDURL identifier of a device.
- The IDURL is always corresponds to your own identity file.
+ The IDURL is always corresponding to the identity file.
When your identity file is updated due to rotation to another identity server,
the "host" component of your IDURL is changed:
@@ -903,7 +903,7 @@ def __hash__(self):
def __repr__(self):
if _Debug:
lg.args(_DebugLevel*2, latest_as_string=self.latest_as_string)
- return '[%s%s]' % ('' if self.is_latest() else '*', self.latest_as_string)
+ return '{%s%s}' % ('' if self.is_latest() else '*', self.latest_as_string)
def __str__(self):
if _Debug:
@@ -944,7 +944,7 @@ def refresh(self, replace_original=True):
caller_modul = os.path.basename(caller_code.co_filename).replace('.py', '')
if caller_method.count('lambda') or caller_method == 'field':
caller_method = sys._getframe(1).f_back.f_code.co_name
- exc = ValueError('tried to modify username of the identity %r -> %r' % (self.current, self.latest))
+ exc = ValueError('while refreshing tried to modify username of the identity %r -> %r' % (self.current, self.latest))
lg.exc(msg='called from %s.%s()' % (caller_modul, caller_method), exc_value=exc)
raise exc
self.latest_host = latest_host
diff --git a/bitdust_forks/Bismuth/apihandler.py b/bitdust_forks/Bismuth/apihandler.py
index decfdbc..39feaee 100644
--- a/bitdust_forks/Bismuth/apihandler.py
+++ b/bitdust_forks/Bismuth/apihandler.py
@@ -703,7 +703,7 @@ def api_gettransaction(self, socket_handler, db_handler, peers):
if self.config.old_sqlite:
db_handler.execute_param(db_handler.h, 'SELECT * FROM transactions WHERE signature like ?1', (transaction_id + '%', ))
else:
- db_handler.execute_param(db_handler.h, 'SELECT * FROM transactions WHERE substr(signature,1,4)=substr(?1,1,4) and signature like ?1', (transaction_id + '%', ))
+ db_handler.execute_param(db_handler.h, 'SELECT * FROM transactions WHERE substr(signature,1,4)=substr(?1,1,4) and signature like ?1', (transaction_id + '%', ))
raw = db_handler.h.fetchone()
if not format:
connections.send(socket_handler, raw)
diff --git a/bitdust_forks/Bismuth/dbhandler.py b/bitdust_forks/Bismuth/dbhandler.py
index c04da05..8c7ca3c 100644
--- a/bitdust_forks/Bismuth/dbhandler.py
+++ b/bitdust_forks/Bismuth/dbhandler.py
@@ -166,7 +166,7 @@ def txsearch(self, address=None, recipient=None, operation=None, openfield=None,
sql += ' AND '.join(queries)
sql += ' LIMIT ?, ?;'
try:
- print('DB:txsearch', sql, params)
+ # print('DB:txsearch', sql, params)
self.execute_param(self.h, sql, tuple(params))
result = self.h.fetchall()
except:
diff --git a/bitdust_forks/Bismuth/worker.py b/bitdust_forks/Bismuth/worker.py
index 9fac411..33932c1 100644
--- a/bitdust_forks/Bismuth/worker.py
+++ b/bitdust_forks/Bismuth/worker.py
@@ -27,11 +27,11 @@ def sendsync(sdef, peer_ip, status, node):
"""
# TODO: ERROR, does **not** save anything. code or comment wrong.
node.logger.app_log.debug(f'Outbound: Synchronization with {peer_ip} finished after: {status}, sending new sync request')
- time.sleep(Decimal(node.pause))
+ time.sleep(int(node.pause))
while node.db_lock.locked():
if node.IS_STOPPING:
return
- time.sleep(Decimal(node.pause))
+ time.sleep(int(node.pause))
send(sdef, 'sendsync')
@@ -332,6 +332,8 @@ def worker(host, port, node):
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type, fname, exc_tb.tb_lineno)
"""
+ import traceback
+ traceback.print_exc()
# remove from active pool
node.peers.remove_client(this_client)
diff --git a/requirements-testing.txt b/requirements-testing.txt
index 451b8c9..9fe4e5d 100644
--- a/requirements-testing.txt
+++ b/requirements-testing.txt
@@ -1,2 +1,3 @@
coverage
mock
+pre_commit
diff --git a/tests/test_id_url.py b/tests/test_id_url.py
index 951853a..fc39a64 100644
--- a/tests/test_id_url.py
+++ b/tests/test_id_url.py
@@ -280,9 +280,9 @@ def test_identity_cached(self):
self._cache_identity('bob')
self.assertTrue(id_url.field(alice_text) != id_url.field(bob))
self.assertEqual(str(id_url.field(alice_text)), 'http://127.0.0.1:8084/alice.xml')
- self.assertEqual(repr(id_url.field(alice_text)), '[http://127.0.0.1:8084/alice.xml]')
+ self.assertEqual(repr(id_url.field(alice_text)), '{http://127.0.0.1:8084/alice.xml}')
self.assertEqual('=%s=' % id_url.field(alice_text), '=http://127.0.0.1:8084/alice.xml=')
- self.assertEqual('=%r=' % id_url.field(alice_text), '=[http://127.0.0.1:8084/alice.xml]=')
+ self.assertEqual('=%r=' % id_url.field(alice_text), '={http://127.0.0.1:8084/alice.xml}=')
def test_identity_not_cached(self):
self._cache_identity('alice')
@@ -601,15 +601,15 @@ def test_fake_name(self):
def test_latest_vs_original(self):
idurl_hans_not_cached = id_url.field(hans1)
- self.assertEqual('=%r=' % idurl_hans_not_cached, '=[http://first.com/hans.xml]=')
+ self.assertEqual('=%r=' % idurl_hans_not_cached, '={http://first.com/hans.xml}=')
self._cache_identity('hans1')
idurl_hans_cached = id_url.field(hans1)
- self.assertEqual('=%r=' % idurl_hans_cached, '=[http://first.com/hans.xml]=')
- self.assertEqual('=%r=' % id_url.field(hans1), '=[http://first.com/hans.xml]=')
+ self.assertEqual('=%r=' % idurl_hans_cached, '={http://first.com/hans.xml}=')
+ self.assertEqual('=%r=' % id_url.field(hans1), '={http://first.com/hans.xml}=')
self._cache_identity('hans2')
- self.assertEqual('=%r=' % id_url.field(hans1), '=[*http://second.net/hans.xml]=')
+ self.assertEqual('=%r=' % id_url.field(hans1), '={*http://second.net/hans.xml}=')
self._cache_identity('hans3')
- self.assertEqual('=%r=' % id_url.field(hans1), '=[*http://third.org/hans.xml]=')
+ self.assertEqual('=%r=' % id_url.field(hans1), '={*http://third.org/hans.xml}=')
self.assertEqual(id_url.field(hans1), id_url.field(hans2))
self.assertNotEqual(id_url.field(hans1).original(), id_url.field(hans2).original())
self.assertEqual(id_url.field(hans1), id_url.field(hans3))
@@ -620,21 +620,21 @@ def test_latest_vs_original(self):
self.assertEqual(id_url.field(hans2).to_text(), hans3)
self.assertEqual(id_url.field(hans3).to_text(), hans3)
idurl_hans1 = id_url.field(hans1)
- self.assertEqual('=%r=' % idurl_hans1, '=[*http://third.org/hans.xml]=')
+ self.assertEqual('=%r=' % idurl_hans1, '={*http://third.org/hans.xml}=')
self.assertFalse(idurl_hans1.refresh())
- self.assertEqual('=%r=' % idurl_hans1, '=[*http://third.org/hans.xml]=')
+ self.assertEqual('=%r=' % idurl_hans1, '={*http://third.org/hans.xml}=')
idurl_hans2 = id_url.field(hans2)
- self.assertEqual('=%r=' % idurl_hans2, '=[*http://third.org/hans.xml]=')
+ self.assertEqual('=%r=' % idurl_hans2, '={*http://third.org/hans.xml}=')
self.assertFalse(idurl_hans2.refresh())
- self.assertEqual('=%r=' % idurl_hans2, '=[*http://third.org/hans.xml]=')
+ self.assertEqual('=%r=' % idurl_hans2, '={*http://third.org/hans.xml}=')
idurl_hans3 = id_url.field(hans3)
- self.assertEqual('=%r=' % idurl_hans3, '=[http://third.org/hans.xml]=')
+ self.assertEqual('=%r=' % idurl_hans3, '={http://third.org/hans.xml}=')
self.assertFalse(idurl_hans3.refresh())
- self.assertEqual('=%r=' % idurl_hans3, '=[http://third.org/hans.xml]=')
+ self.assertEqual('=%r=' % idurl_hans3, '={http://third.org/hans.xml}=')
self.assertTrue(idurl_hans_not_cached.refresh())
- self.assertEqual('=%r=' % idurl_hans_not_cached, '=[http://third.org/hans.xml]=')
+ self.assertEqual('=%r=' % idurl_hans_not_cached, '={http://third.org/hans.xml}=')
self.assertTrue(idurl_hans_cached.refresh())
- self.assertEqual('=%r=' % idurl_hans_cached, '=[http://third.org/hans.xml]=')
+ self.assertEqual('=%r=' % idurl_hans_cached, '={http://third.org/hans.xml}=')
def test_latest_revision_order_123(self):
self._cache_identity('hans1')