Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • cebash/sakia
  • santiago/sakia
  • jonas/sakia
3 results
Show changes
Showing
with 424 additions and 3061 deletions
sakia.png

64.8 KiB

# -*- mode: python -*-
from PyInstaller.compat import is_darwin, is_win, is_linux
import ctypes
import subprocess
import os
block_cipher = None
a = Analysis(['src/sakia/main.py'],
pathex=['.'],
binaries=None,
datas=None,
hiddenimports=['six','packaging', 'packaging.version', 'packaging.specifiers'],
hookspath=['hooks'],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
if is_darwin:
a.binaries = a.binaries - TOC([
('/usr/local/lib/libsodium.so', None, None),])
info = subprocess.check_output(["brew", "info", "libsodium"])
info = info.decode().splitlines(keepends=False)
if len(info) > 1:
library_path = info[3].split(" ")[0]
libsodium_path = os.path.join(library_path, "lib",
"libsodium.dylib")
a.binaries = a.binaries + TOC([('lib/libsodium.dylib', libsodium_path, 'BINARY')])
a.datas = a.datas + [('sakia/root_servers.yml', 'src/sakia/root_servers.yml', 'DATA')]
a.datas = a.datas + [('sakia/g1_licence.html', 'src/sakia/g1_licence.html', 'DATA')]
if is_linux:
libsodium_path = ctypes.util.find_library('libsodium.so')
if not libsodium_path:
if os.path.isfile('/usr/lib/x86_64-linux-gnu/libsodium.so.18.3.0'):
libsodium_path = "/usr/lib/x86_64-linux-gnu/libsodium.so.18.3.0"
if os.path.isfile('/usr/lib/x86_64-linux-gnu/libsodium.so.18.3.0'):
libsodium_path = "/usr/lib/x86_64-linux-gnu/libsodium.so.18.3.0"
a.binaries = a.binaries + TOC([('libsodium.so', libsodium_path, 'BINARY')])
a.datas = a.datas + [('sakia/root_servers.yml', 'src/sakia/root_servers.yml', 'DATA')]
a.datas = a.datas + [('sakia/g1_licence.html', 'src/sakia/g1_licence.html', 'DATA')]
if is_win:
a.binaries = a.binaries + TOC([('libsodium.dll', ctypes.util.find_library('libsodium.dll'), 'BINARY')])
a.datas = a.datas + [('sakia\\root_servers.yml', 'src\\sakia\\root_servers.yml', 'DATA')]
a.datas = a.datas + [('sakia\\g1_licence.html', 'src\\sakia\\g1_licence.html', 'DATA')]
for file in os.listdir(os.path.join("src", "sakia", "data", "repositories")):
if file.endswith(".sql"):
sql_file = os.path.basename(file)
if is_win:
a.datas = a.datas + [('sakia\\data\\repositories\\{:}'.format(sql_file),
'src\\sakia\\data\\repositories\\{:}'.format(sql_file), 'DATA')]
else:
a.datas = a.datas + [('sakia/data/repositories/{:}'.format(sql_file),
'src/sakia/data/repositories/{:}'.format(sql_file), 'DATA')]
print(a.binaries)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
if is_linux or is_darwin:
exe = EXE(pyz,
a.scripts,
exclude_binaries=True,
name='sakia.bin',
debug=True,
strip=False,
upx=True,
console=True,
icon='sakia.ico')
else:
exe = EXE(pyz,
a.scripts,
exclude_binaries=True,
name='sakia',
debug=True,
strip=False,
upx=True,
console=False,
icon='sakia.ico')
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
name='sakia')
if is_darwin:
app = BUNDLE(exe,
name='sakia.app',
icon='sakia.ico',
bundle_identifier=None,) # take care, info.plist will be overridden.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created using Karbon, part of Calligra: http://www.calligra.org/karbon -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="576pt"
height="553pt"
id="svg4189"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="logo.svg"
inkscape:export-filename="/home/inso/code/ucoin/sakia/logo.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<metadata
id="metadata4197">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1366"
inkscape:window-height="712"
id="namedview4195"
showgrid="false"
inkscape:zoom="2.2300076"
inkscape:cx="247.41367"
inkscape:cy="408.41696"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer0"
inkscape:snap-page="false"
showguides="false" />
<defs
id="defs4191">
<linearGradient
inkscape:collect="always"
id="linearGradient6671">
<stop
style="stop-color:#000000;stop-opacity:1"
offset="0"
id="stop6673" />
<stop
id="stop6679"
offset="0.5"
style="stop-color:#008080;stop-opacity:1" />
<stop
style="stop-color:#008080;stop-opacity:0.61290324"
offset="1"
id="stop6675" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient5659">
<stop
style="stop-color:#008080;stop-opacity:1;"
offset="0"
id="stop5661" />
<stop
style="stop-color:#008080;stop-opacity:0;"
offset="1"
id="stop5663" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5659"
id="radialGradient5665"
cx="354.72495"
cy="329.73428"
fx="354.72495"
fy="329.73428"
r="337.09482"
gradientTransform="matrix(1.1531587,-0.08976264,0.0993579,1.2764263,-86.244099,-59.14596)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5659"
id="radialGradient5665-7"
cx="354.72495"
cy="329.73428"
fx="354.72495"
fy="329.73428"
r="337.09482"
gradientTransform="matrix(1.1861924,-0.05070794,0.04011907,0.93849052,-78.590529,37.659826)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5659"
id="radialGradient5665-7-4"
cx="354.72495"
cy="329.73428"
fx="354.72495"
fy="329.73428"
r="337.09482"
gradientTransform="matrix(0.99261208,0.00638331,-0.00467854,0.72752022,5.4994312,86.785213)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5659"
id="radialGradient5665-7-4-5"
cx="354.72495"
cy="329.73428"
fx="354.72495"
fy="329.73428"
r="337.09482"
gradientTransform="matrix(0.69198409,0.00527148,-0.00466889,0.61288279,112.83584,125.41852)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5659"
id="radialGradient5665-7-4-5-9"
cx="354.72495"
cy="329.73428"
fx="354.72495"
fy="329.73428"
r="337.09482"
gradientTransform="matrix(0.42864238,0.03373772,-0.02981182,0.37876324,214.20841,191.76438)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient6671"
id="radialGradient6677"
cx="355.91632"
cy="326.41501"
fx="355.91632"
fy="326.41501"
r="92.90654"
gradientTransform="matrix(1,0,0,0.90102387,0,32.011742)"
gradientUnits="userSpaceOnUse" />
</defs>
<g
id="layer0">
<path
style="fill:url(#radialGradient6677);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 254.93807,326.59977 64.05161,-86.88188 89.41858,8.24427 32.79132,92.85213 c -14.41306,16.98713 -18.0479,19.68178 -60.06082,65.05727 l -84.97936,1.26835 z"
id="path6669"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
id="shape0-4-6-1"
d="m 458.81436,169.64915 c -0.64093,0.0904 -1.54692,0.86419 -2.10296,1.66553 -0.97212,1.61367 -2.75267,3.65667 -9.92839,11.61326 -2.69758,2.95677 -4.87769,5.60216 -4.90524,5.95212 -0.0275,0.34994 -0.27055,0.75336 -0.63153,0.8658 -0.28547,0.048 -2.427,2.20341 -4.67159,4.77329 -8.01724,8.80586 -12.53783,13.45018 -13.02777,13.41162 -0.27995,-0.022 -3.5261,-3.51705 -7.27156,-7.82605 -7.74334,-8.98996 -13.17411,-13.36119 -24.62082,-20.03695 -21.75317,-12.62795 -42.06995,-18.45251 -72.79594,-20.8709 -11.19853,-0.88142 -15.20455,-0.98545 -26.71222,-0.62356 -5.9988,0.16166 -24.35944,2.58988 -25.4054,3.35264 -2.01095,1.39106 -1.34509,5.45766 2.46612,15.19451 2.11202,5.37766 3.7947,9.94683 3.78368,10.08682 -0.0165,0.20997 1.84308,5.21562 4.0565,11.09421 2.28344,5.88411 4.17998,11.31521 4.18386,12.1606 0.0463,1.20088 -0.68113,1.49575 -5.30216,2.04755 -10.59941,1.34889 -17.6954,3.81863 -30.06534,10.66213 -21.04739,11.51276 -37.79505,27.44858 -54.34736,51.63943 -11.29939,16.50548 -24.28931,41.96266 -24.07256,47.26155 l 0.0557,1.97628 11.48789,1.67886 c 23.11026,3.43874 31.29757,4.99866 31.22045,5.97853 -0.0386,0.48994 -0.83375,2.54009 -1.69341,4.51473 -1.6973,3.66933 -3.13829,8.55605 -4.39297,14.65465 -0.88494,4.08539 -1.98121,18.01357 -1.62899,19.80191 0.0904,0.64093 0.23651,3.25813 0.31817,5.79985 0.25623,16.42906 8.31772,46.43022 17.04834,63.45585 8.37665,16.1527 27.00772,43.39447 31.83773,46.45077 l 1.88262,1.13412 4.42468,-5.21528 c 2.4821,-2.90331 5.74673,-6.80141 7.23081,-8.65648 1.48407,-1.85508 5.67124,-6.73691 9.30786,-10.88743 l 6.51276,-7.5862 4.58924,5.2205 c 5.67992,6.57398 7.18504,8.03051 13.76707,12.98532 12.36827,9.28356 26.65318,15.68974 46.59408,20.92132 9.03659,2.40146 13.85493,2.92154 14.88052,1.52335 1.17655,-1.52715 0.84312,-1.76467 -3.74322,-2.5482 -7.01399,-1.2563 -10.47497,-2.02168 -13.29502,-2.87747 -1.51224,-0.47115 -3.85337,-1.14839 -5.16667,-1.46303 -1.31331,-0.31464 -2.96554,-0.79681 -3.57894,-1.05636 -0.61338,-0.25955 -1.78119,-0.63315 -2.61006,-0.83924 -2.13667,-0.59073 -4.25681,-1.39143 -5.8115,-2.21804 -0.74788,-0.34055 -3.06146,-1.36775 -5.11159,-2.16294 -5.74703,-2.14252 -19.37675,-10.60986 -24.31757,-14.9425 -9.01582,-8.03377 -14.3717,-15.14564 -17.72216,-23.5786 -5.22106,-13.29862 -4.16727,-27.58191 2.79232,-38.1612 5.99854,-9.10558 18.87755,-20.62746 28.55706,-25.49956 l 5.13073,-2.55399 7.05707,4.28795 c 10.01546,6.07014 18.25462,8.76093 29.59315,9.65337 6.9346,0.47539 11.67357,0.21456 17.90599,-1.12593 4.4386,-0.91829 4.09415,-1.01583 3.96745,0.59397 -0.23688,3.00959 2.05622,18.61304 3.15467,21.65734 0.70218,1.81587 1.19438,3.61521 1.16683,3.96517 -0.0275,0.34996 1.30292,3.13081 2.97231,6.07918 3.26882,5.89124 9.0612,12.82585 13.25027,15.97254 4.46352,3.23871 12.44863,6.47292 17.74039,7.24155 6.61607,0.94329 7.51494,1.15488 7.77124,2.37227 0.0959,0.57094 3.20497,8.49192 6.84477,17.72231 8.0683,20.07218 9.31063,23.97289 8.04916,24.78912 -0.51748,0.31139 -3.10876,1.02295 -5.90451,1.648 -4.65958,1.04174 -6.44241,1.32397 -11.05241,1.73579 -17.95008,1.68586 -24.53636,2.15341 -28.32689,1.99591 -8.71191,-0.26316 -23.84096,-1.3131 -24.16336,-1.69059 -0.83827,-0.9815 -14.97567,-1.74672 -15.07483,-0.48692 -0.0826,1.04987 11.55388,3.16762 13.29815,3.37533 16.5658,1.58557 30.32256,2.17537 38.3362,1.46804 14.88538,-1.22283 23.794,-2.56395 35.34898,-5.31655 3.5122,-0.77993 3.45873,-0.99542 0.0658,-9.78382 -1.40435,-3.63176 -4.20751,-10.96526 -6.31952,-16.3429 -3.97712,-10.31331 -7.40145,-19.59715 -7.3684,-20.0171 0.011,-0.13998 0.58196,-0.2359 1.28187,-0.18081 1.6098,0.1267 13.81511,-1.94088 18.34573,-3.13362 13.23089,-3.46579 31.04619,-14.17623 47.75916,-28.77671 10.662,-9.30193 18.75474,-18.17227 27.19127,-29.62125 10.09366,-13.71298 14.93215,-21.50139 20.21747,-32.28289 2.52391,-5.22402 4.53811,-8.44586 5.25453,-8.60075 0.85643,-0.14387 1.2025,-0.96171 1.30879,-3.20694 0.18116,-4.98586 1.33795,-4.47227 -15.31663,-7.61417 -5.61968,-1.07613 -10.9594,-2.13023 -11.78826,-2.33632 -1.72775,-0.41769 -6.44856,-1.28223 -12.55817,-2.39691 -2.0132,-0.36974 -4.7853,-0.94004 -6.02861,-1.24918 -1.3133,-0.31464 -3.80543,-0.86291 -5.54418,-1.14062 -4.65633,-0.78904 -5.80761,-1.37263 -5.21301,-2.66388 5.62363,-13.29015 8.2383,-24.141 8.66996,-36.78342 0.82153,-22.96414 -2.37333,-43.21615 -10.66715,-66.68646 -5.86101,-16.79979 -8.69333,-22.86795 -19.99775,-42.98357 -3.27432,-5.82125 -6.21457,-8.7288 -8.42285,-8.40965 z m -137.04472,-6.27938 c 34.68242,3.15234 70.32521,17.36649 88.82152,35.58332 3.9185,3.90006 10.50343,13.29183 12.34812,17.59206 3.43147,8.29848 4.50816,20.56666 2.56135,28.30097 -1.44263,5.8021 -5.63628,14.34551 -9.23046,18.85148 -2.96816,3.71016 -10.77218,10.70175 -14.85854,13.40837 -2.66842,1.69144 -3.08285,1.5884 -9.07904,-2.7569 -4.1301,-3.00121 -10.16097,-6.01116 -14.02536,-7.01957 -1.10333,-0.29811 -3.17,-0.88332 -4.54227,-1.34345 -3.83687,-1.35837 -15.14233,-2.67075 -20.17228,-2.29199 -2.55272,0.22164 -7.69123,1.08483 -11.55887,1.90721 -6.95438,1.56537 -9.51262,1.85699 -8.80007,0.8567 0.39954,-0.60237 -1.30094,-10.31394 -3.08729,-17.14486 -2.48691,-9.5622 -4.54708,-13.80897 -10.34495,-20.67393 -4.63169,-5.57597 -6.47575,-7.20002 -11.2578,-9.97084 -7.0036,-4.07247 -12.55717,-5.9885 -18.36641,-6.44573 l -4.40943,-0.34706 -4.44891,-11.47722 c -11.29367,-29.19954 -13.03532,-33.91421 -12.95819,-34.89408 0.0661,-0.83989 9.77768,-2.54037 17.13385,-2.94732 6.58076,-0.39756 25.47603,-0.67095 26.14839,-0.26591 0.20447,0.0865 4.74286,0.58457 10.12664,1.07875 z m 139.64343,13.52638 c 1.93446,2.26499 8.96751,14.01604 12.01533,20.03073 5.97218,11.8084 10.79533,24.79399 14.35703,38.59584 3.1395,12.00797 3.76842,15.64913 5.19895,28.79024 2.51763,22.59314 -0.58831,43.26473 -8.96298,59.29618 -0.57808,1.08129 -1.09168,2.23808 -1.10821,2.44806 -0.32014,1.38328 -5.80733,7.57131 -9.89534,11.19331 -4.98849,4.3258 -13.7675,8.49411 -19.60591,9.30221 -10.75041,1.47786 -25.45627,-1.3698 -31.69386,-6.22706 -1.39818,-1.02557 -1.48859,-1.66649 -1.08093,-6.84583 0.39113,-4.96935 0.32601,-7.72103 -0.51741,-14.90029 -1.16096,-10.30292 -6.82401,-23.35461 -13.65909,-31.3576 -5.73891,-6.71946 -5.97254,-5.54065 2.02493,-12.30575 11.08743,-9.33886 16.9168,-17.19013 20.06773,-26.80156 1.30491,-4.05233 2.25694,-12.56918 1.88206,-16.75372 -0.44488,-4.19006 -2.34755,-12.22737 -3.66701,-15.14818 -1.32494,-2.85084 -1.3029,-3.13082 -0.0933,-5.07792 1.45264,-2.35051 12.54106,-15.28096 22.10687,-25.86638 3.46909,-3.81158 6.94371,-7.69314 7.66177,-8.76341 1.7271,-2.2585 2.77696,-2.17586 4.96935,0.39113 z m -161.96818,41.05604 c 9.15292,3.60781 18.12241,10.44071 22.17601,17.09796 3.18943,5.11033 7.23166,18.17531 8.08999,26.05999 0.97465,9.09104 1.33174,8.1332 -3.43801,10.57477 -2.41989,1.21801 -6.81928,4.32254 -9.90375,6.82633 -10.86095,9.14542 -18.46473,21.64589 -21.67726,35.61878 -0.75986,3.39099 -1.53464,6.07656 -1.67463,6.06554 -0.34994,-0.0276 -8.40341,-4.18264 -10.69496,-5.48981 -3.43181,-2.03071 -14.07657,-5.47425 -20.94507,-6.78953 -7.98284,-1.4734 -8.05284,-1.47891 -14.58565,-0.79588 -12.50004,1.34014 -23.76502,7.56637 -31.43944,17.38515 l -2.11562,2.72088 -5.99167,-0.82371 c -3.34854,-0.40441 -9.95912,-1.41769 -14.76095,-2.14776 -4.80181,-0.73006 -11.41238,-1.74334 -14.75541,-2.21773 -6.5406,-1.00777 -6.73404,-1.23427 -5.12877,-4.62915 0.42707,-0.95232 1.03821,-2.45356 1.2443,-3.28243 1.19245,-4.41331 10.79879,-22.67181 16.73834,-31.9229 7.5487,-11.80056 15.52511,-21.87727 23.71376,-30.17666 9.72069,-9.86899 12.29318,-12.13138 19.02205,-17.09487 17.04301,-12.53218 34.92183,-19.57591 50.13903,-19.64584 6.90318,-0.0201 10.59065,0.55189 15.98771,2.66687 z m 74.50313,51.07652 c 5.01017,1.66198 9.98728,3.74391 12.27332,5.12105 3.56079,2.18172 8.35223,5.72795 8.31917,6.14789 -0.0165,0.20998 -3.59644,2.74518 -7.9738,5.56976 -4.44185,2.74906 -10.34021,7.00325 -13.26818,9.30807 -4.35694,3.46 -5.5374,4.14175 -6.97966,3.67612 -3.43894,-1.04535 -10.88,-1.34933 -14.95764,-0.54348 -4.71855,0.89625 -6.02797,1.42701 -10.37778,3.90162 l -2.94838,1.6694 -0.89625,-4.71855 c -1.53069,-8.28972 -2.53287,-17.0308 -2.59313,-22.52866 l -0.0768,-5.28788 4.27269,-1.49474 c 7.39248,-2.65766 15.26062,-3.30602 25.1073,-2.24931 4.81835,0.5201 9.34572,1.15814 10.0991,1.42871 z m -43.22039,7.79569 c 0.36874,1.57835 0.77669,5.34295 1.10524,8.32664 0.61692,7.3727 2.45187,17.16527 3.49298,19.14868 0.72971,1.46593 0.55667,1.87485 -1.79646,4.92917 -4.0582,5.03285 -5.68162,9.55308 -6.33555,16.96661 -0.57292,7.27904 -0.27092,7.02111 -6.132,5.433 -1.86221,-0.49868 -4.76327,-1.21999 -6.491,-1.63768 -3.74095,-0.78742 -13.42236,-3.94386 -15.92388,-5.26753 -1.76467,-0.84314 -1.88261,-1.13412 -1.57963,-4.98363 0.95304,-12.10841 8.35561,-26.52618 18.6252,-36.21112 4.11003,-3.90198 12.67681,-9.8476 14.00664,-9.74293 0.27996,0.022 0.73522,1.39593 1.02846,3.03879 z m 68.96367,7.82244 c 4.36599,3.58315 10.90685,13.53486 13.71553,20.79837 2.91009,7.76446 4.54058,17.47052 3.9952,24.39962 -0.32502,4.12946 -0.65619,5.65273 -1.18857,5.2587 -0.40342,-0.24302 -0.96885,-0.2171 -1.28188,0.18082 -0.31852,0.4679 -1.49183,0.16428 -3.51443,-0.98088 -4.38966,-2.38781 -13.28853,-6.53901 -18.07771,-8.32445 -5.74151,-2.21252 -6.80627,-3.00057 -7.11992,-5.27885 -0.56834,-4.41103 -4.87437,-11.44028 -9.7507,-15.69743 l -4.67188,-4.17064 2.05503,-1.95099 c 3.71601,-3.36959 22.48691,-15.48409 23.96774,-15.50837 0.20997,0.0165 1.08128,0.57807 1.87159,1.2741 z m -33.89641,18.1777 c 7.07134,2.31719 13.01081,8.27778 16.01294,15.7678 1.76369,4.4347 1.89653,5.4311 1.44481,11.17035 -0.72003,8.25341 -2.9089,12.79957 -8.4369,17.71673 -9.3785,8.20574 -21.99111,9.18491 -32.31248,2.5273 -4.29762,-2.66227 -8.41897,-7.56424 -10.31712,-12.07996 -1.7802,-4.22472 -2.17452,-12.63629 -0.85309,-16.89859 4.78699,-15.18702 19.85127,-23.15652 34.46184,-18.20363 z m -103.05353,10.12877 c 9.38654,2.42899 15.95143,4.91758 22.76159,8.76354 l 7.21908,4.01901 0.24042,4.10353 c 0.71184,11.53522 3.18935,20.322 8.13857,29.02164 1.6639,3.01836 3.51573,6.33322 4.06852,7.36266 0.55278,1.02946 2.22382,3.06244 3.79892,4.52448 1.57511,1.46204 2.85925,3.04203 2.8262,3.46198 -0.0276,0.34995 -1.14352,1.1072 -2.38294,1.64347 -3.41627,1.35088 -15.45768,11.17806 -21.22482,17.34403 -9.75924,10.35893 -14.21246,19.51573 -15.12139,31.06388 -0.69963,8.88885 0.53619,16.4511 3.83093,22.90778 l 2.19465,4.32777 -2.05665,2.86638 c -1.17657,1.52715 -3.83171,4.8394 -6.00629,7.41479 -2.09909,2.51091 -5.91427,7.14034 -8.33739,10.18915 -2.42312,3.04881 -5.67124,6.73692 -7.11675,8.10206 l -2.67003,2.60682 -4.12685,-4.83198 c -3.55201,-4.08249 -8.40307,-10.45039 -12.25385,-16.10574 -1.95487,-2.90041 -6.52984,-10.09168 -7.14161,-11.26661 -0.37036,-0.66298 -1.90515,-3.53034 -3.44558,-6.32771 -6.76799,-12.43442 -8.72512,-17.09563 -13.32407,-32.03512 -3.75289,-12.26755 -4.88178,-19.39884 -6.5336,-41.36044 -0.24754,-3.11816 0.90381,-17.74625 1.58268,-21.00276 2.82789,-12.6651 8.09508,-22.32123 15.80156,-28.96838 11.02846,-9.48437 23.40667,-11.96089 39.27871,-7.82423 z m 234.01251,17.99619 c 0.89887,0.21158 4.63982,0.999 8.38626,1.71643 3.67647,0.71192 7.49291,1.43485 8.38626,1.71644 0.96886,0.2171 4.7098,1.00451 8.31628,1.71092 10.74942,2.11371 19.37158,4.41211 19.31649,5.11202 -0.20934,2.65965 -12.50937,24.72033 -19.10087,34.2018 -5.32291,7.67985 -14.22184,18.74031 -23.24812,28.73438 -8.25476,9.1393 -34.78885,29.51625 -38.00843,29.26284 -0.48994,-0.0386 -0.86192,0.21386 -0.89498,0.6338 -0.0275,0.34996 -0.33505,0.67787 -0.68501,0.65032 -0.41994,-0.0331 -2.60779,0.9212 -4.95216,2.07474 -4.39776,2.18913 -19.28802,6.15814 -24.30696,6.39692 -2.90268,0.19408 -7.85713,0.50837 -10.97527,0.75592 -0.92092,0.0684 -3.62301,-0.49644 -5.95863,-1.24367 -2.33562,-0.74723 -5.09118,-1.5275 -6.05452,-1.8146 -5.03773,-1.31204 -13.20037,-7.65887 -18.65383,-14.42596 -4.62068,-5.71594 -9.9438,-22.1917 -10.12099,-31.5721 -0.0557,-1.97627 -0.17593,-4.02804 -0.34184,-4.60449 -0.21937,-0.79194 0.90212,-1.61918 3.81744,-2.86863 8.96695,-3.87182 18.54828,-11.07566 24.48457,-18.49596 4.06922,-5.17283 9.02727,-13.58565 10.75374,-18.52031 0.82823,-2.47009 1.84991,-4.71369 2.15742,-5.0416 0.3775,-0.32242 1.83078,0.003 3.53097,0.77088 8.48445,4.04816 22.15695,6.60322 30.39708,5.70245 11.43932,-1.28279 24.38733,-9.20757 31.15188,-19.09798 l 2.5482,-3.74319 4.23639,0.75599 c 2.36315,0.39727 4.99527,0.95655 5.81863,1.23264 z m -91.93952,4.03151 c 3.24938,1.66423 7.10665,3.65801 8.53238,4.33363 3.17939,1.65874 3.12818,3.20405 -0.42454,11.65705 -3.19563,7.49517 -7.39706,14.34778 -10.81658,17.52942 -1.44001,1.29515 -3.12854,3.06371 -3.76009,3.92952 -2.58514,3.31775 -16.49263,11.80084 -19.0123,11.60252 -0.34995,-0.0275 -0.63379,-0.89498 -0.54565,-2.01483 0.26993,-3.42955 -1.87832,-21.76815 -3.11902,-26.58424 -0.65259,-2.44579 -0.56056,-2.72025 1.19797,-4.4833 5.34008,-5.21364 9.65167,-13.46607 10.11992,-19.4153 0.13222,-1.67978 0.38789,-3.13856 0.61439,-3.33201 0.67399,-0.51035 10.58027,3.36804 17.21352,6.77754 z m -106.62137,-6.27926 c 0.51585,0.60399 2.07607,1.36062 3.52934,1.68627 2.49212,0.54827 13.53091,3.45943 21.59314,5.71376 4.75775,1.28999 4.76326,1.21999 6.87691,5.68225 1.99017,4.24127 4.38151,6.96476 9.23194,10.65647 1.85508,1.48409 3.43018,2.94612 3.40815,3.22609 -0.12671,1.60979 -24.31544,17.24163 -26.48516,17.07085 -1.25983,-0.0992 -7.73006,-7.36917 -10.74257,-12.04302 -5.19776,-8.22622 -8.86575,-19.78283 -9.19395,-29.03428 -0.15389,-4.30801 0.17014,-4.84588 1.7822,-2.95839 z m 74.16622,28.51417 c 1.79349,5.84555 2.92916,18.25921 2.35462,26.45364 -0.11732,2.3852 -0.26279,2.44418 -4.50795,3.58896 -2.44579,0.65259 -8.06321,1.33726 -12.57568,1.40463 -7.05969,0.219 -9.08391,-0.0107 -14.88601,-1.45336 -7.2499,-1.83826 -16.16528,-5.7795 -20.27885,-8.99067 -2.38746,-1.87811 -2.44644,-2.02359 -1.19048,-2.76983 11.07155,-6.45272 23.42822,-14.91703 25.07431,-17.04105 0.39953,-0.60238 2.4513,-0.72259 6.02084,-0.44163 5.73925,0.45172 13.12848,-0.37517 16.34579,-1.88255 2.69985,-1.19599 2.9743,-1.10397 3.64341,1.13186 z"
inkscape:connector-curvature="0"
style="fill:url(#radialGradient5665-7-4-5);fill-opacity:1"
sodipodi:nodetypes="cccccccccscccccccccccccccccccccsccccccccsccccccccccccsccccccccsccscccccccsccccccccccccccccccccccccccccccccscccccccccccccccscsccccccccccccccccccccccsccccccccccccccccccccccccccccccccscccccsccccccccccccccccccccccccscccsccccsccccccccccccccccsccccccccsccccccccccccccccccccsccsccsccccccccsccccccccscc" />
<path
style="opacity:0.45899999;fill:#630089;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 196.91112,37.733371 c 13.74045,30.546065 21.01972,84.655599 105.59002,200.716179 l 107.17546,9.5126 C 430.36904,192.07706 447.01846,170.61524 473.72821,128.73739 421.91833,32.839172 258.28521,22.510153 196.91112,37.733371 Z"
id="path6560"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="opacity:0.45899999;fill:#c3cd00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.92575121px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 537.45161,52.857548 c -79.092,85.785042 -71.03039,73.468682 -128.8322,192.669342 l 31.68565,95.5017 C 458.45659,318.33911 486.40479,328.77081 572.682,336.5485 631.37119,251.36579 582.95743,111.43363 537.45161,52.857548 Z"
id="path6560-9"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="opacity:0.459;fill:#006680;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.92575121px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 684.40069,349.98626 C 570.71817,323.70123 584.96163,320.57683 452.77511,329.32717 l -74.93685,78.82516 c 28.69869,4.54704 47.81197,45.65498 87.77894,125.37572 105.42903,5.31684 190.39677,-115.01347 218.78349,-183.54179 z"
id="path6560-9-0"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="opacity:0.45899999;fill:#c3cd00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.92575121px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 171.14999,603.92159 C 361.85436,371.90795 228.60296,460.30738 297.31042,400.99887 l -52.11861,-97.47739 c -39.38246,38.47919 -83.37351,27.31884 -138.78581,21.09064 -25.912543,41.79782 -24.026627,94.96943 -9.211962,143.80994 12.680312,41.80404 13.175312,59.11748 73.955952,135.49953 z"
id="path6560-9-0-3-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccsc" />
<path
style="opacity:0.45899999;fill:#006680;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.92575121px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 15.647435,317.20457 c 304.270285,44.09474 171.479155,-36.31533 238.646825,11.9071 l 65.5073,-89.40274 c -18.08899,0.90067 -22.45162,-17.3846 -88.92032,-115.0142 -50.41601,0.50608 -95.65933,24.06837 -132.608622,62.11549 -40.412676,41.6134 -59.12647,68.88888 -82.625183,130.39435 z"
id="path6560-9-0-3-6-9"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccsc" />
<path
style="opacity:0.45899999;fill:#630089;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.92575121px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 501.72731,618.30232 C 457.9054,512.13475 422.10389,431.4201 384.23836,402.93126 c -74.22656,3.49385 -76.5227,3.72759 -113.43017,5.51355 18.56915,63.32614 0.82359,37.85656 -50.01299,133.89084 24.2346,40.85014 74.47008,69.33294 126.59586,79.11739 57.01171,10.70158 116.82112,6.54529 154.33625,-3.15072 z"
id="path6560-9-0-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccsc" />
<path
id="shape0-4-6"
d="m 478.625,137.10933 c -0.76975,0.10858 -1.85782,1.03787 -2.52561,2.00025 -1.16748,1.93797 -3.30588,4.39157 -11.92372,13.94719 -3.23971,3.55101 -5.85796,6.72805 -5.89104,7.14833 -0.0331,0.42028 -0.32494,0.90477 -0.75846,1.03981 -0.34284,0.0576 -2.91476,2.64623 -5.61045,5.73259 -9.62848,10.57559 -15.05758,16.15329 -15.64598,16.10698 -0.33622,-0.0265 -4.23475,-4.22389 -8.73294,-9.39887 -9.29954,-10.7967 -15.82173,-16.04641 -29.56891,-24.06381 -26.12496,-15.16581 -50.52484,-22.16095 -87.42588,-25.06537 -13.44913,-1.05856 -18.26024,-1.18349 -32.08062,-0.74888 -7.2044,0.19415 -29.25501,3.11037 -30.51119,4.02643 -2.41509,1.67063 -1.6154,6.5545 2.96176,18.24819 2.53647,6.4584 4.55732,11.94585 4.54409,12.11397 -0.0198,0.25217 2.21348,6.26381 4.87174,13.32384 2.74234,7.06665 5.02002,13.58925 5.02469,14.60455 0.0556,1.44221 -0.81801,1.79634 -6.36773,2.45904 -12.7296,1.61998 -21.25168,4.58608 -36.10764,12.80492 -25.27733,13.82651 -45.39079,32.96497 -65.26965,62.01751 -13.57025,19.82262 -29.17078,50.39597 -28.91046,56.7598 l 0.0669,2.37345 13.79665,2.01627 c 27.75478,4.12982 37.5875,6.00325 37.49488,7.18004 -0.0463,0.58841 -1.00131,3.05057 -2.03374,5.42207 -2.03841,4.40676 -3.769,10.27557 -5.27583,17.59982 -1.0628,4.90643 -2.37938,21.63379 -1.95637,23.78153 0.10857,0.76974 0.28405,3.91293 0.38212,6.96546 0.30772,19.73084 9.98934,55.76138 20.47458,76.20871 10.06013,19.39893 32.43551,52.11553 38.23621,55.78606 l 2.26098,1.36203 5.3139,-6.26339 c 2.98094,-3.4868 6.90167,-8.1683 8.68401,-10.39619 1.78233,-2.22789 6.81099,-8.09084 11.17848,-13.07549 l 7.82164,-9.11082 5.51154,6.26967 c 6.82144,7.89517 8.62904,9.64442 16.53388,15.59501 14.85394,11.1493 32.00972,18.84294 55.95818,25.12592 10.85269,2.88408 16.63939,3.50869 17.87107,1.8295 1.41302,-1.83408 1.01258,-2.11933 -4.49549,-3.06032 -8.4236,-1.50879 -12.58014,-2.42799 -15.96694,-3.45576 -1.81617,-0.56583 -4.6278,-1.37918 -6.20503,-1.75705 -1.57724,-0.37788 -3.56153,-0.95695 -4.2982,-1.26866 -0.73666,-0.31172 -2.13917,-0.76041 -3.13461,-1.00792 -2.56608,-0.70944 -5.11231,-1.67105 -6.97946,-2.66379 -0.89817,-0.409 -3.67671,-1.64263 -6.13888,-2.59763 -6.90201,-2.57311 -23.27092,-12.74215 -29.2047,-17.94554 -10.82776,-9.64832 -17.26002,-18.18949 -21.28383,-28.31722 -6.27034,-15.97127 -5.00478,-33.12511 3.35351,-45.83053 7.20406,-10.93556 22.6714,-24.773 34.29622,-30.62426 l 6.16186,-3.06727 8.47535,5.1497 c 12.02829,7.29007 21.92328,10.52164 35.54053,11.59343 8.32827,0.57094 14.01964,0.25768 21.5046,-1.35221 5.33063,-1.10284 4.91696,-1.21998 4.76479,0.71334 -0.28448,3.61444 2.46948,22.35374 3.78868,26.00986 0.84329,2.18081 1.43441,4.34177 1.40133,4.76206 -0.0331,0.42029 1.56477,3.76001 3.56966,7.30092 3.92575,7.07522 10.88225,15.40349 15.9132,19.18257 5.36057,3.88962 14.95045,7.77381 21.30571,8.6969 7.94572,1.13286 9.02524,1.38698 9.33305,2.84904 0.11519,0.68567 3.84907,10.19855 8.22037,21.28399 9.6898,24.10613 11.1818,28.79077 9.66682,29.77103 -0.62148,0.37398 -3.73354,1.22855 -7.09116,1.9792 -5.59603,1.25112 -7.73715,1.59006 -13.27363,2.08465 -21.55754,2.02466 -29.46748,2.58618 -34.01979,2.39702 -10.46276,-0.31604 -28.63233,-1.57698 -29.01953,-2.03034 -1.00674,-1.17875 -17.32435,-2.18574 -17.44343,-0.67271 -0.0992,1.26086 13.21487,3.89216 15.30969,4.14161 19.89506,1.90422 36.41654,2.61255 46.0407,1.76308 17.87692,-1.46859 28.57593,-3.07924 42.45314,-6.38504 4.21804,-0.93666 4.15383,-1.19546 0.0791,-11.75009 -1.68657,-4.36164 -5.0531,-13.16897 -7.58957,-19.62737 -4.77641,-12.38599 -8.88893,-23.53563 -8.84923,-24.03998 0.0132,-0.16811 0.69891,-0.2833 1.5395,-0.21714 1.93331,0.15217 16.59155,-2.33095 22.03269,-3.76339 15.88992,-4.16231 37.2856,-17.02526 57.35741,-34.56002 12.80476,-11.17136 22.52391,-21.82439 32.65595,-35.57429 12.1222,-16.46891 17.93309,-25.82257 24.28062,-38.77084 3.03115,-6.27391 5.45015,-10.14325 6.31055,-10.32926 1.02854,-0.17278 1.44416,-1.155 1.57182,-3.85144 0.21756,-5.98789 1.60683,-5.37108 -18.39485,-9.14441 -6.74908,-1.29241 -13.16193,-2.55835 -14.15737,-2.80586 -2.07497,-0.50163 -7.74454,-1.53992 -15.08201,-2.87862 -2.4178,-0.44405 -5.74702,-1.12897 -7.24019,-1.50023 -1.57724,-0.37788 -4.57021,-1.03633 -6.65841,-1.36985 -5.59213,-0.94762 -6.97478,-1.64849 -6.26067,-3.19926 6.75382,-15.96108 9.89396,-28.99265 10.41238,-44.17584 0.98664,-27.57929 -2.8503,-51.90138 -12.81095,-80.08857 -7.03891,-20.17607 -10.44046,-27.46375 -24.01674,-51.62206 -3.93236,-6.99116 -7.46352,-10.48304 -10.1156,-10.09975 z m -164.58687,-7.54136 c 41.65261,3.78587 84.45861,20.85666 106.67215,42.73456 4.706,4.68387 12.61432,15.96312 14.82975,21.12758 4.12109,9.96624 5.41417,24.69998 3.0761,33.98866 -1.73254,6.96817 -6.76901,17.22856 -11.08552,22.64011 -3.56466,4.45579 -12.93707,12.8525 -17.84469,16.10308 -3.2047,2.03136 -3.70242,1.90761 -10.90367,-3.31097 -4.96013,-3.60436 -12.20304,-7.21923 -16.84407,-8.43031 -1.32506,-0.35802 -3.80708,-1.06084 -5.45514,-1.61344 -4.60796,-1.63136 -18.1855,-3.20749 -24.22634,-2.75261 -3.06574,0.26618 -9.23694,1.30285 -13.88187,2.2905 -8.35202,1.87996 -11.42439,2.23019 -10.56864,1.02887 0.47984,-0.72343 -1.56239,-12.38675 -3.70774,-20.59049 -2.98671,-11.48393 -5.46092,-16.58419 -12.424,-24.82881 -5.56253,-6.69659 -7.77719,-8.64702 -13.52029,-11.9747 -8.41114,-4.89092 -15.08082,-7.19202 -22.05756,-7.74115 l -5.2956,-0.41681 -5.34301,-13.78382 c -13.56338,-35.06782 -15.65506,-40.73001 -15.56243,-41.90681 0.0794,-1.00868 11.74271,-3.05091 20.57727,-3.53964 7.90331,-0.47746 30.596,-0.8058 31.40349,-0.31935 0.24556,0.10388 5.69604,0.70205 12.16181,1.29555 z m 167.70784,16.2448 c 2.32323,2.72019 10.76973,16.83287 14.43007,24.05634 7.17242,14.18156 12.96489,29.7769 17.24239,46.35252 3.77045,14.42124 4.52577,18.79417 6.2438,34.57628 3.0236,27.13372 -0.70654,51.95973 -10.76429,71.21304 -0.69426,1.2986 -1.31108,2.68788 -1.33093,2.94006 -0.38448,1.66128 -6.97444,9.09292 -11.88402,13.44284 -5.99103,5.19517 -16.53438,10.20119 -23.54615,11.17171 -12.91095,1.77486 -30.57226,-1.6451 -38.06343,-7.47853 -1.67918,-1.23169 -1.78776,-2.00142 -1.29818,-8.22165 0.46974,-5.96805 0.39153,-9.27274 -0.62139,-17.89483 -1.39428,-12.37352 -8.19544,-28.04824 -16.40419,-37.65959 -6.89227,-8.0699 -7.17284,-6.65417 2.43188,-14.77887 13.31571,-11.21571 20.31662,-20.64486 24.1008,-32.18792 1.56714,-4.86673 2.71051,-15.09524 2.26029,-20.12076 -0.53428,-5.03213 -2.81934,-14.68471 -4.40396,-18.19254 -1.59123,-3.42378 -1.56477,-3.76001 -0.11204,-6.09843 1.74458,-2.82291 15.06147,-18.35201 26.54973,-31.0648 4.16628,-4.57759 8.3392,-9.23923 9.20157,-10.52461 2.0742,-2.71239 3.33505,-2.61315 5.96805,0.46974 z m -194.51924,49.30715 c 10.99239,4.33287 21.7645,12.53901 26.63278,20.53418 3.83041,6.13736 8.68502,21.82802 9.71584,31.2973 1.17052,10.91809 1.59938,9.76776 -4.12896,12.7 -2.90621,1.46281 -8.18976,5.19126 -11.89412,8.19824 -13.0437,10.9834 -22.17563,25.9961 -26.03378,42.77715 -0.91257,4.07249 -1.84306,7.29778 -2.01118,7.28455 -0.42028,-0.0331 -10.09226,-5.02323 -12.84436,-6.5931 -4.1215,-2.43883 -16.90555,-6.57442 -25.15443,-8.15404 -9.58717,-1.76952 -9.67123,-1.77613 -17.51695,-0.95583 -15.01219,1.60948 -28.54113,9.08699 -37.75789,20.87907 l -2.5408,3.2677 -7.19582,-0.98925 c -4.02151,-0.48568 -11.96062,-1.7026 -17.72748,-2.57939 -5.76685,-0.87679 -13.70596,-2.09371 -17.72085,-2.66344 -7.85506,-1.21031 -8.08739,-1.48233 -6.1595,-5.55947 0.51291,-1.14372 1.24686,-2.94666 1.49436,-3.94212 1.43211,-5.30026 12.96906,-27.22821 20.10229,-38.33851 9.06577,-14.17213 18.64522,-26.27398 28.47955,-36.24131 11.67427,-11.85238 14.76377,-14.56944 22.84495,-20.53045 20.46818,-15.05081 41.94014,-23.51013 60.21555,-23.59411 8.29053,-0.0241 12.71908,0.6628 19.2008,3.20283 z m 89.47617,61.34146 c 6.01707,1.996 11.99445,4.49634 14.73992,6.15024 4.2764,2.62019 10.03078,6.87911 9.99109,7.38345 -0.0199,0.25218 -4.31922,3.29689 -9.57632,6.68912 -5.33453,3.30155 -12.4183,8.41071 -15.9347,11.17874 -5.23258,4.15536 -6.65026,4.97412 -8.38238,4.41491 -4.13008,-1.25543 -13.06659,-1.6205 -17.96371,-0.6527 -5.66685,1.07637 -7.23942,1.7138 -12.46342,4.68574 l -3.54093,2.0049 -1.07636,-5.66685 c -1.83832,-9.95572 -3.04192,-20.45352 -3.11427,-27.05628 l -0.0922,-6.3506 5.13137,-1.79514 c 8.87816,-3.19179 18.32758,-3.97044 30.15317,-2.70137 5.7867,0.62463 11.22394,1.3909 12.12873,1.71584 z m -51.90648,9.3624 c 0.44285,1.89557 0.93278,6.41675 1.32736,10.00008 0.74091,8.8544 2.94463,20.61501 4.19497,22.99702 0.87637,1.76054 0.66855,2.25164 -2.15749,5.9198 -4.87379,6.0443 -6.82346,11.47297 -7.60882,20.37641 -0.68806,8.74193 -0.32537,8.43217 -7.36437,6.5249 -2.23646,-0.59892 -5.72054,-1.46519 -7.7955,-1.96682 -4.49277,-0.94566 -16.11988,-4.73646 -19.12413,-6.32616 -2.11932,-1.01258 -2.26097,-1.36205 -1.89709,-5.98519 1.14457,-14.54186 10.03485,-31.8572 22.36833,-43.48855 4.93605,-4.68615 15.2245,-11.82668 16.82159,-11.70098 0.33623,0.0265 0.88298,1.67648 1.23515,3.64949 z m 82.82344,9.39454 c 5.24343,4.30327 13.09882,16.25499 16.47196,24.97826 3.49495,9.3249 5.45311,20.98161 4.79813,29.30326 -0.39034,4.95937 -0.78807,6.78877 -1.42745,6.31556 -0.48449,-0.29187 -1.16357,-0.26073 -1.53949,0.21714 -0.38253,0.56194 -1.79166,0.1973 -4.22074,-1.17799 -5.27185,-2.86769 -15.95914,-7.85318 -21.71082,-9.99744 -6.89539,-2.65717 -8.17414,-3.6036 -8.55083,-6.33974 -0.68255,-5.29753 -5.85397,-13.73947 -11.71031,-18.85218 l -5.61079,-5.00882 2.46803,-2.34308 c 4.46282,-4.04679 27.00614,-18.59596 28.78458,-18.62512 0.25216,0.0198 1.29859,0.69424 2.24773,1.53015 z m -40.70864,21.83091 c 8.49248,2.78288 15.62562,9.94138 19.23109,18.93668 2.11813,5.32596 2.27768,6.52261 1.73517,13.41529 -0.86473,9.91211 -3.4935,15.37191 -10.13248,21.27729 -11.2633,9.85486 -26.41071,11.03082 -38.80637,3.03522 -5.16132,-3.19731 -10.11094,-9.08444 -12.39057,-14.50769 -2.13799,-5.07378 -2.61154,-15.17583 -1.02454,-20.29474 5.74903,-18.23919 23.84082,-27.81033 41.3877,-21.86205 z m -123.7644,12.16437 c 11.27298,2.91715 19.15722,5.90588 27.33603,10.52477 l 8.66992,4.8267 0.28873,4.92825 c 0.85491,13.85347 3.83032,24.40614 9.77419,34.85417 1.9983,3.62496 4.22229,7.60601 4.88618,8.84234 0.66389,1.23635 2.67074,3.67792 4.5624,5.43378 1.89167,1.75586 3.43388,3.65339 3.39419,4.15773 -0.0331,0.42029 -1.37334,1.32973 -2.86185,1.97377 -4.10285,1.62236 -18.56423,13.42453 -25.49042,20.82969 -11.72057,12.44079 -17.06875,23.43785 -18.16035,37.30684 -0.84024,10.67526 0.64395,19.75732 4.60084,27.5116 l 2.6357,5.19754 -2.46997,3.44244 c -1.41303,1.83407 -4.60176,5.81199 -7.21338,8.90496 -2.52096,3.01553 -7.10287,8.57535 -10.01297,12.23688 -2.91011,3.66153 -6.811,8.09085 -8.54702,9.73035 l -3.20664,3.13072 -4.95622,-5.80308 c -4.26587,-4.90296 -10.09186,-12.55062 -14.71652,-19.34254 -2.34775,-3.48331 -7.84216,-12.11982 -8.57688,-13.53089 -0.44479,-0.79621 -2.28803,-4.23983 -4.13804,-7.5994 -8.12818,-14.93339 -10.47863,-20.53137 -16.00183,-38.47328 -4.50711,-14.73298 -5.86289,-23.29746 -7.84667,-49.67271 -0.2973,-3.74483 1.08545,-21.31275 1.90076,-25.22374 3.39621,-15.21043 9.72196,-26.80717 18.97723,-34.79021 13.24487,-11.39045 28.11075,-14.36469 47.17261,-9.39668 z m 281.04246,21.61292 c 1.07951,0.25411 5.57228,1.19977 10.07166,2.06138 4.41534,0.85499 8.99877,1.72321 10.07166,2.0614 1.16357,0.26073 5.65634,1.20639 9.98762,2.05477 12.90976,2.5385 23.26472,5.29882 23.19856,6.13939 -0.2514,3.19417 -15.0234,29.68842 -22.9396,41.0754 -6.39266,9.22329 -17.08004,22.5066 -27.92034,34.50919 -9.91374,10.97603 -41.78043,35.44817 -45.64706,35.14384 -0.5884,-0.0463 -1.03515,0.25684 -1.07484,0.76118 -0.0331,0.42029 -0.40239,0.8141 -0.82267,0.78102 -0.50434,-0.0397 -3.13189,1.10633 -5.94741,2.4917 -5.2816,2.62909 -23.16438,7.39574 -29.19198,7.68252 -3.48604,0.23308 -9.43619,0.61054 -13.181,0.90783 -1.10599,0.0821 -4.35113,-0.59619 -7.15614,-1.49359 -2.80502,-0.89741 -6.11437,-1.8345 -7.27132,-2.1793 -6.05016,-1.57571 -15.85328,-9.19809 -22.40272,-17.32517 -5.5493,-6.86469 -11.94222,-26.65161 -12.15503,-37.9172 -0.0669,-2.37345 -0.21129,-4.83756 -0.41053,-5.52986 -0.26346,-0.95111 1.08341,-1.9446 4.58463,-3.44516 10.76905,-4.64994 22.27597,-13.30155 29.40529,-22.21312 4.88702,-6.21242 10.8415,-16.31598 12.91493,-22.24238 0.99469,-2.96651 2.2217,-5.66101 2.59101,-6.05482 0.45336,-0.38721 2.19872,0.004 4.24059,0.92581 10.18958,4.86173 26.60987,7.93028 36.50605,6.84849 13.73829,-1.5406 29.2885,-11.05805 37.41252,-22.93614 l 3.06032,-4.49547 5.08779,0.90791 c 2.83808,0.47712 5.99917,1.14881 6.98801,1.48038 z m -110.41679,4.84172 c 3.90241,1.99871 8.53489,4.39318 10.24715,5.20458 3.81837,1.9921 3.75686,3.84797 -0.50985,13.99979 -3.83787,9.00149 -8.88366,17.23127 -12.99042,21.05234 -1.72941,1.55544 -3.75729,3.67943 -4.51576,4.71924 -3.10468,3.98453 -19.80718,14.17248 -22.83323,13.93431 -0.42029,-0.0331 -0.76118,-1.07485 -0.65532,-2.41976 0.32418,-4.11879 -2.25581,-26.14294 -3.74585,-31.92693 -0.78374,-2.93732 -0.67322,-3.26694 1.43872,-5.38431 6.41328,-6.26144 11.5914,-16.17238 12.15376,-23.31723 0.15878,-2.01737 0.46584,-3.76933 0.73784,-4.00166 0.80945,-0.61291 12.70662,4.04492 20.67296,8.13963 z m -128.04927,-7.54121 c 0.61952,0.72538 2.4933,1.63407 4.23864,2.02517 2.99297,0.65846 16.25024,4.15468 25.93276,6.86206 5.71391,1.54924 5.72053,1.46518 8.25897,6.82423 2.39014,5.09364 5.26208,8.36448 11.0873,12.79813 2.22789,1.78234 4.11956,3.5382 4.0931,3.87443 -0.15217,1.93331 -29.20216,20.70671 -31.80794,20.50161 -1.51302,-0.11909 -9.28358,-8.85017 -12.90152,-14.46333 -6.24237,-9.87946 -10.64751,-23.75862 -11.04168,-34.86935 -0.18482,-5.17379 0.20434,-5.81977 2.14037,-3.55295 z m 89.07156,34.24472 c 2.15392,7.02034 3.51784,21.9288 2.82783,31.77009 -0.14091,2.86456 -0.3156,2.93539 -5.41392,4.31023 -2.93734,0.78375 -9.68369,1.60601 -15.10304,1.68693 -8.47849,0.26302 -10.90953,-0.0129 -17.8777,-1.74545 -8.7069,-2.2077 -19.41403,-6.94102 -24.35432,-10.79755 -2.86726,-2.25555 -2.93809,-2.43027 -1.42973,-3.32649 13.29663,-7.74953 28.13663,-17.91493 30.11355,-20.46582 0.47982,-0.72343 2.94394,-0.8678 7.23085,-0.53038 6.89268,0.54251 15.76694,-0.45057 19.63085,-2.26089 3.24243,-1.43635 3.57203,-1.32583 4.37563,1.35933 z"
inkscape:connector-curvature="0"
style="fill:url(#radialGradient5665-7-4);fill-opacity:1;opacity:0.459"
sodipodi:nodetypes="cccccccccscccccccccccccccccccccsccccccccsccccccccccccsccccccccsccscccccccsccccccccccccccccccccccccccccccccsccscccsccccccccscscccccccscccccccccccccsccccccccccccccccccccccccccccccccscccccscccccccccccccccccccccccsscccsccccsccccccccccccccccsccccscccsccccccccccccccccccccsccsccscccccsccsccccccccscc" />
<path
id="shape0"
d="m 537.2729,45.50869 c -1.14115,0.160955 -2.75422,1.538632 -3.74422,2.96535 -1.73077,2.873052 -4.90096,6.510516 -17.67691,20.67672 -4.80288,5.264369 -8.68442,9.974323 -8.73346,10.597396 -0.049,0.623073 -0.48174,1.341336 -1.12443,1.541524 -0.50826,0.08538 -4.32114,3.923034 -8.31749,8.498566 -14.27421,15.678304 -22.32286,23.947254 -23.19516,23.878594 -0.49846,-0.0392 -6.27801,-6.26191 -12.94659,-13.933819 C 447.74806,83.726899 438.07893,75.944208 417.69872,64.058417 378.96847,41.575103 342.79566,31.204806 288.08985,26.899004 c -19.93834,-1.569313 -27.0708,-1.754537 -47.55952,-1.110212 -10.68052,0.287834 -43.37054,4.61112 -45.23284,5.96918 -3.58038,2.4767 -2.39484,9.717047 4.39081,27.052936 3.76032,9.574576 6.75623,17.709734 6.73661,17.958963 -0.0294,0.373844 3.28148,9.286114 7.22237,19.752606 4.0655,10.476303 7.44217,20.146073 7.44908,21.651253 0.0825,2.13806 -1.21269,2.66305 -9.44015,3.64551 -18.87163,2.40163 -31.50561,6.79885 -53.52958,18.9833 -37.47366,20.4978 -67.291888,48.87057 -96.762295,91.94095 -20.117901,29.38704 -43.245676,74.71205 -42.859761,84.14642 l 0.09921,3.51864 20.453531,2.98911 c 41.146459,6.12246 55.723476,8.89982 55.586161,10.64442 -0.06866,0.87231 -1.484435,4.52247 -3.015019,8.03821 -3.021935,6.53303 -5.587537,15.23354 -7.82142,26.09173 -1.575601,7.2738 -3.527434,32.07211 -2.900337,35.25613 0.160956,1.14115 0.421125,5.80093 0.566488,10.32629 0.456209,29.25098 14.809202,82.66626 30.353592,112.97943 14.91415,28.75891 48.08565,77.26128 56.68519,82.70282 l 3.35189,2.01924 7.87788,-9.28549 c 4.41923,-5.16918 10.23173,-12.10949 12.87404,-15.41235 2.6423,-3.30285 10.0973,-11.99469 16.5721,-19.38442 l 11.59557,-13.50679 8.17087,9.29479 c 10.11278,11.70459 12.79256,14.29786 24.51148,23.11959 22.02095,16.52885 47.4544,27.93467 82.958,37.2492 16.08911,4.27562 28.47294,5.51871 30.29891,3.02931 2.0948,-2.71901 -2.30389,-3.45899 -10.4696,-4.85402 -12.48799,-2.23677 -18.65007,-3.59949 -23.67099,-5.12315 -2.69248,-0.83886 -6.86072,-2.04464 -9.19897,-2.60484 -2.33825,-0.5602 -5.27996,-1.41867 -6.37207,-1.88079 -1.09211,-0.46211 -3.17132,-1.12731 -4.64708,-1.49424 -3.80421,-1.05174 -7.57898,-2.47733 -10.34704,-3.94906 -1.33153,-0.60635 -5.45072,-2.4352 -9.10089,-3.85098 -10.23223,-3.81464 -34.49913,-18.89024 -43.29597,-26.60427 -16.05214,-14.30365 -25.58799,-26.96592 -31.55327,-41.98028 -9.2958,-23.67741 -7.41959,-49.10798 4.97158,-67.94377 10.68001,-16.21197 33.61035,-36.72597 50.84414,-45.40046 l 9.13496,-4.54724 12.5647,7.63444 c 17.83196,10.80752 32.50128,15.59832 52.68884,17.18725 12.34666,0.8464 20.78411,0.38202 31.88059,-2.00465 7.90266,-1.63495 7.28939,-1.80861 7.0638,1.05753 -0.42175,5.35843 3.66098,33.13944 5.61671,38.5596 1.25017,3.23307 2.1265,6.43671 2.07746,7.05978 -0.049,0.62307 2.31977,5.57421 5.29203,10.82361 5.81992,10.48901 16.13293,22.83567 23.59132,28.43817 7.94704,5.76635 22.16405,11.52465 31.58572,12.89315 11.77953,1.67946 13.37991,2.0562 13.83624,4.22369 0.17077,1.01653 5.70623,15.11936 12.18671,31.55352 14.36513,35.73736 16.57701,42.68233 14.33105,44.13558 -0.92135,0.55441 -5.53498,1.82131 -10.51265,2.93416 -8.29611,1.85476 -11.47032,2.35724 -19.67816,3.09047 -31.95906,3.00157 -43.68552,3.83401 -50.43434,3.55359 -15.51106,-0.46853 -42.44743,-2.33787 -43.02146,-3.00998 -1.49248,-1.7475 -15.46419,-1.18475 -15.64074,1.05833 -0.14712,1.86922 9.37192,3.71449 12.47747,4.08431 29.49442,2.82301 53.98754,3.87311 68.25535,2.61376 26.50255,-2.17717 42.36381,-4.56497 62.9368,-9.46581 6.25324,-1.38861 6.15805,-1.77226 0.11719,-17.41951 -2.50034,-6.46612 -7.49122,-19.52299 -11.25153,-29.09757 -7.08103,-18.36223 -13.17784,-34.89158 -13.11899,-35.63927 0.0196,-0.24923 1.03615,-0.41999 2.2823,-0.32191 2.86613,0.22559 24.59698,-3.45564 32.66348,-5.57924 23.55681,-6.17063 55.2759,-25.23994 85.03238,-51.23523 18.98303,-16.56155 33.39167,-32.35466 48.41245,-52.73889 17.97116,-24.41516 26.58579,-38.28196 35.99602,-57.47776 4.49367,-9.30108 8.07982,-15.03738 9.3554,-15.31314 1.52479,-0.25614 2.14095,-1.71229 2.3302,-5.70976 0.32254,-8.87706 2.38214,-7.96264 -27.27035,-13.55659 -10.00551,-1.91599 -19.51256,-3.79275 -20.98832,-4.15968 -3.07613,-0.74367 -11.48127,-2.28293 -22.35908,-4.26758 -3.5844,-0.65828 -8.51994,-1.67368 -10.73358,-2.22407 -2.33825,-0.5602 -6.77534,-1.53637 -9.87109,-2.03081 -8.29033,-1.40483 -10.34012,-2.44388 -9.28146,-4.7429 10.01255,-23.66231 14.6678,-42.9816 15.43636,-65.49069 1.46268,-40.88629 -4.22558,-76.9438 -18.99222,-118.73131 C 577.43892,107.10024 572.39612,96.296242 552.26928,60.481555 546.43956,50.117166 541.20461,44.940442 537.2729,45.50869 Z M 293.27286,34.328599 c 61.74999,5.612557 122.96775,29.574718 155.89932,62.008716 6.97666,6.943835 20.94289,25.010615 24.22726,32.666935 6.10951,14.77494 8.02651,36.6177 4.56031,50.38818 -2.56849,10.33031 -10.03505,25.54134 -16.43428,33.56396 -5.28462,6.6057 -19.17921,19.05383 -26.45476,23.87281 -4.75095,3.0115 -5.48883,2.82804 -16.16469,-4.90851 -7.3534,-5.34346 -18.091,-10.70252 -24.97134,-12.49792 -1.96441,-0.53078 -5.64399,-1.57271 -8.08725,-2.39195 -6.83129,-2.41848 -26.96001,-4.75509 -35.91553,-4.08071 -4.54498,0.39459 -13.69378,1.93146 -20.5799,3.39565 -12.38186,2.78704 -16.93664,3.30625 -15.66799,1.5253 0.71135,-1.07249 -2.31625,-18.36336 -5.49675,-30.52542 -4.42778,-17.02492 -8.0958,-24.58604 -18.41857,-36.80871 -8.24644,-9.92767 -11.52968,-12.81921 -20.04384,-17.75249 -12.4695,-7.25078 -22.35731,-10.66215 -32.70033,-11.47623 l -3.81486,4.76323 -11.95687,-25.81568 C 201.14507,48.267708 198.04417,39.873514 198.18148,38.128909 c 0.1177,-1.495375 17.40857,-4.52297 30.50581,-5.247521 11.71666,-0.707827 45.35858,-1.194593 46.55568,-0.473437 0.36404,0.154039 8.44437,1.040801 18.02989,1.920648 z M 541.89974,58.41152 c 3.44419,4.032684 15.96614,24.954732 21.39259,35.66354 10.63311,21.02415 19.22046,44.14425 25.56184,68.71759 5.58968,21.37952 6.70945,27.86237 9.25645,51.25936 4.48248,40.22574 -1.04747,77.0303 -15.95809,105.57334 -1.02923,1.92517 -1.94366,3.98477 -1.97308,4.35862 -0.57001,2.46286 -10.33962,13.48025 -17.61807,19.92903 -8.88171,7.70183 -24.51223,15.12326 -34.90717,16.56205 -19.14048,2.63124 -45.32338,-2.43885 -56.42904,-11.08693 -2.4894,-1.82596 -2.65036,-2.96711 -1.92455,-12.18859 0.69638,-8.84763 0.58044,-13.74684 -0.92122,-26.52907 -2.06702,-18.34375 -12.14974,-41.58155 -24.31921,-55.83036 -10.21777,-11.96363 -10.63374,-9.8648 3.60527,-21.90966 19.74053,-16.62732 30.11938,-30.60603 35.72943,-47.7186 2.32329,-7.21494 4.01835,-22.37869 3.35088,-29.82904 -0.79207,-7.46015 -4.17968,-21.77008 -6.52887,-26.97044 -2.359,-5.07575 -2.31977,-5.57421 -0.16611,-9.04091 2.58635,-4.18497 22.32864,-27.206851 39.35997,-46.053584 6.17654,-6.786277 12.36288,-13.697169 13.64134,-15.602729 3.075,-4.021116 4.94422,-3.873993 8.84764,0.696383 z m -288.37478,73.09786 c 16.29622,6.42349 32.26587,18.58907 39.48308,30.44192 5.67858,9.09863 12.87555,32.36006 14.40374,46.39825 1.7353,16.18607 2.37108,14.4807 -6.1212,18.82775 -4.30845,2.16862 -12.14131,7.69605 -17.63303,12.15388 -19.33727,16.2829 -32.87536,38.53924 -38.59506,63.41714 -1.3529,6.03746 -2.73234,10.81897 -2.98157,10.79935 -0.62307,-0.049 -14.9618,-7.44695 -19.04177,-9.77426 -6.11014,-3.61558 -25.0625,-9.7466 -37.29145,-12.08837 -14.21298,-2.62332 -14.3376,-2.63313 -25.96888,-1.41703 -22.25559,2.38605 -42.31225,13.47147 -55.9761,30.95323 l -3.76673,4.84438 -10.667819,-1.46658 c -5.961885,-0.72002 -17.731615,-2.52411 -26.280981,-3.82395 -8.549367,-1.29984 -20.319096,-3.10392 -26.271173,-3.94855 -11.645127,-1.79428 -11.989546,-2.19755 -9.131458,-8.24192 0.760388,-1.69557 1.84847,-4.36843 2.215398,-5.84419 2.1231,-7.85763 19.226622,-40.36582 29.801635,-56.83683 13.440017,-21.0102 27.641553,-38.95118 42.220958,-53.72776 17.3071,-17.57116 21.88728,-21.59919 33.86764,-30.43639 30.34409,-22.31283 62.17627,-34.85376 89.26957,-34.97825 12.2907,-0.0357 18.85604,0.98258 28.4652,4.74818 z m 132.64841,90.93872 c 8.92032,2.95906 17.78179,6.66581 21.85194,9.11774 6.33976,3.88443 14.87064,10.19828 14.81179,10.94596 -0.0294,0.37385 -6.40325,4.88764 -14.19689,9.91661 -7.90843,4.89455 -18.41014,12.46888 -23.6232,16.57249 -7.75729,6.16031 -9.85901,7.37414 -12.42688,6.54509 -6.12284,-1.86117 -19.37122,-2.40238 -26.63118,-0.96761 -8.40112,1.59572 -10.73245,2.5407 -18.47704,6.9466 l -5.24941,2.97227 -1.59572,-8.40111 c -2.7253,-14.75935 -4.50964,-30.32235 -4.6169,-40.11094 l -0.13669,-9.41475 7.60727,-2.6613 c 13.16187,-4.73183 27.17064,-5.88619 44.70207,-4.00477 8.57879,0.92599 16.6395,2.06199 17.98084,2.54372 z m -76.95134,13.87976 c 0.65652,2.81018 1.38283,9.51283 1.96781,14.82511 1.09839,13.12666 4.36541,30.56176 6.21903,34.0931 1.29921,2.60999 0.99114,3.33806 -3.19848,8.77608 -7.22538,8.96069 -10.11579,17.0087 -11.28007,30.20804 -1.02006,12.95992 -0.48236,12.5007 -10.91767,9.67316 -3.31556,-0.88789 -8.48071,-2.17214 -11.55685,-2.9158 -6.66053,-1.40195 -23.89771,-7.0218 -28.35152,-9.37854 -3.14189,-1.50116 -3.35189,-2.01923 -2.81244,-8.87303 1.69682,-21.55833 14.87667,-47.22831 33.16106,-64.47178 7.31768,-6.94723 22.57033,-17.53306 24.93801,-17.3467 0.49846,0.0392 1.30902,2.48537 1.83112,5.41036 z m 122.78575,13.9274 c 7.77338,6.37961 19.419,24.09802 24.41968,37.03028 5.18126,13.82417 8.08424,31.10524 7.11322,43.44208 -0.57868,7.35226 -1.1683,10.06436 -2.11618,9.36282 -0.71826,-0.43269 -1.72499,-0.38654 -2.2823,0.32191 -0.56711,0.83307 -2.65614,0.29249 -6.25726,-1.74636 -7.81551,-4.25136 -23.65942,-11.64235 -32.18628,-14.82122 -10.22242,-3.93925 -12.11817,-5.34233 -12.67661,-9.39865 -1.01188,-7.85361 -8.67851,-20.36877 -17.36054,-27.94838 l -8.31799,-7.42557 3.65884,-3.47362 c 6.61614,-5.99935 40.03662,-27.5685 42.67314,-27.61175 0.37384,0.0294 1.92518,1.02923 3.33228,2.26846 z m -60.35056,32.36434 c 12.5901,4.12561 23.16499,14.7381 28.51009,28.07362 3.14013,7.89574 3.37666,9.66976 2.57239,19.88816 -1.28198,14.69472 -5.17911,22.78888 -15.0214,31.54359 -16.69786,14.60984 -39.15389,16.35319 -57.53045,4.49971 -7.65167,-4.74 -14.98947,-13.46768 -18.36903,-21.50765 -3.16956,-7.52189 -3.8716,-22.49815 -1.51889,-30.08694 8.52296,-27.03961 35.34402,-41.22883 61.35729,-32.41049 z m -183.48073,18.03367 c 16.71219,4.32466 28.40056,8.75546 40.52565,15.60298 l 12.85316,7.15559 0.42804,7.30611 c 1.2674,20.53777 5.67846,36.18212 14.49026,51.6713 2.96245,5.37402 6.25952,11.27592 7.24374,13.1088 0.98422,1.83288 3.95937,5.45249 6.76377,8.05556 2.80439,2.60308 5.09071,5.41615 5.03186,6.16384 -0.049,0.62307 -2.03596,1.97132 -4.24268,2.92611 -6.08247,2.40515 -27.52146,19.90187 -37.78953,30.88003 -17.37575,18.44347 -25.30443,34.7466 -26.92274,55.30739 -1.24564,15.82606 0.95467,29.29022 6.82074,40.78595 l 3.90744,7.70536 -5.90388,3.75812 c -2.0948,2.71901 -5.92526,10.85841 -9.79699,15.44375 -3.73731,4.47054 -9.18471,11.8161 -13.49894,17.24431 -4.31423,5.42822 -10.0973,11.99469 -12.67095,14.42525 l -4.75384,4.64129 -7.34761,-8.60306 c -3.63359,-6.37178 -13.61588,-18.6063 -20.47195,-28.67531 -3.48053,-5.16403 -12.97129,-17.96764 -14.0605,-20.05956 -0.65942,-1.18038 -3.39201,-6.28553 -6.13467,-11.26609 -12.05002,-22.13877 -14.63771,-31.33464 -22.825862,-57.93352 -6.681783,-21.84163 -9.588576,-33.64163 -12.529533,-72.74295 -0.440741,-5.5517 1.609174,-31.59615 2.817847,-37.39419 5.034881,-22.54945 14.412798,-39.74162 28.133728,-51.57648 19.63554,-16.88635 41.67422,-21.29567 69.93344,-13.93058 z m 416.64546,32.04114 c 1.60038,0.37674 8.26091,1.77868 14.93125,3.05601 6.54572,1.26753 13.34068,2.55467 14.93124,3.05602 1.72499,0.38654 8.38552,1.78849 14.80663,3.0462 19.13872,3.76333 34.48995,7.8555 34.39187,9.10164 -0.37271,4.73536 -22.27218,44.0131 -34.00796,60.89429 -9.47712,13.67353 -25.32116,33.36604 -41.39191,51.1599 -14.69711,16.27195 -61.93949,52.5519 -67.67177,52.10072 -0.8723,-0.0687 -1.5346,0.38076 -1.59345,1.12845 -0.049,0.62307 -0.59654,1.20691 -1.21962,1.15787 -0.74768,-0.0588 -4.643,1.64012 -8.81703,3.69394 -7.82997,3.89763 -34.34119,10.9642 -43.2771,11.38935 -5.16805,0.34555 -13.98915,0.90512 -19.54085,1.34586 -1.63961,0.12172 -6.45054,-0.88387 -10.60897,-2.21427 -4.15843,-1.33039 -9.06455,-2.71964 -10.77973,-3.23079 -8.96936,-2.33599 -23.50249,-13.63619 -33.21204,-25.68458 -8.22683,-10.1769 -17.70433,-39.511 -18.01983,-56.21225 -0.0992,-3.51863 -0.31323,-7.17169 -0.60861,-8.19803 -0.39057,-1.40999 1.60616,-2.88286 6.79671,-5.10744 15.96513,-6.89354 33.02413,-19.71954 43.59336,-32.93095 7.245,-9.20991 16.07251,-24.18844 19.14638,-32.97433 1.47463,-4.39785 3.29367,-8.39244 3.84117,-8.97628 0.67212,-0.57403 3.2596,0.006 6.28669,1.37252 15.10603,7.20753 39.44914,11.75665 54.12021,10.15288 20.36701,-2.28393 43.4202,-16.39355 55.46406,-34.00281 l 4.53693,-6.66456 7.54264,1.34599 c 4.20747,0.70732 8.89378,1.70311 10.35973,2.19465 z m -163.69291,7.17786 c 5.78534,2.96309 12.65298,6.51291 15.19142,7.7158 5.66072,2.95327 5.56955,5.7046 -0.75586,20.75468 -5.68965,13.3447 -13.17004,25.54536 -19.2583,31.21011 -2.56384,2.30594 -5.57019,5.45475 -6.69461,6.99627 -4.60269,5.90706 -29.36415,21.01071 -33.85028,20.65761 -0.62307,-0.049 -1.12845,-1.59346 -0.97151,-3.58729 0.4806,-6.10612 -3.34423,-38.7569 -5.55322,-47.33167 -1.16189,-4.35459 -0.99804,-4.84324 2.13291,-7.98225 9.50768,-9.28259 17.18424,-23.97555 18.01794,-34.56779 0.2354,-2.99075 0.6906,-5.58804 1.09387,-5.93246 1.19999,-0.90864 18.83755,5.99659 30.64764,12.06699 z M 251.29599,328.69243 c 0.91845,1.07538 3.69631,2.4225 6.28379,3.00232 4.43709,0.97617 24.09099,6.1593 38.44531,10.173 8.4709,2.29676 8.48071,2.17214 12.24392,10.11692 3.5434,7.55132 7.80105,12.40035 16.43693,18.97323 3.30285,2.64231 6.10724,5.24538 6.06801,5.74384 -0.22559,2.86614 -43.29219,30.6977 -47.15524,30.39364 -2.24307,-0.17654 -13.76294,-13.12037 -19.12652,-21.44188 -9.2543,-14.6463 -15.78494,-35.22217 -16.36928,-51.69381 -0.27401,-7.67015 0.30292,-8.62783 3.17308,-5.26726 z m 132.0486,50.7678 c 3.1932,10.40765 5.2152,32.50945 4.19226,47.09917 -0.20887,4.2467 -0.4679,4.3517 -8.02614,6.38992 -4.35459,1.1619 -14.35608,2.38089 -22.39026,2.50085 -12.56935,0.38994 -16.17337,-0.0191 -26.50368,-2.58761 -12.90798,-3.27292 -28.78132,-10.29007 -36.10529,-16.00738 -4.25073,-3.34384 -4.35573,-3.60288 -2.11958,-4.93152 19.71225,-11.48868 41.71257,-26.55888 44.64334,-30.34057 0.71134,-1.07249 4.3644,-1.28651 10.71975,-0.7863 10.21839,0.80428 23.37448,-0.66796 29.10272,-3.35177 4.80691,-2.12938 5.29556,-1.96554 6.48688,2.01521 z"
inkscape:connector-curvature="0"
style="fill:url(#radialGradient5665);fill-opacity:1;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none"
sodipodi:nodetypes="cccccccccsccccccccccccsccccccccsccccccccsscccccccccccsccccccccsccssccccccscccccccccccccccccccccccccccccccsccscccsccccccccscscccccccscccccccccccccscccccccccccccccccccccccccccccccscccccscccccccccccccccccccccccsscccsccccscccccccccccccccsccccccccsccccccccccccccccccccsccsccsccccssccsccccccccscc" />
<path
id="shape0-4"
d="m 502.58614,98.775447 c -0.92432,0.130371 -2.23089,1.246273 -3.03278,2.401903 -1.40191,2.32714 -3.96973,5.27345 -14.31811,16.74792 -3.89028,4.26409 -7.03429,8.0791 -7.07402,8.58378 -0.0397,0.50468 -0.39019,1.08646 -0.91077,1.24862 -0.41168,0.0692 -3.50007,3.17762 -6.73707,6.88374 -11.56197,12.69927 -18.08128,19.39703 -18.78784,19.34141 -0.40374,-0.0318 -5.08512,-5.07208 -10.4866,-11.28624 -11.16698,-12.96479 -18.99888,-19.26869 -35.50662,-28.89605 -31.37109,-18.211246 -60.67069,-26.611077 -104.98182,-30.098732 -16.14983,-1.271126 -21.92705,-1.421155 -38.5227,-0.899258 -8.6511,0.233142 -35.12968,3.734957 -36.63812,4.834971 -2.90006,2.006101 -1.93979,7.870701 3.55651,21.912589 3.04583,7.75531 5.47248,14.3447 5.45659,14.54657 -0.0238,0.30281 2.65796,7.52165 5.85003,15.9994 3.29302,8.48569 6.02809,16.3181 6.03369,17.53727 0.0668,1.73182 -0.98227,2.15706 -7.64643,2.95285 -15.28582,1.94528 -25.51921,5.50699 -43.35838,15.37626 -30.35326,16.603 -54.50571,39.58464 -78.37642,74.47119 -16.29529,23.80319 -35.028542,60.51597 -34.715955,68.15771 l 0.08036,2.85006 16.567143,2.42115 c 33.328192,4.95912 45.135422,7.20875 45.024192,8.62186 -0.0556,0.70657 -1.20238,3.66316 -2.44213,6.51087 -2.44774,5.29167 -4.52585,12.339 -6.33526,21.13402 -1.27622,5.8917 -2.85719,25.97806 -2.34925,28.55709 0.13038,0.92431 0.34111,4.69869 0.45886,8.36418 0.36952,23.69299 11.99529,66.9588 24.58607,91.51214 12.08029,23.29441 38.94886,62.58081 45.9144,66.98841 l 2.715,1.63555 6.38099,-7.52114 c 3.57953,-4.18698 8.28759,-9.80857 10.42784,-12.48384 2.14023,-2.67527 8.1787,-9.71557 13.42323,-15.70118 l 9.39229,-10.94036 6.61831,7.52869 c 8.19124,9.4806 10.36183,11.58111 19.85404,18.72662 17.83674,13.38819 38.43756,22.62678 67.19509,30.17145 13.03202,3.46322 19.98074,4.21327 21.45976,2.19687 1.69677,-2.20236 1.21591,-2.5449 -5.39823,-3.67485 -10.11513,-1.81177 -15.10635,-2.91555 -19.17324,-4.14971 -2.18088,-0.67946 -5.55712,-1.65613 -7.45107,-2.10989 -1.89397,-0.45375 -4.27672,-1.14911 -5.16131,-1.52341 -0.8846,-0.37432 -2.56874,-0.91311 -3.76409,-1.21032 -3.08136,-0.8519 -6.13889,-2.00661 -8.38099,-3.19871 -1.07853,-0.49113 -4.41503,-1.97249 -7.37162,-3.11925 -8.288,-3.08981 -27.94394,-15.30089 -35.06928,-21.54918 -13.00207,-11.58579 -20.726,-21.8421 -25.55781,-34.00358 -7.5295,-19.17844 -6.00979,-39.77693 4.02693,-55.03372 8.65069,-13.13152 27.22402,-29.74765 41.1832,-36.77389 l 7.39923,-3.68321 10.17727,6.18381 c 14.4437,8.75397 26.32569,12.63447 42.6774,13.92149 10.00066,0.68557 16.83491,0.30943 25.82294,-1.62374 6.40107,-1.3243 5.90432,-1.46496 5.7216,0.85658 -0.34162,4.34026 2.96536,26.84259 4.54948,31.23287 1.01263,2.61874 1.72244,5.21366 1.68272,5.71834 -0.0397,0.50469 1.87899,4.51506 4.28649,8.76701 4.71407,8.49599 13.0675,18.49665 19.10872,23.03462 6.43702,4.67067 17.95263,9.33485 25.58409,10.44331 9.54129,1.36035 10.83759,1.6655 11.20721,3.42115 0.13832,0.82337 4.622,12.24652 9.8711,25.55801 11.63561,28.94688 13.4272,34.57223 11.608,35.74934 -0.74628,0.44908 -4.48327,1.47525 -8.51513,2.37665 -6.71976,1.50234 -9.29084,1.90934 -15.9391,2.50325 -25.88649,2.43124 -35.38481,3.1055 -40.85127,2.87837 -12.56379,-0.3795 -34.38197,-1.89366 -34.84693,-2.43806 -1.20889,-1.41545 -14.11138,-1.27759 -14.25439,0.5393 -0.11916,1.51405 9.1767,3.32665 11.69217,3.62619 23.89018,2.28661 43.72934,3.13718 55.28611,2.11711 21.46678,-1.76348 34.31424,-3.69757 50.97813,-7.66719 5.06506,-1.12477 4.98795,-1.43553 0.0949,-14.10963 -2.02525,-5.23749 -6.06781,-15.81342 -9.11363,-23.56872 -5.73555,-14.87321 -10.6739,-28.26181 -10.62624,-28.86743 0.0159,-0.20187 0.83927,-0.34019 1.84864,-0.26075 2.32154,0.18273 19.9233,-2.79902 26.45707,-4.51912 19.08077,-4.99813 44.77289,-20.44408 68.87532,-41.49998 15.37607,-13.41468 27.04691,-26.20693 39.21357,-42.71794 14.55645,-19.77603 21.53421,-31.00798 29.15639,-46.55638 3.63983,-7.53378 6.54458,-12.18012 7.57777,-12.40348 1.23508,-0.20748 1.73416,-1.38693 1.88744,-4.62485 0.26126,-7.19032 1.92951,-6.44964 -22.08869,-10.98069 -8.10436,-1.55194 -15.80497,-3.07209 -17.00031,-3.3693 -2.49164,-0.60236 -9.29971,-1.84914 -18.11062,-3.45668 -2.90332,-0.53321 -6.90106,-1.35567 -8.69408,-1.80149 -1.89397,-0.45376 -5.48796,-1.24444 -7.99548,-1.64493 -6.71508,-1.1379 -8.37538,-1.97951 -7.51788,-3.84169 8.11005,-19.16622 11.88076,-34.81465 12.50329,-53.04677 1.18475,-33.11746 -3.42268,-62.32365 -15.3835,-96.1711 -8.4524,-24.2276 -12.53701,-32.97873 -28.83953,-61.98824 -4.72202,-8.39505 -8.96227,-12.588138 -12.14691,-12.127863 z M 304.9487,89.719692 c 50.01684,4.546112 101.41868,25.044878 128.0929,51.316068 5.65102,5.62443 15.14741,19.16866 17.80771,25.37019 4.94864,11.96756 6.50139,29.65996 3.69381,40.81391 -2.08045,8.36743 -8.1283,20.68821 -13.31159,27.18644 -4.28049,5.35055 -15.53496,15.43341 -21.42808,19.33672 -3.84822,2.43929 -4.4459,2.29069 -13.09323,-3.97583 -5.95616,-4.32815 -14.65352,-8.66893 -20.22651,-10.12319 -1.59115,-0.42992 -4.57158,-1.27388 -6.55058,-1.93745 -5.53328,-1.95894 -21.83733,-3.85157 -29.09121,-3.30534 -3.68138,0.31962 -11.09182,1.56447 -16.66949,2.75045 -10.02918,2.25747 -13.71851,2.67802 -12.69091,1.23547 0.57618,-0.8687 -1.87614,-14.87413 -4.45231,-24.72526 -3.58645,-13.79 -6.55752,-19.91444 -14.91885,-29.81466 -6.67953,-8.04132 -9.33892,-10.38343 -16.23529,-14.37933 -10.10017,-5.87306 -18.10919,-8.63624 -26.48692,-9.29564 l -6.359,-0.50051 -6.41594,-16.55174 C 230.32618,101.01022 227.81448,94.211019 227.9257,92.797899 c 0.0953,-1.211234 14.10076,-3.663553 24.70938,-4.250432 9.49036,-0.573332 36.73997,-0.967607 37.7096,-0.38348 0.29487,0.124771 6.83985,0.843038 14.60402,1.555705 z M 506.33382,109.2266 c 2.78976,3.26644 12.93241,20.21307 17.32778,28.88708 8.6127,17.02935 15.56836,35.75638 20.70482,55.66053 4.52758,17.31717 5.43458,22.56822 7.49761,41.51953 3.63077,32.58243 -0.84843,62.39373 -12.92587,85.51329 -0.83366,1.55936 -1.57435,3.22762 -1.59818,3.53043 -0.46169,1.99489 -8.37498,10.91887 -14.27045,16.1423 -7.19409,6.2384 -19.85464,12.24968 -28.27443,13.41509 -15.50359,2.13127 -36.71146,-1.97545 -45.70692,-8.98029 -2.01639,-1.47902 -2.14676,-2.40333 -1.55887,-9.87264 0.56407,-7.16648 0.47015,-11.13479 -0.74618,-21.48826 -1.67426,-14.85824 -9.84115,-33.68061 -19.6983,-45.222 -8.27629,-9.69041 -8.61321,-7.99039 2.92024,-17.7466 15.98961,-13.46793 24.39637,-24.79055 28.94045,-38.65154 1.88184,-5.84403 3.25482,-18.12651 2.71419,-24.16121 -0.64158,-6.04264 -3.38551,-17.63354 -5.28833,-21.84577 -1.91076,-4.11131 -1.87898,-4.51506 -0.13454,-7.32305 2.09491,-3.38977 18.08596,-22.03726 31.88116,-37.3029 5.00292,-5.49681 10.01379,-11.09457 11.04934,-12.63805 2.49071,-3.25706 4.00476,-3.13789 7.16648,0.56406 z m -233.5805,59.20849 c 13.19976,5.20296 26.13502,15.05695 31.98089,24.65764 4.59958,7.36979 10.42904,26.21129 11.66687,37.58209 1.40557,13.11054 1.92055,11.72921 -4.9581,15.25027 -3.4898,1.75656 -9.83434,6.23372 -14.28258,9.84452 -15.66298,13.18896 -26.62869,31.21636 -31.26158,51.3672 -1.09584,4.89028 -2.21317,8.76325 -2.41505,8.74736 -0.50468,-0.0397 -12.11889,-6.03195 -15.42362,-7.91705 -4.94915,-2.92858 -20.30036,-7.89463 -30.20568,-9.79145 -11.51237,-2.12486 -11.61331,-2.1328 -21.03452,-1.14779 -18.02679,1.93269 -34.27247,10.91177 -45.34004,25.0718 l -3.05102,3.92389 -8.64081,-1.18791 c -4.82906,-0.58322 -14.36242,-2.0445 -21.28731,-3.09735 -6.92489,-1.05286 -16.45825,-2.51414 -21.279371,-3.19829 -9.432429,-1.45335 -9.711404,-1.77999 -7.396385,-6.67587 0.615907,-1.37339 1.497242,-3.53838 1.79445,-4.73373 1.719689,-6.3646 15.573356,-32.69589 24.139006,-46.03723 10.88627,-17.01803 22.38936,-31.55004 34.19852,-43.51891 14.01857,-14.23245 17.72848,-17.49512 27.43242,-24.65316 24.5784,-18.07315 50.36213,-28.23117 72.30741,-28.33201 9.95533,-0.0289 15.27319,0.79588 23.0565,3.84598 z m 107.44381,73.65939 c 7.22536,2.39682 14.40305,5.39925 17.69984,7.38527 5.13513,3.14636 12.04505,8.2605 11.99738,8.86612 -0.0238,0.30282 -5.18656,3.95893 -11.49932,8.03234 -6.40575,3.96454 -14.91202,10.09967 -19.13455,13.42355 -6.28332,4.98979 -7.98569,5.97297 -10.06563,5.30146 -4.95944,-1.50754 -15.69048,-1.94591 -21.57098,-0.78376 -6.80481,1.29251 -8.69317,2.05794 -14.96621,5.62667 l -4.25196,2.4075 -1.29251,-6.8048 c -2.20747,-11.95492 -3.65277,-24.56078 -3.73965,-32.48944 l -0.11071,-7.62585 6.16181,-2.15561 c 10.66097,-3.83274 22.00793,-4.76776 36.20819,-3.24384 6.94873,0.75005 13.47782,1.6702 14.5643,2.06039 z m -62.32977,11.24246 c 0.53177,2.27621 1.12008,7.7053 1.5939,12.00819 0.88969,10.63245 3.53594,24.75469 5.03736,27.61504 1.05234,2.11406 0.8028,2.70379 -2.59074,7.10854 -5.85249,7.25805 -8.19368,13.77686 -9.13674,24.46819 -0.82623,10.49739 -0.39071,10.12543 -8.8432,7.83515 -2.68556,-0.71918 -6.86928,-1.7594 -9.36092,-2.36177 -5.39496,-1.13556 -19.35689,-5.68757 -22.96442,-7.59651 -2.54491,-1.21592 -2.715,-1.63555 -2.27805,-7.18706 1.37441,-17.46202 12.04994,-38.25443 26.8601,-52.22146 5.92725,-5.62718 18.28173,-14.20159 20.19953,-14.05064 0.40374,0.0318 1.06028,2.01312 1.48318,4.38233 z m 99.45515,11.28105 c 6.29636,5.16741 15.72918,19.51915 19.77969,29.99413 4.19675,11.19743 6.54814,25.19491 5.76163,35.18763 -0.46873,5.95525 -0.94632,8.15202 -1.71409,7.58378 -0.58178,-0.35048 -1.39722,-0.3131 -1.84864,0.26074 -0.45935,0.67478 -2.15144,0.23692 -5.06831,-1.41454 -6.33048,-3.44355 -19.16389,-9.43017 -26.07054,-12.00501 -8.28006,-3.19076 -9.8156,-4.32724 -10.26793,-7.61282 -0.81961,-6.36134 -7.0295,-16.49849 -14.06185,-22.63788 l -6.73749,-6.01464 2.96363,-2.81359 c 5.359,-4.85942 32.42923,-22.3302 34.56479,-22.36523 0.30281,0.0238 1.55937,0.83367 2.69911,1.83743 z m -48.88331,26.21477 c 10.19784,3.3417 18.76339,11.9377 23.09287,22.73934 2.54348,6.39546 2.73506,7.8324 2.0836,16.10919 -1.03839,11.90256 -4.19502,18.45875 -12.16717,25.54997 -13.52508,11.83382 -31.71422,13.24592 -46.59905,3.64473 -6.19776,-3.83936 -12.14131,-10.90868 -14.87872,-17.42097 -2.56731,-6.09265 -3.13596,-18.22327 -1.23028,-24.3701 6.90351,-21.9018 28.62828,-33.39492 49.69875,-26.25216 z m -148.61744,14.60708 c 13.53669,3.50294 23.00416,7.09183 32.82534,12.63825 l 10.41093,5.79595 0.34671,5.91787 c 1.02658,16.63538 4.59949,29.30713 11.73695,41.85321 2.39956,4.35289 5.07015,9.13337 5.86735,10.61798 0.79721,1.48461 3.20706,4.41646 5.47858,6.52492 2.27153,2.10847 4.12343,4.38702 4.07577,4.99264 -0.0397,0.50469 -1.64911,1.59676 -3.43653,2.37013 -4.92675,1.94814 -22.2921,16.1203 -30.60913,25.01249 -14.07417,14.93901 -20.49632,28.14438 -21.80713,44.7984 -1.00896,12.81894 0.77328,23.72477 5.52473,33.03618 l 3.16498,6.24126 -2.96596,4.1337 c -1.69678,2.20238 -5.52584,6.97909 -8.6619,10.69316 -3.02718,3.62109 -8.52918,10.29736 -12.02366,14.69416 -3.49449,4.3968 -8.17871,9.71557 -10.26334,11.6843 l -3.85056,3.75939 -5.95149,-6.96838 c -5.1225,-5.88752 -12.11838,-15.07091 -17.67173,-23.22671 -2.81919,-4.18279 -9.41693,-14.55359 -10.29919,-16.24801 -0.53412,-0.9561 -2.74749,-5.09123 -4.96901,-9.12543 -9.76039,-17.93216 -12.58284,-24.65427 -19.21514,-46.19907 -5.41218,-17.6915 -7.04021,-27.97581 -9.42235,-59.64747 -0.357,-4.49682 1.30341,-25.59254 2.28242,-30.28889 4.07821,-18.26483 11.67422,-32.1903 22.78803,-41.77641 15.90456,-13.67776 33.75566,-17.24926 56.64533,-11.28362 z m 337.47839,25.95299 c 1.29629,0.30514 6.69125,1.44071 12.09415,2.47534 5.30196,1.02667 10.80581,2.06924 12.09414,2.47533 1.39723,0.31309 6.79219,1.44865 11.99322,2.4674 15.50216,3.04825 27.93649,6.36286 27.85705,7.37223 -0.30189,3.83559 -18.04023,35.65014 -27.54609,49.32372 -7.67637,11.07542 -20.50987,27.02614 -33.527,41.43897 -11.9045,13.18011 -50.17034,42.56649 -54.81342,42.20104 -0.70655,-0.0556 -1.24301,0.30841 -1.29068,0.91402 -0.0397,0.50469 -0.48319,0.97759 -0.98787,0.93787 -0.60562,-0.0477 -3.76079,1.32848 -7.1417,2.99205 -6.3422,3.15704 -27.816,8.88088 -35.054,9.22525 -4.18606,0.27989 -11.33106,0.73314 -15.82787,1.09013 -1.32808,0.0986 -5.22487,-0.71592 -8.59316,-1.79352 -3.36828,-1.07761 -7.34219,-2.20289 -8.73146,-2.61692 -7.26508,-1.89213 -19.03677,-11.04516 -26.90141,-20.80423 -6.66363,-8.24318 -14.34031,-32.0035 -14.59586,-45.53133 -0.0804,-2.85005 -0.25372,-5.80899 -0.49298,-6.64031 -0.31635,-1.14209 1.30098,-2.33509 5.50528,-4.13697 12.93158,-5.5837 26.74918,-15.97263 35.31015,-26.67373 5.86837,-7.45992 13.01856,-19.59237 15.50836,-26.70885 1.19443,-3.56221 2.66785,-6.79779 3.11131,-7.27069 0.5444,-0.46497 2.64024,0.005 5.09215,1.11173 12.23573,5.83801 31.95338,9.52276 43.8368,8.22373 16.49706,-1.84997 35.16989,-13.27861 44.92529,-27.54193 l 3.67487,-5.39821 6.10946,1.09023 c 3.408,0.57293 7.20387,1.3795 8.39127,1.77765 z m -132.58951,5.81398 c 4.68605,2.40008 10.24877,5.27539 12.30488,6.24971 4.58513,2.39213 4.51128,4.62068 -0.61224,16.81108 -4.60855,10.80907 -10.66759,20.69147 -15.59901,25.27985 -2.07669,1.86779 -4.5118,4.41829 -5.42257,5.66691 -3.72813,4.78466 -23.78465,17.01845 -27.41836,16.73245 -0.50469,-0.0397 -0.91403,-1.29069 -0.78692,-2.90568 0.38928,-4.94588 -2.70878,-31.39267 -4.49804,-38.33814 -0.94113,-3.52717 -0.80841,-3.92298 1.72763,-6.46554 7.70112,-7.5188 13.91905,-19.41994 14.59434,-27.99954 0.19067,-2.42248 0.55938,-4.52625 0.88602,-4.80523 0.97198,-0.73599 15.25822,4.85718 24.82427,9.77413 z m -153.76276,-9.05555 c 0.74394,0.87105 2.99398,1.9622 5.08981,2.43185 3.59399,0.79069 19.51344,4.98897 31.14029,8.24002 6.86133,1.86035 6.86928,1.75941 9.91744,8.1946 2.87012,6.11649 6.31876,10.04415 13.31374,15.36811 2.67528,2.14024 4.94681,4.2487 4.91503,4.65245 -0.18273,2.32154 -35.06622,24.86481 -38.19525,24.61853 -1.81685,-0.143 -11.14783,-10.62737 -15.49228,-17.3677 -7.49589,-11.86334 -12.78563,-28.52958 -13.25894,-41.87144 -0.22194,-6.21274 0.24536,-6.98844 2.57016,-4.26642 z m 106.95797,41.12138 c 2.58645,8.43009 4.22425,26.33231 3.39568,38.14983 -0.16918,3.43978 -0.379,3.52483 -6.50109,5.17576 -3.52717,0.94113 -11.62827,1.9285 -18.13587,2.02567 -10.18104,0.31584 -13.10025,-0.0155 -21.4677,-2.09594 -10.45533,-2.65103 -23.31256,-8.33485 -29.2449,-12.96581 -3.44304,-2.70848 -3.52809,-2.91829 -1.71683,-3.99448 15.96671,-9.30571 33.78673,-21.51241 36.16063,-24.57554 0.57618,-0.86871 3.53511,-1.04206 8.68287,-0.63689 8.27679,0.65146 18.93309,-0.54104 23.57291,-2.71489 3.89354,-1.72478 4.28933,-1.59208 5.2543,1.63229 z"
inkscape:connector-curvature="0"
style="fill:url(#radialGradient5665-7);fill-opacity:1"
sodipodi:nodetypes="cccccccccscccccccccccccccccccccsccccccccsccccccccccccsccccccccsccssccccccsccccccccccccccccccccccccccccccccsccccccsccccccccscscccccccscccccccccccccscccccccccccccccccccccccccccccccscccccscccccccccccccccccccccccsscccsccccscccccccccccccccsccccccccsccccccccccccccccccccsccsccsccccssccsccccccccscc" />
<path
id="shape0-4-6-1-3"
d="m 434.55426,206.34638 c -0.49065,0.0691 -1.18422,0.66156 -1.60989,1.27501 -0.74419,1.23533 -2.10727,2.79932 -7.60052,8.89034 -2.06506,2.26351 -3.73401,4.28864 -3.7551,4.55655 -0.0211,0.26789 -0.20712,0.57671 -0.48347,0.66279 -0.21854,0.0368 -1.85796,1.68679 -3.57626,3.65412 -6.13746,6.74117 -9.59812,10.29655 -9.97316,10.26703 -0.21434,-0.0169 -2.69937,-2.69242 -5.56663,-5.9911 -5.92779,-6.8821 -10.08522,-10.22843 -18.84804,-15.33894 -16.65278,-9.6671 -32.20593,-14.12601 -55.72768,-15.97736 -8.57284,-0.67476 -11.63958,-0.75439 -20.44909,-0.47736 -4.59226,0.12377 -18.64794,1.98265 -19.44866,2.56656 -1.53945,1.06491 -1.02972,4.17801 1.8879,11.63189 1.61682,4.11679 2.90498,7.61464 2.89654,7.72181 -0.0127,0.16072 1.41092,3.99272 3.10537,8.49298 1.74805,4.50448 3.19991,8.66216 3.20289,9.30933 0.0354,0.91931 -0.52143,1.14504 -4.05899,1.56747 -8.11419,1.03261 -13.54639,2.9233 -23.01599,8.1622 -16.11248,8.8134 -28.93336,21.01279 -41.60469,39.53168 -8.65006,12.63549 -18.59426,32.12379 -18.42834,36.18027 l 0.0427,1.51291 8.79436,1.28521 c 17.69167,2.63247 23.95932,3.82664 23.90028,4.57677 -0.0295,0.37506 -0.63827,1.94451 -1.29636,3.45617 -1.29933,2.80898 -2.40247,6.54993 -3.36296,11.2186 -0.67747,3.12752 -1.51669,13.78998 -1.24711,15.15902 0.0691,0.49064 0.18107,2.4942 0.24359,4.43997 0.19615,12.577 6.36749,35.54386 13.05104,48.57753 6.41261,12.36543 20.6753,33.21989 24.37284,35.5596 l 1.44121,0.8682 3.38722,-3.99248 c 1.90014,-2.22258 4.39931,-5.2067 5.53542,-6.62681 1.13612,-1.42013 4.34152,-5.15733 7.12548,-8.33467 l 4.98573,-5.80749 3.51322,3.99645 c 4.34817,5.03261 5.50039,6.14762 10.53914,9.9407 9.46832,7.10686 20.40389,12.01101 35.6693,16.01594 6.91781,1.8384 10.60639,2.23656 11.39151,1.16618 0.90069,-1.16908 0.64545,-1.35092 -2.86555,-1.95073 -5.36943,-0.96174 -8.01893,-1.54766 -10.17777,-2.2028 -1.15768,-0.36067 -2.94988,-0.87912 -3.95526,-1.11999 -1.00538,-0.24087 -2.27022,-0.60999 -2.73979,-0.80866 -0.46956,-0.19872 -1.36356,-0.48471 -1.99809,-0.64249 -1.63569,-0.45223 -3.25873,-1.06518 -4.4489,-1.69799 -0.57252,-0.26068 -2.34364,-1.04704 -3.91308,-1.6558 -4.39954,-1.64015 -14.83354,-8.12218 -18.61589,-11.43896 -6.90192,-6.15012 -11.00202,-11.59449 -13.5669,-18.05019 -3.9969,-10.18052 -3.19018,-21.11485 2.13761,-29.21366 4.59208,-6.97061 14.45139,-15.79097 21.86136,-19.52074 l 3.92775,-1.95516 5.40241,3.28257 c 7.66718,4.64688 13.97451,6.70677 22.65452,7.38995 5.30869,0.36388 8.93652,0.16425 13.70763,-0.86192 3.39789,-0.70297 3.1342,-0.77766 3.0372,0.4547 -0.18134,2.30394 1.57413,14.2489 2.41503,16.57941 0.53754,1.39011 0.91433,2.76756 0.89324,3.03546 -0.0211,0.26791 0.99742,2.39674 2.27539,4.65381 2.5024,4.50994 6.93666,9.81859 10.14352,12.22751 3.41698,2.47934 9.52983,4.95523 13.58086,5.54364 5.06482,0.7221 5.75293,0.88411 5.94914,1.81605 0.0734,0.43706 2.45349,6.50083 5.23989,13.56701 6.17654,15.36591 7.12758,18.35203 6.1619,18.97687 -0.39615,0.23839 -2.37985,0.78311 -4.5201,1.2616 -3.56706,0.7975 -4.93188,1.01356 -8.46099,1.32881 -13.74137,1.29058 -18.78339,1.64851 -21.68516,1.52794 -6.66924,-0.20146 -18.25104,-1.00523 -18.49785,-1.29419 -0.64172,-0.75138 -12.04868,-1.64571 -12.12459,-0.68123 -0.0633,0.80372 9.4292,2.73338 10.76449,2.89239 12.68166,1.2138 23.21291,1.66531 29.34761,1.12383 11.39527,-0.93611 18.2151,-1.96279 27.0608,-4.07 2.68872,-0.59705 2.64778,-0.76202 0.0504,-7.48983 -1.07507,-2.78023 -3.22099,-8.39426 -4.83778,-12.51103 -3.04464,-7.89517 -5.66607,-15.00227 -5.64077,-15.32373 0.008,-0.10709 0.44551,-0.18059 0.98132,-0.13842 1.23235,0.097 10.57591,-1.48582 14.04424,-2.3989 10.12869,-2.65317 23.76689,-10.85236 36.56123,-22.0295 8.1621,-7.12094 14.35735,-13.91146 20.81579,-22.67604 7.72703,-10.49775 11.43105,-16.46001 15.47714,-24.71362 1.93214,-3.99914 3.47408,-6.46558 4.02252,-6.58415 0.65561,-0.11014 0.92055,-0.73622 1.00191,-2.45501 0.13868,-3.81685 1.02425,-3.42368 -11.72539,-5.82889 -4.30203,-0.82383 -8.38977,-1.63078 -9.02429,-1.78854 -1.32265,-0.31975 -4.93658,-0.98159 -9.61369,-1.83492 -1.54116,-0.28305 -3.66329,-0.71963 -4.6151,-0.95628 -1.00538,-0.24088 -2.91318,-0.66058 -4.24425,-0.87318 -3.56457,-0.60404 -4.44591,-1.0508 -3.99073,-2.03929 4.30508,-10.17404 6.30668,-18.48074 6.63714,-28.15891 0.62891,-17.57981 -1.81686,-33.08337 -8.16604,-51.05067 -4.48681,-12.86078 -6.65505,-17.50617 -15.30894,-32.90535 -2.50661,-4.45634 -4.75746,-6.68217 -6.44796,-6.43785 z m -104.91223,-4.80706 c 26.55053,2.41321 53.83625,13.29461 67.99578,27.24019 2.99975,2.98563 8.04072,10.17533 9.45289,13.4673 2.6269,6.35276 3.45114,15.74445 1.9608,21.66532 -1.10437,4.4417 -4.31475,10.98196 -7.06621,14.43143 -2.27223,2.84023 -8.24646,8.19254 -11.37471,10.26455 -2.04277,1.29483 -2.36002,1.21596 -6.9503,-2.11051 -3.16173,-2.29753 -7.77856,-4.60173 -10.73688,-5.37371 -0.84463,-0.22821 -2.42674,-0.67621 -3.47726,-1.02846 -2.93724,-1.03987 -11.59194,-2.04454 -15.44254,-1.75458 -1.95419,0.16967 -5.88788,0.83047 -8.84868,1.46002 -5.3238,1.19834 -7.28222,1.4216 -6.73673,0.65584 0.30584,-0.46113 -0.99592,-7.89566 -2.36343,-13.12495 -1.90381,-7.32018 -3.48094,-10.57121 -7.91941,-15.82657 -3.5457,-4.26859 -4.9574,-5.51184 -8.61821,-7.63302 -5.36148,-3.1176 -9.61293,-4.58439 -14.06008,-4.93442 l -3.37558,-0.26568 -3.40577,-8.78619 c -8.64568,-22.35319 -9.97897,-25.96242 -9.91993,-26.71255 0.0506,-0.64296 7.48513,-1.94474 13.11653,-2.25626 5.03779,-0.30436 19.50273,-0.51365 20.01745,-0.20358 0.15652,0.0663 3.63081,0.44753 7.75227,0.82583 z m 106.90162,10.35488 c 1.48089,1.73392 6.86492,10.72975 9.19812,15.33417 4.57191,9.03972 8.26419,18.98062 10.99078,29.54639 2.40339,9.19249 2.88486,11.97992 3.97997,22.03987 1.92732,17.2958 -0.45036,33.12057 -6.86145,45.39318 -0.44253,0.82776 -0.83573,1.71331 -0.84838,1.87406 -0.24508,1.05894 -4.4457,5.79607 -7.57519,8.56883 -3.81887,3.31155 -10.53948,6.50254 -15.00898,7.12117 -8.22979,1.13134 -19.4876,-1.04863 -24.26268,-4.76702 -1.07035,-0.78513 -1.13957,-1.27576 -0.8275,-5.24071 0.29943,-3.80421 0.24958,-5.91071 -0.3961,-11.40665 -0.88874,-7.88723 -5.22399,-17.87874 -10.45647,-24.00529 -4.39332,-5.14396 -4.57218,-4.24154 1.55015,-9.42045 8.48779,-7.1492 12.95037,-13.15961 15.36251,-20.51747 0.99894,-3.10219 1.72776,-9.62213 1.44078,-12.82552 -0.34057,-3.20763 -1.79713,-9.36045 -2.80721,-11.59643 -1.01429,-2.18242 -0.99742,-2.39675 -0.0714,-3.88732 1.11204,-1.79938 9.6006,-11.69806 16.92353,-19.80155 2.6557,-2.91788 5.31563,-5.88935 5.86534,-6.70868 1.32214,-1.72894 2.12585,-1.66568 3.8042,0.29942 z M 312.5517,243.32393 c 7.00685,2.7619 13.87331,7.99271 16.97648,13.08906 2.44159,3.91213 5.53606,13.9138 6.19313,19.94978 0.74613,6.9595 1.01951,6.22624 -2.63189,8.09532 -1.85252,0.93243 -5.2204,3.30906 -7.58165,5.22579 -8.31442,7.00112 -14.13536,16.57064 -16.59465,27.26734 -0.58171,2.59591 -1.17484,4.65181 -1.28199,4.64338 -0.26789,-0.0211 -6.43309,-3.20195 -8.18735,-4.20262 -2.62715,-1.55459 -10.77606,-4.19074 -16.03414,-5.19763 -6.11113,-1.12793 -6.16469,-1.13215 -11.16579,-0.60926 -9.56919,1.02591 -18.19291,5.7923 -24.06792,13.3089 l -1.61958,2.08291 -4.58681,-0.63058 c -2.56343,-0.30951 -7.62403,-1.08528 -11.29999,-1.64418 -3.67594,-0.55888 -8.73655,-1.33457 -11.29575,-1.69773 -5.00704,-0.77148 -5.15514,-0.94488 -3.92625,-3.54376 0.32695,-0.72903 0.79478,-1.87828 0.95255,-2.51283 0.91287,-3.37853 8.26684,-17.356 12.81377,-24.43802 5.77875,-9.0337 11.88498,-16.74776 18.15364,-23.10121 7.44151,-7.55503 9.41083,-9.28698 14.56201,-13.08668 13.04698,-9.59379 26.73381,-14.986 38.38306,-15.03954 5.28462,-0.0153 8.1075,0.42248 12.23912,2.04156 z m 57.03459,39.10076 c 3.83545,1.2723 7.64559,2.86609 9.39562,3.92033 2.72592,1.67018 6.39391,4.38495 6.36861,4.70643 -0.0127,0.16073 -2.75319,2.10152 -6.10422,4.26382 -3.40037,2.10449 -7.91575,5.36121 -10.15721,7.12563 -3.33539,2.64875 -4.23906,3.17065 -5.34315,2.81421 -2.63263,-0.80027 -8.32901,-1.03297 -11.45058,-0.41607 -3.6122,0.68612 -4.61461,1.09243 -7.94453,2.98682 l -2.25708,1.27799 -0.68611,-3.61221 c -1.17179,-6.34605 -1.939,-13.03764 -1.98511,-17.24644 l -0.0588,-4.04803 3.27088,-1.14427 c 5.65918,-2.03454 11.68249,-2.53089 19.22046,-1.72192 3.68862,0.39807 7.15445,0.88658 7.73119,1.09371 z m -33.08663,5.96786 c 0.28229,1.20826 0.59459,4.09019 0.8461,6.37431 0.47227,5.64405 1.87699,13.14059 2.674,14.65894 0.55861,1.12222 0.42614,1.43527 -1.37525,3.77344 -3.10668,3.85282 -4.34947,7.3132 -4.85007,12.98849 -0.43859,5.57236 -0.20742,5.3749 -4.69425,4.15916 -1.4256,-0.38176 -3.64645,-0.93395 -4.96907,-1.2537 -2.86382,-0.6028 -10.27525,-3.01915 -12.19026,-4.03247 -1.35092,-0.64544 -1.4412,-0.86821 -1.20925,-3.81513 0.72958,-9.26938 6.39649,-20.30667 14.25819,-27.72082 3.14638,-2.98706 9.70452,-7.53864 10.72255,-7.45851 0.21433,0.0169 0.56283,1.06863 0.78731,2.32629 z m 52.79396,5.98833 c 3.34231,2.74303 8.34955,10.36139 10.49968,15.92184 2.22777,5.94395 3.47596,13.37425 3.05846,18.6787 -0.24882,3.16124 -0.50234,4.32736 -0.9099,4.02572 -0.30882,-0.18604 -0.74168,-0.16613 -0.98132,0.13843 -0.24383,0.35818 -1.14204,0.12574 -2.69039,-0.75091 -3.36045,-1.82795 -10.17281,-5.00582 -13.8391,-6.37264 -4.39532,-1.69375 -5.21042,-2.29703 -5.45053,-4.04113 -0.43507,-3.37678 -3.73148,-8.75792 -7.46448,-12.0169 l -3.57648,-3.19276 1.5732,-1.49355 c 2.84472,-2.57953 17.21446,-11.85357 18.34808,-11.87216 0.16075,0.0127 0.82777,0.44252 1.43278,0.97536 z m -25.94883,13.91563 c 5.41334,1.77389 9.96021,6.33691 12.25844,12.07077 1.35017,3.3949 1.45185,4.15768 1.10604,8.55126 -0.55127,6.31826 -2.22684,9.79849 -6.45872,13.56275 -7.17954,6.28175 -16.83492,7.03135 -24.73625,1.93473 -3.28998,-2.03806 -6.445,-5.79069 -7.89808,-9.24761 -1.36282,-3.23416 -1.66469,-9.67349 -0.65308,-12.93642 3.66459,-11.62617 15.19679,-17.72707 26.38165,-13.93548 z m -78.89084,7.75391 c 7.18571,1.85947 12.21133,3.76456 17.42474,6.70878 l 5.52643,3.07667 0.18406,3.14139 c 0.54493,8.83059 2.44156,15.55716 6.23034,22.21702 1.27377,2.31065 2.69141,4.84829 3.11459,5.63634 0.42318,0.78809 1.7024,2.34441 2.90819,3.46365 1.2058,1.11925 2.18886,2.32876 2.16356,2.65025 -0.0211,0.26792 -0.87541,0.84761 -1.82423,1.25815 -2.61527,1.03412 -11.83335,8.55716 -16.24829,13.27742 -7.47101,7.9301 -10.88009,14.93992 -11.57591,23.7804 -0.53559,6.80471 0.41046,12.59387 2.9327,17.53668 l 1.68007,3.31304 -1.57443,2.19431 c -0.9007,1.16907 -2.93328,3.70471 -4.59801,5.67627 -1.60694,1.92217 -4.52757,5.46616 -6.38255,7.80012 -1.85497,2.33395 -4.34151,5.15734 -5.4481,6.20239 l -2.044,1.9956 -3.15924,-3.69904 c -2.71918,-3.12527 -6.43283,-8.00011 -9.3807,-12.32947 -1.49654,-2.22034 -4.99883,-7.72551 -5.46716,-8.62495 -0.28352,-0.50754 -1.45844,-2.70259 -2.63771,-4.84408 -5.18111,-9.51895 -6.67937,-13.08725 -10.20001,-24.52393 -2.87295,-9.39121 -3.73714,-14.85045 -5.00167,-31.66276 -0.18951,-2.38706 0.69189,-13.58534 1.21153,-16.0783 2.16484,-9.69557 6.19706,-17.08765 12.09661,-22.17626 8.44266,-7.2606 17.91857,-9.15645 30.06914,-5.98969 z m 179.14423,13.77668 c 0.68812,0.16191 3.55194,0.76476 6.41997,1.31397 2.81445,0.54499 5.73606,1.09843 6.41994,1.31399 0.74172,0.16613 3.60552,0.76898 6.3664,1.30976 8.22904,1.61812 14.82957,3.37763 14.78739,3.91343 -0.16025,2.03605 -9.57631,18.92422 -14.62232,26.18259 -4.07487,5.87918 -10.88729,14.34632 -17.7972,21.99711 -6.31929,6.99643 -26.63202,22.59566 -29.09671,22.40167 -0.37506,-0.0295 -0.65983,0.16372 -0.68514,0.48519 -0.0211,0.26789 -0.25649,0.51894 -0.52439,0.49785 -0.32146,-0.0253 -1.99635,0.70521 -3.79103,1.58827 -3.36664,1.67586 -14.76561,4.71425 -18.60779,4.89705 -2.22208,0.14857 -6.01488,0.38918 -8.40193,0.57869 -0.70497,0.0523 -2.77353,-0.38004 -4.56151,-0.95208 -1.788,-0.57202 -3.89748,-1.16935 -4.63495,-1.38914 -3.85653,-1.00439 -10.10531,-5.8631 -14.28011,-11.04353 -3.53727,-4.37574 -7.6123,-16.98849 -7.74794,-24.16947 -0.0427,-1.51291 -0.13469,-3.08361 -0.26169,-3.5249 -0.16794,-0.60626 0.6906,-1.23954 2.92236,-2.19604 6.8645,-2.964 14.19933,-8.47876 18.74375,-14.15924 3.11511,-3.95998 6.91067,-10.40027 8.23234,-14.17792 0.63405,-1.89093 1.41618,-3.60849 1.65157,-3.85951 0.289,-0.24682 1.40152,0.003 2.70308,0.59014 6.49513,3.09899 16.96187,5.05498 23.26996,4.3654 8.75718,-0.98201 18.6693,-7.04868 23.84778,-14.62012 l 1.95073,-2.86554 3.2431,0.57874 c 1.80906,0.30411 3.82403,0.73227 4.45434,0.94364 z m -70.3827,3.08624 c 2.48751,1.27403 5.44038,2.80032 6.53182,3.31753 2.43392,1.26982 2.39472,2.45282 -0.325,8.92385 -2.44638,5.73782 -5.6627,10.98371 -8.28045,13.41936 -1.10237,0.99147 -2.39501,2.34536 -2.87847,3.00817 -1.97901,2.53984 -12.62566,9.03392 -14.55454,8.8821 -0.26791,-0.0211 -0.48519,-0.68514 -0.41771,-1.5424 0.20664,-2.62545 -1.43793,-16.66422 -2.38771,-20.35111 -0.49958,-1.87234 -0.42914,-2.08244 0.91709,-3.43212 4.08799,-3.99122 7.38865,-10.30871 7.74711,-14.86304 0.10122,-1.28594 0.29686,-2.40268 0.47034,-2.55077 0.51597,-0.39068 8.09955,2.57834 13.17752,5.18843 z m -81.62216,-4.80698 c 0.39491,0.46237 1.58929,1.0416 2.70183,1.29089 1.9078,0.41971 10.35835,2.64831 16.53026,4.37408 3.64219,0.98753 3.64641,0.93394 5.2645,4.34995 1.52355,3.24683 3.35418,5.33175 7.06734,8.15787 1.42012,1.13612 2.62594,2.25536 2.60907,2.46967 -0.097,1.23236 -18.61427,13.19905 -20.27527,13.06831 -0.96444,-0.0759 -5.91762,-5.64135 -8.22378,-9.21934 -3.97906,-6.29742 -6.78703,-15.1444 -7.03828,-22.22669 -0.11781,-3.29791 0.13025,-3.70967 1.36433,-2.26474 z M 368.37,349.93488 c 1.37296,4.47496 2.24236,13.97803 1.80253,20.25114 -0.0897,1.82596 -0.20123,1.87109 -3.45098,2.74747 -1.87234,0.49958 -6.17265,1.02372 -9.6271,1.07528 -5.40442,0.16766 -6.95404,-0.008 -11.39572,-1.11259 -5.55003,-1.40725 -12.37505,-4.42439 -15.52411,-6.88265 -1.8277,-1.43776 -1.87285,-1.54913 -0.91137,-2.1204 8.47564,-4.93975 17.93507,-11.41946 19.19521,-13.04548 0.30586,-0.46114 1.87654,-0.55316 4.60915,-0.33808 4.39359,0.34581 10.05027,-0.28719 12.51324,-1.44115 2.06682,-0.91557 2.27692,-0.84514 2.78915,0.86646 z"
inkscape:connector-curvature="0"
style="fill:url(#radialGradient5665-7-4-5-9);fill-opacity:1"
sodipodi:nodetypes="cccccccccscccccccccccccccccccccsccccccccsccccccccccccsccccccccsccccccccccsccccccccccccccccccccccccccccccccsccsccccccccccccscsccccccccccccccccccccccsccccccccccccccccccccccccccccccccscccccsccccccccccccccccccccccccscccsccccsccccccccccccccccccccccccccccccccccccccccccccccsccscccccccsccccccccccccscc" />
</g>
</svg>
#!/usr/bin/python from setuptools import setup, find_packages
# -*- coding: utf-8 -*- import os
import re
import subprocess
import sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), 'src')))
import sakia
# source d'inspiration: http://wiki.wxpython.org/cx_freeze
import sys, os, subprocess, multiprocessing def which(program):
from cx_Freeze import setup, Executable """
Detect whether or not a program is installed.
Thanks to http://stackoverflow.com/a/377028/70191
"""
def is_exe(fpath):
return os.path.exists(fpath) and os.access(fpath, os.X_OK)
fpath, _ = os.path.split(program)
if fpath:
if is_exe(program):
return program
else:
for path in os.environ['PATH'].split(os.pathsep):
exe_file = os.path.join(path, program)
if is_exe(exe_file):
return exe_file
return None
path = os.path.abspath(os.path.join(os.path.dirname(__file__)))
subprocess.call(
"python {0}/gen_resources.py".format(path), shell=True
)
subprocess.call(
"python {0}/gen_translations.py".format(path), shell=True
)
EDITABLE_REQUIREMENT = re.compile(r'^-e (?P<link>(?P<vcs>git|svn|hg|bzr).+#egg=(?P<package>.+)-(?P<version>\d(?:\.\d)*))$')
install_requires = []
dependency_links = []
data_files = [('sakia', ['src/sakia/root_servers.yml', 'src/sakia/g1_license.html'])]
for requirement in (l.strip() for l in open('requirements.txt')):
match = EDITABLE_REQUIREMENT.match(requirement)
if match:
assert which(match.group('vcs')) is not None, \
"VCS '%(vcs)s' must be installed in order to install %(link)s" % match.groupdict()
install_requires.append("%(package)s==%(version)s" % match.groupdict())
dependency_links.append(match.group('link'))
else:
install_requires.append(requirement)
sql_files = []
for file in os.listdir(os.path.join("src", "sakia", "data", "repositories")):
if file.endswith(".sql"):
sql_file = os.path.basename(file)
sql_files.append('src/sakia/data/repositories/{:}'.format(sql_file))
data_files.append(('sakia/data/repositories/', sql_files))
#############################################################################
# preparation des options
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), 'lib')))
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), 'src')))
print(sys.path)
includes = ["sip", "re", "json", "logging", "hashlib", "os", "urllib", "ucoinpy", "pylibscrypt", "requests"]
excludes = []
packages = ["libnacl"]
includefiles = []
if sys.platform == "win32":
includefiles.append("platforms/win32/libEGL.dll")
includefiles.append("platforms/win32/libsodium.dll")
elif sys.platform == "darwin":
pass
else:
pass
options = {"path": sys.path,
"includes": includes,
"include_files": includefiles,
"excludes": excludes,
"packages": packages,
}
#############################################################################
# preparation des cibles
base = None
file_type=""
if sys.platform == "win32":
base = "Win32GUI"
file_type=".exe"
target = Executable(
script = "src/cutecoin/main.py",
targetName="cutecoin"+file_type,
base = base,
compress = False,
icon = None,
)
#############################################################################
# creation du setup
setup( setup(
name = "cutecoin", name='sakia',
version = "0.5",
description = "UCoin client", version=sakia.__version__,
author = "Inso", author="inso",
options = {"build_exe": options},
executables = [target] author_email="insomniak.fr@gmail.com",
)
description="A [duniter](https://github.com/duniter/duniter) Python client",
long_description=open('README.md').read(),
long_description_content_type="text/markdown",
# Active la prise en compte du fichier MANIFEST.in
include_package_data=True,
url='https://github.com/duniter/sakia',
classifiers=[
"Programming Language :: Python",
"Development Status :: 4 - Beta",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"Natural Language :: French",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3.5",
"Topic :: Communications",
],
install_requires=install_requires,
dependency_links=dependency_links,
packages=find_packages('src', exclude=["*.tests", "*.tests.*", "tests.*", "tests"]),
package_dir={'sakia': 'src/sakia',
'i18n_rc': 'src/i18n_rc',
'icons_rc': 'src/icons_rc'},
entry_points={
'console_scripts': [
'sakia = sakia.main:main'
]
},
data_files=data_files
)
__version_info__ = ('0', '9', '0')
__version__ = '.'.join(__version_info__)
'''
Created on 1 févr. 2014
@author: inso
'''
from ucoinpy import PROTOCOL_VERSION
from ucoinpy.api import bma
from ucoinpy.documents.certification import SelfCertification, Certification
from ucoinpy.documents.membership import Membership
from ucoinpy.key import SigningKey
import logging
import time
from PyQt5.QtCore import QObject, pyqtSignal, Qt
from .wallet import Wallet
from .community import Community
from .person import Person
from ..tools.exceptions import ContactAlreadyExists
def quantitative(units, community):
return int(units)
def relative(units, community):
ud = community.dividend
relative_value = units / float(ud)
return relative_value
def quantitative_zerosum(units, community):
median = community.monetary_mass / community.nb_members
return units - median
def relative_zerosum(units, community):
median = community.monetary_mass / community.nb_members
ud = community.dividend
relative_value = units / float(ud)
relative_median = median / ud
return relative_value - relative_median
class Account(QObject):
'''
An account is specific to a key.
Each account has only one key, and a key can
be locally referenced by only one account.
'''
referentials = {'Units': (quantitative, '{0}', quantitative, '{0}'),
'UD': (relative, 'ud {0}', relative, 'ud {0}'),
'Quant Z-sum': (quantitative_zerosum, 'q0 {0}',
quantitative, '{0}'),
'Relat Z-sum': (relative_zerosum, 'r0 {0}',
relative, 'ud {0}')
}
loading_progressed = pyqtSignal(int, int)
def __init__(self, salt, pubkey, name, communities, wallets, contacts):
'''
Create an account
:param str salt: The root key salt
:param str pubkey: Known account pubkey. Used to check that password \
is OK by comparing (salt, given_passwd) = (pubkey, privkey) \
with known pubkey
:param str name: The account name, same as network identity uid
:param array communities: Community objects referenced by this account
:param array wallets: Wallet objects owned by this account
:param array contacts: Contacts of this account
.. warnings:: The class methods create and load should be used to create an account
'''
super().__init__()
self.salt = salt
self.pubkey = pubkey
self.name = name
self.communities = communities
self.wallets = wallets
self.contacts = contacts
self.referential = 'Units'
@classmethod
def create(cls, name):
'''
Factory method to create an empty account object
This new account doesn't have any key and it should be given
one later
It doesn't have any community nor does it have wallets.
Communities could be added later, wallets will be managed
by its wallet pool size.
:param str name: The account name, same as network identity uid
:return: A new empty account object
'''
account = cls(None, None, name, [], [], [])
return account
@classmethod
def load(cls, json_data):
'''
Factory method to create an Account object from its json view.
:param dict json_data: The account view as a json dict
:return: A new account object created from the json datas
'''
salt = json_data['salt']
pubkey = json_data['pubkey']
name = json_data['name']
contacts = []
for contact_data in json_data['contacts']:
contacts.append(Person.from_json(contact_data))
wallets = []
for data in json_data['wallets']:
wallets.append(Wallet.load(data))
communities = []
for data in json_data['communities']:
community = Community.load(data)
communities.append(community)
account = cls(salt, pubkey, name, communities, wallets,
contacts)
return account
def __eq__(self, other):
'''
:return: True if account.pubkey == other.pubkey
'''
if other is not None:
return other.pubkey == self.pubkey
else:
return False
def check_password(self, password):
'''
Method to verify the key password validity
:param str password: The key password
:return: True if the generated pubkey is the same as the account
.. warnings:: Generates a new temporary SigningKey
'''
key = SigningKey(self.salt, password)
return (key.pubkey == self.pubkey)
#TODO: Contacts should be pure json, not Person objects
def add_contact(self, person):
same_contact = [contact for contact in self.contacts
if person.pubkey == contact.pubkey]
if len(same_contact) > 0:
raise ContactAlreadyExists(person.uid, same_contact[0].uid)
self.contacts.append(person)
def add_community(self, community):
'''
Add a community to the account
:param community: A community object to add
'''
self.communities.append(community)
return community
def refresh_cache(self):
'''
Refresh the local account cache
This needs n_wallets * n_communities cache refreshing to end
.. note:: emit the Account pyqtSignal loading_progressed during refresh
'''
loaded_wallets = 0
def progressing(value, maximum):
account_value = maximum * len(self.communities) * loaded_wallets + value
account_max = maximum * len(self.communities) * len(self.wallets)
self.loading_progressed.emit(account_value, account_max)
for w in self.wallets:
w.refresh_progressed.connect(progressing, type=Qt.DirectConnection)
for c in self.communities:
w.refresh_cache(c)
loaded_wallets = loaded_wallets + 1
def set_display_referential(self, index):
self.referential = index
@property
def units_to_ref(self):
return Account.referentials[self.referential][0]
@property
def units_to_diff_ref(self):
return Account.referentials[self.referential][2]
def ref_name(self, currency):
return Account.referentials[self.referential][1].format(currency)
def diff_ref_name(self, currency):
return Account.referentials[self.referential][3].format(currency)
def set_walletpool_size(self, size, password):
'''
Change the size of the wallet pool
:param int size: The new size of the wallet pool
:param str password: The password of the account, same for all wallets
'''
logging.debug("Defining wallet pool size")
if len(self.wallets) < size:
for i in range(len(self.wallets), size):
wallet = Wallet.create(i, self.salt, password,
"Wallet {0}".format(i))
self.wallets.append(wallet)
else:
self.wallets = self.wallets[:size]
def certify(self, password, community, pubkey):
'''
Certify an other identity
:param str password: The account SigningKey password
:param community: The community target of the certification
:param str pubkey: The certified identity pubkey
'''
certified = Person.lookup(pubkey, community)
blockid = community.current_blockid()
certification = Certification(PROTOCOL_VERSION, community.currency,
self.pubkey, certified.pubkey,
blockid['number'], blockid['hash'], None)
selfcert = certified.selfcert(community)
logging.debug("SelfCertification : {0}".format(selfcert.raw()))
key = SigningKey(self.salt, password)
certification.sign(selfcert, [key])
signed_cert = certification.signed_raw(selfcert)
logging.debug("Certification : {0}".format(signed_cert))
data = {'pubkey': certified.pubkey,
'self_': selfcert.signed_raw(),
'other': "{0}\n".format(certification.inline())}
logging.debug("Posted data : {0}".format(data))
community.broadcast(bma.wot.Add, {}, data)
def transfers(self, community):
'''
Get all transfers done in a community by all the wallets
owned by this account
:param community: The target community of this request
:return: All account wallets transfers
'''
sent = []
for w in self.wallets:
for transfer in w.transfers(community):
sent.append(transfer)
return sent
def amount(self, community):
'''
Get amount of money owned in a community by all the wallets
owned by this account
:param community: The target community of this request
:return: The value of all wallets values accumulated
'''
value = 0
for w in self.wallets:
value += w.value(community)
return value
def member_of(self, community):
'''
Check if this account identity is a member of a community
:param community: The target community of this request
:return: True if the account is a member of the target community
'''
self_person = Person.lookup(self.pubkey, community)
return self_person.is_member(community)
def send_selfcert(self, password, community):
'''
Send our self certification to a target community
:param str password: The account SigningKey password
:param community: The community target of the self certification
'''
selfcert = SelfCertification(PROTOCOL_VERSION,
community.currency,
self.pubkey,
int(time.time()),
self.name,
None)
key = SigningKey(self.salt, password)
selfcert.sign([key])
logging.debug("Key publish : {0}".format(selfcert.signed_raw()))
community.broadcast(bma.wot.Add, {}, {'pubkey': self.pubkey,
'self_': selfcert.signed_raw(),
'other': []})
def send_membership(self, password, community, mstype):
'''
Send a membership document to a target community
:param str password: The account SigningKey password
:param community: The community target of the membership document
:param str mstype: The type of membership demand. "IN" to join, "OUT" to leave
'''
self_ = Person.lookup(self.pubkey, community)
selfcert = self_.selfcert(community)
blockid = community.current_blockid()
membership = Membership(PROTOCOL_VERSION, community.currency,
selfcert.pubkey, blockid['number'],
blockid['hash'], mstype, selfcert.uid,
selfcert.timestamp, None)
key = SigningKey(self.salt, password)
membership.sign([key])
logging.debug("Membership : {0}".format(membership.signed_raw()))
community.broadcast(bma.blockchain.Membership, {},
{'membership': membership.signed_raw()})
def jsonify(self):
'''
Get the account in a json format.
:return: A dict view of the account to be saved as json
'''
data_communities = []
for c in self.communities:
data_communities.append(c.jsonify())
data_wallets = []
for w in self.wallets:
data_wallets.append(w.jsonify())
data_contacts = []
for p in self.contacts:
data_contacts.append(p.jsonify())
data = {'name': self.name,
'salt': self.salt,
'pubkey': self.pubkey,
'communities': data_communities,
'wallets': data_wallets,
'contacts': data_contacts}
return data
def get_person(self):
return Person.from_metadata({'text': self.name,
'id': self.pubkey})
'''
Created on 1 févr. 2014
@author: inso
'''
import os
import logging
import json
import tarfile
import shutil
from PyQt5.QtCore import QObject, pyqtSignal
from . import config
from ..tools.exceptions import NameAlreadyExists, BadAccountFile
from .account import Account
from . import person
from .. import __version__
class Application(QObject):
'''
Managing core application datas :
Accounts list and general configuration
Saving and loading the application state
'''
loading_progressed = pyqtSignal(int, int)
def __init__(self, argv):
'''
Create a new "cutecoin" application
:param argv: The argv parameters of the call
'''
super().__init__()
self.accounts = {}
self.default_account = ""
self.current_account = None
config.parse_arguments(argv)
self.load()
def get_account(self, name):
'''
Load an account then return it
:param str name: The account name
:return: The loaded account if it's a success, else return None
'''
self.load_account(name)
if name in self.accounts.keys():
return self.accounts[name]
else:
return None
def create_account(self, name):
'''
Create a new account from its name
:param str name: The account name
:return: The new account
:raise: NameAlreadyExists if the account name is already used locally
'''
for a in self.accounts:
if a == name:
raise NameAlreadyExists(a)
account = Account.create(name)
return account
def add_account(self, account):
self.accounts[account.name] = account
def delete_account(self, account):
'''
Delete an account.
Current account changes to None if it is deleted.
'''
self.accounts.pop(account.name)
if self.current_account == account:
self.current_account = None
def change_current_account(self, account):
'''
Change current account displayed and refresh its cache.
:param account: The account object to display
.. note:: Emits the application pyqtSignal loading_progressed
during cache refresh
'''
def progressing(value, maximum):
self.loading_progressed.emit(value, maximum)
if self.current_account is not None:
self.save_cache(self.current_account)
account.loading_progressed.connect(progressing)
account.refresh_cache()
self.current_account = account
def load(self):
'''
Load a saved application state from the data file.
Loads only jsonified objects but not their cache.
If the standard application state file can't be found,
no error is raised.
'''
self.load_persons()
try:
logging.debug("Loading data...")
with open(config.parameters['data'], 'r') as json_data:
data = json.load(json_data)
if 'default_account' in data.keys():
self.default_account = data['default_account']
for account_name in data['local_accounts']:
self.accounts[account_name] = None
except FileNotFoundError:
pass
def load_persons(self):
'''
Load the Person instances of the person module.
Each instance is unique, and can be find by its public key.
'''
try:
persons_path = os.path.join(config.parameters['home'],
'__persons__')
with open(persons_path, 'r') as persons_path:
data = json.load(persons_path)
person.load_cache(data)
except FileNotFoundError:
pass
def load_account(self, account_name):
'''
Load an account from its name
:param str account_name: The account name
'''
account_path = os.path.join(config.parameters['home'],
account_name, 'properties')
with open(account_path, 'r') as json_data:
data = json.load(json_data)
account = Account.load(data)
self.load_cache(account)
self.accounts[account_name] = account
def load_cache(self, account):
'''
Load an account cache
:param account: The account object to load the cache
'''
for community in account.communities:
community_path = os.path.join(config.parameters['home'],
account.name, '__cache__',
community.currency)
network_path = os.path.join(config.parameters['home'],
account.name, '__cache__',
community.currency + '_network')
if os.path.exists(network_path):
with open(network_path, 'r') as json_data:
data = json.load(json_data)
if 'version' in data and data['version'] == __version__:
community.load_merge_network(data['network'])
else:
os.remove(network_path)
if os.path.exists(community_path):
with open(community_path, 'r') as json_data:
data = json.load(json_data)
if 'version' in data and data['version'] == __version__:
community.load_cache(data)
else:
os.remove(community_path)
for wallet in account.wallets:
wallet_path = os.path.join(config.parameters['home'],
account.name, '__cache__', wallet.pubkey)
if os.path.exists(wallet_path):
with open(wallet_path, 'r') as json_data:
data = json.load(json_data)
if 'version' in data and data['version'] == __version__:
wallet.load_caches(data)
else:
os.remove(wallet_path)
def save(self, account):
'''
Save an account
:param account: The account object to save
'''
with open(config.parameters['data'], 'w') as outfile:
json.dump(self.jsonify(), outfile, indent=4, sort_keys=True)
account_path = os.path.join(config.parameters['home'],
account.name)
if account.name in self.accounts:
properties_path = os.path.join(account_path, 'properties')
if not os.path.exists(account_path):
logging.info("Creating account directory")
os.makedirs(account_path)
with open(properties_path, 'w') as outfile:
json.dump(account.jsonify(), outfile, indent=4, sort_keys=True)
else:
account_path = os.path.join(config.parameters['home'], account.name)
shutil.rmtree(account_path)
def save_persons(self):
'''
Save the person module cache
'''
persons_path = os.path.join(config.parameters['home'],
'__persons__')
with open(persons_path, 'w')as outfile:
data = person.jsonify_cache()
data['version'] = __version__
json.dump(data, outfile, indent=4, sort_keys=True)
def save_cache(self, account):
'''
Save the cache of an account
:param account: The account object to save the cache
'''
if not os.path.exists(os.path.join(config.parameters['home'],
account.name, '__cache__')):
os.makedirs(os.path.join(config.parameters['home'],
account.name, '__cache__'))
for wallet in account.wallets:
wallet_path = os.path.join(config.parameters['home'],
account.name, '__cache__', wallet.pubkey)
with open(wallet_path, 'w') as outfile:
data = wallet.jsonify_caches()
data['version'] = __version__
json.dump(data, outfile, indent=4, sort_keys=True)
for community in account.communities:
community_path = os.path.join(config.parameters['home'],
account.name, '__cache__',
community.currency)
network_path = os.path.join(config.parameters['home'],
account.name, '__cache__',
community.currency + '_network')
with open(network_path, 'w') as outfile:
data['network'] = community.jsonify_network()
data['version'] = __version__
json.dump(data, outfile, indent=4, sort_keys=True)
with open(community_path, 'w') as outfile:
data = community.jsonify_cache()
data['version'] = __version__
json.dump(data, outfile, indent=4, sort_keys=True)
def import_account(self, file, name):
'''
Import an account from a tar file
:param str file: The file path of the tar file
:param str name: The account name
'''
with tarfile.open(file, "r") as tar:
path = os.path.join(config.parameters['home'],
name)
for obj in ["properties"]:
try:
tar.getmember(obj)
except KeyError:
raise BadAccountFile(file)
tar.extractall(path)
account_path = os.path.join(config.parameters['home'],
name, 'properties')
json_data = open(account_path, 'r')
data = json.load(json_data)
account = Account.load(data)
account.name = name
self.accounts.append(account)
self.save(account)
def export_account(self, file, account):
'''
Export an account to a tar file
:param str file: The filepath of the tar file
:param account: The account object to export
'''
with tarfile.open(file, "w") as tar:
for file in ["properties"]:
path = os.path.join(config.parameters['home'],
account.name, file)
tar.add(path, file)
def jsonify_accounts(self):
'''
Jsonify an account
:return: The account as a dict to format as json
'''
data = []
logging.debug("{0}".format(self.accounts))
for account in self.accounts:
data.append(account)
return data
def jsonify(self):
'''
Jsonify the app datas
:return: The accounts of the app to format as json
'''
data = {'default_account': self.default_account,
'local_accounts': self.jsonify_accounts()}
return data
'''
Created on 1 févr. 2014
@author: inso
'''
from ucoinpy.api import bma
from ucoinpy.documents.block import Block
from ..tools.exceptions import NoPeerAvailable
from .net.node import Node
from .net.network import Network
import logging
import inspect
import hashlib
import re
from requests.exceptions import RequestException
class Cache():
_saved_requests = [hash(bma.blockchain.Block),
hash(bma.wot.Lookup)]
def __init__(self, community):
'''
Init an empty cache
'''
self.latest_block = 0
self.community = community
self.data = {}
def load_from_json(self, data):
'''
Put data in the cache from json datas.
:param dict data: The cache in json format
'''
self.data = {}
for entry in data['cache']:
key = entry['key']
cache_key = (key[0], key[1], key[2], key[3], key[4])
self.data[cache_key] = entry['value']
self.latest_block = data['latest_block']
def jsonify(self):
'''
Get the cache in json format
:return: The cache as a dict in json format
'''
data = {k: self.data[k] for k in self.data.keys()
if k[0] in Cache._saved_requests}
entries = []
for d in data:
entries.append({'key': d,
'value': data[d]})
return {'latest_block': self.latest_block,
'cache': entries}
def refresh(self):
'''
Refreshing the cache just clears every last requests which
cannot be saved because they can change from one block to another.
'''
self.latest_block = self.community.current_blockid()['number']
self.data = {k: self.data[k] for k in self.data.keys()
if k[0] in Cache._saved_requests}
def request(self, request, req_args={}, get_args={}):
'''
Send a cached request to a community.
If the request was already sent in current block, return last value get.
:param request: The request bma class
:param req_args: The arguments passed to the request constructor
:param get_args: The arguments passed to the requests __get__ method
'''
cache_key = (hash(request),
hash(tuple(frozenset(sorted(req_args.keys())))),
hash(tuple(frozenset(sorted(req_args.items())))),
hash(tuple(frozenset(sorted(get_args.keys())))),
hash(tuple(frozenset(sorted(get_args.items())))))
if cache_key not in self.data.keys():
result = self.community.request(request, req_args, get_args,
cached=False)
# Do not cache block 0
if self.latest_block == 0:
return result
else:
self.data[cache_key] = result
return self.data[cache_key]
else:
return self.data[cache_key]
class Community(object):
'''
A community is a group of nodes using the same currency.
.. warning:: The currency name is supposed to be unique in cutecoin
but nothing exists in ucoin to assert that a currency name is unique.
'''
def __init__(self, currency, network):
'''
Initialize community attributes with a currency and a network.
:param str currency: The currency name of the community.
:param network: The network of the community
.. warning:: The community object should be created using its factory
class methods.
'''
self.currency = currency
self._network = network
self._cache = Cache(self)
self._cache.refresh()
@classmethod
def create(cls, node):
'''
Create a community from its first node.
:param node: The first Node of the community
'''
network = Network.create(node)
community = cls(node.currency, network)
logging.debug("Creating community")
return community
@classmethod
def load(cls, json_data):
'''
Load a community from json
:param dict json_data: The community as a dict in json format
'''
currency = json_data['currency']
network = Network.from_json(currency, json_data['peers'])
community = cls(currency, network)
return community
def load_merge_network(self, json_data):
'''
Load the last state of the network.
This network is merged with the network currently
known network.
:param dict json_data:
'''
self._network.merge_with_json(json_data)
def load_cache(self, json_data):
'''
Load the community cache.
:param dict json_data: The community as a dict in json format.
'''
self._cache.load_from_json(json_data)
def jsonify_cache(self):
'''
Get the cache jsonified.
:return: The cache as a dict in json format.
'''
return self._cache.jsonify()
def jsonify_network(self):
'''
Get the network jsonified.
'''
return self._network.jsonify()
@property
def name(self):
'''
The community name is its currency name.
:return: The community name
'''
return self.currency
def __eq__(self, other):
'''
:return: True if this community has the same currency name as the other one.
'''
return (other.currency == self.currency)
@property
def short_currency(self):
'''
Format the currency name to a short one
:return: The currency name in a shot format.
'''
words = re.split('[_\W]+', self.currency)
shortened = ""
if len(words) > 1:
shortened = ''.join([w[0] for w in words])
else:
vowels = ('a', 'e', 'i', 'o', 'u', 'y')
shortened = self.currency
shortened = ''.join([c for c in shortened if c not in vowels])
return shortened.upper()
@property
def currency_symbol(self):
'''
Format the currency name to a symbol one.
:return: The currency name as a utf-8 circled symbol.
'''
letter = self.currency[0]
u = ord('\u24B6') + ord(letter) - ord('A')
return chr(u)
@property
def dividend(self):
'''
Get the last generated community universal dividend.
:return: The last UD or 1 if no UD was generated.
'''
block = self.get_ud_block()
if block:
return block['dividend']
else:
return 1
def get_ud_block(self, x=0):
'''
Get a block with universal dividend
:param int x: Get the 'x' older block with UD in it
:return: The last block with universal dividend.
'''
blocks = self.request(bma.blockchain.UD)['result']['blocks']
if len(blocks) > 0:
block_number = blocks[len(blocks)-(1+x)]
block = self.request(bma.blockchain.Block,
req_args={'number': block_number})
return block
else:
return False
@property
def monetary_mass(self):
'''
Get the community monetary mass
:return: The monetary mass value
'''
try:
block = self.request(bma.blockchain.Current)
return block['monetaryMass']
except ValueError as e:
if '404' in e:
return 0
@property
def nb_members(self):
'''
Get the community members number
:return: The community members number
'''
try:
block = self.request(bma.blockchain.Current)
return block['membersCount']
except ValueError as e:
if '404' in e:
return 0
@property
def nodes(self):
'''
Get the known community nodes
:return: All community known nodes
'''
return self._network.all_nodes
@property
def network(self):
'''
Get the community network instance.
:return: The community network instance.
'''
return self._network
@property
def parameters(self):
'''
'''
return self.request(bma.blockchain.Parameters)
@property
def add_peer(self, peer):
'''
Add a peer to the community.
:param peer: The new peer as a ucoinpy Peer object.
'''
self._network.add_node(Node.from_peer(peer))
def get_block(self, number=None):
'''
Get a block
:param int number: The block number. If none, returns current block.
'''
if number is None:
data = self.request(bma.blockchain.Current)
else:
data = self.request(bma.blockchain.Block,
req_args={'number': number})
return Block.from_signed_raw("{0}{1}\n".format(data['raw'],
data['signature']))
def current_blockid(self):
'''
Get the current block id.
:return: The current block ID as [NUMBER-HASH] format.
'''
try:
block = self.request(bma.blockchain.Current, cached=False)
signed_raw = "{0}{1}\n".format(block['raw'], block['signature'])
block_hash = hashlib.sha1(signed_raw.encode("ascii")).hexdigest().upper()
block_number = block['number']
except ValueError as e:
if '404' in str(e):
block_number = 0
block_hash = "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"
else:
raise
return {'number': block_number, 'hash': block_hash}
def members_pubkeys(self):
'''
Listing members pubkeys of a community
:return: All members pubkeys.
'''
memberships = self.request(bma.wot.Members)
return [m['pubkey'] for m in memberships["results"]]
def refresh_cache(self):
'''
Start the refresh processing of the cache
'''
self._cache.refresh()
def request(self, request, req_args={}, get_args={}, cached=True):
'''
Start a request to the community.
:param request: A ucoinpy bma request class
:param req_args: Arguments to pass to the request constructor
:param get_args: Arguments to pass to the request __get__ method
:return: The returned data
'''
if cached:
return self._cache.request(request, req_args, get_args)
else:
nodes = self._network.online_nodes
for node in nodes:
try:
req = request(node.endpoint.conn_handler(), **req_args)
data = req.get(**get_args)
if inspect.isgenerator(data):
generated = []
for d in data:
generated.append(d)
return generated
else:
return data
except ValueError as e:
if '502' in str(e):
continue
else:
raise
except RequestException:
continue
raise NoPeerAvailable(self.currency, len(nodes))
def post(self, request, req_args={}, post_args={}):
'''
Post data to a community.
Only sends the data to one node.
:param request: A ucoinpy bma request class
:param req_args: Arguments to pass to the request constructor
:param post_args: Arguments to pass to the request __post__ method
:return: The returned data
'''
nodes = self._network.online_nodes
for node in nodes:
req = request(node.endpoint.conn_handler(), **req_args)
logging.debug("Trying to connect to : " + node.pubkey)
req = request(node.endpoint.conn_handler(), **req_args)
try:
req.post(**post_args)
return
except ValueError as e:
raise
except RequestException:
continue
raise NoPeerAvailable(self.currency, len(nodes))
def broadcast(self, request, req_args={}, post_args={}):
'''
Broadcast data to a community.
Sends the data to all knew nodes.
:param request: A ucoinpy bma request class
:param req_args: Arguments to pass to the request constructor
:param post_args: Arguments to pass to the request __post__ method
:return: The returned data
.. note:: If one node accept the requests (returns 200),
the broadcast is considered accepted by the network.
'''
tries = 0
ok = False
value_error = None
nodes = self._network.online_nodes
for node in nodes:
logging.debug("Trying to connect to : " + node.pubkey)
req = request(node.endpoint.conn_handler(), **req_args)
try:
req.post(**post_args)
ok = True
except ValueError as e:
value_error = e
continue
except RequestException:
tries = tries + 1
continue
if not ok:
raise value_error
if tries == len(self.nodes):
raise NoPeerAvailable(self.currency, len(nodes))
def jsonify(self):
'''
Jsonify the community datas.
:return: The community as a dict in json format.
'''
data = {'currency': self.currency,
'peers': self._network.jsonify()}
return data
\ No newline at end of file
'''
Created on 7 févr. 2014
@author: inso
'''
import logging
from logging import FileHandler
from optparse import OptionParser
from os import environ, path, makedirs
if "XDG_CONFIG_HOME" in environ:
config_path = environ["XDG_CONFIG_HOME"]
elif "HOME" in environ:
config_path = path.join(environ["HOME"], ".config")
elif "APPDATA" in environ:
config_path = environ["APPDATA"]
else:
config_path = path.dirname(__file__)
parameters = {'home': path.join(config_path, 'cutecoin'),
'data': path.join(config_path, 'cutecoin', 'data')}
if not path.exists(parameters['home']):
logging.info("Creating home directory")
makedirs((parameters['home']))
def parse_arguments(argv):
parser = OptionParser()
parser.add_option("-v", "--verbose",
action="store_true", dest="verbose", default=False,
help="Print INFO messages to stdout")
parser.add_option("-d", "--debug",
action="store_true", dest="debug", default=False,
help="Print DEBUG messages to stdout")
(options, args) = parser.parse_args(argv)
if options.debug:
logging.basicConfig(format='%(levelname)s:%(module)s:%(message)s',
level=logging.DEBUG)
elif options.verbose:
logging.basicConfig(format='%(levelname)s:%(message)s',
level=logging.INFO)
else:
logging.getLogger().propagate = False
logfile = FileHandler(path.join(parameters['home'], 'cutecoin.log'))
logging.getLogger().addHandler(logfile)
import logging
import copy
import time
import datetime
from cutecoin.core.person import Person
from cutecoin.gui.views.wot import NODE_STATUS_HIGHLIGHTED, NODE_STATUS_OUT, ARC_STATUS_STRONG, ARC_STATUS_WEAK
class Graph(object):
def __init__(self, community, graph=None):
"""
Init Graph instance
:param cutecoin.core.community.Community community:
:return:
"""
self.community = community
self.signature_validity = self.community.parameters['sigValidity']
# arc considered strong during 75% of signature validity time
self.ARC_STATUS_STRONG_time = int(self.signature_validity * 0.75)
# graph empty if None parameter
self._graph = graph or (dict() and (graph is None))
def set(self, graph):
"""
Set the graph from dict
:param dict graph:
:return:
"""
self._graph = graph
def get(self):
"""
Return the graph dict
:return:
"""
return self._graph
def get_shortest_path_between_members(self, from_person, to_person):
"""
Return path list of nodes from from_person to to_person
:param Person from_person:
:param Person to_person:
:return:
"""
path = list()
logging.debug("path between %s to %s..." % (from_person.name, to_person.name))
if from_person.pubkey not in self._graph.keys():
self.add_person(from_person)
certifier_list = from_person.certifiers_of(self.community)
self.add_certifier_list(certifier_list, from_person, to_person)
certified_list = from_person.certified_by(self.community)
self.add_certified_list(certified_list, from_person, to_person)
if to_person.pubkey not in self._graph.keys():
# recursively feed graph searching for account node...
self.explore_to_find_member(to_person, self._graph[from_person.pubkey]['connected'], list())
if len(self._graph[from_person.pubkey]['connected']) > 0:
# calculate path of nodes between person and to_person
path = self.find_shortest_path(self._graph[from_person.pubkey], self._graph[to_person.pubkey])
if path:
logging.debug([node['text'] for node in path])
else:
logging.debug('no wot path')
return path
def explore_to_find_member(self, person, connected=None, done=None):
"""
Scan graph recursively to find person
:param Person person: Person instance to find
:param list connected: Optional, default=None, Pubkey list of the connected nodes
around the current scanned node
:param list done: Optional, default=None, List of node already scanned
:return:
"""
# functions keywords args are persistent... Need to reset it with None trick
connected = connected or (list() and (connected is None))
done = done or (list() and (done is None))
logging.debug("search %s in " % person.name)
logging.debug([self._graph[pubkey]['text'] for pubkey in connected])
# for each pubkey connected...
for pubkey in tuple(connected):
# capture node connected
node = self._graph[pubkey]
if node['id'] in tuple(done):
continue
person_selected = Person.from_metadata(node)
certifier_list = person_selected.certifiers_of(self.community)
self.add_certifier_list(certifier_list, person_selected, person)
if person.pubkey in tuple(self._graph.keys()):
return False
certified_list = person_selected.certified_by(self.community)
self.add_certified_list(certified_list, person_selected, person)
if person.pubkey in tuple(self._graph.keys()):
return False
if node['id'] not in tuple(done):
done.append(node['id'])
if len(done) >= len(self._graph):
return True
result = self.explore_to_find_member(person, self._graph[person_selected.pubkey]['connected'], done)
if not result:
return False
return True
def find_shortest_path(self, start, end, path=None):
"""
Find recursively the shortest path between two nodes
:param dict start: Start node
:param dict end: End node
:param list path: Optional, default=None, List of nodes
:return:
"""
path = path or (list() and (path is None))
path = path + [start]
if start['id'] == end['id']:
return path
if start['id'] not in self._graph.keys():
return None
shortest = None
for pubkey in tuple(self._graph[start['id']]['connected']):
node = self._graph[pubkey]
if node not in path:
newpath = self.find_shortest_path(node, end, path)
if newpath:
if not shortest or len(newpath) < len(shortest):
shortest = newpath
return shortest
def add_certifier_list(self, certifier_list, person, person_account):
"""
Add list of certifiers to graph
:param list certifier_list: List of certifiers from api
:param Person person: Person instance which is certified
:param Person person_account: Account person instance
:return:
"""
# add certifiers of uid
for certifier in tuple(certifier_list):
# add only valid certification...
if (time.time() - certifier['cert_time']['medianTime']) > self.signature_validity:
continue
# new node
if certifier['pubkey'] not in self._graph.keys():
node_status = 0
if certifier['pubkey'] == person_account.pubkey:
node_status += NODE_STATUS_HIGHLIGHTED
if certifier['isMember'] is False:
node_status += NODE_STATUS_OUT
self._graph[certifier['pubkey']] = {
'id': certifier['pubkey'],
'arcs': list(),
'text': certifier['uid'],
'tooltip': certifier['pubkey'],
'status': node_status,
'connected': [person.pubkey]
}
# keep only the latest certification
if self._graph[certifier['pubkey']]['arcs']:
if certifier['cert_time']['medianTime'] < self._graph[certifier['pubkey']]['arcs'][0]['cert_time']:
continue
# display validity status
if (time.time() - certifier['cert_time']['medianTime']) > self.ARC_STATUS_STRONG_time:
arc_status = ARC_STATUS_WEAK
else:
arc_status = ARC_STATUS_STRONG
arc = {
'id': person.pubkey,
'status': arc_status,
'tooltip': datetime.datetime.fromtimestamp(
certifier['cert_time']['medianTime'] + self.signature_validity
).strftime("%d/%m/%Y"),
'cert_time': certifier['cert_time']['medianTime']
}
# add arc to certifier
self._graph[certifier['pubkey']]['arcs'].append(arc)
# if certifier node not in person nodes
if certifier['pubkey'] not in tuple(self._graph[person.pubkey]['connected']):
# add certifier node to person node
self._graph[person.pubkey]['connected'].append(certifier['pubkey'])
def add_certified_list(self, certified_list, person, person_account):
"""
Add list of certified from api to graph
:param list certified_list: List of certified from api
:param Person person: Person instance which is certifier
:param Person person_account: Account person instance
:return:
"""
# add certified by uid
for certified in tuple(certified_list):
# add only valid certification...
if (time.time() - certified['cert_time']['medianTime']) > self.signature_validity:
continue
if certified['pubkey'] not in self._graph.keys():
node_status = 0
if certified['pubkey'] == person_account.pubkey:
node_status += NODE_STATUS_HIGHLIGHTED
if certified['isMember'] is False:
node_status += NODE_STATUS_OUT
self._graph[certified['pubkey']] = {
'id': certified['pubkey'],
'arcs': list(),
'text': certified['uid'],
'tooltip': certified['pubkey'],
'status': node_status,
'connected': [person.pubkey]
}
# display validity status
if (time.time() - certified['cert_time']['medianTime']) > self.ARC_STATUS_STRONG_time:
arc_status = ARC_STATUS_WEAK
else:
arc_status = ARC_STATUS_STRONG
arc = {
'id': certified['pubkey'],
'status': arc_status,
'tooltip': datetime.datetime.fromtimestamp(
certified['cert_time']['medianTime'] + self.signature_validity
).strftime("%d/%m/%Y"),
'cert_time': certified['cert_time']['medianTime']
}
# replace old arc if this one is more recent
new_arc = True
index = 0
for a in self._graph[person.pubkey]['arcs']:
# if same arc already exists...
if a['id'] == arc['id']:
# if arc more recent, dont keep old one...
if arc['cert_time'] >= a['cert_time']:
self._graph[person.pubkey]['arcs'][index] = arc
new_arc = False
index += 1
# if arc not in graph...
if new_arc:
# add arc in graph
self._graph[person.pubkey]['arcs'].append(arc)
# if certified node not in person nodes
if certified['pubkey'] not in tuple(self._graph[person.pubkey]['connected']):
# add certified node to person node
self._graph[person.pubkey]['connected'].append(certified['pubkey'])
def add_person(self, person, status=None, arcs=None, connected=None):
"""
Add person as a new node in graph
:param Person person: Person instance
:param int status: Optional, default=None, Node status (see cutecoin.gui.views.wot)
:param list arcs: Optional, default=None, List of arcs (certified by person)
:param list connected: Optional, default=None, Public key list of the connected nodes around the person
:return:
"""
# functions keywords args are persistent... Need to reset it with None trick
status = status or (0 and (status is None))
arcs = arcs or (list() and (arcs is None))
connected = connected or (list() and (connected is None))
self._graph[person.pubkey] = {
'id': person.pubkey,
'arcs': arcs,
'text': person.name,
'tooltip': person.pubkey,
'status': status,
'connected': connected
}
'''
Created on 24 févr. 2015
@author: inso
'''
from ucoinpy.documents.peer import Peer, BMAEndpoint
from ucoinpy.api import bma
from .node import Node
import logging
import time
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot
class Network(QObject):
'''
A network is managing nodes polling and crawling of a
given community.
'''
nodes_changed = pyqtSignal()
def __init__(self, currency, nodes):
'''
Constructor of a network
:param str currency: The currency name of the community
:param list nodes: The nodes of the network
'''
super().__init__()
self.currency = currency
self._nodes = nodes
for n in self._nodes:
n.changed.connect(self.nodes_changed)
self.must_crawl = False
@classmethod
def create(cls, node):
'''
Create a new network with one knew node
Crawls the nodes from the first node to build the
community network
:param node: The first knew node of the network
'''
nodes = [node]
network = cls(node.currency, nodes)
nodes = network.crawling()
block_max = max([n.block for n in nodes])
for node in nodes:
node.check_sync(block_max)
network._nodes = nodes
return network
def merge_with_json(self, json_data):
'''
We merge with knew nodes when we
last stopped cutecoin
:param dict json_data: Nodes in json format
'''
for data in json_data:
node = Node.from_json(self.currency, data)
self._nodes.append(node)
logging.debug("Loading : {:}".format(data['pubkey']))
self._nodes = self.crawling()
@classmethod
def from_json(cls, currency, json_data):
'''
Load a network from a configured community
:param str currency: The currency name of a community
:param dict json_data: A json_data view of a network
'''
nodes = []
for data in json_data:
node = Node.from_json(currency, data)
nodes.append(node)
logging.debug("Loading : {:}".format(data['pubkey']))
block_max = max([n.block for n in nodes])
for node in nodes:
node.check_sync(block_max)
return cls(currency, nodes)
def jsonify(self):
'''
Get the network in json format.
:return: The network as a dict in json format.
'''
data = []
for node in self._nodes:
data.append(node.jsonify())
return data
def stop_crawling(self):
'''
Stop network nodes crawling.
'''
self.must_crawl = False
@property
def online_nodes(self):
'''
Get nodes which are in the ONLINE state.
'''
return [n for n in self._nodes if n.state == Node.ONLINE]
@property
def all_nodes(self):
'''
Get all knew nodes.
'''
return self._nodes.copy()
def add_nodes(self, node):
'''
Add a node to the network.
'''
self._nodes.append(node)
node.changed.connect(self.nodes_changed)
def start_perpetual_crawling(self):
'''
Start crawling which never stops.
To stop this crawling, call "stop_crawling" method.
'''
self.must_crawl = True
while self.must_crawl:
nodes = self.crawling(interval=10)
new_inlines = [n.endpoint.inline() for n in nodes]
last_inlines = [n.endpoint.inline() for n in self._nodes]
hash_new_nodes = hash(tuple(frozenset(sorted(new_inlines))))
hash_last_nodes = hash(tuple(frozenset(sorted(last_inlines))))
if hash_new_nodes != hash_last_nodes:
self._nodes = nodes
self.nodes_changed.emit()
for n in self._nodes:
n.changed.connect(self.nodes_changed)
def crawling(self, interval=0):
'''
One network crawling.
:param int interval: The interval between two nodes request.
'''
nodes = []
traversed_pubkeys = []
for n in self._nodes.copy():
logging.debug(traversed_pubkeys)
logging.debug("Peering : next to read : {0} : {1}".format(n.pubkey,
(n.pubkey not in traversed_pubkeys)))
if n.pubkey not in traversed_pubkeys:
n.peering_traversal(nodes,
traversed_pubkeys, interval)
time.sleep(interval)
block_max = max([n.block for n in nodes])
for node in [n for n in nodes if n.state == Node.ONLINE]:
node.check_sync(block_max)
#TODO: Offline nodes for too long have to be removed
#TODO: Corrupted nodes should maybe be removed faster ?
logging.debug("Nodes found : {0}".format(nodes))
return nodes
'''
Created on 21 févr. 2015
@author: inso
'''
from ucoinpy.documents.peer import Peer, BMAEndpoint, Endpoint
from ucoinpy.api import bma
from ucoinpy.api.bma import ConnectionHandler
from requests.exceptions import RequestException
from ...tools.exceptions import InvalidNodeCurrency
import logging
import time
from PyQt5.QtCore import QObject, pyqtSignal
class Node(QObject):
'''
A node is a peer seend from the client point of view.
This node can have multiple states :
- ONLINE : The node is available for requests
- OFFLINE: The node is disconnected
- DESYNCED : The node is online but is desynced from the network
- CORRUPTED : The node is corrupted, some weird behaviour is going on
'''
ONLINE = 1
OFFLINE = 2
DESYNCED = 3
CORRUPTED = 4
changed = pyqtSignal()
def __init__(self, currency, endpoints, pubkey, block, state):
'''
Constructor of a node
:param str currency: The currency name of this node community
:param list endpoints: Endpoints ucoinpy objects
:param str pubkey: The node pubkey
:param int block: The node last current block
:param state: The state of the node
'''
super().__init__()
self._endpoints = endpoints
self._pubkey = pubkey
self._block = block
self._state = state
self._neighbours = []
self._currency = currency
@classmethod
def from_address(cls, currency, address, port):
'''
Factory method to get a node from a given address
:param str currency: The node currency. None if we don't know\
the currency it should have, for example if its the first one we add
:param str address: The node address
:param int port: The node port
'''
peer_data = bma.network.Peering(ConnectionHandler(address, port)).get()
peer = Peer.from_signed_raw("{0}{1}\n".format(peer_data['raw'],
peer_data['signature']))
if currency is not None:
if peer.currency != currency:
raise InvalidNodeCurrency(peer.currency, currency)
node = cls(peer.currency, peer.endpoints, peer.pubkey, 0, Node.ONLINE)
node.refresh_state()
return node
@classmethod
def from_peer(cls, currency, peer):
'''
Factory method to get a node from a peer document.
:param str currency: The node currency. None if we don't know\
the currency it should have, for example if its the first one we add
:param peer: The peer document
'''
if currency is not None:
if peer.currency != currency:
raise InvalidNodeCurrency(peer.currency, currency)
node = cls(peer.currency, peer.endpoints, "", 0, Node.ONLINE)
node.refresh_state()
return node
@classmethod
def from_json(cls, currency, data):
endpoints = []
for endpoint_data in data['endpoints']:
endpoints.append(Endpoint.from_inline(endpoint_data))
if currency in data:
currency = data['currency']
node = cls(currency, endpoints, "", 0, Node.ONLINE)
node.refresh_state()
return node
def jsonify(self):
data = {'pubkey': self._pubkey,
'currency': self._currency}
endpoints = []
for e in self._endpoints:
endpoints.append(e.inline())
data['endpoints'] = endpoints
return data
@property
def pubkey(self):
return self._pubkey
@property
def endpoint(self):
return next((e for e in self._endpoints if type(e) is BMAEndpoint))
@property
def block(self):
return self._block
@property
def state(self):
return self._state
@property
def currency(self):
return self._currency
@property
def neighbours(self):
return self._neighbours
def check_sync(self, block):
if self._block < block:
self._state = Node.DESYNCED
else:
self._state = Node.ONLINE
def refresh_state(self):
emit_change = False
try:
informations = bma.network.Peering(self.endpoint.conn_handler()).get()
block = bma.blockchain.Current(self.endpoint.conn_handler()).get()
peers_data = bma.network.peering.Peers(self.endpoint.conn_handler()).get()
neighbours = []
for p in peers_data:
peer = Peer.from_signed_raw("{0}{1}\n".format(p['value']['raw'],
p['value']['signature']))
neighbours.append(peer.endpoints)
block_number = block["number"]
node_pubkey = informations["pubkey"]
node_currency = informations["currency"]
except ValueError as e:
if '404' in e:
block_number = 0
except RequestException:
self._state = Node.OFFLINE
emit_change = True
# If not is offline, do not refresh last data
if self._state != Node.OFFLINE:
# If not changed its currency, consider it corrupted
if node_currency != self._currency:
self.state = Node.CORRUPTED
emit_change = True
else:
if block_number != self._block:
self._block = block_number
emit_change = True
if node_pubkey != self._pubkey:
self._pubkey = node_pubkey
emit_change = True
logging.debug(neighbours)
new_inlines = [e.inline() for n in neighbours for e in n]
last_inlines = [e.inline() for n in self._neighbours for e in n]
hash_new_neighbours = hash(tuple(frozenset(sorted(new_inlines))))
hash_last_neighbours = hash(tuple(frozenset(sorted(last_inlines))))
if hash_new_neighbours != hash_last_neighbours:
self._neighbours = neighbours
emit_change = True
if emit_change:
self.changed.emit()
def peering_traversal(self, found_nodes,
traversed_pubkeys, interval):
logging.debug("Read {0} peering".format(self.pubkey))
traversed_pubkeys.append(self.pubkey)
self.refresh_state()
if self.pubkey not in [n.pubkey for n in found_nodes]:
# if node is corrupted remove it
if self._state != Node.CORRUPTED:
found_nodes.append(self)
try:
logging.debug(self.neighbours)
for n in self.neighbours:
e = next(e for e in n if type(e) is BMAEndpoint)
peering = bma.network.Peering(e.conn_handler()).get()
peer = Peer.from_signed_raw("{0}{1}\n".format(peering['raw'],
peering['signature']))
node = Node.from_peer(self._currency, peer)
logging.debug(traversed_pubkeys)
logging.debug("Traversing : next to read : {0} : {1}".format(node.pubkey,
(node.pubkey not in traversed_pubkeys)))
if node.pubkey not in traversed_pubkeys:
node.peering_traversal(found_nodes,
traversed_pubkeys, interval)
time.sleep(interval)
except RequestException as e:
self._state = Node.OFFLINE
'''
Created on 11 févr. 2014
@author: inso
'''
import logging
import functools
import datetime
from ucoinpy.api import bma
from ucoinpy import PROTOCOL_VERSION
from ucoinpy.documents.certification import SelfCertification
from ucoinpy.documents.membership import Membership
from ..tools.exceptions import Error, PersonNotFoundError,\
MembershipNotFoundError
from PyQt5.QtCore import QMutex
def load_cache(json_data):
for person_data in json_data['persons']:
person = Person.from_json(person_data)
Person._instances[person.pubkey] = person
def jsonify_cache():
data = []
for person in Person._instances.values():
data.append(person.jsonify())
return {'persons': data}
class cached(object):
'''
Decorator. Caches a function's return value each time it is called.
If called later with the same arguments, the cached value is returned
(not reevaluated).
Delete it to clear it from the cache
'''
def __init__(self, func):
self.func = func
def __call__(self, inst, community):
inst._cache_mutex.lock()
try:
inst._cache[community.currency]
except KeyError:
inst._cache[community.currency] = {}
try:
value = inst._cache[community.currency][self.func.__name__]
except KeyError:
value = self.func(inst, community)
inst._cache[community.currency][self.func.__name__] = value
finally:
inst._cache_mutex.unlock()
inst._cache_mutex.unlock()
return value
def __repr__(self):
'''Return the function's docstring.'''
return self.func.__repr__
def __get__(self, inst, objtype):
if inst is None:
return self.func
return functools.partial(self, inst)
#TODO: Change Person to Identity ?
class Person(object):
'''
A person with a name and a pubkey
'''
_instances = {}
def __init__(self, name, pubkey, cache):
'''
Initializing a person object.
:param str name: The person name, also known as its uid on the network
:param str pubkey: The person pubkey
:param cache: The last returned values of the person properties.
'''
self.name = name
self.pubkey = pubkey
self._cache = cache
self._cache_mutex = QMutex()
@classmethod
def lookup(cls, pubkey, community, cached=True):
'''
Get a person from the pubkey found in a community
:param str pubkey: The person pubkey
:param community: The community in which to look for the pubkey
:param bool cached: True if the person should be searched in the
cache before requesting the community.
:return: A new person if the pubkey was unknown or\
the known instance if pubkey was already known.
'''
if cached and pubkey in Person._instances:
return Person._instances[pubkey]
else:
try:
data = community.request(bma.wot.Lookup, req_args={'search': pubkey},
cached=cached)
except ValueError as e:
if '404' in str(e):
raise PersonNotFoundError(pubkey, community.name)
timestamp = 0
for result in data['results']:
if result["pubkey"] == pubkey:
uids = result['uids']
for uid in uids:
if uid["meta"]["timestamp"] > timestamp:
timestamp = uid["meta"]["timestamp"]
name = uid["uid"]
person = cls(name, pubkey, {})
Person._instances[pubkey] = person
logging.debug("{0}".format(Person._instances.keys()))
return person
raise PersonNotFoundError(pubkey, community.name)
@classmethod
def from_metadata(cls, metadata):
'''
Get a person from a metadata dict.
A metadata dict has a 'text' key corresponding to the person name,
and a 'id' key corresponding to the person pubkey.
:param dict metadata: The person metadata
:return: A new person if pubkey wasn't knwon, else the existing instance.
'''
name = metadata['text']
pubkey = metadata['id']
if pubkey in Person._instances:
return Person._instances[pubkey]
else:
person = cls(name, pubkey, {})
Person._instances[pubkey] = person
return person
@classmethod
#TODO: Remove name from person, contats should not use the person class
def from_json(cls, json_data):
'''
Create a person from json data
:param dict json_data: The person as a dict in json format
:return: A new person if pubkey wasn't known, else a new person instance.
'''
pubkey = json_data['pubkey']
if pubkey in Person._instances:
return Person._instances[pubkey]
else:
name = json_data['name']
if 'cache' in json_data:
cache = json_data['cache']
else:
cache = {}
person = cls(name, pubkey, cache)
Person._instances[pubkey] = person
return person
def selfcert(self, community):
'''
Get the person self certification.
This request is not cached in the person object.
:param community: The community target to request the self certification
:return: A SelfCertification ucoinpy object
'''
data = community.request(bma.wot.Lookup, req_args={'search': self.pubkey})
logging.debug(data)
timestamp = 0
for result in data['results']:
if result["pubkey"] == self.pubkey:
uids = result['uids']
for uid in uids:
if uid["meta"]["timestamp"] > timestamp:
timestamp = uid["meta"]["timestamp"]
name = uid["uid"]
signature = uid["self"]
return SelfCertification(PROTOCOL_VERSION,
community.currency,
self.pubkey,
timestamp,
name,
signature)
raise PersonNotFoundError(self.pubkey, community.name)
#TODO: Cache this data by returning only the timestamp instead of a datetime object
def get_join_date(self, community):
'''
Get the person join date.
This request is not cached in the person object.
:param community: The community target to request the join date
:return: A datetime object
'''
try:
search = community.request(bma.blockchain.Membership, {'search': self.pubkey})
membership_data = None
if len(search['memberships']) > 0:
membership_data = search['memberships'][0]
return datetime.datetime.fromtimestamp(community.get_block(membership_data['blockNumber']).mediantime).strftime("%d/%m/%Y %I:%M")
else:
return None
except ValueError as e:
if '400' in str(e):
raise MembershipNotFoundError(self.pubkey, community.name)
#TODO: Manage 'OUT' memberships
@cached
def membership(self, community):
'''
Get the person last membership document.
:param community: The community target to request the join date
:return: The membership data in BMA json format
'''
try:
search = community.request(bma.blockchain.Membership,
{'search': self.pubkey})
block_number = -1
for ms in search['memberships']:
if ms['blockNumber'] > block_number:
block_number = ms['blockNumber']
if 'type' in ms:
if ms['type'] is 'IN':
membership_data = ms
else:
membership_data = ms
if membership_data is None:
raise MembershipNotFoundError(self.pubkey, community.name)
except ValueError as e:
if '400' in str(e):
raise MembershipNotFoundError(self.pubkey, community.name)
return membership_data
@cached
def is_member(self, community):
'''
Check if the person is a member of a community
:param community: The community target to request the join date
:return: True if the person is a member of a community
'''
try:
certifiers = community.request(bma.wot.CertifiersOf, {'search': self.pubkey})
return certifiers['isMember']
except ValueError:
return False
@cached
def certifiers_of(self, community):
'''
Get the list of this person certifiers
:param community: The community target to request the join date
:return: The list of the certifiers of this community in BMA json format
'''
try:
certifiers = community.request(bma.wot.CertifiersOf, {'search': self.pubkey})
except ValueError as e:
logging.debug('bma.wot.CertifiersOf request ValueError : ' + str(e))
try:
data = community.request(bma.wot.Lookup, {'search': self.pubkey})
except ValueError as e:
logging.debug('bma.wot.Lookup request ValueError : ' + str(e))
return list()
# convert api data to certifiers list
certifiers = list()
# add certifiers of uid
for certifier in data['results'][0]['uids'][0]['others']:
# for each uid found for this pubkey...
for uid in certifier['uids']:
# add a certifier
certifier['uid'] = uid
certifier['cert_time'] = dict()
certifier['cert_time']['medianTime'] = community.get_block(certifier['meta']['block_number']).mediantime
certifiers.append(certifier)
return certifiers
except Exception as e:
logging.debug('bma.wot.CertifiersOf request error : ' + str(e))
return list()
return certifiers['certifications']
@cached
def certified_by(self, community):
'''
Get the list of persons certified by this person
:param community: The community target to request the join date
:return: The list of the certified persons of this community in BMA json format
'''
try:
certified_list = community.request(bma.wot.CertifiedBy, {'search': self.pubkey})
except ValueError as e:
logging.debug('bma.wot.CertifiersOf request ValueError : ' + str(e))
try:
data = community.request(bma.wot.Lookup, {'search': self.pubkey})
except ValueError as e:
logging.debug('bma.wot.Lookup request ValueError : ' + str(e))
return list()
certified_list = list()
for certified in data['results'][0]['signed']:
certified['cert_time'] = dict()
certified['cert_time']['medianTime'] = certified['meta']['timestamp']
certified_list.append(certified)
return certified_list
except Exception as e:
logging.debug('bma.wot.CertifiersOf request error : ' + str(e))
return list()
return certified_list['certifications']
def reload(self, func, community):
'''
Reload a cached property of this person in a community.
This method is thread safe.
This method clears the cache entry for this community and get it back.
:param func: The cached property to reload
:param community: The community to request for data
:return: True if a changed was made by the reload.
'''
self._cache_mutex.lock()
try:
if community.currency not in self._cache:
self._cache[community.currency] = {}
change = False
before = self._cache[community.currency][func.__name__]
value = func(self, community)
if not change:
if type(value) is dict:
hash_before = (hash(tuple(frozenset(sorted(before.keys())))),
hash(tuple(frozenset(sorted(before.items())))))
hash_after = (hash(tuple(frozenset(sorted(value.keys())))),
hash(tuple(frozenset(sorted(value.items())))))
change = hash_before != hash_after
elif type(value) is bool:
change = before != value
self._cache[community.currency][func.__name__] = value
except KeyError:
change = True
except Error:
return False
finally:
self._cache_mutex.unlock()
return change
def jsonify(self):
'''
Get the community as dict in json format.
:return: The community as a dict in json format
'''
data = {'name': self.name,
'pubkey': self.pubkey,
'cache': self._cache}
return data
'''
Created on 31 janv. 2015
@author: inso
'''
import logging
from ucoinpy.api import bma
from ucoinpy.documents.transaction import Transaction
class Transfer(object):
'''
A transfer is the lifecycle of a transaction.
TO_SEND means the transaction wasn't sent yet
AWAITING means the transaction is waiting for a blockchain validation
VALIDATED means the transaction was registered in the blockchain
REFUSED means the transaction took too long to be registered in the blockchain,
therefore it is considered as refused
DROPPED means the transaction was canceled locally. It can still be validated
in the blockchain if it was sent, if the guy is unlucky ;)
'''
TO_SEND = 0
AWAITING = 1
VALIDATED = 2
REFUSED = 3
DROPPED = 5
def __init__(self, txdoc, state, metadata):
'''
The constructor of a transfer.
Check for metadata keys which must be present :
- receiver
- block
- time
- issuer
- amount
- comment
:param txdoc: The Transaction ucoinpy object
:param state: The state of the Transfer (TO_SEND, AWAITING, VALIDATED, REFUSED or DROPPED)
:param metadata: The transfer metadata
'''
assert('receiver' in metadata)
assert('block' in metadata)
assert('time' in metadata)
assert('issuer' in metadata)
assert('amount' in metadata)
assert('comment' in metadata)
self.txdoc = txdoc
self.state = state
self._metadata = metadata
@classmethod
def initiate(cls, metadata):
'''
Create a new transfer in a "TO_SEND" state.
'''
return cls(None, Transfer.TO_SEND, metadata)
@classmethod
def create_validated(cls, txdoc, metadata):
'''
Create a new transfer in a "VALIDATED" state.
'''
return cls(txdoc, Transfer.VALIDATED, metadata)
@classmethod
def load(cls, data):
'''
Create a new transfer from a dict in json format.
'''
if data['state'] is Transfer.TO_SEND:
txdoc = None
else:
txdoc = Transaction.from_signed_raw(data['txdoc'])
return cls(txdoc, data['state'], data['metadata'])
@property
def metadata(self):
'''
:return: this transfer metadata
'''
return self._metadata
def jsonify(self):
'''
:return: The transfer as a dict in json format
'''
if self.txdoc:
txraw = self.txdoc.signed_raw()
else:
txraw = None
return {'txdoc': txraw,
'state': self.state,
'metadata': self._metadata}
def send(self, txdoc, community):
'''
Send a transaction and update the transfer state to AWAITING if accepted.
If the transaction was refused (return code != 200), state becomes REFUSED
The txdoc is saved as the transfer txdoc.
:param txdoc: A transaction ucoinpy object
:param community: The community target of the transaction
'''
try:
self.txdoc = txdoc
community.broadcast(bma.tx.Process,
post_args={'transaction': self.txdoc.signed_raw()})
self.state = Transfer.AWAITING
except ValueError as e:
if '400' in str(e):
self.state = Transfer.REFUSED
raise
finally:
self._metadata['block'] = community.current_blockid()['number']
self._metadata['time'] = community.get_block().mediantime
def check_registered(self, tx, block, time):
'''
Check if the transfer was registered in a block.
Update the transfer state to VALIDATED if it was registered.
:param tx: A transaction ucoinpy object found in the block
:param int block: The block number checked
:param int time: The time of the block
'''
if tx.signed_raw() == self.txdoc.signed_raw():
self.state = Transfer.VALIDATED
self._metadata['block'] = block
self._metadata['time'] = time
def check_refused(self, block):
'''
Check if the transfer was refused
If more than 15 blocks were mined since the transaction
transfer, it is considered as refused.
:param int block: The current block number
'''
if block > self._metadata['block'] + 15:
self.state = Transfer.REFUSED
def drop(self):
'''
Cancel the transfer locally.
The transfer state becomes "DROPPED".
'''
self.state = Transfer.DROPPED
class Received(Transfer):
def __init__(self, txdoc, metadata):
'''
A transfer were the receiver is the local user.
:param txdoc: The transaction document of the received transfer
:param metadata: The metadata of the transfer
'''
super().__init__(txdoc, Transfer.VALIDATED, metadata)
@classmethod
def load(cls, data):
'''
Create a transfer from a dict in json format.
:param data: The transfer as a dict in json format
'''
txdoc = Transaction.from_signed_raw(data['txdoc'])
return cls(txdoc, data['metadata'])
'''
Created on 1 févr. 2014
@author: inso
'''
from ucoinpy import PROTOCOL_VERSION
from ucoinpy.api import bma
from ucoinpy.documents.block import Block
from ucoinpy.documents.transaction import InputSource, OutputSource, Transaction
from ucoinpy.key import SigningKey
from ..tools.exceptions import NotEnoughMoneyError, NoPeerAvailable
from .transfer import Transfer, Received
from PyQt5.QtCore import QObject, pyqtSignal
import logging
class Cache():
def __init__(self, wallet):
self.latest_block = 0
self.wallet = wallet
self._transfers = []
self.available_sources = []
def load_from_json(self, data):
self._transfers = []
logging.debug(data)
data_sent = data['transfers']
for s in data_sent:
if s['metadata']['issuer'] == self.wallet.pubkey:
self._transfers.append(Transfer.load(s))
else:
self._transfers.append(Received.load(s))
for s in data['sources']:
self.available_sources.append(InputSource.from_inline(s['inline']))
self.latest_block = data['latest_block']
def jsonify(self):
data_transfer = []
for s in self.transfers:
data_transfer.append(s.jsonify())
data_sources = []
for s in self.available_sources:
s.index = 0
data_sources.append({'inline': "{0}\n".format(s.inline())})
return {'latest_block': self.latest_block,
'transfers': data_transfer,
'sources': data_sources}
@property
def transfers(self):
return [t for t in self._transfers if t.state != Transfer.DROPPED]
#TODO: Refactor to reduce this method size and split it to more methods
def refresh(self, community):
current_block = 0
try:
block_data = community.current_blockid()
current_block = block_data['number']
# Lets look if transactions took too long to be validated
awaiting = [t for t in self._transfers
if t.state == Transfer.AWAITING]
with_tx = community.request(bma.blockchain.TX)
# We parse only blocks with transactions
parsed_blocks = reversed(range(self.latest_block + 1,
current_block + 1))
logging.debug("Refresh from {0} to {1}".format(self.latest_block + 1,
current_block + 1))
parsed_blocks = [n for n in parsed_blocks
if n in with_tx['result']['blocks']]
self.wallet.refresh_progressed.emit(self.latest_block, current_block)
for block_number in parsed_blocks:
block = community.request(bma.blockchain.Block,
req_args={'number': block_number})
signed_raw = "{0}{1}\n".format(block['raw'],
block['signature'])
try:
block_doc = Block.from_signed_raw(signed_raw)
except:
logging.debug("Error in {0}".format(block_number))
raise
for tx in block_doc.transactions:
metadata = {'block': block_number,
'time': block_doc.mediantime,
'comment': tx.comment,
'issuer': tx.issuers[0]}
receivers = [o.pubkey for o in tx.outputs
if o.pubkey != metadata['issuer']]
metadata['receiver'] = receivers[0]
in_issuers = len([i for i in tx.issuers
if i == self.wallet.pubkey]) > 0
if in_issuers:
outputs = [o for o in tx.outputs
if o.pubkey != self.wallet.pubkey]
amount = 0
for o in outputs:
amount += o.amount
metadata['amount'] = amount
awaiting = [t for t in self._transfers
if t.state == Transfer.AWAITING]
awaiting_docs = [t.txdoc.signed_raw() for t in awaiting]
if tx.signed_raw() not in awaiting_docs:
transfer = Transfer.create_validated(tx,
metadata.copy())
self._transfers.append(transfer)
else:
for transfer in awaiting:
transfer.check_registered(tx, block_number,
block_doc.mediantime)
else:
outputs = [o for o in tx.outputs
if o.pubkey == self.wallet.pubkey]
if len(outputs) > 0:
amount = 0
for o in outputs:
amount += o.amount
metadata['amount'] = amount
self._transfers.append(Received(tx,
metadata.copy()))
logging.debug("Receivers : {0}".format(self.wallet.receivers(self.wallet.refresh_progressed)))
self.wallet.refresh_progressed.emit(current_block - block_number,
current_block - self.latest_block)
if current_block > self.latest_block:
self.available_sources = self.wallet.sources(community)
for transfer in awaiting:
transfer.check_refused(current_block)
except NoPeerAvailable:
return
self.latest_block = current_block
class Wallet(QObject):
'''
A wallet is used to manage money with a unique key.
'''
refresh_progressed = pyqtSignal(int, int)
def __init__(self, walletid, pubkey, name):
'''
Constructor of a wallet object
:param int walletid: The wallet number, unique between all wallets
:param str pubkey: The wallet pubkey
:param str name: The wallet name
'''
super().__init__()
self.coins = []
self.walletid = walletid
self.pubkey = pubkey
self.name = name
self.caches = {}
@classmethod
def create(cls, walletid, salt, password, name):
'''
Factory method to create a new wallet
:param int walletid: The wallet number, unique between all wallets
:param str salt: The account salt
:param str password: The account password
:param str name: The account name
'''
if walletid == 0:
key = SigningKey(salt, password)
else:
key = SigningKey("{0}{1}".format(salt, walletid), password)
return cls(walletid, key.pubkey, name)
@classmethod
def load(cls, json_data):
'''
Factory method to load a saved wallet.
:param dict json_data: The wallet as a dict in json format
'''
walletid = json_data['walletid']
pubkey = json_data['pubkey']
name = json_data['name']
return cls(walletid, pubkey, name)
def load_caches(self, json_data):
'''
Load this wallet caches.
Each cache correspond to one different community.
:param dict json_data: The caches as a dict in json format
'''
for currency in json_data:
if currency != 'version':
self.caches[currency] = Cache(self)
self.caches[currency].load_from_json(json_data[currency])
def jsonify_caches(self):
'''
Get this wallet caches as json.
:return: The wallet caches as a dict in json format
'''
data = {}
for currency in self.caches:
data[currency] = self.caches[currency].jsonify()
return data
def refresh_cache(self, community):
'''
Refresh the cache of this wallet for the specified community.
:param community: The community to refresh its cache
'''
if community.currency not in self.caches:
self.caches[community.currency] = Cache(self)
self.caches[community.currency].refresh(community)
def check_password(self, salt, password):
'''
Check if wallet password is ok.
:param salt: The account salt
:param password: The given password
:return: True if (salt, password) generates the good public key
.. warning:: Generates a new temporary SigningKey from salt and password
'''
key = None
if self.walletid == 0:
key = SigningKey(salt, password)
else:
key = SigningKey("{0}{1}".format(salt, self.walletid), password)
return (key.pubkey == self.pubkey)
def relative_value(self, community):
'''
Get wallet value relative to last generated UD
:param community: The community to get value
:return: The wallet relative value
'''
value = self.value(community)
ud = community.dividend
relative_value = value / float(ud)
return relative_value
def value(self, community):
'''
Get wallet absolute value
:param community: The community to get value
:return: The wallet absolute value
'''
value = 0
for s in self.sources(community):
value += s.amount
return value
def tx_inputs(self, amount, community):
'''
Get inputs to generate a transaction with a given amount of money
:param int amount: The amount target value
:param community: The community target of the transaction
:return: The list of inputs to use in the transaction document
'''
value = 0
inputs = []
cache = self.caches[community.currency]
logging.debug("Available inputs : {0}".format(cache.available_sources))
buf_inputs = list(cache.available_sources)
for s in cache.available_sources:
value += s.amount
s.index = 0
inputs.append(s)
buf_inputs.remove(s)
if value >= amount:
return (inputs, buf_inputs)
raise NotEnoughMoneyError(value, community.currency,
len(inputs), amount)
def tx_outputs(self, pubkey, amount, inputs):
'''
Get outputs to generate a transaction with a given amount of money
:param str pubkey: The target pubkey of the transaction
:param int amount: The amount to send
:param list inputs: The inputs used to send the given amount of money
:return: The list of outputs to use in the transaction document
'''
outputs = []
inputs_value = 0
for i in inputs:
logging.debug(i)
inputs_value += i.amount
overhead = inputs_value - int(amount)
outputs.append(OutputSource(pubkey, int(amount)))
if overhead != 0:
outputs.append(OutputSource(self.pubkey, overhead))
return outputs
def send_money(self, salt, password, community,
recipient, amount, message):
'''
Send money to a given recipient in a specified community
:param str salt: The account salt
:param str password: The account password
:param community: The community target of the transfer
:param str recipient: The pubkey of the recipient
:param int amount: The amount of money to transfer
:param str message: The message to send with the transfer
'''
time = community.get_block().mediantime
block_number = community.current_blockid()['number']
key = None
logging.debug("Key : {0} : {1}".format(salt, password))
if self.walletid == 0:
key = SigningKey(salt, password)
else:
key = SigningKey("{0}{1}".format(salt, self.walletid), password)
logging.debug("Sender pubkey:{0}".format(key.pubkey))
metadata = {'block': block_number,
'time': time,
'amount': amount,
'issuer': key.pubkey,
'receiver': recipient,
'comment': message
}
transfer = Transfer.initiate(metadata)
self.caches[community.currency]._transfers.append(transfer)
result = self.tx_inputs(int(amount), community)
inputs = result[0]
self.caches[community.currency].available_sources = result[1]
logging.debug("Inputs : {0}".format(inputs))
outputs = self.tx_outputs(recipient, amount, inputs)
logging.debug("Outputs : {0}".format(outputs))
tx = Transaction(PROTOCOL_VERSION, community.currency,
[self.pubkey], inputs,
outputs, message, None)
logging.debug("TX : {0}".format(tx.raw()))
tx.sign([key])
logging.debug("Transaction : {0}".format(tx.signed_raw()))
transfer.send(tx, community)
def sources(self, community):
'''
Get available sources in a given community
:param community: The community where we want available sources
:return: List of InputSource ucoinpy objects
'''
data = community.request(bma.tx.Sources,
req_args={'pubkey': self.pubkey})
tx = []
for s in data['sources']:
tx.append(InputSource.from_bma(s))
return tx
def transfers(self, community):
'''
Get all transfers objects of this wallet
:param community: The community we want to get the executed transfers
:return: A list of Transfer objects
'''
return self.caches[community.currency].transfers
def jsonify(self):
'''
Get the wallet as json format.
:return: The wallet as a dict in json format.
'''
return {'walletid': self.walletid,
'pubkey': self.pubkey,
'name': self.name}
'''
Created on 27 févr. 2015
@author: inso
'''
from PyQt5.QtCore import QObject, pyqtSlot, pyqtSignal
import logging
import time
from requests.exceptions import RequestException
from ...tools.exceptions import NoPeerAvailable
class BlockchainWatcher(QObject):
def __init__(self, account, community):
super().__init__()
self.account = account
self.community = community
self.time_to_wait = int(self.community.parameters['avgGenTime'] / 10)
self.exiting = False
blockid = self.community.current_blockid()
self.last_block = blockid['number']
@pyqtSlot()
def watch(self):
while not self.exiting:
time.sleep(self.time_to_wait)
try:
blockid = self.community.current_blockid()
block_number = blockid['number']
if self.last_block != block_number:
self.community.refresh_cache()
for w in self.account.wallets:
w.refresh_cache(self.community)
logging.debug("New block, {0} mined in {1}".format(block_number,
self.community.currency))
self.new_block_mined.emit(block_number)
self.last_block = block_number
except NoPeerAvailable:
return
except RequestException as e:
self.connection_error.emit("Cannot check new block : {0}".format(str(e)))
new_block_mined = pyqtSignal(int)
connection_error = pyqtSignal(str)
\ No newline at end of file
'''
Created on 27 févr. 2015
@author: inso
'''
from PyQt5.QtCore import QObject, pyqtSlot
class NetworkWatcher(QObject):
'''
This will crawl the network to always
have up to date informations about the nodes
'''
def __init__(self, community):
super().__init__()
self.community = community
@pyqtSlot()
def watch(self):
#self.community.network.moveToThread(self.thread())
self.community.network.start_perpetual_crawling()
@pyqtSlot()
def stop(self):
self.community.network.stop_crawling()
'''
Created on 27 févr. 2015
@author: inso
'''
from PyQt5.QtCore import QObject, pyqtSlot, pyqtSignal
from ..person import Person
import logging
class PersonsWatcher(QObject):
'''
This will crawl the network to always
have up to date informations about the nodes
'''
person_changed = pyqtSignal(str)
end_watching = pyqtSignal()
def __init__(self, community):
super().__init__()
self.community = community
@pyqtSlot()
def watch(self):
logging.debug("Watching persons")
for p in Person._instances.values():
for func in [Person.membership,
Person.is_member,
Person.certifiers_of,
Person.certified_by]:
if p.reload(func, self.community):
logging.debug("Change detected on {0} about {1}".format(p.pubkey,
func.__name__))
self.person_changed.emit(p.pubkey)
self.end_watching.emit()
'''
Created on 11 mars 2014
@author: inso
'''
'''
Created on 24 dec. 2014
@author: inso
'''
from PyQt5.QtWidgets import QDialog, QMessageBox, QDialogButtonBox
from ..tools.exceptions import NoPeerAvailable
from ..gen_resources.certification_uic import Ui_CertificationDialog
class CertificationDialog(QDialog, Ui_CertificationDialog):
'''
classdocs
'''
def __init__(self, certifier, password_asker):
'''
Constructor
'''
super().__init__()
self.setupUi(self)
self.account = certifier
self.password_asker = password_asker
self.community = self.account.communities[0]
for community in self.account.communities:
self.combo_community.addItem(community.currency)
for contact in certifier.contacts:
self.combo_contact.addItem(contact.name)
def accept(self):
if self.radio_contact.isChecked():
index = self.combo_contact.currentIndex()
pubkey = self.account.contacts[index].pubkey
else:
pubkey = self.edit_pubkey.text()
password = self.password_asker.exec_()
if password == "":
return
try:
self.account.certify(password, self.community, pubkey)
QMessageBox.information(self, "Certification",
"Success certifying {0} from {1}".format(pubkey,
self.community.currency))
except ValueError as e:
QMessageBox.critical(self, "Certification",
"Something wrong happened : {0}".format(e),
QMessageBox.Ok)
return
except NoPeerAvailable as e:
QMessageBox.critical(self, "Certification",
"Couldn't connect to network : {0}".format(e),
QMessageBox.Ok)
return
except Exception as e:
QMessageBox.critical(self, "Error",
"{0}".format(e),
QMessageBox.Ok)
return
super().accept()
def change_current_community(self, index):
self.community = self.account.communities[index]
if self.account.pubkey in self.community.members_pubkeys():
self.button_box.button(QDialogButtonBox.Ok).setEnabled(True)
else:
self.button_box.button(QDialogButtonBox.Ok).setEnabled(False)
def recipient_mode_changed(self, pubkey_toggled):
self.edit_pubkey.setEnabled(pubkey_toggled)
self.combo_contact.setEnabled(not pubkey_toggled)