From 0b0e2c513edc42913b5245eeca24ecf47fab90e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoel=20Ben=C3=ADtez=20Fonseca?= Date: Thu, 2 Mar 2017 09:20:37 -0500 Subject: [PATCH] Adding nstock appliance --- nstock/.gitignore | 47 + nstock/ABOUT | 2 + nstock/LICENSE | 21 + nstock/README.md | 31 + nstock/__init__.py | 1 + nstock/cache/.gitignore | 5 + nstock/controllers/appadmin.py | 701 +++++ nstock/controllers/default.py | 60 + nstock/controllers/desk.py | 247 ++ nstock/controllers/item.py | 197 ++ nstock/controllers/notifications.py | 60 + nstock/controllers/org.py | 151 + nstock/controllers/plugin_ckeditor.py | 59 + nstock/controllers/plugin_comment.py | 49 + nstock/controllers/plugin_package.py | 124 + nstock/controllers/plugin_photoset.py | 250 ++ nstock/controllers/plugin_picture.py | 239 ++ nstock/controllers/plugin_text.py | 153 + nstock/cron/.gitignore | 5 + nstock/databases/.gitignore | 5 + nstock/errors/.gitignore | 5 + nstock/languages/default.py | 122 + nstock/languages/en-us.py | 232 ++ nstock/languages/en.py | 123 + nstock/languages/es-ES.py | 768 +++++ nstock/languages/es.py | 772 +++++ nstock/languages/plural-en.py | 17 + nstock/languages/plural-es.py | 8 + nstock/models/db.py | 132 + nstock/models/dc.py | 219 ++ nstock/models/desk/z_menu.py | 23 + nstock/models/menu.py | 178 ++ nstock/models/plugin_comment.py | 36 + nstock/models/plugin_package.py | 39 + nstock/models/plugin_photoset.py | 52 + nstock/models/plugin_picture.py | 96 + nstock/models/plugin_text.py | 42 + nstock/modules/__init__.py | 1 + nstock/modules/app.py | 212 ++ nstock/modules/content_plugin.py | 48 + nstock/modules/html2text.py | 914 ++++++ nstock/modules/mail.py | 28 + nstock/modules/perms.py | 35 + nstock/modules/plugin_ckeditor.py | 238 ++ nstock/modules/plugin_package/__init__.py | 0 .../modules/plugin_package/content_package.py | 50 + nstock/modules/plugin_photoset/__init__.py | 0 .../plugin_photoset/content_photoset.py | 41 + nstock/modules/plugin_picture/__init__.py | 0 .../modules/plugin_picture/content_picture.py | 34 + nstock/modules/plugin_text/__init__.py | 1 + nstock/modules/plugin_text/content_text.py | 32 + nstock/modules/slugify/__init__.py | 6 + nstock/modules/slugify/slugify.py | 160 + nstock/modules/unidecode/__init__.py | 103 + nstock/modules/unidecode/util.py | 58 + nstock/modules/unidecode/x000.py | 165 + nstock/modules/unidecode/x001.py | 258 ++ nstock/modules/unidecode/x002.py | 257 ++ nstock/modules/unidecode/x003.py | 257 ++ nstock/modules/unidecode/x004.py | 257 ++ nstock/modules/unidecode/x005.py | 257 ++ nstock/modules/unidecode/x006.py | 257 ++ nstock/modules/unidecode/x007.py | 257 ++ nstock/modules/unidecode/x009.py | 257 ++ nstock/modules/unidecode/x00a.py | 257 ++ nstock/modules/unidecode/x00b.py | 257 ++ nstock/modules/unidecode/x00c.py | 257 ++ nstock/modules/unidecode/x00d.py | 257 ++ nstock/modules/unidecode/x00e.py | 257 ++ nstock/modules/unidecode/x00f.py | 257 ++ nstock/modules/unidecode/x010.py | 257 ++ nstock/modules/unidecode/x011.py | 257 ++ nstock/modules/unidecode/x012.py | 258 ++ nstock/modules/unidecode/x013.py | 257 ++ nstock/modules/unidecode/x014.py | 258 ++ nstock/modules/unidecode/x015.py | 258 ++ nstock/modules/unidecode/x016.py | 257 ++ nstock/modules/unidecode/x017.py | 257 ++ nstock/modules/unidecode/x018.py | 257 ++ nstock/modules/unidecode/x01d.py | 257 ++ nstock/modules/unidecode/x01e.py | 257 ++ nstock/modules/unidecode/x01f.py | 257 ++ nstock/modules/unidecode/x020.py | 257 ++ nstock/modules/unidecode/x021.py | 257 ++ nstock/modules/unidecode/x022.py | 257 ++ nstock/modules/unidecode/x023.py | 257 ++ nstock/modules/unidecode/x024.py | 257 ++ nstock/modules/unidecode/x025.py | 257 ++ nstock/modules/unidecode/x026.py | 257 ++ nstock/modules/unidecode/x027.py | 257 ++ nstock/modules/unidecode/x028.py | 258 ++ nstock/modules/unidecode/x029.py | 257 ++ nstock/modules/unidecode/x02a.py | 257 ++ nstock/modules/unidecode/x02c.py | 257 ++ nstock/modules/unidecode/x02e.py | 257 ++ nstock/modules/unidecode/x02f.py | 257 ++ nstock/modules/unidecode/x030.py | 257 ++ nstock/modules/unidecode/x031.py | 257 ++ nstock/modules/unidecode/x032.py | 257 ++ nstock/modules/unidecode/x033.py | 257 ++ nstock/modules/unidecode/x04d.py | 257 ++ nstock/modules/unidecode/x04e.py | 258 ++ nstock/modules/unidecode/x04f.py | 258 ++ nstock/modules/unidecode/x050.py | 258 ++ nstock/modules/unidecode/x051.py | 258 ++ nstock/modules/unidecode/x052.py | 258 ++ nstock/modules/unidecode/x053.py | 258 ++ nstock/modules/unidecode/x054.py | 258 ++ nstock/modules/unidecode/x055.py | 258 ++ nstock/modules/unidecode/x056.py | 258 ++ nstock/modules/unidecode/x057.py | 258 ++ nstock/modules/unidecode/x058.py | 258 ++ nstock/modules/unidecode/x059.py | 258 ++ nstock/modules/unidecode/x05a.py | 258 ++ nstock/modules/unidecode/x05b.py | 258 ++ nstock/modules/unidecode/x05c.py | 258 ++ nstock/modules/unidecode/x05d.py | 258 ++ nstock/modules/unidecode/x05e.py | 258 ++ nstock/modules/unidecode/x05f.py | 258 ++ nstock/modules/unidecode/x060.py | 258 ++ nstock/modules/unidecode/x061.py | 258 ++ nstock/modules/unidecode/x062.py | 258 ++ nstock/modules/unidecode/x063.py | 258 ++ nstock/modules/unidecode/x064.py | 258 ++ nstock/modules/unidecode/x065.py | 258 ++ nstock/modules/unidecode/x066.py | 258 ++ nstock/modules/unidecode/x067.py | 258 ++ nstock/modules/unidecode/x068.py | 258 ++ nstock/modules/unidecode/x069.py | 258 ++ nstock/modules/unidecode/x06a.py | 258 ++ nstock/modules/unidecode/x06b.py | 258 ++ nstock/modules/unidecode/x06c.py | 258 ++ nstock/modules/unidecode/x06d.py | 258 ++ nstock/modules/unidecode/x06e.py | 258 ++ nstock/modules/unidecode/x06f.py | 258 ++ nstock/modules/unidecode/x070.py | 258 ++ nstock/modules/unidecode/x071.py | 258 ++ nstock/modules/unidecode/x072.py | 258 ++ nstock/modules/unidecode/x073.py | 258 ++ nstock/modules/unidecode/x074.py | 258 ++ nstock/modules/unidecode/x075.py | 258 ++ nstock/modules/unidecode/x076.py | 258 ++ nstock/modules/unidecode/x077.py | 258 ++ nstock/modules/unidecode/x078.py | 258 ++ nstock/modules/unidecode/x079.py | 258 ++ nstock/modules/unidecode/x07a.py | 258 ++ nstock/modules/unidecode/x07b.py | 258 ++ nstock/modules/unidecode/x07c.py | 258 ++ nstock/modules/unidecode/x07d.py | 258 ++ nstock/modules/unidecode/x07e.py | 258 ++ nstock/modules/unidecode/x07f.py | 258 ++ nstock/modules/unidecode/x080.py | 258 ++ nstock/modules/unidecode/x081.py | 258 ++ nstock/modules/unidecode/x082.py | 258 ++ nstock/modules/unidecode/x083.py | 258 ++ nstock/modules/unidecode/x084.py | 258 ++ nstock/modules/unidecode/x085.py | 258 ++ nstock/modules/unidecode/x086.py | 258 ++ nstock/modules/unidecode/x087.py | 258 ++ nstock/modules/unidecode/x088.py | 258 ++ nstock/modules/unidecode/x089.py | 258 ++ nstock/modules/unidecode/x08a.py | 258 ++ nstock/modules/unidecode/x08b.py | 258 ++ nstock/modules/unidecode/x08c.py | 258 ++ nstock/modules/unidecode/x08d.py | 258 ++ nstock/modules/unidecode/x08e.py | 258 ++ nstock/modules/unidecode/x08f.py | 258 ++ nstock/modules/unidecode/x090.py | 258 ++ nstock/modules/unidecode/x091.py | 258 ++ nstock/modules/unidecode/x092.py | 258 ++ nstock/modules/unidecode/x093.py | 258 ++ nstock/modules/unidecode/x094.py | 258 ++ nstock/modules/unidecode/x095.py | 258 ++ nstock/modules/unidecode/x096.py | 258 ++ nstock/modules/unidecode/x097.py | 258 ++ nstock/modules/unidecode/x098.py | 258 ++ nstock/modules/unidecode/x099.py | 258 ++ nstock/modules/unidecode/x09a.py | 258 ++ nstock/modules/unidecode/x09b.py | 258 ++ nstock/modules/unidecode/x09c.py | 258 ++ nstock/modules/unidecode/x09d.py | 258 ++ nstock/modules/unidecode/x09e.py | 258 ++ nstock/modules/unidecode/x09f.py | 257 ++ nstock/modules/unidecode/x0a0.py | 258 ++ nstock/modules/unidecode/x0a1.py | 258 ++ nstock/modules/unidecode/x0a2.py | 258 ++ nstock/modules/unidecode/x0a3.py | 258 ++ nstock/modules/unidecode/x0a4.py | 257 ++ nstock/modules/unidecode/x0ac.py | 258 ++ nstock/modules/unidecode/x0ad.py | 258 ++ nstock/modules/unidecode/x0ae.py | 258 ++ nstock/modules/unidecode/x0af.py | 258 ++ nstock/modules/unidecode/x0b0.py | 258 ++ nstock/modules/unidecode/x0b1.py | 258 ++ nstock/modules/unidecode/x0b2.py | 258 ++ nstock/modules/unidecode/x0b3.py | 258 ++ nstock/modules/unidecode/x0b4.py | 258 ++ nstock/modules/unidecode/x0b5.py | 258 ++ nstock/modules/unidecode/x0b6.py | 258 ++ nstock/modules/unidecode/x0b7.py | 258 ++ nstock/modules/unidecode/x0b8.py | 258 ++ nstock/modules/unidecode/x0b9.py | 258 ++ nstock/modules/unidecode/x0ba.py | 258 ++ nstock/modules/unidecode/x0bb.py | 258 ++ nstock/modules/unidecode/x0bc.py | 258 ++ nstock/modules/unidecode/x0bd.py | 258 ++ nstock/modules/unidecode/x0be.py | 258 ++ nstock/modules/unidecode/x0bf.py | 258 ++ nstock/modules/unidecode/x0c0.py | 258 ++ nstock/modules/unidecode/x0c1.py | 258 ++ nstock/modules/unidecode/x0c2.py | 258 ++ nstock/modules/unidecode/x0c3.py | 258 ++ nstock/modules/unidecode/x0c4.py | 258 ++ nstock/modules/unidecode/x0c5.py | 258 ++ nstock/modules/unidecode/x0c6.py | 258 ++ nstock/modules/unidecode/x0c7.py | 258 ++ nstock/modules/unidecode/x0c8.py | 258 ++ nstock/modules/unidecode/x0c9.py | 258 ++ nstock/modules/unidecode/x0ca.py | 258 ++ nstock/modules/unidecode/x0cb.py | 258 ++ nstock/modules/unidecode/x0cc.py | 258 ++ nstock/modules/unidecode/x0cd.py | 258 ++ nstock/modules/unidecode/x0ce.py | 258 ++ nstock/modules/unidecode/x0cf.py | 258 ++ nstock/modules/unidecode/x0d0.py | 258 ++ nstock/modules/unidecode/x0d1.py | 258 ++ nstock/modules/unidecode/x0d2.py | 258 ++ nstock/modules/unidecode/x0d3.py | 258 ++ nstock/modules/unidecode/x0d4.py | 258 ++ nstock/modules/unidecode/x0d5.py | 258 ++ nstock/modules/unidecode/x0d6.py | 258 ++ nstock/modules/unidecode/x0d7.py | 257 ++ nstock/modules/unidecode/x0f9.py | 258 ++ nstock/modules/unidecode/x0fa.py | 257 ++ nstock/modules/unidecode/x0fb.py | 258 ++ nstock/modules/unidecode/x0fc.py | 258 ++ nstock/modules/unidecode/x0fd.py | 257 ++ nstock/modules/unidecode/x0fe.py | 258 ++ nstock/modules/unidecode/x0ff.py | 258 ++ nstock/modules/unidecode/x1d4.py | 258 ++ nstock/modules/unidecode/x1d5.py | 258 ++ nstock/modules/unidecode/x1d6.py | 258 ++ nstock/modules/unidecode/x1d7.py | 258 ++ nstock/modules/whoosh/__init__.py | 49 + nstock/modules/whoosh/analysis/__init__.py | 69 + nstock/modules/whoosh/analysis/acore.py | 156 + nstock/modules/whoosh/analysis/analyzers.py | 296 ++ nstock/modules/whoosh/analysis/filters.py | 479 +++ nstock/modules/whoosh/analysis/intraword.py | 494 +++ nstock/modules/whoosh/analysis/morph.py | 267 ++ nstock/modules/whoosh/analysis/ngrams.py | 237 ++ nstock/modules/whoosh/analysis/tokenizers.py | 338 +++ nstock/modules/whoosh/automata/__init__.py | 0 nstock/modules/whoosh/automata/fsa.py | 715 +++++ nstock/modules/whoosh/automata/glob.py | 90 + nstock/modules/whoosh/automata/lev.py | 30 + nstock/modules/whoosh/automata/nfa.py | 388 +++ nstock/modules/whoosh/automata/reg.py | 135 + nstock/modules/whoosh/classify.py | 377 +++ nstock/modules/whoosh/codec/__init__.py | 32 + nstock/modules/whoosh/codec/base.py | 843 ++++++ nstock/modules/whoosh/codec/memory.py | 334 +++ nstock/modules/whoosh/codec/plaintext.py | 452 +++ nstock/modules/whoosh/codec/whoosh3.py | 1291 ++++++++ nstock/modules/whoosh/collectors.py | 1165 +++++++ nstock/modules/whoosh/columns.py | 1474 +++++++++ nstock/modules/whoosh/compat.py | 208 ++ nstock/modules/whoosh/externalsort.py | 240 ++ nstock/modules/whoosh/fields.py | 1613 ++++++++++ nstock/modules/whoosh/filedb/__init__.py | 0 nstock/modules/whoosh/filedb/compound.py | 331 ++ nstock/modules/whoosh/filedb/filestore.py | 662 ++++ nstock/modules/whoosh/filedb/filetables.py | 735 +++++ nstock/modules/whoosh/filedb/gae.py | 164 + nstock/modules/whoosh/filedb/structfile.py | 402 +++ nstock/modules/whoosh/formats.py | 481 +++ nstock/modules/whoosh/highlight.py | 954 ++++++ nstock/modules/whoosh/idsets.py | 703 +++++ nstock/modules/whoosh/index.py | 710 +++++ nstock/modules/whoosh/lang/__init__.py | 140 + nstock/modules/whoosh/lang/dmetaphone.py | 415 +++ nstock/modules/whoosh/lang/isri.py | 382 +++ nstock/modules/whoosh/lang/lovins.py | 570 ++++ nstock/modules/whoosh/lang/morph_en.py | 933 ++++++ nstock/modules/whoosh/lang/paicehusk.py | 242 ++ nstock/modules/whoosh/lang/phonetic.py | 119 + nstock/modules/whoosh/lang/porter.py | 175 ++ nstock/modules/whoosh/lang/porter2.py | 313 ++ .../modules/whoosh/lang/snowball/__init__.py | 74 + nstock/modules/whoosh/lang/snowball/bases.py | 133 + nstock/modules/whoosh/lang/snowball/danish.py | 115 + nstock/modules/whoosh/lang/snowball/dutch.py | 173 ++ .../modules/whoosh/lang/snowball/english.py | 465 +++ .../modules/whoosh/lang/snowball/finnish.py | 266 ++ nstock/modules/whoosh/lang/snowball/french.py | 348 +++ nstock/modules/whoosh/lang/snowball/german.py | 144 + .../modules/whoosh/lang/snowball/hungarian.py | 268 ++ .../modules/whoosh/lang/snowball/italian.py | 230 ++ .../modules/whoosh/lang/snowball/norwegian.py | 84 + .../modules/whoosh/lang/snowball/portugese.py | 205 ++ .../modules/whoosh/lang/snowball/romanian.py | 257 ++ .../modules/whoosh/lang/snowball/russian.py | 422 +++ .../modules/whoosh/lang/snowball/spanish.py | 248 ++ .../modules/whoosh/lang/snowball/swedish.py | 80 + nstock/modules/whoosh/lang/stopwords.py | 285 ++ nstock/modules/whoosh/lang/wordnet.py | 242 ++ nstock/modules/whoosh/legacy.py | 77 + nstock/modules/whoosh/matching/__init__.py | 31 + nstock/modules/whoosh/matching/binary.py | 803 +++++ nstock/modules/whoosh/matching/combo.py | 312 ++ nstock/modules/whoosh/matching/mcore.py | 622 ++++ nstock/modules/whoosh/matching/wrappers.py | 572 ++++ nstock/modules/whoosh/multiproc.py | 385 +++ nstock/modules/whoosh/qparser/__init__.py | 30 + nstock/modules/whoosh/qparser/common.py | 65 + nstock/modules/whoosh/qparser/dateparse.py | 922 ++++++ nstock/modules/whoosh/qparser/default.py | 439 +++ nstock/modules/whoosh/qparser/plugins.py | 1413 +++++++++ nstock/modules/whoosh/qparser/syntax.py | 645 ++++ nstock/modules/whoosh/qparser/taggers.py | 93 + nstock/modules/whoosh/query/__init__.py | 36 + nstock/modules/whoosh/query/compound.py | 660 ++++ nstock/modules/whoosh/query/nested.py | 415 +++ nstock/modules/whoosh/query/positional.py | 249 ++ nstock/modules/whoosh/query/qcolumns.py | 117 + nstock/modules/whoosh/query/qcore.py | 715 +++++ nstock/modules/whoosh/query/ranges.py | 347 +++ nstock/modules/whoosh/query/spans.py | 881 ++++++ nstock/modules/whoosh/query/terms.py | 535 ++++ nstock/modules/whoosh/query/wrappers.py | 198 ++ nstock/modules/whoosh/reading.py | 1296 ++++++++ nstock/modules/whoosh/scoring.py | 616 ++++ nstock/modules/whoosh/searching.py | 1653 ++++++++++ nstock/modules/whoosh/sorting.py | 1156 +++++++ nstock/modules/whoosh/spelling.py | 343 +++ nstock/modules/whoosh/support/__init__.py | 0 nstock/modules/whoosh/support/base85.py | 103 + nstock/modules/whoosh/support/bench.py | 610 ++++ nstock/modules/whoosh/support/charset.py | 1379 +++++++++ nstock/modules/whoosh/support/levenshtein.py | 70 + .../modules/whoosh/support/relativedelta.py | 437 +++ nstock/modules/whoosh/support/unicode.py | 527 ++++ nstock/modules/whoosh/system.py | 79 + nstock/modules/whoosh/util/__init__.py | 142 + nstock/modules/whoosh/util/cache.py | 375 +++ nstock/modules/whoosh/util/filelock.py | 163 + nstock/modules/whoosh/util/loading.py | 84 + nstock/modules/whoosh/util/numeric.py | 317 ++ nstock/modules/whoosh/util/numlists.py | 373 +++ nstock/modules/whoosh/util/testing.py | 130 + nstock/modules/whoosh/util/text.py | 132 + nstock/modules/whoosh/util/times.py | 467 +++ nstock/modules/whoosh/util/varints.py | 110 + nstock/modules/whoosh/util/versions.py | 165 + nstock/modules/whoosh/writing.py | 1275 ++++++++ nstock/modules/z_whoosh.py | 36 + nstock/private/appconfig.ini | 30 + nstock/private/language-codes.csv | 185 ++ nstock/routes.example.py | 41 + nstock/sessions/.gitignore | 5 + nstock/shot-full.png | Bin 0 -> 655451 bytes nstock/shot-thumb.png | Bin 0 -> 32567 bytes nstock/static/403.html | 1 + nstock/static/404.html | 1 + nstock/static/500.html | 1 + nstock/static/css/bootstrap.min.css | 11 + nstock/static/css/bootstrap.min.css.map | 1 + nstock/static/css/calendar.css | 7 + nstock/static/css/diffview.css | 83 + nstock/static/css/font-awesome.min.css | 4 + nstock/static/css/fonts.css | 16 + nstock/static/css/jquery.simple-dtpicker.css | 315 ++ nstock/static/css/pace.css | 76 + nstock/static/css/style.css | 147 + nstock/static/css/web2py-bootstrap3.css | 304 ++ nstock/static/fonts/FontAwesome.otf | Bin 0 -> 134808 bytes .../static/fonts/PlayfairDisplay-Regular.ttf | Bin 0 -> 186856 bytes nstock/static/fonts/Raleway-Regular.ttf | Bin 0 -> 178520 bytes nstock/static/fonts/fontawesome-webfont.eot | Bin 0 -> 165742 bytes nstock/static/fonts/fontawesome-webfont.svg | 2671 +++++++++++++++++ nstock/static/fonts/fontawesome-webfont.ttf | Bin 0 -> 165548 bytes nstock/static/fonts/fontawesome-webfont.woff | Bin 0 -> 98024 bytes nstock/static/fonts/fontawesome-webfont.woff2 | Bin 0 -> 77160 bytes .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes .../fonts/glyphicons-halflings-regular.svg | 288 ++ .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes nstock/static/images/background.jpg | Bin 0 -> 740881 bytes nstock/static/images/facebook.png | Bin 0 -> 991 bytes nstock/static/images/favicon.ico | Bin 0 -> 198 bytes nstock/static/images/favicon.png | Bin 0 -> 323 bytes nstock/static/images/gplus-32.png | Bin 0 -> 1513 bytes nstock/static/images/twitter.png | Bin 0 -> 1120 bytes nstock/static/js/analytics.min.js | 8 + nstock/static/js/bootstrap.min.js | 7 + nstock/static/js/calendar.js | 29 + nstock/static/js/difflib.js | 413 +++ nstock/static/js/diffview.js | 198 ++ nstock/static/js/holder.min.js | 12 + nstock/static/js/jquery.js | 5 + nstock/static/js/jquery.simple-dtpicker.js | 1382 +++++++++ nstock/static/js/modernizr-2.8.3.min.js | 4 + nstock/static/js/npm.js | 13 + nstock/static/js/pace.min.js | 2 + nstock/static/js/respond-1.4.2.min.js | 6 + nstock/static/js/share.js | 44 + nstock/static/js/vue.min.js | 8 + nstock/static/js/web2py-bootstrap3.js | 82 + nstock/static/js/web2py.js | 769 +++++ nstock/static/plugin_ckeditor/CHANGES.md | 1053 +++++++ nstock/static/plugin_ckeditor/LICENSE.md | 1420 +++++++++ nstock/static/plugin_ckeditor/README.md | 39 + .../static/plugin_ckeditor/adapters/jquery.js | 10 + nstock/static/plugin_ckeditor/build-config.js | 182 ++ nstock/static/plugin_ckeditor/ckeditor.js | 1084 +++++++ nstock/static/plugin_ckeditor/config.js | 31 + nstock/static/plugin_ckeditor/contents.css | 132 + nstock/static/plugin_ckeditor/lang/af.js | 5 + nstock/static/plugin_ckeditor/lang/ar.js | 5 + nstock/static/plugin_ckeditor/lang/bg.js | 5 + nstock/static/plugin_ckeditor/lang/bn.js | 5 + nstock/static/plugin_ckeditor/lang/bs.js | 5 + nstock/static/plugin_ckeditor/lang/ca.js | 5 + nstock/static/plugin_ckeditor/lang/cs.js | 5 + nstock/static/plugin_ckeditor/lang/cy.js | 5 + nstock/static/plugin_ckeditor/lang/da.js | 5 + nstock/static/plugin_ckeditor/lang/de-ch.js | 5 + nstock/static/plugin_ckeditor/lang/de.js | 5 + nstock/static/plugin_ckeditor/lang/el.js | 5 + nstock/static/plugin_ckeditor/lang/en-au.js | 5 + nstock/static/plugin_ckeditor/lang/en-ca.js | 5 + nstock/static/plugin_ckeditor/lang/en-gb.js | 5 + nstock/static/plugin_ckeditor/lang/en.js | 5 + nstock/static/plugin_ckeditor/lang/eo.js | 5 + nstock/static/plugin_ckeditor/lang/es.js | 5 + nstock/static/plugin_ckeditor/lang/et.js | 5 + nstock/static/plugin_ckeditor/lang/eu.js | 5 + nstock/static/plugin_ckeditor/lang/fa.js | 5 + nstock/static/plugin_ckeditor/lang/fi.js | 5 + nstock/static/plugin_ckeditor/lang/fo.js | 5 + nstock/static/plugin_ckeditor/lang/fr-ca.js | 5 + nstock/static/plugin_ckeditor/lang/fr.js | 5 + nstock/static/plugin_ckeditor/lang/gl.js | 5 + nstock/static/plugin_ckeditor/lang/gu.js | 5 + nstock/static/plugin_ckeditor/lang/he.js | 5 + nstock/static/plugin_ckeditor/lang/hi.js | 5 + nstock/static/plugin_ckeditor/lang/hr.js | 5 + nstock/static/plugin_ckeditor/lang/hu.js | 5 + nstock/static/plugin_ckeditor/lang/id.js | 5 + nstock/static/plugin_ckeditor/lang/is.js | 5 + nstock/static/plugin_ckeditor/lang/it.js | 5 + nstock/static/plugin_ckeditor/lang/ja.js | 5 + nstock/static/plugin_ckeditor/lang/ka.js | 5 + nstock/static/plugin_ckeditor/lang/km.js | 5 + nstock/static/plugin_ckeditor/lang/ko.js | 5 + nstock/static/plugin_ckeditor/lang/ku.js | 5 + nstock/static/plugin_ckeditor/lang/lt.js | 5 + nstock/static/plugin_ckeditor/lang/lv.js | 5 + nstock/static/plugin_ckeditor/lang/mk.js | 5 + nstock/static/plugin_ckeditor/lang/mn.js | 5 + nstock/static/plugin_ckeditor/lang/ms.js | 5 + nstock/static/plugin_ckeditor/lang/nb.js | 5 + nstock/static/plugin_ckeditor/lang/nl.js | 5 + nstock/static/plugin_ckeditor/lang/no.js | 5 + nstock/static/plugin_ckeditor/lang/pl.js | 5 + nstock/static/plugin_ckeditor/lang/pt-br.js | 5 + nstock/static/plugin_ckeditor/lang/pt.js | 5 + nstock/static/plugin_ckeditor/lang/ro.js | 5 + nstock/static/plugin_ckeditor/lang/ru.js | 5 + nstock/static/plugin_ckeditor/lang/si.js | 5 + nstock/static/plugin_ckeditor/lang/sk.js | 5 + nstock/static/plugin_ckeditor/lang/sl.js | 5 + nstock/static/plugin_ckeditor/lang/sq.js | 5 + nstock/static/plugin_ckeditor/lang/sr-latn.js | 5 + nstock/static/plugin_ckeditor/lang/sr.js | 5 + nstock/static/plugin_ckeditor/lang/sv.js | 5 + nstock/static/plugin_ckeditor/lang/th.js | 5 + nstock/static/plugin_ckeditor/lang/tr.js | 5 + nstock/static/plugin_ckeditor/lang/tt.js | 5 + nstock/static/plugin_ckeditor/lang/ug.js | 5 + nstock/static/plugin_ckeditor/lang/uk.js | 5 + nstock/static/plugin_ckeditor/lang/vi.js | 5 + nstock/static/plugin_ckeditor/lang/zh-cn.js | 5 + nstock/static/plugin_ckeditor/lang/zh.js | 5 + .../plugins/a11yhelp/dialogs/a11yhelp.js | 10 + .../dialogs/lang/_translationstatus.txt | 25 + .../plugins/a11yhelp/dialogs/lang/af.js | 11 + .../plugins/a11yhelp/dialogs/lang/ar.js | 11 + .../plugins/a11yhelp/dialogs/lang/bg.js | 11 + .../plugins/a11yhelp/dialogs/lang/ca.js | 12 + .../plugins/a11yhelp/dialogs/lang/cs.js | 12 + .../plugins/a11yhelp/dialogs/lang/cy.js | 11 + .../plugins/a11yhelp/dialogs/lang/da.js | 11 + .../plugins/a11yhelp/dialogs/lang/de-ch.js | 12 + .../plugins/a11yhelp/dialogs/lang/de.js | 12 + .../plugins/a11yhelp/dialogs/lang/el.js | 12 + .../plugins/a11yhelp/dialogs/lang/en-gb.js | 11 + .../plugins/a11yhelp/dialogs/lang/en.js | 11 + .../plugins/a11yhelp/dialogs/lang/eo.js | 13 + .../plugins/a11yhelp/dialogs/lang/es.js | 12 + .../plugins/a11yhelp/dialogs/lang/et.js | 11 + .../plugins/a11yhelp/dialogs/lang/eu.js | 12 + .../plugins/a11yhelp/dialogs/lang/fa.js | 11 + .../plugins/a11yhelp/dialogs/lang/fi.js | 11 + .../plugins/a11yhelp/dialogs/lang/fo.js | 11 + .../plugins/a11yhelp/dialogs/lang/fr-ca.js | 11 + .../plugins/a11yhelp/dialogs/lang/fr.js | 12 + .../plugins/a11yhelp/dialogs/lang/gl.js | 12 + .../plugins/a11yhelp/dialogs/lang/gu.js | 11 + .../plugins/a11yhelp/dialogs/lang/he.js | 11 + .../plugins/a11yhelp/dialogs/lang/hi.js | 11 + .../plugins/a11yhelp/dialogs/lang/hr.js | 11 + .../plugins/a11yhelp/dialogs/lang/hu.js | 12 + .../plugins/a11yhelp/dialogs/lang/id.js | 11 + .../plugins/a11yhelp/dialogs/lang/it.js | 13 + .../plugins/a11yhelp/dialogs/lang/ja.js | 9 + .../plugins/a11yhelp/dialogs/lang/km.js | 11 + .../plugins/a11yhelp/dialogs/lang/ko.js | 10 + .../plugins/a11yhelp/dialogs/lang/ku.js | 11 + .../plugins/a11yhelp/dialogs/lang/lt.js | 11 + .../plugins/a11yhelp/dialogs/lang/lv.js | 12 + .../plugins/a11yhelp/dialogs/lang/mk.js | 11 + .../plugins/a11yhelp/dialogs/lang/mn.js | 11 + .../plugins/a11yhelp/dialogs/lang/nb.js | 12 + .../plugins/a11yhelp/dialogs/lang/nl.js | 11 + .../plugins/a11yhelp/dialogs/lang/no.js | 11 + .../plugins/a11yhelp/dialogs/lang/pl.js | 13 + .../plugins/a11yhelp/dialogs/lang/pt-br.js | 13 + .../plugins/a11yhelp/dialogs/lang/pt.js | 12 + .../plugins/a11yhelp/dialogs/lang/ro.js | 11 + .../plugins/a11yhelp/dialogs/lang/ru.js | 11 + .../plugins/a11yhelp/dialogs/lang/si.js | 10 + .../plugins/a11yhelp/dialogs/lang/sk.js | 11 + .../plugins/a11yhelp/dialogs/lang/sl.js | 11 + .../plugins/a11yhelp/dialogs/lang/sq.js | 11 + .../plugins/a11yhelp/dialogs/lang/sr-latn.js | 11 + .../plugins/a11yhelp/dialogs/lang/sr.js | 11 + .../plugins/a11yhelp/dialogs/lang/sv.js | 11 + .../plugins/a11yhelp/dialogs/lang/th.js | 11 + .../plugins/a11yhelp/dialogs/lang/tr.js | 12 + .../plugins/a11yhelp/dialogs/lang/tt.js | 11 + .../plugins/a11yhelp/dialogs/lang/ug.js | 12 + .../plugins/a11yhelp/dialogs/lang/uk.js | 12 + .../plugins/a11yhelp/dialogs/lang/vi.js | 11 + .../plugins/a11yhelp/dialogs/lang/zh-cn.js | 9 + .../plugins/a11yhelp/dialogs/lang/zh.js | 9 + .../plugins/about/dialogs/about.js | 7 + .../about/dialogs/hidpi/logo_ckeditor.png | Bin 0 -> 13339 bytes .../plugins/about/dialogs/logo_ckeditor.png | Bin 0 -> 6757 bytes .../plugins/clipboard/dialogs/paste.js | 12 + .../colordialog/dialogs/colordialog.js | 13 + .../plugins/dialog/dialogDefinition.js | 4 + .../plugins/div/dialogs/div.js | 9 + .../plugins/find/dialogs/find.js | 24 + .../plugins/flash/dialogs/flash.js | 24 + .../plugins/flash/images/placeholder.png | Bin 0 -> 256 bytes .../plugins/forms/dialogs/button.js | 8 + .../plugins/forms/dialogs/checkbox.js | 9 + .../plugins/forms/dialogs/form.js | 8 + .../plugins/forms/dialogs/hiddenfield.js | 7 + .../plugins/forms/dialogs/radio.js | 9 + .../plugins/forms/dialogs/select.js | 20 + .../plugins/forms/dialogs/textarea.js | 8 + .../plugins/forms/dialogs/textfield.js | 11 + .../plugins/forms/images/hiddenfield.gif | Bin 0 -> 178 bytes .../static/plugin_ckeditor/plugins/icons.png | Bin 0 -> 20634 bytes .../plugin_ckeditor/plugins/icons_hidpi.png | Bin 0 -> 67753 bytes .../plugins/iframe/dialogs/iframe.js | 10 + .../plugins/iframe/images/placeholder.png | Bin 0 -> 265 bytes .../plugins/image/dialogs/image.js | 44 + .../plugins/image/images/noimage.png | Bin 0 -> 1610 bytes .../plugins/link/dialogs/anchor.js | 7 + .../plugins/link/dialogs/link.js | 26 + .../plugins/link/images/anchor.png | Bin 0 -> 589 bytes .../plugins/link/images/hidpi/anchor.png | Bin 0 -> 1379 bytes .../plugins/liststyle/dialogs/liststyle.js | 10 + .../magicline/images/hidpi/icon-rtl.png | Bin 0 -> 176 bytes .../plugins/magicline/images/hidpi/icon.png | Bin 0 -> 199 bytes .../plugins/magicline/images/icon-rtl.png | Bin 0 -> 138 bytes .../plugins/magicline/images/icon.png | Bin 0 -> 133 bytes .../plugins/pagebreak/images/pagebreak.gif | Bin 0 -> 99 bytes .../plugins/pastefromword/filter/default.js | 32 + .../plugins/preview/preview.html | 13 + .../plugins/scayt/CHANGELOG.md | 20 + .../plugin_ckeditor/plugins/scayt/LICENSE.md | 28 + .../plugin_ckeditor/plugins/scayt/README.md | 25 + .../plugins/scayt/dialogs/options.js | 19 + .../plugins/scayt/dialogs/toolbar.css | 71 + .../showblocks/images/block_address.png | Bin 0 -> 152 bytes .../showblocks/images/block_blockquote.png | Bin 0 -> 154 bytes .../plugins/showblocks/images/block_div.png | Bin 0 -> 127 bytes .../plugins/showblocks/images/block_h1.png | Bin 0 -> 120 bytes .../plugins/showblocks/images/block_h2.png | Bin 0 -> 127 bytes .../plugins/showblocks/images/block_h3.png | Bin 0 -> 123 bytes .../plugins/showblocks/images/block_h4.png | Bin 0 -> 123 bytes .../plugins/showblocks/images/block_h5.png | Bin 0 -> 126 bytes .../plugins/showblocks/images/block_h6.png | Bin 0 -> 123 bytes .../plugins/showblocks/images/block_p.png | Bin 0 -> 115 bytes .../plugins/showblocks/images/block_pre.png | Bin 0 -> 128 bytes .../plugins/smiley/dialogs/smiley.js | 11 + .../plugins/smiley/images/angel_smile.gif | Bin 0 -> 1245 bytes .../plugins/smiley/images/angel_smile.png | Bin 0 -> 1172 bytes .../plugins/smiley/images/angry_smile.gif | Bin 0 -> 1219 bytes .../plugins/smiley/images/angry_smile.png | Bin 0 -> 1220 bytes .../plugins/smiley/images/broken_heart.gif | Bin 0 -> 732 bytes .../plugins/smiley/images/broken_heart.png | Bin 0 -> 1139 bytes .../plugins/smiley/images/confused_smile.gif | Bin 0 -> 1202 bytes .../plugins/smiley/images/confused_smile.png | Bin 0 -> 1101 bytes .../plugins/smiley/images/cry_smile.gif | Bin 0 -> 795 bytes .../plugins/smiley/images/cry_smile.png | Bin 0 -> 1214 bytes .../plugins/smiley/images/devil_smile.gif | Bin 0 -> 1239 bytes .../plugins/smiley/images/devil_smile.png | Bin 0 -> 1220 bytes .../smiley/images/embaressed_smile.gif | Bin 0 -> 786 bytes .../smiley/images/embarrassed_smile.gif | Bin 0 -> 786 bytes .../smiley/images/embarrassed_smile.png | Bin 0 -> 1145 bytes .../plugins/smiley/images/envelope.gif | Bin 0 -> 506 bytes .../plugins/smiley/images/envelope.png | Bin 0 -> 760 bytes .../plugins/smiley/images/heart.gif | Bin 0 -> 692 bytes .../plugins/smiley/images/heart.png | Bin 0 -> 999 bytes .../plugins/smiley/images/kiss.gif | Bin 0 -> 683 bytes .../plugins/smiley/images/kiss.png | Bin 0 -> 1003 bytes .../plugins/smiley/images/lightbulb.gif | Bin 0 -> 660 bytes .../plugins/smiley/images/lightbulb.png | Bin 0 -> 919 bytes .../plugins/smiley/images/omg_smile.gif | Bin 0 -> 820 bytes .../plugins/smiley/images/omg_smile.png | Bin 0 -> 1122 bytes .../plugins/smiley/images/regular_smile.gif | Bin 0 -> 1209 bytes .../plugins/smiley/images/regular_smile.png | Bin 0 -> 1084 bytes .../plugins/smiley/images/sad_smile.gif | Bin 0 -> 782 bytes .../plugins/smiley/images/sad_smile.png | Bin 0 -> 1115 bytes .../plugins/smiley/images/shades_smile.gif | Bin 0 -> 1231 bytes .../plugins/smiley/images/shades_smile.png | Bin 0 -> 1204 bytes .../plugins/smiley/images/teeth_smile.gif | Bin 0 -> 1201 bytes .../plugins/smiley/images/teeth_smile.png | Bin 0 -> 1183 bytes .../plugins/smiley/images/thumbs_down.gif | Bin 0 -> 715 bytes .../plugins/smiley/images/thumbs_down.png | Bin 0 -> 985 bytes .../plugins/smiley/images/thumbs_up.gif | Bin 0 -> 714 bytes .../plugins/smiley/images/thumbs_up.png | Bin 0 -> 959 bytes .../plugins/smiley/images/tongue_smile.gif | Bin 0 -> 1210 bytes .../plugins/smiley/images/tongue_smile.png | Bin 0 -> 1132 bytes .../plugins/smiley/images/tounge_smile.gif | Bin 0 -> 1210 bytes .../images/whatchutalkingabout_smile.gif | Bin 0 -> 775 bytes .../images/whatchutalkingabout_smile.png | Bin 0 -> 1039 bytes .../plugins/smiley/images/wink_smile.gif | Bin 0 -> 1202 bytes .../plugins/smiley/images/wink_smile.png | Bin 0 -> 1114 bytes .../dialogs/lang/_translationstatus.txt | 20 + .../plugins/specialchar/dialogs/lang/af.js | 13 + .../plugins/specialchar/dialogs/lang/ar.js | 13 + .../plugins/specialchar/dialogs/lang/bg.js | 13 + .../plugins/specialchar/dialogs/lang/ca.js | 14 + .../plugins/specialchar/dialogs/lang/cs.js | 13 + .../plugins/specialchar/dialogs/lang/cy.js | 14 + .../plugins/specialchar/dialogs/lang/da.js | 11 + .../plugins/specialchar/dialogs/lang/de-ch.js | 13 + .../plugins/specialchar/dialogs/lang/de.js | 13 + .../plugins/specialchar/dialogs/lang/el.js | 13 + .../plugins/specialchar/dialogs/lang/en-gb.js | 13 + .../plugins/specialchar/dialogs/lang/en.js | 13 + .../plugins/specialchar/dialogs/lang/eo.js | 12 + .../plugins/specialchar/dialogs/lang/es.js | 13 + .../plugins/specialchar/dialogs/lang/et.js | 13 + .../plugins/specialchar/dialogs/lang/eu.js | 13 + .../plugins/specialchar/dialogs/lang/fa.js | 12 + .../plugins/specialchar/dialogs/lang/fi.js | 13 + .../plugins/specialchar/dialogs/lang/fr-ca.js | 10 + .../plugins/specialchar/dialogs/lang/fr.js | 11 + .../plugins/specialchar/dialogs/lang/gl.js | 13 + .../plugins/specialchar/dialogs/lang/he.js | 12 + .../plugins/specialchar/dialogs/lang/hr.js | 13 + .../plugins/specialchar/dialogs/lang/hu.js | 12 + .../plugins/specialchar/dialogs/lang/id.js | 13 + .../plugins/specialchar/dialogs/lang/it.js | 14 + .../plugins/specialchar/dialogs/lang/ja.js | 9 + .../plugins/specialchar/dialogs/lang/km.js | 13 + .../plugins/specialchar/dialogs/lang/ko.js | 10 + .../plugins/specialchar/dialogs/lang/ku.js | 13 + .../plugins/specialchar/dialogs/lang/lt.js | 13 + .../plugins/specialchar/dialogs/lang/lv.js | 13 + .../plugins/specialchar/dialogs/lang/nb.js | 11 + .../plugins/specialchar/dialogs/lang/nl.js | 13 + .../plugins/specialchar/dialogs/lang/no.js | 11 + .../plugins/specialchar/dialogs/lang/pl.js | 12 + .../plugins/specialchar/dialogs/lang/pt-br.js | 11 + .../plugins/specialchar/dialogs/lang/pt.js | 13 + .../plugins/specialchar/dialogs/lang/ru.js | 13 + .../plugins/specialchar/dialogs/lang/si.js | 13 + .../plugins/specialchar/dialogs/lang/sk.js | 13 + .../plugins/specialchar/dialogs/lang/sl.js | 12 + .../plugins/specialchar/dialogs/lang/sq.js | 13 + .../plugins/specialchar/dialogs/lang/sv.js | 11 + .../plugins/specialchar/dialogs/lang/th.js | 13 + .../plugins/specialchar/dialogs/lang/tr.js | 12 + .../plugins/specialchar/dialogs/lang/tt.js | 13 + .../plugins/specialchar/dialogs/lang/ug.js | 13 + .../plugins/specialchar/dialogs/lang/uk.js | 12 + .../plugins/specialchar/dialogs/lang/vi.js | 14 + .../plugins/specialchar/dialogs/lang/zh-cn.js | 9 + .../plugins/specialchar/dialogs/lang/zh.js | 9 + .../specialchar/dialogs/specialchar.js | 14 + .../plugins/table/dialogs/table.js | 21 + .../plugins/tabletools/dialogs/tableCell.js | 17 + .../plugins/templates/dialogs/templates.css | 84 + .../plugins/templates/dialogs/templates.js | 10 + .../plugins/templates/templates/default.js | 7 + .../templates/templates/images/template1.gif | Bin 0 -> 375 bytes .../templates/templates/images/template2.gif | Bin 0 -> 333 bytes .../templates/templates/images/template3.gif | Bin 0 -> 422 bytes .../plugin_ckeditor/plugins/wsc/LICENSE.md | 28 + .../plugin_ckeditor/plugins/wsc/README.md | 25 + .../plugins/wsc/dialogs/ciframe.html | 66 + .../plugins/wsc/dialogs/tmpFrameset.html | 52 + .../plugins/wsc/dialogs/wsc.css | 82 + .../plugins/wsc/dialogs/wsc.js | 92 + .../plugins/wsc/dialogs/wsc_ie.js | 11 + .../plugin_ckeditor/samples/css/samples.css | 1640 ++++++++++ .../samples/img/github-top.png | Bin 0 -> 383 bytes .../plugin_ckeditor/samples/img/header-bg.png | Bin 0 -> 13086 bytes .../samples/img/header-separator.png | Bin 0 -> 123 bytes .../plugin_ckeditor/samples/img/logo.png | Bin 0 -> 5891 bytes .../samples/img/navigation-tip.png | Bin 0 -> 12029 bytes .../static/plugin_ckeditor/samples/index.html | 128 + .../plugin_ckeditor/samples/js/sample.js | 53 + .../static/plugin_ckeditor/samples/js/sf.js | 17 + .../plugin_ckeditor/samples/old/ajax.html | 85 + .../plugin_ckeditor/samples/old/api.html | 210 ++ .../plugin_ckeditor/samples/old/appendto.html | 59 + .../samples/old/assets/inlineall/logo.png | Bin 0 -> 4283 bytes .../old/assets/outputxhtml/outputxhtml.css | 204 ++ .../samples/old/assets/posteddata.php | 59 + .../samples/old/assets/sample.jpg | Bin 0 -> 14449 bytes .../old/assets/uilanguages/languages.js | 7 + .../samples/old/datafiltering.html | 508 ++++ .../samples/old/dialog/assets/my_dialog.js | 48 + .../samples/old/dialog/dialog.html | 190 ++ .../samples/old/divreplace.html | 144 + .../samples/old/enterkey/enterkey.html | 106 + .../assets/outputforflash/outputforflash.fla | Bin 0 -> 85504 bytes .../assets/outputforflash/outputforflash.swf | Bin 0 -> 15571 bytes .../assets/outputforflash/swfobject.js | 19 + .../old/htmlwriter/outputforflash.html | 283 ++ .../samples/old/htmlwriter/outputhtml.html | 224 ++ .../plugin_ckeditor/samples/old/index.html | 131 + .../samples/old/inlineall.html | 314 ++ .../samples/old/inlinebycode.html | 124 + .../samples/old/inlinetextarea.html | 113 + .../plugin_ckeditor/samples/old/jquery.html | 103 + .../samples/old/magicline/magicline.html | 209 ++ .../plugin_ckeditor/samples/old/readonly.html | 76 + .../samples/old/replacebyclass.html | 60 + .../samples/old/replacebycode.html | 59 + .../plugin_ckeditor/samples/old/sample.css | 357 +++ .../plugin_ckeditor/samples/old/sample.js | 50 + .../samples/old/sample_posteddata.php | 16 + .../plugin_ckeditor/samples/old/tabindex.html | 78 + .../samples/old/toolbar/toolbar.html | 235 ++ .../plugin_ckeditor/samples/old/uicolor.html | 72 + .../samples/old/uilanguages.html | 122 + .../samples/old/wysiwygarea/fullpage.html | 80 + .../samples/old/xhtmlstyle.html | 234 ++ .../toolbarconfigurator/css/fontello.css | 55 + .../toolbarconfigurator/font/LICENSE.txt | 10 + .../toolbarconfigurator/font/config.json | 28 + .../toolbarconfigurator/font/fontello.eot | Bin 0 -> 4988 bytes .../toolbarconfigurator/font/fontello.svg | 14 + .../toolbarconfigurator/font/fontello.ttf | Bin 0 -> 4820 bytes .../toolbarconfigurator/font/fontello.woff | Bin 0 -> 2904 bytes .../samples/toolbarconfigurator/index.html | 446 +++ .../js/abstracttoolbarmodifier.js | 13 + .../js/fulltoolbareditor.js | 9 + .../toolbarconfigurator/js/toolbarmodifier.js | 33 + .../js/toolbartextmodifier.js | 14 + .../skins/bootstrapck/.temp/css/dialog.css | 1 + .../skins/bootstrapck/.temp/css/dialog_ie.css | 1 + .../bootstrapck/.temp/css/dialog_ie7.css | 1 + .../bootstrapck/.temp/css/dialog_ie8.css | 1 + .../bootstrapck/.temp/css/dialog_iequirks.css | 1 + .../bootstrapck/.temp/css/dialog_opera.css | 1 + .../skins/bootstrapck/.temp/css/editor.css | 1 + .../bootstrapck/.temp/css/editor_gecko.css | 1 + .../skins/bootstrapck/.temp/css/editor_ie.css | 1 + .../bootstrapck/.temp/css/editor_ie7.css | 1 + .../bootstrapck/.temp/css/editor_ie8.css | 1 + .../bootstrapck/.temp/css/editor_iequirks.css | 1 + .../skins/bootstrapck/dialog.css | 1 + .../skins/bootstrapck/dialog_ie.css | 1 + .../skins/bootstrapck/dialog_ie7.css | 1 + .../skins/bootstrapck/dialog_ie8.css | 1 + .../skins/bootstrapck/dialog_iequirks.css | 1 + .../skins/bootstrapck/dialog_opera.css | 1 + .../skins/bootstrapck/editor.css | 1 + .../skins/bootstrapck/editor_gecko.css | 1 + .../skins/bootstrapck/editor_ie.css | 1 + .../skins/bootstrapck/editor_ie7.css | 1 + .../skins/bootstrapck/editor_ie8.css | 1 + .../skins/bootstrapck/editor_iequirks.css | 1 + .../skins/bootstrapck/icons.png | Bin 0 -> 20634 bytes .../skins/bootstrapck/icons_hidpi.png | Bin 0 -> 67753 bytes .../skins/bootstrapck/images/arrow.png | Bin 0 -> 261 bytes .../skins/bootstrapck/images/close.png | Bin 0 -> 415 bytes .../skins/bootstrapck/images/hidpi/close.png | Bin 0 -> 498 bytes .../bootstrapck/images/hidpi/lock-open.png | Bin 0 -> 573 bytes .../skins/bootstrapck/images/hidpi/lock.png | Bin 0 -> 571 bytes .../bootstrapck/images/hidpi/refresh.png | Bin 0 -> 867 bytes .../skins/bootstrapck/images/lock-open.png | Bin 0 -> 402 bytes .../skins/bootstrapck/images/lock.png | Bin 0 -> 413 bytes .../skins/bootstrapck/images/refresh.png | Bin 0 -> 532 bytes .../skins/bootstrapck/readme.md | 35 + .../sample/bootstrapck-sample.html | 127 + .../sample/css/bootstrapck-sample.css | 1 + .../skins/bootstrapck/sample/js/analytics.js | 4 + .../sample/js/jquery-1.11.0.min.js | 189 ++ .../browser-specific/gecko/editor_gecko.scss | 25 + .../scss/browser-specific/ie/dialog_ie.scss | 62 + .../scss/browser-specific/ie/editor_ie.scss | 71 + .../scss/browser-specific/ie7/dialog_ie7.scss | 68 + .../scss/browser-specific/ie7/editor_ie7.scss | 213 ++ .../scss/browser-specific/ie8/dialog_ie8.scss | 24 + .../scss/browser-specific/ie8/editor_ie8.scss | 27 + .../iequirks/dialog_iequirks.scss | 21 + .../iequirks/editor_iequirks.scss | 79 + .../browser-specific/opera/dialog_opera.scss | 31 + .../scss/components/_colorpanel.scss | 119 + .../scss/components/_elementspath.scss | 66 + .../bootstrapck/scss/components/_mainui.scss | 189 ++ .../bootstrapck/scss/components/_menu.scss | 182 ++ .../bootstrapck/scss/components/_panel.scss | 199 ++ .../bootstrapck/scss/components/_presets.scss | 32 + .../bootstrapck/scss/components/_reset.scss | 107 + .../scss/components/_richcombo.scss | 174 ++ .../bootstrapck/scss/components/_toolbar.scss | 317 ++ .../bootstrapck/scss/components/editor.scss | 66 + .../bootstrapck/scss/config/_colors.scss | 61 + .../bootstrapck/scss/config/_config.scss | 9 + .../bootstrapck/scss/config/_defaults.scss | 37 + .../skins/bootstrapck/scss/dialog/dialog.scss | 822 +++++ .../plugin_ckeditor/skins/moono/dialog.css | 5 + .../plugin_ckeditor/skins/moono/dialog_ie.css | 5 + .../skins/moono/dialog_ie7.css | 5 + .../skins/moono/dialog_ie8.css | 5 + .../skins/moono/dialog_iequirks.css | 5 + .../plugin_ckeditor/skins/moono/editor.css | 5 + .../skins/moono/editor_gecko.css | 5 + .../plugin_ckeditor/skins/moono/editor_ie.css | 5 + .../skins/moono/editor_ie7.css | 5 + .../skins/moono/editor_ie8.css | 5 + .../skins/moono/editor_iequirks.css | 5 + .../plugin_ckeditor/skins/moono/icons.png | Bin 0 -> 20634 bytes .../skins/moono/icons_hidpi.png | Bin 0 -> 67753 bytes .../skins/moono/images/arrow.png | Bin 0 -> 191 bytes .../skins/moono/images/close.png | Bin 0 -> 468 bytes .../skins/moono/images/hidpi/close.png | Bin 0 -> 1271 bytes .../skins/moono/images/hidpi/lock-open.png | Bin 0 -> 1329 bytes .../skins/moono/images/hidpi/lock.png | Bin 0 -> 1299 bytes .../skins/moono/images/hidpi/refresh.png | Bin 0 -> 1842 bytes .../skins/moono/images/lock-open.png | Bin 0 -> 349 bytes .../skins/moono/images/lock.png | Bin 0 -> 475 bytes .../skins/moono/images/refresh.png | Bin 0 -> 422 bytes .../skins/moono/images/spinner.gif | Bin 0 -> 2984 bytes .../plugin_ckeditor/skins/moono/readme.md | 49 + nstock/static/plugin_ckeditor/style.css | 6 + nstock/static/plugin_ckeditor/styles.js | 111 + .../plugin_photoset/css/fileuploader.css | 122 + nstock/static/plugin_photoset/css/style.css | 12 + .../static/plugin_photoset/images/loading.gif | Bin 0 -> 1688 bytes .../static/plugin_photoset/js/fileuploader.js | 1443 +++++++++ nstock/uploads/.gitignore | 5 + nstock/views/__init__.py | 1 + nstock/views/appadmin.html | 278 ++ nstock/views/changes_email.txt | 23 + nstock/views/default/index.html | 8 + nstock/views/default/user.html | 32 + nstock/views/desk/create.html | 24 + nstock/views/desk/delete.html | 43 + nstock/views/desk/desk_menu.html | 54 + nstock/views/desk/edit.html | 31 + nstock/views/desk/index.html | 31 + nstock/views/desk/item_list.load | 63 + nstock/views/desk/user_perms.html | 80 + nstock/views/desk/users.html | 73 + nstock/views/generic.html | 16 + nstock/views/generic.ics | 17 + nstock/views/generic.json | 1 + nstock/views/generic.jsonp | 23 + nstock/views/generic.load | 30 + nstock/views/generic.map | 69 + nstock/views/generic.pdf | Bin 0 -> 306 bytes nstock/views/generic.rss | 10 + nstock/views/generic.xml | 1 + nstock/views/item/add_items.html | 16 + nstock/views/item/changelog.html | 33 + nstock/views/item/diff.html | 33 + nstock/views/item/full_text.txt | 15 + nstock/views/item/index.html | 87 + nstock/views/item/index.load | 2 + nstock/views/item/item_layout.html | 76 + nstock/views/item/meta.html | 11 + nstock/views/item/meta.load | 1 + nstock/views/item/preview.html | 126 + nstock/views/item/share.html | 4 + nstock/views/item/share.load | 18 + nstock/views/layout.html | 166 + nstock/views/notifications.html | 37 + nstock/views/notifications/index.html | 32 + nstock/views/org/create.html | 5 + nstock/views/org/edit.html | 19 + nstock/views/org/index.html | 42 + nstock/views/org/members.html | 72 + nstock/views/org/org_sidebar.html | 25 + nstock/views/org/view.html | 49 + nstock/views/plugin_ckeditor/browse.html | 102 + nstock/views/plugin_ckeditor/upload.html | 7 + nstock/views/plugin_comment/index.load | 118 + .../plugin_comment/someone_commented.txt | 21 + nstock/views/plugin_package/changelog.html | 25 + nstock/views/plugin_package/create.html | 52 + .../plugin_package/create_group_form.load | 14 + nstock/views/plugin_package/diff.html | 59 + nstock/views/plugin_package/full_text.txt | 2 + nstock/views/plugin_package/index.html | 35 + nstock/views/plugin_package/preview.html | 32 + nstock/views/plugin_package/view_group.load | 114 + .../plugin_package/view_package_groups.load | 8 + nstock/views/plugin_photoset/changelog.html | 24 + nstock/views/plugin_photoset/create.html | 55 + nstock/views/plugin_photoset/diff.html | 134 + nstock/views/plugin_photoset/full_text.txt | 4 + nstock/views/plugin_photoset/index.html | 27 + nstock/views/plugin_photoset/preview.html | 39 + .../views/plugin_photoset/preview_photo.load | 37 + .../views/plugin_photoset/view_photoset.load | 125 + .../views/plugin_picture/add_rendition.html | 10 + nstock/views/plugin_picture/changelog.html | 25 + nstock/views/plugin_picture/create.html | 6 + nstock/views/plugin_picture/diff.html | 196 ++ nstock/views/plugin_picture/full_text.txt | 5 + nstock/views/plugin_picture/index.html | 82 + nstock/views/plugin_picture/preview.html | 38 + nstock/views/plugin_text/changelog.html | 32 + nstock/views/plugin_text/create.html | 6 + nstock/views/plugin_text/diff.html | 93 + nstock/views/plugin_text/full_text.txt | 4 + nstock/views/plugin_text/index.html | 24 + nstock/views/plugin_text/index_old.html | 89 + nstock/views/plugin_text/preview.html | 15 + nstock/views/share_email.txt | 17 + nstock/views/web2py_ajax.html | 16 + nstock/web2py.app.nstock.w2p | Bin 0 -> 4303849 bytes 948 files changed, 131958 insertions(+) create mode 100644 nstock/.gitignore create mode 100644 nstock/ABOUT create mode 100644 nstock/LICENSE create mode 100644 nstock/README.md create mode 100644 nstock/__init__.py create mode 100644 nstock/cache/.gitignore create mode 100644 nstock/controllers/appadmin.py create mode 100644 nstock/controllers/default.py create mode 100644 nstock/controllers/desk.py create mode 100644 nstock/controllers/item.py create mode 100644 nstock/controllers/notifications.py create mode 100644 nstock/controllers/org.py create mode 100644 nstock/controllers/plugin_ckeditor.py create mode 100644 nstock/controllers/plugin_comment.py create mode 100644 nstock/controllers/plugin_package.py create mode 100644 nstock/controllers/plugin_photoset.py create mode 100644 nstock/controllers/plugin_picture.py create mode 100644 nstock/controllers/plugin_text.py create mode 100644 nstock/cron/.gitignore create mode 100644 nstock/databases/.gitignore create mode 100644 nstock/errors/.gitignore create mode 100644 nstock/languages/default.py create mode 100644 nstock/languages/en-us.py create mode 100644 nstock/languages/en.py create mode 100644 nstock/languages/es-ES.py create mode 100644 nstock/languages/es.py create mode 100644 nstock/languages/plural-en.py create mode 100644 nstock/languages/plural-es.py create mode 100644 nstock/models/db.py create mode 100644 nstock/models/dc.py create mode 100644 nstock/models/desk/z_menu.py create mode 100644 nstock/models/menu.py create mode 100644 nstock/models/plugin_comment.py create mode 100644 nstock/models/plugin_package.py create mode 100644 nstock/models/plugin_photoset.py create mode 100644 nstock/models/plugin_picture.py create mode 100644 nstock/models/plugin_text.py create mode 100644 nstock/modules/__init__.py create mode 100644 nstock/modules/app.py create mode 100644 nstock/modules/content_plugin.py create mode 100644 nstock/modules/html2text.py create mode 100644 nstock/modules/mail.py create mode 100644 nstock/modules/perms.py create mode 100644 nstock/modules/plugin_ckeditor.py create mode 100644 nstock/modules/plugin_package/__init__.py create mode 100644 nstock/modules/plugin_package/content_package.py create mode 100644 nstock/modules/plugin_photoset/__init__.py create mode 100644 nstock/modules/plugin_photoset/content_photoset.py create mode 100644 nstock/modules/plugin_picture/__init__.py create mode 100644 nstock/modules/plugin_picture/content_picture.py create mode 100644 nstock/modules/plugin_text/__init__.py create mode 100644 nstock/modules/plugin_text/content_text.py create mode 100644 nstock/modules/slugify/__init__.py create mode 100644 nstock/modules/slugify/slugify.py create mode 100644 nstock/modules/unidecode/__init__.py create mode 100644 nstock/modules/unidecode/util.py create mode 100644 nstock/modules/unidecode/x000.py create mode 100644 nstock/modules/unidecode/x001.py create mode 100644 nstock/modules/unidecode/x002.py create mode 100644 nstock/modules/unidecode/x003.py create mode 100644 nstock/modules/unidecode/x004.py create mode 100644 nstock/modules/unidecode/x005.py create mode 100644 nstock/modules/unidecode/x006.py create mode 100644 nstock/modules/unidecode/x007.py create mode 100644 nstock/modules/unidecode/x009.py create mode 100644 nstock/modules/unidecode/x00a.py create mode 100644 nstock/modules/unidecode/x00b.py create mode 100644 nstock/modules/unidecode/x00c.py create mode 100644 nstock/modules/unidecode/x00d.py create mode 100644 nstock/modules/unidecode/x00e.py create mode 100644 nstock/modules/unidecode/x00f.py create mode 100644 nstock/modules/unidecode/x010.py create mode 100644 nstock/modules/unidecode/x011.py create mode 100644 nstock/modules/unidecode/x012.py create mode 100644 nstock/modules/unidecode/x013.py create mode 100644 nstock/modules/unidecode/x014.py create mode 100644 nstock/modules/unidecode/x015.py create mode 100644 nstock/modules/unidecode/x016.py create mode 100644 nstock/modules/unidecode/x017.py create mode 100644 nstock/modules/unidecode/x018.py create mode 100644 nstock/modules/unidecode/x01d.py create mode 100644 nstock/modules/unidecode/x01e.py create mode 100644 nstock/modules/unidecode/x01f.py create mode 100644 nstock/modules/unidecode/x020.py create mode 100644 nstock/modules/unidecode/x021.py create mode 100644 nstock/modules/unidecode/x022.py create mode 100644 nstock/modules/unidecode/x023.py create mode 100644 nstock/modules/unidecode/x024.py create mode 100644 nstock/modules/unidecode/x025.py create mode 100644 nstock/modules/unidecode/x026.py create mode 100644 nstock/modules/unidecode/x027.py create mode 100644 nstock/modules/unidecode/x028.py create mode 100644 nstock/modules/unidecode/x029.py create mode 100644 nstock/modules/unidecode/x02a.py create mode 100644 nstock/modules/unidecode/x02c.py create mode 100644 nstock/modules/unidecode/x02e.py create mode 100644 nstock/modules/unidecode/x02f.py create mode 100644 nstock/modules/unidecode/x030.py create mode 100644 nstock/modules/unidecode/x031.py create mode 100644 nstock/modules/unidecode/x032.py create mode 100644 nstock/modules/unidecode/x033.py create mode 100644 nstock/modules/unidecode/x04d.py create mode 100644 nstock/modules/unidecode/x04e.py create mode 100644 nstock/modules/unidecode/x04f.py create mode 100644 nstock/modules/unidecode/x050.py create mode 100644 nstock/modules/unidecode/x051.py create mode 100644 nstock/modules/unidecode/x052.py create mode 100644 nstock/modules/unidecode/x053.py create mode 100644 nstock/modules/unidecode/x054.py create mode 100644 nstock/modules/unidecode/x055.py create mode 100644 nstock/modules/unidecode/x056.py create mode 100644 nstock/modules/unidecode/x057.py create mode 100644 nstock/modules/unidecode/x058.py create mode 100644 nstock/modules/unidecode/x059.py create mode 100644 nstock/modules/unidecode/x05a.py create mode 100644 nstock/modules/unidecode/x05b.py create mode 100644 nstock/modules/unidecode/x05c.py create mode 100644 nstock/modules/unidecode/x05d.py create mode 100644 nstock/modules/unidecode/x05e.py create mode 100644 nstock/modules/unidecode/x05f.py create mode 100644 nstock/modules/unidecode/x060.py create mode 100644 nstock/modules/unidecode/x061.py create mode 100644 nstock/modules/unidecode/x062.py create mode 100644 nstock/modules/unidecode/x063.py create mode 100644 nstock/modules/unidecode/x064.py create mode 100644 nstock/modules/unidecode/x065.py create mode 100644 nstock/modules/unidecode/x066.py create mode 100644 nstock/modules/unidecode/x067.py create mode 100644 nstock/modules/unidecode/x068.py create mode 100644 nstock/modules/unidecode/x069.py create mode 100644 nstock/modules/unidecode/x06a.py create mode 100644 nstock/modules/unidecode/x06b.py create mode 100644 nstock/modules/unidecode/x06c.py create mode 100644 nstock/modules/unidecode/x06d.py create mode 100644 nstock/modules/unidecode/x06e.py create mode 100644 nstock/modules/unidecode/x06f.py create mode 100644 nstock/modules/unidecode/x070.py create mode 100644 nstock/modules/unidecode/x071.py create mode 100644 nstock/modules/unidecode/x072.py create mode 100644 nstock/modules/unidecode/x073.py create mode 100644 nstock/modules/unidecode/x074.py create mode 100644 nstock/modules/unidecode/x075.py create mode 100644 nstock/modules/unidecode/x076.py create mode 100644 nstock/modules/unidecode/x077.py create mode 100644 nstock/modules/unidecode/x078.py create mode 100644 nstock/modules/unidecode/x079.py create mode 100644 nstock/modules/unidecode/x07a.py create mode 100644 nstock/modules/unidecode/x07b.py create mode 100644 nstock/modules/unidecode/x07c.py create mode 100644 nstock/modules/unidecode/x07d.py create mode 100644 nstock/modules/unidecode/x07e.py create mode 100644 nstock/modules/unidecode/x07f.py create mode 100644 nstock/modules/unidecode/x080.py create mode 100644 nstock/modules/unidecode/x081.py create mode 100644 nstock/modules/unidecode/x082.py create mode 100644 nstock/modules/unidecode/x083.py create mode 100644 nstock/modules/unidecode/x084.py create mode 100644 nstock/modules/unidecode/x085.py create mode 100644 nstock/modules/unidecode/x086.py create mode 100644 nstock/modules/unidecode/x087.py create mode 100644 nstock/modules/unidecode/x088.py create mode 100644 nstock/modules/unidecode/x089.py create mode 100644 nstock/modules/unidecode/x08a.py create mode 100644 nstock/modules/unidecode/x08b.py create mode 100644 nstock/modules/unidecode/x08c.py create mode 100644 nstock/modules/unidecode/x08d.py create mode 100644 nstock/modules/unidecode/x08e.py create mode 100644 nstock/modules/unidecode/x08f.py create mode 100644 nstock/modules/unidecode/x090.py create mode 100644 nstock/modules/unidecode/x091.py create mode 100644 nstock/modules/unidecode/x092.py create mode 100644 nstock/modules/unidecode/x093.py create mode 100644 nstock/modules/unidecode/x094.py create mode 100644 nstock/modules/unidecode/x095.py create mode 100644 nstock/modules/unidecode/x096.py create mode 100644 nstock/modules/unidecode/x097.py create mode 100644 nstock/modules/unidecode/x098.py create mode 100644 nstock/modules/unidecode/x099.py create mode 100644 nstock/modules/unidecode/x09a.py create mode 100644 nstock/modules/unidecode/x09b.py create mode 100644 nstock/modules/unidecode/x09c.py create mode 100644 nstock/modules/unidecode/x09d.py create mode 100644 nstock/modules/unidecode/x09e.py create mode 100644 nstock/modules/unidecode/x09f.py create mode 100644 nstock/modules/unidecode/x0a0.py create mode 100644 nstock/modules/unidecode/x0a1.py create mode 100644 nstock/modules/unidecode/x0a2.py create mode 100644 nstock/modules/unidecode/x0a3.py create mode 100644 nstock/modules/unidecode/x0a4.py create mode 100644 nstock/modules/unidecode/x0ac.py create mode 100644 nstock/modules/unidecode/x0ad.py create mode 100644 nstock/modules/unidecode/x0ae.py create mode 100644 nstock/modules/unidecode/x0af.py create mode 100644 nstock/modules/unidecode/x0b0.py create mode 100644 nstock/modules/unidecode/x0b1.py create mode 100644 nstock/modules/unidecode/x0b2.py create mode 100644 nstock/modules/unidecode/x0b3.py create mode 100644 nstock/modules/unidecode/x0b4.py create mode 100644 nstock/modules/unidecode/x0b5.py create mode 100644 nstock/modules/unidecode/x0b6.py create mode 100644 nstock/modules/unidecode/x0b7.py create mode 100644 nstock/modules/unidecode/x0b8.py create mode 100644 nstock/modules/unidecode/x0b9.py create mode 100644 nstock/modules/unidecode/x0ba.py create mode 100644 nstock/modules/unidecode/x0bb.py create mode 100644 nstock/modules/unidecode/x0bc.py create mode 100644 nstock/modules/unidecode/x0bd.py create mode 100644 nstock/modules/unidecode/x0be.py create mode 100644 nstock/modules/unidecode/x0bf.py create mode 100644 nstock/modules/unidecode/x0c0.py create mode 100644 nstock/modules/unidecode/x0c1.py create mode 100644 nstock/modules/unidecode/x0c2.py create mode 100644 nstock/modules/unidecode/x0c3.py create mode 100644 nstock/modules/unidecode/x0c4.py create mode 100644 nstock/modules/unidecode/x0c5.py create mode 100644 nstock/modules/unidecode/x0c6.py create mode 100644 nstock/modules/unidecode/x0c7.py create mode 100644 nstock/modules/unidecode/x0c8.py create mode 100644 nstock/modules/unidecode/x0c9.py create mode 100644 nstock/modules/unidecode/x0ca.py create mode 100644 nstock/modules/unidecode/x0cb.py create mode 100644 nstock/modules/unidecode/x0cc.py create mode 100644 nstock/modules/unidecode/x0cd.py create mode 100644 nstock/modules/unidecode/x0ce.py create mode 100644 nstock/modules/unidecode/x0cf.py create mode 100644 nstock/modules/unidecode/x0d0.py create mode 100644 nstock/modules/unidecode/x0d1.py create mode 100644 nstock/modules/unidecode/x0d2.py create mode 100644 nstock/modules/unidecode/x0d3.py create mode 100644 nstock/modules/unidecode/x0d4.py create mode 100644 nstock/modules/unidecode/x0d5.py create mode 100644 nstock/modules/unidecode/x0d6.py create mode 100644 nstock/modules/unidecode/x0d7.py create mode 100644 nstock/modules/unidecode/x0f9.py create mode 100644 nstock/modules/unidecode/x0fa.py create mode 100644 nstock/modules/unidecode/x0fb.py create mode 100644 nstock/modules/unidecode/x0fc.py create mode 100644 nstock/modules/unidecode/x0fd.py create mode 100644 nstock/modules/unidecode/x0fe.py create mode 100644 nstock/modules/unidecode/x0ff.py create mode 100644 nstock/modules/unidecode/x1d4.py create mode 100644 nstock/modules/unidecode/x1d5.py create mode 100644 nstock/modules/unidecode/x1d6.py create mode 100644 nstock/modules/unidecode/x1d7.py create mode 100644 nstock/modules/whoosh/__init__.py create mode 100644 nstock/modules/whoosh/analysis/__init__.py create mode 100644 nstock/modules/whoosh/analysis/acore.py create mode 100644 nstock/modules/whoosh/analysis/analyzers.py create mode 100644 nstock/modules/whoosh/analysis/filters.py create mode 100644 nstock/modules/whoosh/analysis/intraword.py create mode 100644 nstock/modules/whoosh/analysis/morph.py create mode 100644 nstock/modules/whoosh/analysis/ngrams.py create mode 100644 nstock/modules/whoosh/analysis/tokenizers.py create mode 100644 nstock/modules/whoosh/automata/__init__.py create mode 100644 nstock/modules/whoosh/automata/fsa.py create mode 100644 nstock/modules/whoosh/automata/glob.py create mode 100644 nstock/modules/whoosh/automata/lev.py create mode 100644 nstock/modules/whoosh/automata/nfa.py create mode 100644 nstock/modules/whoosh/automata/reg.py create mode 100755 nstock/modules/whoosh/classify.py create mode 100644 nstock/modules/whoosh/codec/__init__.py create mode 100644 nstock/modules/whoosh/codec/base.py create mode 100644 nstock/modules/whoosh/codec/memory.py create mode 100644 nstock/modules/whoosh/codec/plaintext.py create mode 100644 nstock/modules/whoosh/codec/whoosh3.py create mode 100644 nstock/modules/whoosh/collectors.py create mode 100644 nstock/modules/whoosh/columns.py create mode 100644 nstock/modules/whoosh/compat.py create mode 100644 nstock/modules/whoosh/externalsort.py create mode 100644 nstock/modules/whoosh/fields.py create mode 100644 nstock/modules/whoosh/filedb/__init__.py create mode 100644 nstock/modules/whoosh/filedb/compound.py create mode 100644 nstock/modules/whoosh/filedb/filestore.py create mode 100644 nstock/modules/whoosh/filedb/filetables.py create mode 100644 nstock/modules/whoosh/filedb/gae.py create mode 100644 nstock/modules/whoosh/filedb/structfile.py create mode 100644 nstock/modules/whoosh/formats.py create mode 100644 nstock/modules/whoosh/highlight.py create mode 100644 nstock/modules/whoosh/idsets.py create mode 100644 nstock/modules/whoosh/index.py create mode 100644 nstock/modules/whoosh/lang/__init__.py create mode 100644 nstock/modules/whoosh/lang/dmetaphone.py create mode 100644 nstock/modules/whoosh/lang/isri.py create mode 100644 nstock/modules/whoosh/lang/lovins.py create mode 100644 nstock/modules/whoosh/lang/morph_en.py create mode 100644 nstock/modules/whoosh/lang/paicehusk.py create mode 100644 nstock/modules/whoosh/lang/phonetic.py create mode 100755 nstock/modules/whoosh/lang/porter.py create mode 100644 nstock/modules/whoosh/lang/porter2.py create mode 100644 nstock/modules/whoosh/lang/snowball/__init__.py create mode 100644 nstock/modules/whoosh/lang/snowball/bases.py create mode 100644 nstock/modules/whoosh/lang/snowball/danish.py create mode 100644 nstock/modules/whoosh/lang/snowball/dutch.py create mode 100644 nstock/modules/whoosh/lang/snowball/english.py create mode 100644 nstock/modules/whoosh/lang/snowball/finnish.py create mode 100644 nstock/modules/whoosh/lang/snowball/french.py create mode 100644 nstock/modules/whoosh/lang/snowball/german.py create mode 100644 nstock/modules/whoosh/lang/snowball/hungarian.py create mode 100644 nstock/modules/whoosh/lang/snowball/italian.py create mode 100644 nstock/modules/whoosh/lang/snowball/norwegian.py create mode 100644 nstock/modules/whoosh/lang/snowball/portugese.py create mode 100644 nstock/modules/whoosh/lang/snowball/romanian.py create mode 100644 nstock/modules/whoosh/lang/snowball/russian.py create mode 100644 nstock/modules/whoosh/lang/snowball/spanish.py create mode 100644 nstock/modules/whoosh/lang/snowball/swedish.py create mode 100644 nstock/modules/whoosh/lang/stopwords.py create mode 100644 nstock/modules/whoosh/lang/wordnet.py create mode 100644 nstock/modules/whoosh/legacy.py create mode 100644 nstock/modules/whoosh/matching/__init__.py create mode 100644 nstock/modules/whoosh/matching/binary.py create mode 100644 nstock/modules/whoosh/matching/combo.py create mode 100644 nstock/modules/whoosh/matching/mcore.py create mode 100644 nstock/modules/whoosh/matching/wrappers.py create mode 100644 nstock/modules/whoosh/multiproc.py create mode 100644 nstock/modules/whoosh/qparser/__init__.py create mode 100644 nstock/modules/whoosh/qparser/common.py create mode 100644 nstock/modules/whoosh/qparser/dateparse.py create mode 100644 nstock/modules/whoosh/qparser/default.py create mode 100644 nstock/modules/whoosh/qparser/plugins.py create mode 100644 nstock/modules/whoosh/qparser/syntax.py create mode 100644 nstock/modules/whoosh/qparser/taggers.py create mode 100644 nstock/modules/whoosh/query/__init__.py create mode 100644 nstock/modules/whoosh/query/compound.py create mode 100644 nstock/modules/whoosh/query/nested.py create mode 100644 nstock/modules/whoosh/query/positional.py create mode 100644 nstock/modules/whoosh/query/qcolumns.py create mode 100644 nstock/modules/whoosh/query/qcore.py create mode 100644 nstock/modules/whoosh/query/ranges.py create mode 100644 nstock/modules/whoosh/query/spans.py create mode 100644 nstock/modules/whoosh/query/terms.py create mode 100644 nstock/modules/whoosh/query/wrappers.py create mode 100644 nstock/modules/whoosh/reading.py create mode 100644 nstock/modules/whoosh/scoring.py create mode 100644 nstock/modules/whoosh/searching.py create mode 100644 nstock/modules/whoosh/sorting.py create mode 100644 nstock/modules/whoosh/spelling.py create mode 100644 nstock/modules/whoosh/support/__init__.py create mode 100644 nstock/modules/whoosh/support/base85.py create mode 100644 nstock/modules/whoosh/support/bench.py create mode 100644 nstock/modules/whoosh/support/charset.py create mode 100644 nstock/modules/whoosh/support/levenshtein.py create mode 100644 nstock/modules/whoosh/support/relativedelta.py create mode 100644 nstock/modules/whoosh/support/unicode.py create mode 100644 nstock/modules/whoosh/system.py create mode 100644 nstock/modules/whoosh/util/__init__.py create mode 100644 nstock/modules/whoosh/util/cache.py create mode 100644 nstock/modules/whoosh/util/filelock.py create mode 100644 nstock/modules/whoosh/util/loading.py create mode 100644 nstock/modules/whoosh/util/numeric.py create mode 100644 nstock/modules/whoosh/util/numlists.py create mode 100644 nstock/modules/whoosh/util/testing.py create mode 100644 nstock/modules/whoosh/util/text.py create mode 100644 nstock/modules/whoosh/util/times.py create mode 100644 nstock/modules/whoosh/util/varints.py create mode 100644 nstock/modules/whoosh/util/versions.py create mode 100644 nstock/modules/whoosh/writing.py create mode 100644 nstock/modules/z_whoosh.py create mode 100644 nstock/private/appconfig.ini create mode 100644 nstock/private/language-codes.csv create mode 100644 nstock/routes.example.py create mode 100644 nstock/sessions/.gitignore create mode 100644 nstock/shot-full.png create mode 100644 nstock/shot-thumb.png create mode 100644 nstock/static/403.html create mode 100644 nstock/static/404.html create mode 100644 nstock/static/500.html create mode 100644 nstock/static/css/bootstrap.min.css create mode 100644 nstock/static/css/bootstrap.min.css.map create mode 100644 nstock/static/css/calendar.css create mode 100644 nstock/static/css/diffview.css create mode 100644 nstock/static/css/font-awesome.min.css create mode 100644 nstock/static/css/fonts.css create mode 100644 nstock/static/css/jquery.simple-dtpicker.css create mode 100644 nstock/static/css/pace.css create mode 100644 nstock/static/css/style.css create mode 100644 nstock/static/css/web2py-bootstrap3.css create mode 100644 nstock/static/fonts/FontAwesome.otf create mode 100644 nstock/static/fonts/PlayfairDisplay-Regular.ttf create mode 100644 nstock/static/fonts/Raleway-Regular.ttf create mode 100644 nstock/static/fonts/fontawesome-webfont.eot create mode 100644 nstock/static/fonts/fontawesome-webfont.svg create mode 100644 nstock/static/fonts/fontawesome-webfont.ttf create mode 100644 nstock/static/fonts/fontawesome-webfont.woff create mode 100644 nstock/static/fonts/fontawesome-webfont.woff2 create mode 100644 nstock/static/fonts/glyphicons-halflings-regular.eot create mode 100644 nstock/static/fonts/glyphicons-halflings-regular.svg create mode 100644 nstock/static/fonts/glyphicons-halflings-regular.ttf create mode 100644 nstock/static/fonts/glyphicons-halflings-regular.woff create mode 100644 nstock/static/fonts/glyphicons-halflings-regular.woff2 create mode 100644 nstock/static/images/background.jpg create mode 100644 nstock/static/images/facebook.png create mode 100644 nstock/static/images/favicon.ico create mode 100644 nstock/static/images/favicon.png create mode 100644 nstock/static/images/gplus-32.png create mode 100644 nstock/static/images/twitter.png create mode 100644 nstock/static/js/analytics.min.js create mode 100644 nstock/static/js/bootstrap.min.js create mode 100644 nstock/static/js/calendar.js create mode 100755 nstock/static/js/difflib.js create mode 100644 nstock/static/js/diffview.js create mode 100644 nstock/static/js/holder.min.js create mode 100644 nstock/static/js/jquery.js create mode 100644 nstock/static/js/jquery.simple-dtpicker.js create mode 100644 nstock/static/js/modernizr-2.8.3.min.js create mode 100644 nstock/static/js/npm.js create mode 100644 nstock/static/js/pace.min.js create mode 100644 nstock/static/js/respond-1.4.2.min.js create mode 100644 nstock/static/js/share.js create mode 100644 nstock/static/js/vue.min.js create mode 100644 nstock/static/js/web2py-bootstrap3.js create mode 100644 nstock/static/js/web2py.js create mode 100644 nstock/static/plugin_ckeditor/CHANGES.md create mode 100644 nstock/static/plugin_ckeditor/LICENSE.md create mode 100644 nstock/static/plugin_ckeditor/README.md create mode 100644 nstock/static/plugin_ckeditor/adapters/jquery.js create mode 100644 nstock/static/plugin_ckeditor/build-config.js create mode 100644 nstock/static/plugin_ckeditor/ckeditor.js create mode 100644 nstock/static/plugin_ckeditor/config.js create mode 100644 nstock/static/plugin_ckeditor/contents.css create mode 100644 nstock/static/plugin_ckeditor/lang/af.js create mode 100644 nstock/static/plugin_ckeditor/lang/ar.js create mode 100644 nstock/static/plugin_ckeditor/lang/bg.js create mode 100644 nstock/static/plugin_ckeditor/lang/bn.js create mode 100644 nstock/static/plugin_ckeditor/lang/bs.js create mode 100644 nstock/static/plugin_ckeditor/lang/ca.js create mode 100644 nstock/static/plugin_ckeditor/lang/cs.js create mode 100644 nstock/static/plugin_ckeditor/lang/cy.js create mode 100644 nstock/static/plugin_ckeditor/lang/da.js create mode 100644 nstock/static/plugin_ckeditor/lang/de-ch.js create mode 100644 nstock/static/plugin_ckeditor/lang/de.js create mode 100644 nstock/static/plugin_ckeditor/lang/el.js create mode 100644 nstock/static/plugin_ckeditor/lang/en-au.js create mode 100644 nstock/static/plugin_ckeditor/lang/en-ca.js create mode 100644 nstock/static/plugin_ckeditor/lang/en-gb.js create mode 100644 nstock/static/plugin_ckeditor/lang/en.js create mode 100644 nstock/static/plugin_ckeditor/lang/eo.js create mode 100644 nstock/static/plugin_ckeditor/lang/es.js create mode 100644 nstock/static/plugin_ckeditor/lang/et.js create mode 100644 nstock/static/plugin_ckeditor/lang/eu.js create mode 100644 nstock/static/plugin_ckeditor/lang/fa.js create mode 100644 nstock/static/plugin_ckeditor/lang/fi.js create mode 100644 nstock/static/plugin_ckeditor/lang/fo.js create mode 100644 nstock/static/plugin_ckeditor/lang/fr-ca.js create mode 100644 nstock/static/plugin_ckeditor/lang/fr.js create mode 100644 nstock/static/plugin_ckeditor/lang/gl.js create mode 100644 nstock/static/plugin_ckeditor/lang/gu.js create mode 100644 nstock/static/plugin_ckeditor/lang/he.js create mode 100644 nstock/static/plugin_ckeditor/lang/hi.js create mode 100644 nstock/static/plugin_ckeditor/lang/hr.js create mode 100644 nstock/static/plugin_ckeditor/lang/hu.js create mode 100644 nstock/static/plugin_ckeditor/lang/id.js create mode 100644 nstock/static/plugin_ckeditor/lang/is.js create mode 100644 nstock/static/plugin_ckeditor/lang/it.js create mode 100644 nstock/static/plugin_ckeditor/lang/ja.js create mode 100644 nstock/static/plugin_ckeditor/lang/ka.js create mode 100644 nstock/static/plugin_ckeditor/lang/km.js create mode 100644 nstock/static/plugin_ckeditor/lang/ko.js create mode 100644 nstock/static/plugin_ckeditor/lang/ku.js create mode 100644 nstock/static/plugin_ckeditor/lang/lt.js create mode 100644 nstock/static/plugin_ckeditor/lang/lv.js create mode 100644 nstock/static/plugin_ckeditor/lang/mk.js create mode 100644 nstock/static/plugin_ckeditor/lang/mn.js create mode 100644 nstock/static/plugin_ckeditor/lang/ms.js create mode 100644 nstock/static/plugin_ckeditor/lang/nb.js create mode 100644 nstock/static/plugin_ckeditor/lang/nl.js create mode 100644 nstock/static/plugin_ckeditor/lang/no.js create mode 100644 nstock/static/plugin_ckeditor/lang/pl.js create mode 100644 nstock/static/plugin_ckeditor/lang/pt-br.js create mode 100644 nstock/static/plugin_ckeditor/lang/pt.js create mode 100644 nstock/static/plugin_ckeditor/lang/ro.js create mode 100644 nstock/static/plugin_ckeditor/lang/ru.js create mode 100644 nstock/static/plugin_ckeditor/lang/si.js create mode 100644 nstock/static/plugin_ckeditor/lang/sk.js create mode 100644 nstock/static/plugin_ckeditor/lang/sl.js create mode 100644 nstock/static/plugin_ckeditor/lang/sq.js create mode 100644 nstock/static/plugin_ckeditor/lang/sr-latn.js create mode 100644 nstock/static/plugin_ckeditor/lang/sr.js create mode 100644 nstock/static/plugin_ckeditor/lang/sv.js create mode 100644 nstock/static/plugin_ckeditor/lang/th.js create mode 100644 nstock/static/plugin_ckeditor/lang/tr.js create mode 100644 nstock/static/plugin_ckeditor/lang/tt.js create mode 100644 nstock/static/plugin_ckeditor/lang/ug.js create mode 100644 nstock/static/plugin_ckeditor/lang/uk.js create mode 100644 nstock/static/plugin_ckeditor/lang/vi.js create mode 100644 nstock/static/plugin_ckeditor/lang/zh-cn.js create mode 100644 nstock/static/plugin_ckeditor/lang/zh.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/a11yhelp.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/_translationstatus.txt create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/af.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/ar.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/bg.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/ca.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/cs.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/cy.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/da.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/de-ch.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/de.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/el.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/en-gb.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/en.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/eo.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/es.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/et.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/eu.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/fa.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/fi.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/fo.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/fr-ca.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/fr.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/gl.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/gu.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/he.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/hi.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/hr.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/hu.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/id.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/it.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/ja.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/km.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/ko.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/ku.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/lt.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/lv.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/mk.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/mn.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/nb.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/nl.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/no.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/pl.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/pt-br.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/pt.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/ro.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/ru.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/si.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/sk.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/sl.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/sq.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/sr-latn.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/sr.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/sv.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/th.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/tr.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/tt.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/ug.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/uk.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/vi.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/zh-cn.js create mode 100644 nstock/static/plugin_ckeditor/plugins/a11yhelp/dialogs/lang/zh.js create mode 100644 nstock/static/plugin_ckeditor/plugins/about/dialogs/about.js create mode 100644 nstock/static/plugin_ckeditor/plugins/about/dialogs/hidpi/logo_ckeditor.png create mode 100644 nstock/static/plugin_ckeditor/plugins/about/dialogs/logo_ckeditor.png create mode 100644 nstock/static/plugin_ckeditor/plugins/clipboard/dialogs/paste.js create mode 100644 nstock/static/plugin_ckeditor/plugins/colordialog/dialogs/colordialog.js create mode 100644 nstock/static/plugin_ckeditor/plugins/dialog/dialogDefinition.js create mode 100644 nstock/static/plugin_ckeditor/plugins/div/dialogs/div.js create mode 100644 nstock/static/plugin_ckeditor/plugins/find/dialogs/find.js create mode 100644 nstock/static/plugin_ckeditor/plugins/flash/dialogs/flash.js create mode 100644 nstock/static/plugin_ckeditor/plugins/flash/images/placeholder.png create mode 100644 nstock/static/plugin_ckeditor/plugins/forms/dialogs/button.js create mode 100644 nstock/static/plugin_ckeditor/plugins/forms/dialogs/checkbox.js create mode 100644 nstock/static/plugin_ckeditor/plugins/forms/dialogs/form.js create mode 100644 nstock/static/plugin_ckeditor/plugins/forms/dialogs/hiddenfield.js create mode 100644 nstock/static/plugin_ckeditor/plugins/forms/dialogs/radio.js create mode 100644 nstock/static/plugin_ckeditor/plugins/forms/dialogs/select.js create mode 100644 nstock/static/plugin_ckeditor/plugins/forms/dialogs/textarea.js create mode 100644 nstock/static/plugin_ckeditor/plugins/forms/dialogs/textfield.js create mode 100644 nstock/static/plugin_ckeditor/plugins/forms/images/hiddenfield.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/icons.png create mode 100644 nstock/static/plugin_ckeditor/plugins/icons_hidpi.png create mode 100644 nstock/static/plugin_ckeditor/plugins/iframe/dialogs/iframe.js create mode 100644 nstock/static/plugin_ckeditor/plugins/iframe/images/placeholder.png create mode 100644 nstock/static/plugin_ckeditor/plugins/image/dialogs/image.js create mode 100644 nstock/static/plugin_ckeditor/plugins/image/images/noimage.png create mode 100644 nstock/static/plugin_ckeditor/plugins/link/dialogs/anchor.js create mode 100644 nstock/static/plugin_ckeditor/plugins/link/dialogs/link.js create mode 100644 nstock/static/plugin_ckeditor/plugins/link/images/anchor.png create mode 100644 nstock/static/plugin_ckeditor/plugins/link/images/hidpi/anchor.png create mode 100644 nstock/static/plugin_ckeditor/plugins/liststyle/dialogs/liststyle.js create mode 100644 nstock/static/plugin_ckeditor/plugins/magicline/images/hidpi/icon-rtl.png create mode 100644 nstock/static/plugin_ckeditor/plugins/magicline/images/hidpi/icon.png create mode 100644 nstock/static/plugin_ckeditor/plugins/magicline/images/icon-rtl.png create mode 100644 nstock/static/plugin_ckeditor/plugins/magicline/images/icon.png create mode 100644 nstock/static/plugin_ckeditor/plugins/pagebreak/images/pagebreak.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/pastefromword/filter/default.js create mode 100644 nstock/static/plugin_ckeditor/plugins/preview/preview.html create mode 100644 nstock/static/plugin_ckeditor/plugins/scayt/CHANGELOG.md create mode 100644 nstock/static/plugin_ckeditor/plugins/scayt/LICENSE.md create mode 100644 nstock/static/plugin_ckeditor/plugins/scayt/README.md create mode 100644 nstock/static/plugin_ckeditor/plugins/scayt/dialogs/options.js create mode 100644 nstock/static/plugin_ckeditor/plugins/scayt/dialogs/toolbar.css create mode 100644 nstock/static/plugin_ckeditor/plugins/showblocks/images/block_address.png create mode 100644 nstock/static/plugin_ckeditor/plugins/showblocks/images/block_blockquote.png create mode 100644 nstock/static/plugin_ckeditor/plugins/showblocks/images/block_div.png create mode 100644 nstock/static/plugin_ckeditor/plugins/showblocks/images/block_h1.png create mode 100644 nstock/static/plugin_ckeditor/plugins/showblocks/images/block_h2.png create mode 100644 nstock/static/plugin_ckeditor/plugins/showblocks/images/block_h3.png create mode 100644 nstock/static/plugin_ckeditor/plugins/showblocks/images/block_h4.png create mode 100644 nstock/static/plugin_ckeditor/plugins/showblocks/images/block_h5.png create mode 100644 nstock/static/plugin_ckeditor/plugins/showblocks/images/block_h6.png create mode 100644 nstock/static/plugin_ckeditor/plugins/showblocks/images/block_p.png create mode 100644 nstock/static/plugin_ckeditor/plugins/showblocks/images/block_pre.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/dialogs/smiley.js create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/angel_smile.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/angel_smile.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/angry_smile.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/angry_smile.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/broken_heart.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/broken_heart.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/confused_smile.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/confused_smile.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/cry_smile.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/cry_smile.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/devil_smile.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/devil_smile.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/embaressed_smile.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/embarrassed_smile.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/embarrassed_smile.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/envelope.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/envelope.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/heart.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/heart.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/kiss.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/kiss.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/lightbulb.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/lightbulb.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/omg_smile.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/omg_smile.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/regular_smile.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/regular_smile.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/sad_smile.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/sad_smile.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/shades_smile.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/shades_smile.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/teeth_smile.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/teeth_smile.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/thumbs_down.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/thumbs_down.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/thumbs_up.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/thumbs_up.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/tongue_smile.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/tongue_smile.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/tounge_smile.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/whatchutalkingabout_smile.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/whatchutalkingabout_smile.png create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/wink_smile.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/smiley/images/wink_smile.png create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/_translationstatus.txt create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/af.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/ar.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/bg.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/ca.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/cs.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/cy.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/da.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/de-ch.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/de.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/el.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/en-gb.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/en.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/eo.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/es.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/et.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/eu.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/fa.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/fi.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/fr-ca.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/fr.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/gl.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/he.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/hr.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/hu.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/id.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/it.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/ja.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/km.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/ko.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/ku.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/lt.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/lv.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/nb.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/nl.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/no.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/pl.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/pt-br.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/pt.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/ru.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/si.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/sk.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/sl.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/sq.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/sv.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/th.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/tr.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/tt.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/ug.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/uk.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/vi.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/zh-cn.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/lang/zh.js create mode 100644 nstock/static/plugin_ckeditor/plugins/specialchar/dialogs/specialchar.js create mode 100644 nstock/static/plugin_ckeditor/plugins/table/dialogs/table.js create mode 100644 nstock/static/plugin_ckeditor/plugins/tabletools/dialogs/tableCell.js create mode 100644 nstock/static/plugin_ckeditor/plugins/templates/dialogs/templates.css create mode 100644 nstock/static/plugin_ckeditor/plugins/templates/dialogs/templates.js create mode 100644 nstock/static/plugin_ckeditor/plugins/templates/templates/default.js create mode 100644 nstock/static/plugin_ckeditor/plugins/templates/templates/images/template1.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/templates/templates/images/template2.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/templates/templates/images/template3.gif create mode 100644 nstock/static/plugin_ckeditor/plugins/wsc/LICENSE.md create mode 100644 nstock/static/plugin_ckeditor/plugins/wsc/README.md create mode 100644 nstock/static/plugin_ckeditor/plugins/wsc/dialogs/ciframe.html create mode 100644 nstock/static/plugin_ckeditor/plugins/wsc/dialogs/tmpFrameset.html create mode 100644 nstock/static/plugin_ckeditor/plugins/wsc/dialogs/wsc.css create mode 100644 nstock/static/plugin_ckeditor/plugins/wsc/dialogs/wsc.js create mode 100644 nstock/static/plugin_ckeditor/plugins/wsc/dialogs/wsc_ie.js create mode 100644 nstock/static/plugin_ckeditor/samples/css/samples.css create mode 100644 nstock/static/plugin_ckeditor/samples/img/github-top.png create mode 100644 nstock/static/plugin_ckeditor/samples/img/header-bg.png create mode 100644 nstock/static/plugin_ckeditor/samples/img/header-separator.png create mode 100644 nstock/static/plugin_ckeditor/samples/img/logo.png create mode 100644 nstock/static/plugin_ckeditor/samples/img/navigation-tip.png create mode 100644 nstock/static/plugin_ckeditor/samples/index.html create mode 100644 nstock/static/plugin_ckeditor/samples/js/sample.js create mode 100644 nstock/static/plugin_ckeditor/samples/js/sf.js create mode 100644 nstock/static/plugin_ckeditor/samples/old/ajax.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/api.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/appendto.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/assets/inlineall/logo.png create mode 100644 nstock/static/plugin_ckeditor/samples/old/assets/outputxhtml/outputxhtml.css create mode 100644 nstock/static/plugin_ckeditor/samples/old/assets/posteddata.php create mode 100644 nstock/static/plugin_ckeditor/samples/old/assets/sample.jpg create mode 100644 nstock/static/plugin_ckeditor/samples/old/assets/uilanguages/languages.js create mode 100644 nstock/static/plugin_ckeditor/samples/old/datafiltering.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/dialog/assets/my_dialog.js create mode 100644 nstock/static/plugin_ckeditor/samples/old/dialog/dialog.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/divreplace.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/enterkey/enterkey.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/htmlwriter/assets/outputforflash/outputforflash.fla create mode 100644 nstock/static/plugin_ckeditor/samples/old/htmlwriter/assets/outputforflash/outputforflash.swf create mode 100644 nstock/static/plugin_ckeditor/samples/old/htmlwriter/assets/outputforflash/swfobject.js create mode 100644 nstock/static/plugin_ckeditor/samples/old/htmlwriter/outputforflash.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/htmlwriter/outputhtml.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/index.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/inlineall.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/inlinebycode.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/inlinetextarea.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/jquery.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/magicline/magicline.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/readonly.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/replacebyclass.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/replacebycode.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/sample.css create mode 100644 nstock/static/plugin_ckeditor/samples/old/sample.js create mode 100644 nstock/static/plugin_ckeditor/samples/old/sample_posteddata.php create mode 100644 nstock/static/plugin_ckeditor/samples/old/tabindex.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/toolbar/toolbar.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/uicolor.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/uilanguages.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/wysiwygarea/fullpage.html create mode 100644 nstock/static/plugin_ckeditor/samples/old/xhtmlstyle.html create mode 100644 nstock/static/plugin_ckeditor/samples/toolbarconfigurator/css/fontello.css create mode 100644 nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/LICENSE.txt create mode 100644 nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/config.json create mode 100644 nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/fontello.eot create mode 100644 nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/fontello.svg create mode 100644 nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/fontello.ttf create mode 100644 nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/fontello.woff create mode 100644 nstock/static/plugin_ckeditor/samples/toolbarconfigurator/index.html create mode 100644 nstock/static/plugin_ckeditor/samples/toolbarconfigurator/js/abstracttoolbarmodifier.js create mode 100644 nstock/static/plugin_ckeditor/samples/toolbarconfigurator/js/fulltoolbareditor.js create mode 100644 nstock/static/plugin_ckeditor/samples/toolbarconfigurator/js/toolbarmodifier.js create mode 100644 nstock/static/plugin_ckeditor/samples/toolbarconfigurator/js/toolbartextmodifier.js create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_ie.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_ie7.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_ie8.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_iequirks.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_opera.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_gecko.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_ie.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_ie7.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_ie8.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_iequirks.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/dialog.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_ie.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_ie7.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_ie8.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_iequirks.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_opera.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/editor.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/editor_gecko.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/editor_ie.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/editor_ie7.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/editor_ie8.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/editor_iequirks.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/icons.png create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/icons_hidpi.png create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/images/arrow.png create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/images/close.png create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/images/hidpi/close.png create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/images/hidpi/lock-open.png create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/images/hidpi/lock.png create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/images/hidpi/refresh.png create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/images/lock-open.png create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/images/lock.png create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/images/refresh.png create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/readme.md create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/sample/bootstrapck-sample.html create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/sample/css/bootstrapck-sample.css create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/sample/js/analytics.js create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/sample/js/jquery-1.11.0.min.js create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/browser-specific/gecko/editor_gecko.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/browser-specific/ie/dialog_ie.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/browser-specific/ie/editor_ie.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/browser-specific/ie7/dialog_ie7.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/browser-specific/ie7/editor_ie7.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/browser-specific/ie8/dialog_ie8.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/browser-specific/ie8/editor_ie8.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/browser-specific/iequirks/dialog_iequirks.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/browser-specific/iequirks/editor_iequirks.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/browser-specific/opera/dialog_opera.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/components/_colorpanel.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/components/_elementspath.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/components/_mainui.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/components/_menu.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/components/_panel.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/components/_presets.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/components/_reset.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/components/_richcombo.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/components/_toolbar.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/components/editor.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/config/_colors.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/config/_config.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/config/_defaults.scss create mode 100644 nstock/static/plugin_ckeditor/skins/bootstrapck/scss/dialog/dialog.scss create mode 100644 nstock/static/plugin_ckeditor/skins/moono/dialog.css create mode 100644 nstock/static/plugin_ckeditor/skins/moono/dialog_ie.css create mode 100644 nstock/static/plugin_ckeditor/skins/moono/dialog_ie7.css create mode 100644 nstock/static/plugin_ckeditor/skins/moono/dialog_ie8.css create mode 100644 nstock/static/plugin_ckeditor/skins/moono/dialog_iequirks.css create mode 100644 nstock/static/plugin_ckeditor/skins/moono/editor.css create mode 100644 nstock/static/plugin_ckeditor/skins/moono/editor_gecko.css create mode 100644 nstock/static/plugin_ckeditor/skins/moono/editor_ie.css create mode 100644 nstock/static/plugin_ckeditor/skins/moono/editor_ie7.css create mode 100644 nstock/static/plugin_ckeditor/skins/moono/editor_ie8.css create mode 100644 nstock/static/plugin_ckeditor/skins/moono/editor_iequirks.css create mode 100644 nstock/static/plugin_ckeditor/skins/moono/icons.png create mode 100644 nstock/static/plugin_ckeditor/skins/moono/icons_hidpi.png create mode 100644 nstock/static/plugin_ckeditor/skins/moono/images/arrow.png create mode 100644 nstock/static/plugin_ckeditor/skins/moono/images/close.png create mode 100644 nstock/static/plugin_ckeditor/skins/moono/images/hidpi/close.png create mode 100644 nstock/static/plugin_ckeditor/skins/moono/images/hidpi/lock-open.png create mode 100644 nstock/static/plugin_ckeditor/skins/moono/images/hidpi/lock.png create mode 100644 nstock/static/plugin_ckeditor/skins/moono/images/hidpi/refresh.png create mode 100644 nstock/static/plugin_ckeditor/skins/moono/images/lock-open.png create mode 100644 nstock/static/plugin_ckeditor/skins/moono/images/lock.png create mode 100644 nstock/static/plugin_ckeditor/skins/moono/images/refresh.png create mode 100644 nstock/static/plugin_ckeditor/skins/moono/images/spinner.gif create mode 100644 nstock/static/plugin_ckeditor/skins/moono/readme.md create mode 100644 nstock/static/plugin_ckeditor/style.css create mode 100644 nstock/static/plugin_ckeditor/styles.js create mode 100644 nstock/static/plugin_photoset/css/fileuploader.css create mode 100644 nstock/static/plugin_photoset/css/style.css create mode 100644 nstock/static/plugin_photoset/images/loading.gif create mode 100644 nstock/static/plugin_photoset/js/fileuploader.js create mode 100644 nstock/uploads/.gitignore create mode 100644 nstock/views/__init__.py create mode 100644 nstock/views/appadmin.html create mode 100644 nstock/views/changes_email.txt create mode 100644 nstock/views/default/index.html create mode 100644 nstock/views/default/user.html create mode 100644 nstock/views/desk/create.html create mode 100644 nstock/views/desk/delete.html create mode 100644 nstock/views/desk/desk_menu.html create mode 100644 nstock/views/desk/edit.html create mode 100644 nstock/views/desk/index.html create mode 100644 nstock/views/desk/item_list.load create mode 100644 nstock/views/desk/user_perms.html create mode 100644 nstock/views/desk/users.html create mode 100644 nstock/views/generic.html create mode 100644 nstock/views/generic.ics create mode 100644 nstock/views/generic.json create mode 100644 nstock/views/generic.jsonp create mode 100644 nstock/views/generic.load create mode 100644 nstock/views/generic.map create mode 100644 nstock/views/generic.pdf create mode 100644 nstock/views/generic.rss create mode 100644 nstock/views/generic.xml create mode 100644 nstock/views/item/add_items.html create mode 100644 nstock/views/item/changelog.html create mode 100644 nstock/views/item/diff.html create mode 100644 nstock/views/item/full_text.txt create mode 100644 nstock/views/item/index.html create mode 100644 nstock/views/item/index.load create mode 100644 nstock/views/item/item_layout.html create mode 100644 nstock/views/item/meta.html create mode 100644 nstock/views/item/meta.load create mode 100644 nstock/views/item/preview.html create mode 100644 nstock/views/item/share.html create mode 100644 nstock/views/item/share.load create mode 100644 nstock/views/layout.html create mode 100644 nstock/views/notifications.html create mode 100644 nstock/views/notifications/index.html create mode 100644 nstock/views/org/create.html create mode 100644 nstock/views/org/edit.html create mode 100644 nstock/views/org/index.html create mode 100644 nstock/views/org/members.html create mode 100644 nstock/views/org/org_sidebar.html create mode 100644 nstock/views/org/view.html create mode 100644 nstock/views/plugin_ckeditor/browse.html create mode 100644 nstock/views/plugin_ckeditor/upload.html create mode 100644 nstock/views/plugin_comment/index.load create mode 100644 nstock/views/plugin_comment/someone_commented.txt create mode 100644 nstock/views/plugin_package/changelog.html create mode 100644 nstock/views/plugin_package/create.html create mode 100644 nstock/views/plugin_package/create_group_form.load create mode 100644 nstock/views/plugin_package/diff.html create mode 100644 nstock/views/plugin_package/full_text.txt create mode 100644 nstock/views/plugin_package/index.html create mode 100644 nstock/views/plugin_package/preview.html create mode 100644 nstock/views/plugin_package/view_group.load create mode 100644 nstock/views/plugin_package/view_package_groups.load create mode 100644 nstock/views/plugin_photoset/changelog.html create mode 100644 nstock/views/plugin_photoset/create.html create mode 100644 nstock/views/plugin_photoset/diff.html create mode 100644 nstock/views/plugin_photoset/full_text.txt create mode 100644 nstock/views/plugin_photoset/index.html create mode 100644 nstock/views/plugin_photoset/preview.html create mode 100644 nstock/views/plugin_photoset/preview_photo.load create mode 100644 nstock/views/plugin_photoset/view_photoset.load create mode 100644 nstock/views/plugin_picture/add_rendition.html create mode 100644 nstock/views/plugin_picture/changelog.html create mode 100644 nstock/views/plugin_picture/create.html create mode 100644 nstock/views/plugin_picture/diff.html create mode 100644 nstock/views/plugin_picture/full_text.txt create mode 100644 nstock/views/plugin_picture/index.html create mode 100644 nstock/views/plugin_picture/preview.html create mode 100644 nstock/views/plugin_text/changelog.html create mode 100644 nstock/views/plugin_text/create.html create mode 100644 nstock/views/plugin_text/diff.html create mode 100644 nstock/views/plugin_text/full_text.txt create mode 100644 nstock/views/plugin_text/index.html create mode 100644 nstock/views/plugin_text/index_old.html create mode 100644 nstock/views/plugin_text/preview.html create mode 100644 nstock/views/share_email.txt create mode 100644 nstock/views/web2py_ajax.html create mode 100644 nstock/web2py.app.nstock.w2p diff --git a/nstock/.gitignore b/nstock/.gitignore new file mode 100644 index 0000000..8f34e87 --- /dev/null +++ b/nstock/.gitignore @@ -0,0 +1,47 @@ +__pycache__/ +*.py[cod] +*.so +.Python +env/ +venv/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.coverage +.cache +nosetests.xml +coverage.xml +*.mo +*.pot +*.log +docs/_build/ +target/ +cache/* +databases/* +errors/* +sessions/* +uploads/* +whoosh/* +*.bak +.pythonhistory +.project +.pydevproject +.settings +*.pkl +enews.nja diff --git a/nstock/ABOUT b/nstock/ABOUT new file mode 100644 index 0000000..184b19c --- /dev/null +++ b/nstock/ABOUT @@ -0,0 +1,2 @@ +Write something about this app. +Developed with web2py. diff --git a/nstock/LICENSE b/nstock/LICENSE new file mode 100644 index 0000000..cc30c52 --- /dev/null +++ b/nstock/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Yoel Benítez Fonseca + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/nstock/README.md b/nstock/README.md new file mode 100644 index 0000000..53c55a1 --- /dev/null +++ b/nstock/README.md @@ -0,0 +1,31 @@ +# nStock + +A system for news item management, i mean the pictures, texts, translations, +etc. those bits of info that glued together make the news as you can see on +the newspaper site. + +In nStock each user has a personal desk. Each new Item is stored on the user personal desktop. + +Organizations consist of a set of desk, over which users will have some permissions, for example: view the contents of the desk, send items to the desk or edit the contents of the desk (Items). In this way, several workflows can be represented. + +## Install + +This is a web2py application. Fallow the instructions on [web2py book](http://web2py.com/books/default/chapter/29/13/deployment-recipes) or for testing purposes download [web2py](http://www.web2py.com/) and clone this repo in the applications folder in your local web2py instance. + +## Requirements. + +- PIL: you need to install python-pil for image handling. + +## First time. + +The first time the system is used, the site admin will need to give permissions for some users to be able to create organizations. For that, go to appadmin: + +``` +http://YOUR.SITE.NAME/nstock/appadmin +``` + +And give the permission ```create_org``` to the user group. + +## SC + +![nStock Desk](https://i.screenshot.net/x52m9tx) diff --git a/nstock/__init__.py b/nstock/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/nstock/__init__.py @@ -0,0 +1 @@ + diff --git a/nstock/cache/.gitignore b/nstock/cache/.gitignore new file mode 100644 index 0000000..76bedae --- /dev/null +++ b/nstock/cache/.gitignore @@ -0,0 +1,5 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore + diff --git a/nstock/controllers/appadmin.py b/nstock/controllers/appadmin.py new file mode 100644 index 0000000..2f78074 --- /dev/null +++ b/nstock/controllers/appadmin.py @@ -0,0 +1,701 @@ +# -*- coding: utf-8 -*- + +# ########################################################## +# ## make sure administrator is on localhost +# ########################################################### + +import os +import socket +import datetime +import copy +import gluon.contenttype +import gluon.fileutils + +try: + import pygraphviz as pgv +except ImportError: + pgv = None + +is_gae = request.env.web2py_runtime_gae or False + +# ## critical --- make a copy of the environment + +global_env = copy.copy(globals()) +global_env['datetime'] = datetime + +http_host = request.env.http_host.split(':')[0] +remote_addr = request.env.remote_addr +try: + hosts = (http_host, socket.gethostname(), + socket.gethostbyname(http_host), + '::1', '127.0.0.1', '::ffff:127.0.0.1') +except: + hosts = (http_host, ) + +if request.is_https: + session.secure() +elif (remote_addr not in hosts) and (remote_addr != "127.0.0.1") and \ + (request.function != 'manage'): + raise HTTP(200, T('appadmin is disabled because insecure channel')) + +if request.function == 'manage': + if not 'auth' in globals() or not request.args: + redirect(URL(request.controller, 'index')) + manager_action = auth.settings.manager_actions.get(request.args(0), None) + if manager_action is None and request.args(0) == 'auth': + manager_action = dict(role=auth.settings.auth_manager_role, + heading=T('Manage Access Control'), + tables=[auth.table_user(), + auth.table_group(), + auth.table_permission()]) + manager_role = manager_action.get('role', None) if manager_action else None + if not (gluon.fileutils.check_credentials(request) or auth.has_membership(manager_role)): + raise HTTP(403, "Not authorized") + menu = False +elif (request.application == 'admin' and not session.authorized) or \ + (request.application != 'admin' and not gluon.fileutils.check_credentials(request)): + redirect(URL('admin', 'default', 'index', + vars=dict(send=URL(args=request.args, vars=request.vars)))) +else: + response.subtitle = T('Database Administration (appadmin)') + menu = True + +ignore_rw = True +response.view = 'appadmin.html' +if menu: + response.menu = [[T('design'), False, URL('admin', 'default', 'design', + args=[request.application])], [T('db'), False, + URL('index')], [T('state'), False, + URL('state')], [T('cache'), False, + URL('ccache')]] + +# ########################################################## +# ## auxiliary functions +# ########################################################### + +if False and request.tickets_db: + from gluon.restricted import TicketStorage + ts = TicketStorage() + ts._get_table(request.tickets_db, ts.tablename, request.application) + +def get_databases(request): + dbs = {} + for (key, value) in global_env.items(): + try: + cond = isinstance(value, GQLDB) + except: + cond = isinstance(value, SQLDB) + if cond: + dbs[key] = value + return dbs + +databases = get_databases(None) + +def eval_in_global_env(text): + exec ('_ret=%s' % text, {}, global_env) + return global_env['_ret'] + + +def get_database(request): + if request.args and request.args[0] in databases: + return eval_in_global_env(request.args[0]) + else: + session.flash = T('invalid request') + redirect(URL('index')) + +def get_table(request): + db = get_database(request) + if len(request.args) > 1 and request.args[1] in db.tables: + return (db, request.args[1]) + else: + session.flash = T('invalid request') + redirect(URL('index')) + + +def get_query(request): + try: + return eval_in_global_env(request.vars.query) + except Exception: + return None + + +def query_by_table_type(tablename, db, request=request): + keyed = hasattr(db[tablename], '_primarykey') + if keyed: + firstkey = db[tablename][db[tablename]._primarykey[0]] + cond = '>0' + if firstkey.type in ['string', 'text']: + cond = '!=""' + qry = '%s.%s.%s%s' % ( + request.args[0], request.args[1], firstkey.name, cond) + else: + qry = '%s.%s.id>0' % tuple(request.args[:2]) + return qry + + +# ########################################################## +# ## list all databases and tables +# ########################################################### +def index(): + return dict(databases=databases) + + +# ########################################################## +# ## insert a new record +# ########################################################### + + +def insert(): + (db, table) = get_table(request) + form = SQLFORM(db[table], ignore_rw=ignore_rw) + if form.accepts(request.vars, session): + response.flash = T('new record inserted') + return dict(form=form, table=db[table]) + + +# ########################################################## +# ## list all records in table and insert new record +# ########################################################### + + +def download(): + import os + db = get_database(request) + return response.download(request, db) + + +def csv(): + import gluon.contenttype + response.headers['Content-Type'] = \ + gluon.contenttype.contenttype('.csv') + db = get_database(request) + query = get_query(request) + if not query: + return None + response.headers['Content-disposition'] = 'attachment; filename=%s_%s.csv'\ + % tuple(request.vars.query.split('.')[:2]) + return str(db(query, ignore_common_filters=True).select()) + + +def import_csv(table, file): + table.import_from_csv_file(file) + + +def select(): + import re + db = get_database(request) + dbname = request.args[0] + try: + is_imap = db._uri.startswith("imap://") + except (KeyError, AttributeError, TypeError): + is_imap = False + regex = re.compile('(?P\w+)\.(?P\w+)=(?P\d+)') + if len(request.args) > 1 and hasattr(db[request.args[1]], '_primarykey'): + regex = re.compile('(?P
\w+)\.(?P\w+)=(?P.+)') + if request.vars.query: + match = regex.match(request.vars.query) + if match: + request.vars.query = '%s.%s.%s==%s' % (request.args[0], + match.group('table'), match.group('field'), + match.group('value')) + else: + request.vars.query = session.last_query + query = get_query(request) + if request.vars.start: + start = int(request.vars.start) + else: + start = 0 + nrows = 0 + + step = 100 + fields = [] + + if is_imap: + step = 3 + + stop = start + step + + table = None + rows = [] + orderby = request.vars.orderby + if orderby: + orderby = dbname + '.' + orderby + if orderby == session.last_orderby: + if orderby[0] == '~': + orderby = orderby[1:] + else: + orderby = '~' + orderby + session.last_orderby = orderby + session.last_query = request.vars.query + form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px', + _name='query', _value=request.vars.query or '', + requires=IS_NOT_EMPTY( + error_message=T("Cannot be empty")))), TR(T('Update:'), + INPUT(_name='update_check', _type='checkbox', + value=False), INPUT(_style='width:400px', + _name='update_fields', _value=request.vars.update_fields + or '')), TR(T('Delete:'), INPUT(_name='delete_check', + _class='delete', _type='checkbox', value=False), ''), + TR('', '', INPUT(_type='submit', _value=T('submit')))), + _action=URL(r=request, args=request.args)) + + tb = None + if form.accepts(request.vars, formname=None): + regex = re.compile(request.args[0] + '\.(?P
\w+)\..+') + match = regex.match(form.vars.query.strip()) + if match: + table = match.group('table') + try: + nrows = db(query, ignore_common_filters=True).count() + if form.vars.update_check and form.vars.update_fields: + db(query, ignore_common_filters=True).update( + **eval_in_global_env('dict(%s)' % form.vars.update_fields)) + response.flash = T('%s %%{row} updated', nrows) + elif form.vars.delete_check: + db(query, ignore_common_filters=True).delete() + response.flash = T('%s %%{row} deleted', nrows) + nrows = db(query, ignore_common_filters=True).count() + + if is_imap: + fields = [db[table][name] for name in + ("id", "uid", "created", "to", + "sender", "subject")] + if orderby: + rows = db(query, ignore_common_filters=True).select( + *fields, limitby=(start, stop), + orderby=eval_in_global_env(orderby)) + else: + rows = db(query, ignore_common_filters=True).select( + *fields, limitby=(start, stop)) + except Exception, e: + import traceback + tb = traceback.format_exc() + (rows, nrows) = ([], 0) + response.flash = DIV(T('Invalid Query'), PRE(str(e))) + # begin handle upload csv + csv_table = table or request.vars.table + if csv_table: + formcsv = FORM(str(T('or import from csv file')) + " ", + INPUT(_type='file', _name='csvfile'), + INPUT(_type='hidden', _value=csv_table, _name='table'), + INPUT(_type='submit', _value=T('import'))) + else: + formcsv = None + if formcsv and formcsv.process().accepted: + try: + import_csv(db[request.vars.table], + request.vars.csvfile.file) + response.flash = T('data uploaded') + except Exception, e: + response.flash = DIV(T('unable to parse csv file'), PRE(str(e))) + # end handle upload csv + + return dict( + form=form, + table=table, + start=start, + stop=stop, + step=step, + nrows=nrows, + rows=rows, + query=request.vars.query, + formcsv=formcsv, + tb=tb + ) + + +# ########################################################## +# ## edit delete one record +# ########################################################### + + +def update(): + (db, table) = get_table(request) + keyed = hasattr(db[table], '_primarykey') + record = None + db[table]._common_filter = None + if keyed: + key = [f for f in request.vars if f in db[table]._primarykey] + if key: + record = db(db[table][key[0]] == request.vars[key[ + 0]]).select().first() + else: + record = db(db[table].id == request.args( + 2)).select().first() + + if not record: + qry = query_by_table_type(table, db) + session.flash = T('record does not exist') + redirect(URL('select', args=request.args[:1], + vars=dict(query=qry))) + + if keyed: + for k in db[table]._primarykey: + db[table][k].writable = False + + form = SQLFORM( + db[table], record, deletable=True, delete_label=T('Check to delete'), + ignore_rw=ignore_rw and not keyed, + linkto=URL('select', + args=request.args[:1]), upload=URL(r=request, + f='download', args=request.args[:1])) + + if form.accepts(request.vars, session): + session.flash = T('done!') + qry = query_by_table_type(table, db) + redirect(URL('select', args=request.args[:1], + vars=dict(query=qry))) + return dict(form=form, table=db[table]) + + +# ########################################################## +# ## get global variables +# ########################################################### + + +def state(): + return dict() + + +def ccache(): + if is_gae: + form = FORM( + P(TAG.BUTTON(T("Clear CACHE?"), _type="submit", _name="yes", _value="yes"))) + else: + cache.ram.initialize() + cache.disk.initialize() + + form = FORM( + P(TAG.BUTTON( + T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")), + P(TAG.BUTTON( + T("Clear RAM"), _type="submit", _name="ram", _value="ram")), + P(TAG.BUTTON( + T("Clear DISK"), _type="submit", _name="disk", _value="disk")), + ) + + if form.accepts(request.vars, session): + session.flash = "" + if is_gae: + if request.vars.yes: + cache.ram.clear() + session.flash += T("Cache Cleared") + else: + clear_ram = False + clear_disk = False + if request.vars.yes: + clear_ram = clear_disk = True + if request.vars.ram: + clear_ram = True + if request.vars.disk: + clear_disk = True + if clear_ram: + cache.ram.clear() + session.flash += T("Ram Cleared") + if clear_disk: + cache.disk.clear() + session.flash += T("Disk Cleared") + redirect(URL(r=request)) + + try: + from guppy import hpy + hp = hpy() + except ImportError: + hp = False + + import shelve + import os + import copy + import time + import math + from gluon import portalocker + + ram = { + 'entries': 0, + 'bytes': 0, + 'objects': 0, + 'hits': 0, + 'misses': 0, + 'ratio': 0, + 'oldest': time.time(), + 'keys': [] + } + + disk = copy.copy(ram) + total = copy.copy(ram) + disk['keys'] = [] + total['keys'] = [] + + def GetInHMS(seconds): + hours = math.floor(seconds / 3600) + seconds -= hours * 3600 + minutes = math.floor(seconds / 60) + seconds -= minutes * 60 + seconds = math.floor(seconds) + + return (hours, minutes, seconds) + + if is_gae: + gae_stats = cache.ram.client.get_stats() + try: + gae_stats['ratio'] = ((gae_stats['hits'] * 100) / + (gae_stats['hits'] + gae_stats['misses'])) + except ZeroDivisionError: + gae_stats['ratio'] = T("?") + gae_stats['oldest'] = GetInHMS(time.time() - gae_stats['oldest_item_age']) + total.update(gae_stats) + else: + # get ram stats directly from the cache object + ram_stats = cache.ram.stats[request.application] + ram['hits'] = ram_stats['hit_total'] - ram_stats['misses'] + ram['misses'] = ram_stats['misses'] + try: + ram['ratio'] = ram['hits'] * 100 / ram_stats['hit_total'] + except (KeyError, ZeroDivisionError): + ram['ratio'] = 0 + + for key, value in cache.ram.storage.iteritems(): + if hp: + ram['bytes'] += hp.iso(value[1]).size + ram['objects'] += hp.iso(value[1]).count + ram['entries'] += 1 + if value[0] < ram['oldest']: + ram['oldest'] = value[0] + ram['keys'].append((key, GetInHMS(time.time() - value[0]))) + + for key in cache.disk.storage: + value = cache.disk.storage[key] + if isinstance(value[1], dict): + disk['hits'] = value[1]['hit_total'] - value[1]['misses'] + disk['misses'] = value[1]['misses'] + try: + disk['ratio'] = disk['hits'] * 100 / value[1]['hit_total'] + except (KeyError, ZeroDivisionError): + disk['ratio'] = 0 + else: + if hp: + disk['bytes'] += hp.iso(value[1]).size + disk['objects'] += hp.iso(value[1]).count + disk['entries'] += 1 + if value[0] < disk['oldest']: + disk['oldest'] = value[0] + disk['keys'].append((key, GetInHMS(time.time() - value[0]))) + + ram_keys = ram.keys() # ['hits', 'objects', 'ratio', 'entries', 'keys', 'oldest', 'bytes', 'misses'] + ram_keys.remove('ratio') + ram_keys.remove('oldest') + for key in ram_keys: + total[key] = ram[key] + disk[key] + + try: + total['ratio'] = total['hits'] * 100 / (total['hits'] + + total['misses']) + except (KeyError, ZeroDivisionError): + total['ratio'] = 0 + + if disk['oldest'] < ram['oldest']: + total['oldest'] = disk['oldest'] + else: + total['oldest'] = ram['oldest'] + + ram['oldest'] = GetInHMS(time.time() - ram['oldest']) + disk['oldest'] = GetInHMS(time.time() - disk['oldest']) + total['oldest'] = GetInHMS(time.time() - total['oldest']) + + def key_table(keys): + return TABLE( + TR(TD(B(T('Key'))), TD(B(T('Time in Cache (h:m:s)')))), + *[TR(TD(k[0]), TD('%02d:%02d:%02d' % k[1])) for k in keys], + **dict(_class='cache-keys', + _style="border-collapse: separate; border-spacing: .5em;")) + + if not is_gae: + ram['keys'] = key_table(ram['keys']) + disk['keys'] = key_table(disk['keys']) + total['keys'] = key_table(total['keys']) + + return dict(form=form, total=total, + ram=ram, disk=disk, object_stats=hp != False) + + +def table_template(table): + from gluon.html import TR, TD, TABLE, TAG + + def FONT(*args, **kwargs): + return TAG.font(*args, **kwargs) + + def types(field): + f_type = field.type + if not isinstance(f_type,str): + return ' ' + elif f_type == 'string': + return field.length + elif f_type == 'id': + return B('pk') + elif f_type.startswith('reference') or \ + f_type.startswith('list:reference'): + return B('fk') + else: + return ' ' + + # This is horribe HTML but the only one graphiz understands + rows = [] + cellpadding = 4 + color = "#000000" + bgcolor = "#FFFFFF" + face = "Helvetica" + face_bold = "Helvetica Bold" + border = 0 + + rows.append(TR(TD(FONT(table, _face=face_bold, _color=bgcolor), + _colspan=3, _cellpadding=cellpadding, + _align="center", _bgcolor=color))) + for row in db[table]: + rows.append(TR(TD(FONT(row.name, _color=color, _face=face_bold), + _align="left", _cellpadding=cellpadding, + _border=border), + TD(FONT(row.type, _color=color, _face=face), + _align="left", _cellpadding=cellpadding, + _border=border), + TD(FONT(types(row), _color=color, _face=face), + _align="center", _cellpadding=cellpadding, + _border=border))) + return "< %s >" % TABLE(*rows, **dict(_bgcolor=bgcolor, _border=1, + _cellborder=0, _cellspacing=0) + ).xml() + + +def bg_graph_model(): + graph = pgv.AGraph(layout='dot', directed=True, strict=False, rankdir='LR') + + subgraphs = dict() + for tablename in db.tables: + if hasattr(db[tablename],'_meta_graphmodel'): + meta_graphmodel = db[tablename]._meta_graphmodel + else: + meta_graphmodel = dict(group=request.application, color='#ECECEC') + + group = meta_graphmodel['group'].replace(' ', '') + if group not in subgraphs: + subgraphs[group] = dict(meta=meta_graphmodel, tables=[]) + subgraphs[group]['tables'].append(tablename) + + graph.add_node(tablename, name=tablename, shape='plaintext', + label=table_template(tablename)) + + for n, key in enumerate(subgraphs.iterkeys()): + graph.subgraph(nbunch=subgraphs[key]['tables'], + name='cluster%d' % n, + style='filled', + color=subgraphs[key]['meta']['color'], + label=subgraphs[key]['meta']['group']) + + for tablename in db.tables: + for field in db[tablename]: + f_type = field.type + if isinstance(f_type,str) and ( + f_type.startswith('reference') or + f_type.startswith('list:reference')): + referenced_table = f_type.split()[1].split('.')[0] + n1 = graph.get_node(tablename) + n2 = graph.get_node(referenced_table) + graph.add_edge(n1, n2, color="#4C4C4C", label='') + + graph.layout() + if not request.args: + response.headers['Content-Type'] = 'image/png' + return graph.draw(format='png', prog='dot') + else: + response.headers['Content-Disposition']='attachment;filename=graph.%s'%request.args(0) + if request.args(0) == 'dot': + return graph.string() + else: + return graph.draw(format=request.args(0), prog='dot') + +def graph_model(): + return dict(databases=databases, pgv=pgv) + +def manage(): + tables = manager_action['tables'] + if isinstance(tables[0], str): + db = manager_action.get('db', auth.db) + db = globals()[db] if isinstance(db, str) else db + tables = [db[table] for table in tables] + if request.args(0) == 'auth': + auth.table_user()._plural = T('Users') + auth.table_group()._plural = T('Roles') + auth.table_membership()._plural = T('Memberships') + auth.table_permission()._plural = T('Permissions') + if request.extension != 'load': + return dict(heading=manager_action.get('heading', + T('Manage %(action)s') % dict(action=request.args(0).replace('_', ' ').title())), + tablenames=[table._tablename for table in tables], + labels=[table._plural.title() for table in tables]) + + table = tables[request.args(1, cast=int)] + formname = '%s_grid' % table._tablename + linked_tables = orderby = None + if request.args(0) == 'auth': + auth.table_group()._id.readable = \ + auth.table_membership()._id.readable = \ + auth.table_permission()._id.readable = False + auth.table_membership().user_id.label = T('User') + auth.table_membership().group_id.label = T('Role') + auth.table_permission().group_id.label = T('Role') + auth.table_permission().name.label = T('Permission') + if table == auth.table_user(): + linked_tables=[auth.settings.table_membership_name] + elif table == auth.table_group(): + orderby = 'role' if not request.args(3) or '.group_id' not in request.args(3) else None + elif table == auth.table_permission(): + orderby = 'group_id' + kwargs = dict(user_signature=True, maxtextlength=1000, + orderby=orderby, linked_tables=linked_tables) + smartgrid_args = manager_action.get('smartgrid_args', {}) + kwargs.update(**smartgrid_args.get('DEFAULT', {})) + kwargs.update(**smartgrid_args.get(table._tablename, {})) + grid = SQLFORM.smartgrid(table, args=request.args[:2], formname=formname, **kwargs) + return grid + +def hooks(): + import functools + import inspect + list_op=['_%s_%s' %(h,m) for h in ['before', 'after'] for m in ['insert','update','delete']] + tables=[] + with_build_it=False + for db_str in sorted(databases): + db = databases[db_str] + for t in db.tables: + method_hooks=[] + for op in list_op: + functions = [] + for f in getattr(db[t], op): + if hasattr(f, '__call__'): + try: + if isinstance(f, (functools.partial)): + f = f.func + filename = inspect.getsourcefile(f) + details = {'funcname':f.__name__, + 'filename':filename[len(request.folder):] if request.folder in filename else None, + 'lineno': inspect.getsourcelines(f)[1]} + if details['filename']: # Built in functions as delete_uploaded_files are not editable + details['url'] = URL(a='admin',c='default',f='edit', args=[request['application'], details['filename']],vars={'lineno':details['lineno']}) + if details['filename'] or with_build_it: + functions.append(details) + # compiled app and windows build don't support code inspection + except: + pass + if len(functions): + method_hooks.append({'name':op, 'functions':functions}) + if len(method_hooks): + tables.append({'name':"%s.%s" % (db_str,t), 'slug': IS_SLUG()("%s.%s" % (db_str,t))[0], 'method_hooks':method_hooks}) + # Render + ul_main = UL(_class='nav nav-list') + for t in tables: + ul_main.append(A(t['name'], _onclick="collapse('a_%s')" % t['slug'])) + ul_t = UL(_class='nav nav-list', _id="a_%s" % t['slug'], _style='display:none') + for op in t['method_hooks']: + ul_t.append(LI (op['name'])) + ul_t.append(UL([LI(A(f['funcname'], _class="editor_filelink", _href=f['url']if 'url' in f else None, **{'_data-lineno':f['lineno']-1})) for f in op['functions']])) + ul_main.append(ul_t) + return ul_main diff --git a/nstock/controllers/default.py b/nstock/controllers/default.py new file mode 100644 index 0000000..1a73292 --- /dev/null +++ b/nstock/controllers/default.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +if False: + from gluon import current, redirect, URL + request = current.request + response = current.response + session = current.session + cache = current.cache + T = current.T + from db import db, auth, service + from dc import application + + +@auth.requires_login() +def index(): + """ + LOAD all components with ajax + """ + user_desk = application.getUserDesk() + redirect(URL('desk', 'index', args=[user_desk.id])) + return locals() + + +def user(): + """ + exposes: + http://..../[app]/default/user/login + http://..../[app]/default/user/logout + http://..../[app]/default/user/register + http://..../[app]/default/user/profile + http://..../[app]/default/user/retrieve_password + http://..../[app]/default/user/change_password + http://..../[app]/default/user/bulk_register + use @auth.requires_login() + @auth.requires_membership('group name') + @auth.requires_permission('read','table name',record_id) + to decorate functions that need access control + also notice there is http://..../[app]/appadmin/manage/auth + to allow administrator to manage users + """ + form = auth() + return dict(form=form) + + +@cache.action() +def download(): + """ + allows downloading of uploaded files + http://..../[app]/default/download/[filename] + """ + return response.download(request, db) + + +def call(): + """ + exposes services. for example: + http://..../[app]/default/call/jsonrpc + decorate with @services.jsonrpc the functions to expose + supports xml, json, xmlrpc, jsonrpc, amfrpc, rss, csv + """ + return service() diff --git a/nstock/controllers/desk.py b/nstock/controllers/desk.py new file mode 100644 index 0000000..ce77ea4 --- /dev/null +++ b/nstock/controllers/desk.py @@ -0,0 +1,247 @@ +# -*- coding: utf-8 -*- +if False: + from gluon import current, URL, SQLFORM, redirect + from gluon import IS_NOT_EMPTY, Field + request = current.request + response = current.response + session = current.session + cache = current.cache + T = current.T + from db import db, auth + from dc import application + + +@auth.requires( + lambda: auth.has_permission('owner', db.desk, request.args(0)) or + (auth.has_permission('read', db.desk, request.args(0)) or + auth.has_permission('update', db.desk, request.args(0)) or + auth.has_permission('update_items', db.desk, request.args(0))) +) +def index(): + """Show the list of items in this desk""" + desk = db.desk(request.args(0)) + + if desk.id == application.getUserDesk().id: + session.org_id = None + session.desk_id = desk.id + # used to mark items for package creation + session.marked_items = [] + + return locals() + + +@auth.requires( + lambda: auth.has_permission('owner', db.desk, request.args(0)) or + (auth.has_permission('read', db.desk, request.args(0)) or + auth.has_permission('update', db.desk, request.args(0)) or + auth.has_permission('update_items', db.desk, request.args(0))) +) +def item_list(): + """Show the list of items in this desk""" + desk = db.desk(request.args(0)) + + if desk.id == application.getUserDesk().id: + session.org_id = None + session.desk_id = desk.id + + return locals() + + +@auth.requires_login() +def toogle_mark(): + if session.marked_items is None: + session.marked_items = [] + + item = application.getItemByUUID(request.args(0)) + session.marked_items.append(item.unique_id) + + return '' + + +@auth.requires( + lambda: auth.has_permission('update', db.desk, request.args(0))) +def edit(): + desk = db.desk(request.args(0)) + session.desk_id = desk.id + + db.desk.item_list.readable = False + db.desk.item_list.writable = False + form = SQLFORM(db.desk, record=desk, showid=False) + + if form.process().accepted: + redirect(URL('index', args=[desk.id])) + + return locals() + + +@auth.requires( + lambda: auth.has_permission('update', db.desk, request.args(0))) +def delete(): + desk = db.desk(request.args(0)) + session.desk_id = desk.id + + db.desk.item_list.readable = False + db.desk.item_list.writable = False + form = SQLFORM.confirm( + T("Are you sure?"), + {T('Cancel'): URL('index', args=[desk.id])}) + + if form.accepted: + # empty move all the items in the desk to the owners desk + for item_id in desk.item_list: + item = db.item(item_id) + owner = db.auth_user(item.created_by) + owner_desk = application.getUserDesk(user=owner) + owner_desk_items = owner_desk.item_list + owner_desk_items.append(item_id) + owner_desk.update_record(item_list=owner_desk_items) + + # remove desk from org + org = db( + db.organization.desks.contains(desk.id) + ).select().first() + desk_list = org.desks + desk_list.remove(desk.id) + org.update_record(desks=desk_list) + # delete the desk from db. + del db.desk[desk.id] + # cleanup context + session.desk_id = None + # go to org view + redirect(URL('org','view', args=[org.id])) + + return locals() + + +@auth.requires( + lambda: auth.has_permission('update', db.desk, request.args(0))) +def users(): + desk = db.desk(request.args(0)) + session.desk_id = desk.id + + org = db.organization(session.org_id) + + if request.args(1): + my_user = db.auth_user(request.args(1)) + + fld_read_desk = Field('read_desk', 'boolean') + fld_read_desk.label = T("Read '%s' content", (desk.name,)) + fld_read_desk.comment = T( + "Allow the user read only access to the desk item list.") + fld_read_desk.default = auth.has_permission( + 'read', db.desk, desk.id, my_user.id) + + fld_update_items = Field('update_items', 'boolean') + fld_update_items.label = T("Read/Update items in '%s'", (desk.name,)) + fld_update_items.comment = T( + "Allow the user make modifications to the items in the desk.") + fld_update_items.default = auth.has_permission( + 'update_items', db.desk, desk.id, my_user.id) + + fld_push_items = Field('push_items', 'boolean') + fld_push_items.label = T("Push items into '%s'", (desk.name,)) + fld_push_items.comment = T( + """Allow the user move items into the desk.""" + ) + fld_push_items.default = auth.has_permission( + 'push_items', db.desk, desk.id, my_user.id) + + fld_update_desk = Field('update_desk', 'boolean') + fld_update_desk.label = T("Update/Manage '%s'", (desk.name,)) + fld_update_desk.comment = T( + """ + Allow the user to manage/administrate this desk. Use with caution. + """ + ) + fld_update_desk.default = auth.has_permission( + 'update', db.desk, desk.id, my_user.id) + + form = SQLFORM.factory( + fld_read_desk, + fld_update_items, + fld_push_items, + fld_update_desk, + table_name='desk_perms' + ) + + if form.process().accepted: + if form.vars.read_desk: + # give perm + auth.add_permission( + auth.user_group(my_user.id), 'read', db.desk, desk.id) + else: + auth.del_permission( + auth.user_group(my_user.id), 'read', db.desk, desk.id) + + if form.vars.update_items: + # give perm + auth.add_permission( + auth.user_group(my_user.id), 'update_items', db.desk, + desk.id) + else: + auth.del_permission( + auth.user_group(my_user.id), 'update_items', db.desk, + desk.id) + + if form.vars.push_items: + # give perm + auth.add_permission( + auth.user_group(my_user.id), 'push_items', db.desk, + desk.id) + else: + auth.del_permission( + auth.user_group(my_user.id), 'push_items', db.desk, + desk.id) + + if form.vars.update_desk: + # give perm + auth.add_permission( + auth.user_group(my_user.id), 'update_desk', db.desk, + desk.id) + else: + auth.del_permission( + auth.user_group(my_user.id), 'update_desk', db.desk, + desk.id) + + redirect(URL('desk', 'users', args=[desk.id])) + + response.view = "desk/user_perms.html" + else: + # select user view + query = (db.auth_user.id > 0) + query &= (db.auth_user.id.belongs(org.users)) + + my_users = db(query).select() + + return locals() + + +@auth.requires( + lambda: auth.has_permission('update', db.organization, session.org_id)) +def create(): + org = db.organization(session.org_id) + tbl = db.desk + tbl.item_list.readable = False + tbl.item_list.writable = False + tbl.name.requires = IS_NOT_EMPTY() + + form = SQLFORM(db.desk) + form.add_button(T('Cancel'), URL('org', 'view', args=[org.id])) + + if form.process().accepted: + # add the new desk to the org list + desk_id = form.vars.id + # add current users as the one with permission to update manage + # this desk + auth.add_permission( + auth.user_group(auth.user.id), + 'update', + db.desk, + desk_id) + desk_list = org.desks + desk_list.insert(0, desk_id) + org.update_record(desks=desk_list) + # return to the org desk list + redirect(URL('org', 'view', args=[org.id])) + + return locals() diff --git a/nstock/controllers/item.py b/nstock/controllers/item.py new file mode 100644 index 0000000..3f27667 --- /dev/null +++ b/nstock/controllers/item.py @@ -0,0 +1,197 @@ +# -*- coding: utf-8 -*- +if False: + from gluon import redirect, current, Field, HTTP + from gluon import A, CAT, SPAN, SQLFORM, URL, IS_IN_SET + request = current.request + response = current.response + session = current.session + cache = current.cache + T = current.T + from db import auth, db + from dc import application + + +@auth.requires(lambda: application.canReadItem(request.args(0))) +def index(): + """ + Make it the same as all_items or search views but showing only one item. + """ + item = application.getItemByUUID(request.args(0)) + + return locals() + + +@auth.requires(lambda: application.canUpdateItem(request.args(0))) +def meta(): + """ + Edit/Show item metadata info + """ + item = application.getItemByUUID(request.args(0)) + + if item is None: + raise HTTP(404) + + contentType = application.getContentType(item.item_type) + l_names = [ + (r.language_tag, r.english_name) for r in db( + db.languages.id > 0 + ).select(orderby=db.languages.english_name) + ] + db.item.language_tag.requires = IS_IN_SET( + l_names, + zero=None + ) + + # issue #5 hidde some fields from metadata + db.item.provider.readable = False + db.item.provider.writable = False + db.item.provider_service.readable = False + db.item.provider_service.writable = False + db.item.copyright_holder.readable = False + db.item.copyright_holder.writable = False + db.item.copyright_url.readable = False + db.item.copyright_url.writable = False + db.item.copyright_notice.readable = False + db.item.copyright_notice.writable = False + db.item.pubstatus.readable = False + db.item.pubstatus.writable = False + + form = SQLFORM(db.item, record=item) + + if form.process().accepted: + # session.flash = "Done !" + # send an email to all the users who has access to this item + application.notifyChanges(item.unique_id) + application.indexItem(item.unique_id) + if request.ajax: + response.js = "$('#metaModal').modal('hide');" + else: + redirect(application.getItemURL(item.unique_id)) + + return locals() + + +@auth.requires(lambda: application.canReadItem(request.args(0))) +def changelog(): + """ + Show item change log over the time + """ + item = application.getItemByUUID(request.args(0)) + if item is None: + raise HTTP(404) + + query = (db.item_archive.current_record == item.id) + db.item_archive.modified_on.label = T('Date & Time') + db.item_archive.modified_on.readable = True + db.item_archive.modified_by.label = T('User') + db.item_archive.modified_by.readable = True + fields = [ + db.item_archive.modified_on, + db.item_archive.modified_by + ] + + def gen_links(row): + diff = A( + SPAN(_class="glyphicon glyphicon-random"), + _href=URL( + 'diff', + args=[item.unique_id, row.id]), + _class="btn btn-default", + _title=T("Differences"), + ) + + return CAT(diff) + + links = [dict(header='', body=gen_links)] + + changes = SQLFORM.grid( + query, + orderby=[~db.item_archive.modified_on], + fields=fields, + args=request.args[:1], + create=False, editable=False, details=False, deletable=False, + searchable=False, + csv=False, + links=links, + ) + + return dict(item=item, changes=changes) + + +@auth.requires(lambda: application.canReadItem(request.args(0))) +def diff(): + """ + Show the diff betwen the actual item and the archive one + """ + item = application.getItemByUUID(request.args(0)) + if item is None: + raise HTTP(404) + item_archive = db.item_archive(request.args(1)) + if item_archive is None: + raise HTTP(503) + + fields = [] + fields_archived = [] + + # allow view of administrative metadata + db.item.modified_by.readable = True + db.item.modified_on.readable = True + db.item_archive.modified_by.readable = True + db.item_archive.modified_on.readable = True + + for f in db.item: + if item[f.name] != item_archive[f.name]: + f.comment = None + fields.append(f) + db.item_archive[f.name].comment = None + fields_archived.append(db.item_archive[f.name]) + + # build two readonly forms + form_actual = SQLFORM.factory( + *fields, + record=item, + readonly=True, + showid=False, + formstyle='divs' + ) + form_archive = SQLFORM.factory( + *fields_archived, + record=item_archive, + readonly=True, + showid=False, + formstyle='divs') + + return dict(item=item, form_actual=form_actual, form_archive=form_archive) + + +@auth.requires(lambda: application.canUpdateItem(request.args(0))) +def share(): + """ + Show the list of desk to with the item can be push + """ + item = application.getItemByUUID(request.args(0)) + if item is None: + raise HTTP(404) + + query = (db.desk.id != session.desk_id) + query &= auth.accessible_query('push_items', db.desk) + + posible_desk = db(query).select() + + fld_to_desk = Field('to_desk', 'integer') + fld_to_desk.label = T("Push to") + fld_to_desk.comment = T("Select where to push the item") + fld_to_desk.requires = IS_IN_SET( + [(desk.id, desk.name) for desk in posible_desk] + ) + form = SQLFORM.factory( + fld_to_desk, + submit_button=T("Send"), + table_name='share') + if form.process().accepted: + # send the item to the selected desk + ct = application.getContentType(item.item_type) + ct.shareItem(item.unique_id, session.desk_id, form.vars.to_desk) + response.js = "$('#metaModal').modal('hide');" + + return locals() diff --git a/nstock/controllers/notifications.py b/nstock/controllers/notifications.py new file mode 100644 index 0000000..e5d2e81 --- /dev/null +++ b/nstock/controllers/notifications.py @@ -0,0 +1,60 @@ +# coding: utf-8 +if False: + from gluon import current, SQLFORM, I, XML + response = current.response + request = current.request + from db import db, auth + + +@auth.requires_login() +def index(): + """ + Show notifications for the current user + """ + tbl = db.notification + query = (tbl.id > 0) + query &= (tbl.to_user == auth.user.id) + + def p_seen_rpr(v, r): + if v: + return I(_class="fa fa-envelope-open-o") + + return I(_class="fa fa-envelope") + tbl.seen.represent = p_seen_rpr + + if request.args(0) == 'view': + tbl.seen.readable = False + tbl.message_content.represent = lambda v, r: XML(v) + msg = tbl(request.args(2)) + msg.update_record(seen=True) + tbl.from_user.represent = lambda v, r: db.auth_user(v).email + + grid = SQLFORM.grid( + query, + fields=[tbl.subject, tbl.from_user, tbl.seen, tbl.msg_date], + paginate=10, + showbuttontext=False, + editable=False, + csv=False, + maxtextlengths={'notification.subject': 100}, + create=False, + searchable=False, + orderby=[~tbl.msg_date], + formstyle='bootstrap', + ) + + return dict(grid=grid) + + +@auth.requires_login() +def has_notifications(): + query = (db.notification.id > 0) + query &= (db.notification.seen == False) + query &= (db.notification.to_user == auth.user.id) + + nots = db(query).select(db.notification.ALL) + + if nots: + return response.json(True) + + return response.json(False) diff --git a/nstock/controllers/org.py b/nstock/controllers/org.py new file mode 100644 index 0000000..94847b2 --- /dev/null +++ b/nstock/controllers/org.py @@ -0,0 +1,151 @@ +# -*- coding: utf-8 -*- +if False: + from gluon import current, URL, SQLFORM, redirect + from gluon import IS_NOT_EMPTY, Field, IS_EMAIL + from gluon import IS_NOT_IN_DB + request = current.request + response = current.response + session = current.session + cache = current.cache + T = current.T + from db import db, auth + + +@auth.requires_login() +def index(): + """ + Show the user the organizations he/she can access + """ + query = (db.organization.id > 0) + query &= ( + auth.accessible_query('read', db.organization) | + auth.accessible_query('update', db.organization)) + + orgs = db(query).select(db.organization.ALL) + + return locals() + + +@auth.requires( + auth.has_permission('read', db.organization, request.args(0)) or + auth.has_permission('update', db.organization, request.args(0)) +) +def view(): + """ + Show the list of desks in this org + """ + org = db.organization(request.args(0)) + session.org_id = org.id + return locals() + + +@auth.requires(auth.has_permission('update', db.organization, request.args(0))) +def edit(): + org = db.organization(request.args(0)) + tbl = db.organization + tbl.users.readable = False + tbl.users.writable = False + tbl.desks.readable = False + tbl.desks.writable = False + tbl.name.requires = [IS_NOT_EMPTY()] + + # edit form + form = SQLFORM(db.organization, record=org, showid=False) + if form.process().accepted: + redirect(URL('view', args=[org.id])) + + return locals() + + +@auth.requires(auth.has_permission('update', db.organization, request.args(0))) +def members(): + org = db.organization(request.args(0)) + + if not request.args(1): + fld_email = Field('email', 'string', label=T("Email")) + fld_email.requires = IS_EMAIL() + + form = SQLFORM.factory( + fld_email, + formstyle='bootstrap3_inline', + submit_button=T("Add user"), + table_name='members') + + if form.process().accepted: + u = db.auth_user(email=form.vars.email) + if u is not None: + # create new share + if u.id in org.users: + form.errors.email = T( + "The user is already in the organization") + else: + user_list = org.users + user_list.insert(0, u.id) + org.update_record(users=user_list) + g_id = auth.user_group(u.id) + auth.add_permission(g_id, 'read', db.organization, org.id) + else: + # no user with that email + response.flash = "" + form.errors.email = T("The user don't exists on this system") + elif request.args(1) == 'delete': + # remove the user on args(2) from the org members list + # TODO: remove else any perms on the org desks + user_to_remove = db.auth_user(request.args(2)) + if user_to_remove is not None: + user_list = org.users + user_list.remove(user_to_remove.id) + org.update_record(users=user_list) + # remove perms over the org + auth.del_permission( + auth.user_group(user_to_remove.id), + 'read', + db.organization, + org.id) + # remove, also, all rights over the desks in the org. + desk_perms = [ + 'read_desk', 'update_items', 'push_items', 'update_desk'] + for desk_id in org.desks: + for perm in desk_perms: + auth.del_permission( + auth.user_group(user_to_remove.id), + perm, + db.desk, + desk_id + ) + redirect(URL('org', 'members', args=[org.id])) + + return locals() + + +@auth.requires_login() +def create(): + """Create a new organization""" + tbl = db.organization + tbl.users.readable = False + tbl.users.writable = False + tbl.desks.readable = False + tbl.desks.writable = False + tbl.name.requires = [ + IS_NOT_EMPTY( + error_message=T("Cannot be empty") + ), + IS_NOT_IN_DB( + db, + 'organization.name', + error_message=T( + "An Organization witch that name is allready in nStock"))] + + form = SQLFORM(tbl) + form.add_button(T('Cancel'), URL('index')) + + if form.process().accepted: + # add the new organization + g_id = auth.user_group(auth.user.id) + # give the user all perms over this org + auth.add_permission(g_id, 'update', tbl, form.vars.id) + auth.add_permission(g_id, 'read', tbl, form.vars.id) + auth.add_permission(g_id, 'delete', tbl, form.vars.id) + redirect(URL('index')) + + return locals() diff --git a/nstock/controllers/plugin_ckeditor.py b/nstock/controllers/plugin_ckeditor.py new file mode 100644 index 0000000..c04a7e7 --- /dev/null +++ b/nstock/controllers/plugin_ckeditor.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- + +import os +from gluon import * + +def upload(): + (new_filename, old_filename, length, + mime_type) = current.plugin_ckeditor.handle_upload() + + title = os.path.splitext(old_filename)[0] + + result = current.plugin_ckeditor.settings.table_upload.validate_and_insert( + title=title, + filename=old_filename, + upload=new_filename, + flength=length, + mime_type=mime_type + ) + + text = '' + url = URL(*current.plugin_ckeditor.settings.download_url, + args=[new_filename]) + + if not result.id: + text = result.errors + + return dict(text=text, cknum=request.vars.CKEditorFuncNum, url=url) + +def browse(): + db = current.plugin_ckeditor.db + table_upload = current.plugin_ckeditor.settings.table_upload + browse_filter = current.plugin_ckeditor.settings.browse_filter + set = db(table_upload.id>0) + for key, val in browse_filter.items(): + if value[0] == '<': + set = set(table_upload[key]': + set = set(table_upload[key]>value[1:]) + elif value[0] == '!': + set = set(table_upload[key]!=value[1:]) + else: + set = set(table_upload[key]==value) + + rows = set.select(orderby=table_upload.title) + + return dict(rows=rows, cknum=request.vars.CKEditorFuncNum) + +def delete(): + filename = request.args(0) + if not filename: + raise HTTP(401, 'Required argument filename missing.') + + db = current.plugin_ckeditor.db + table_upload = current.plugin_ckeditor.settings.table_upload + db(table_upload.upload == filename).delete() + + # delete the file from storage + current.plugin_ckeditor.unlink(filename) + diff --git a/nstock/controllers/plugin_comment.py b/nstock/controllers/plugin_comment.py new file mode 100644 index 0000000..f92f7b0 --- /dev/null +++ b/nstock/controllers/plugin_comment.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +if False: + from gluon import T, SQLFORM, HTTP + from gluon import current + from db import db, auth + from dc import application + request = current.request + response = current.response + session = current.session + cache = current.cache + + +@auth.requires_login() +def index(): + item = application.getItemByUUID(request.args(0)) + if item is None: + raise HTTP(404) + + short = request.vars.short if request.vars.short is not None else False + + tbl = db.plugin_comment_comment + tbl.item_id.default = item.unique_id + form = SQLFORM( + tbl, + submit_button=T('Comment'), + formstyle='bootstrap3_stacked') + + rows = db( + (tbl.id > 0) & (tbl.item_id == item.unique_id) + ).select(orderby=~tbl.created_on) + + if form.process().accepted: + response.js = "jQuery('#%s').get(0).reload();" % request.cid + # send notifications to the users, except the current one + subject = T("Comments on %s", (item.headline,)) + # get the comment body + comment = tbl(form.vars.id) + message = response.render( + 'plugin_comment/someone_commented.txt', + dict(item=item, comment=comment, user=auth.user) + ) + application.notifyCollaborators( + item.unique_id, + subject, + message + ) + + return dict(form=form, comments=rows, short=short, item=item) diff --git a/nstock/controllers/plugin_package.py b/nstock/controllers/plugin_package.py new file mode 100644 index 0000000..25ac430 --- /dev/null +++ b/nstock/controllers/plugin_package.py @@ -0,0 +1,124 @@ +# -*- coding: utf-8 -*- +if False: + from gluon import CAT, SQLFORM, A, SPAN, URL + from gluon import current, redirect + request = current.request + response = current.response + session = current.session + T = current.T + from db import db, auth + from dc import application + + +@auth.requires(lambda: application.canUpdateItem(request.args(0))) +def index(): + """ + Edit/Show package content + """ + pkg_item = application.getItemByUUID(request.args(0)) + content = db.plugin_package_content(item_id=pkg_item.unique_id) + + form = SQLFORM( + db.plugin_package_content, + record=content, + showid=False) + + if form.process().accepted: + application.indexItem(pkg_item.unique_id) + redirect(URL('default', 'index')) + + return locals() + + +@auth.requires(lambda: application.canReadItem(request.args(0))) +def diff(): + item = application.getItemByUUID(request.args(0)) + content = db.plugin_package_content(item_id=item.unique_id) + archive = db.plugin_package_content_archive(request.args(1)) + return locals() + + +@auth.requires(lambda: application.canReadItem(request.args(0))) +def changelog(): + item = application.getItemByUUID(request.args(0)) + pkg_content = db.plugin_package_content(item_id=item.unique_id) + query = ( + db.plugin_package_content_archive.current_record == pkg_content.id) + db.plugin_package_content_archive.modified_on.label = T('Date & Time') + db.plugin_package_content_archive.modified_on.readable = True + db.plugin_package_content_archive.modified_by.label = T('User') + db.plugin_package_content_archive.modified_by.readable = True + fields = [ + db.plugin_package_content_archive.modified_on, + db.plugin_package_content_archive.modified_by + ] + + def gen_links(row): + diff = A(SPAN( + _class="glyphicon glyphicon-random"), + _href=URL( + 'diff', + args=[item.unique_id, row.id]), + _class="btn btn-default", + _title=T("Differences"), + ) + + return CAT(diff) + + links = [dict(header='', body=gen_links)] + + changes = SQLFORM.grid( + query, + orderby=[~db.plugin_package_content_archive.modified_on], + fields=fields, + args=request.args[:1], + create=False, editable=False, details=False, deletable=False, + searchable=False, + csv=False, + links=links, + ) + + return locals() + + +@auth.requires_login() +def create(): + if not session.marked_items: + session.flash = T('You must mark some items first') + redirect(URL('default', 'index')) + + fields = [] + # i need the input of the based item fields + fdl_headline = db.item.headline + fields.append(fdl_headline) + fdl_keywords = db.item.keywords + keywords_list = [] + for item_id in session.marked_items: + _item = application.getItemByUUID(item_id) + keywords_list.extend(_item.keywords) + keywords_list = list(set(keywords_list)) # remove any dup + fdl_keywords.default = keywords_list + fields.append(fdl_keywords) + fields.append(db.item.genre) + fdl_item_type = db.item.item_type + fdl_item_type.writable = False + fdl_item_type.readable = False + fdl_item_type.default = 'package' + fields.append(db.plugin_package_content.description) + + form = SQLFORM.factory( + *fields, + table_name='plugin_package_item' # to allow the correct file name + ) + + if form.process(dbio=False).accepted: + form.vars.item_id = application.createItem('package', form.vars) + form.vars.item_list = session.marked_items + db.plugin_package_content.insert( + **db.plugin_package_content._filter_fields(form.vars) + ) + application.indexItem(form.vars.item_id) + session.marked_items = [] + redirect(URL('default', 'index')) + + return locals() diff --git a/nstock/controllers/plugin_photoset.py b/nstock/controllers/plugin_photoset.py new file mode 100644 index 0000000..824ba2b --- /dev/null +++ b/nstock/controllers/plugin_photoset.py @@ -0,0 +1,250 @@ +# -*- coding: utf-8 -*- +from gluon.storage import Storage +from PIL import Image +from tempfile import NamedTemporaryFile +import os + +if False: + from gluon import URL, IMG, CAT, SQLFORM, A, SPAN + from gluon import current, redirect + T = current.T + request = current.request + response = current.response + session = current.session + from db import db, auth + from dc import application + + +@auth.requires(lambda: application.canUpdateItem(request.args(0))) +def index(): + item = application.getItemByUUID(request.args(0)) + content = db.plugin_photoset_content(item_id=item.id) + + return locals() + + +@auth.requires(lambda: application.canReadItem(request.args(0))) +def view_photoset(): + item = application.getItemByUUID(request.args(0)) + content = db.plugin_photoset_content(item_id=item.unique_id) + photos = content.photoset + if not photos: + photos = [] + return locals() + + +@auth.requires(lambda: application.canReadItem(request.args(0))) +def preview_photo(): + item = application.getItemByUUID(request.args(0)) + photo = db.plugin_photoset_photo(request.args(1)) + return IMG( + _src=URL('default', 'download', args=[photo.picture]), + _class="img-responsive center-block", + _alt=item.slugline, + ) + + +@auth.requires(lambda: application.canUpdateItem(request.args(0))) +def delete_photo(): + item = application.getItemByUUID(request.args(0)) + content = db.plugin_photoset_content(item_id=item.unique_id) + photo = db.plugin_photoset_photo(request.args(1)) + + content.photoset.remove(photo.id) + del db.plugin_photoset_photo[photo.id] + content.update_record() + application.notifyChanges(item.unique_id) + + return CAT('') + + +@auth.requires(lambda: application.canUpdateItem(request.args(0))) +def edit_form(): + item = application.getItemByUUID(request.args(0)) + content = db.plugin_photoset_content(item_id=item.unique_id) + + db.plugin_photoset_content.photoset.readable = False + db.plugin_photoset_content.photoset.writable = False + db.plugin_photoset_content.item_id.readable = False + db.plugin_photoset_content.item_id.writable = False + + form = SQLFORM( + db.plugin_photoset_content, + record=content, + showid=False, + submit_button=T('Save') + ) + + if form.process().accepted: + application.notifyChanges(item.unique_id) + application.indexItem(item.unique_id) + response.flash = T('Saved') + + return form + + +@auth.requires(lambda: application.canReadItem(request.args(0))) +def changelog(): + """ + Show item change log over the time + """ + item = application.getItemByUUID(request.args(0)) + content = db.plugin_photoset_content(item_id=item.unique_id) + + query = (db.plugin_photoset_content_archive.current_record == content.id) + db.plugin_photoset_content_archive.modified_on.label = T('Date & Time') + db.plugin_photoset_content_archive.modified_on.readable = True + db.plugin_photoset_content_archive.modified_by.label = T('User') + db.plugin_photoset_content_archive.modified_by.readable = True + fields = [ + db.plugin_photoset_content_archive.modified_on, + db.plugin_photoset_content_archive.modified_by + ] + + def gen_links(row): + diff = A( + SPAN(_class="glyphicon glyphicon-random"), + _href=URL( + 'diff', + args=[item.unique_id, row.id]), + _class="btn btn-default", + _title=T("Differences"), + ) + + return CAT(diff) + + links = [dict(header='', body=gen_links)] + + changes = SQLFORM.grid( + query, + orderby=[~db.plugin_photoset_content_archive.modified_on], + fields=fields, + args=request.args[:1], + create=False, editable=False, details=False, deletable=False, + searchable=False, + csv=False, + links=links, + ) + + return locals() + + +@auth.requires(lambda: application.canReadItem(request.args(0))) +def diff(): + item = application.getItemByUUID(request.args(0)) + content = db.plugin_photoset_content(item_id=item.unique_id) + archive = db.plugin_photoset_content_archive(request.args(1)) + + fields = [] + fields_archived = [] + fields_names = [] + + for f in db.plugin_photoset_content: + # if values diff + if content[f.name] != archive[f.name]: + fields_names.append(f.name) + f.comment = None + fields.append(f) + db.plugin_photoset_content_archive[f.name].comment = None + fields_archived.append(db.plugin_photoset_content_archive[f.name]) + + # build two readonly forms + form_actual = SQLFORM.factory( + *fields, + record=content, + readonly=True, + showid=False, + formstyle='divs' + ) + form_archive = SQLFORM.factory( + *fields_archived, + record=archive, + readonly=True, + showid=False, + formstyle='divs') + + return locals() + + +@auth.requires_login() +def create(): + fields = [] + + fld_headline = db.item.headline + fields.extend([fld_headline, db.item.keywords, db.item.genre]) + fdl_item_type = db.item.item_type + fdl_item_type.writable = False + fdl_item_type.readable = False + fdl_item_type.default = 'photoset' + + form = SQLFORM.factory( + *fields, + table_name='plugin_photo_set' # to allow the correct form name + ) + + if form.process(dbio=False).accepted: + # item_id = CT_REG.photoset.create_item(form.vars) + item_id = application.createItem('photoset', form.vars) + form.vars.item_id = item_id + if session.plugin_photoset: + form.vars.photoset = session.plugin_photoset.photos + else: + form.vars.phoset = [] + db.plugin_photoset_content.insert( + **db.plugin_photoset_content._filter_fields( + form.vars + ) + ) + application.indexItem(item_id) + session.plugin_photoset = None + redirect(URL('default', 'index.html')) + + return locals() + + +@auth.requires_login() +def upload_photo(): + """upload one or more photos""" + if not session.plugin_photoset: + session.plugin_photoset = Storage() + session.plugin_photoset.photos = [] + + for r in request.vars: + if r == "qqfile": + filename = request.vars.qqfile + photo_id = db.plugin_photoset_photo.insert( + picture=db.plugin_photoset_photo.picture.store( + request.body, filename + ) + ) + # generate the thumbnail + photo = db.plugin_photoset_photo(photo_id) + (filename, stream) = db.plugin_photoset_photo.picture.retrieve( + photo.picture + ) + filename = stream.name + im = Image.open(filename) + # -------------------------------- + size = (200, 200) + im.thumbnail(size) + fl = NamedTemporaryFile(suffix=".jpg", delete=True) + fl.close() + im.save(fl.name, "JPEG") + thumb = db.plugin_photoset_photo.thumbnail.store( + open(fl.name, 'rb'), fl.name) + photo.update_record(thumbnail=thumb) + os.unlink(fl.name) # cleanup + # if a photoset is given add this photo to the set + if request.args(0): + item = application.getItemByUUID(request.args(0)) + photoset = db.plugin_photoset_content(item_id=item.unique_id) + if photoset.photoset is None: + photoset.photoset = [photo_id] + else: + photoset.photoset.append(photo_id) + photoset.update_record() + else: + # in the create stage, i guess + session.plugin_photoset.photos.append(photo_id) + + return response.json({'success': 'true'}) diff --git a/nstock/controllers/plugin_picture.py b/nstock/controllers/plugin_picture.py new file mode 100644 index 0000000..d8561df --- /dev/null +++ b/nstock/controllers/plugin_picture.py @@ -0,0 +1,239 @@ +# -*- coding: utf-8 -*- +from PIL import Image +from tempfile import NamedTemporaryFile +import os + +if False: + from gluon import SQLFORM, CAT, A, SPAN, URL, IS_IMAGE + from gluon import current, redirect + request = current.request + response = current.response + T = current.T + from db import db, auth + from dc import application + + +@auth.requires(lambda: application.canUpdateItem(request.args(0))) +def index(): + """ + Edit content + """ + item = application.getItemByUUID(request.args(0)) + + db.plugin_picture_info.thumbnail.readable = False + db.plugin_picture_info.thumbnail.writable = False + db.plugin_picture_info.renditions.readable = False + db.plugin_picture_info.renditions.writable = False + + content = db.plugin_picture_info(item_id=item.unique_id) + + form = SQLFORM( + db.plugin_picture_info, + record=content, + showid=False, + submit_button=T('Save')) + + if form.process().accepted: + application.notifyChanges(item.unique_id) + application.indexItem(item.unique_id) + response.flash = None + + return dict(form=form, item=item, content=content) + + +@auth.requires(lambda: application.canUpdateItem(request.args(0))) +def delete_rendition(): + item = application.getItemByUUID(request.args(0)) + content = db.plugin_picture_info(item_id=item.unique_id) + rend = db.plugin_picture_rendition(request.args(1)) + + if item and content and rend: + # remove rendition + # update content.renditions + # update content db record + r_id = rend.id + del db.plugin_picture_rendition[r_id] + content.renditions.remove(r_id) + content.update_record() + + return CAT('') + + +@auth.requires(lambda: application.canReadItem(request.args(0))) +def diff(): + item = application.getItemByUUID(request.args(0)) + content = db.plugin_picture_info(item_id=item.unique_id) + archive = db.plugin_picture_info_archive(request.args(1)) + + fields = [] + fields_archived = [] + fields_names = [] + + for f in db.plugin_picture_info: + # if values diff + if content[f.name] != archive[f.name]: + fields_names.append(f.name) + f.comment = None + fields.append(f) + db.plugin_picture_info_archive[f.name].comment = None + fields_archived.append(db.plugin_picture_info_archive[f.name]) + + # build two readonly forms + form_actual = SQLFORM.factory( + *fields, + record=content, + readonly=True, + showid=False, + formstyle='divs' + ) + form_archive = SQLFORM.factory( + *fields, + record=archive, + readonly=True, + showid=False, + formstyle='divs') + + return locals() + + +@auth.requires(lambda: application.canReadItem(request.args(0))) +def changelog(): + item = application.getItemByUUID(request.args(0)) + pic_info = db.plugin_picture_info(item_id=item.unique_id) + + query = (db.plugin_picture_info_archive.current_record == pic_info.id) + db.plugin_picture_info_archive.modified_on.label = T('Date & Time') + db.plugin_picture_info_archive.modified_on.readable = True + db.plugin_picture_info_archive.modified_by.label = T('User') + db.plugin_picture_info_archive.modified_by.readable = True + fields = [ + db.plugin_picture_info_archive.modified_on, + db.plugin_picture_info_archive.modified_by + ] + + def gen_links(row): + diff = A( + SPAN(_class="glyphicon glyphicon-random"), + _href=URL( + 'diff', + args=[item.unique_id, row.id]), + _class="btn btn-default", + _title=T("Differences"), + ) + + return CAT(diff) + + links = [dict(header='', body=gen_links)] + + changes = SQLFORM.grid( + query, + orderby=[~db.plugin_picture_info_archive.modified_on], + fields=fields, + args=request.args[:1], + create=False, editable=False, details=False, deletable=False, + searchable=False, + csv=False, + links=links, + ) + + return locals() + + +@auth.requires(lambda: application.canReadItem(request.args(0))) +def add_rendition(): + item = application.getItemByUUID(request.args(0)) + content = db.plugin_picture_info(item_id=item.unique_id) + + form = SQLFORM(db.plugin_picture_rendition) + + if form.process().accepted: + r_id = form.vars.id + rend = db.plugin_picture_rendition(r_id) + (filename, stream) = db.plugin_picture_rendition.picture.retrieve( + rend.picture) + filename = stream.name + im = Image.open(filename) + # update rendition with image info + rend.height = im.height + rend.width = im.width + rend.format = im.format + rend.color = im.mode + rend.update_record() + # append this rendition to the item content + content.renditions.append(r_id) + content.update_record() + redirect(application.getItemURL(item.unique_id)) + + return locals() + + +@auth.requires_login() +def create(): + + fields = [] + # i need the input of the based item fields + fdl_headline = db.item.headline + fields.append(fdl_headline) + fields.append(db.item.keywords) + fields.append(db.item.genre) + fdl_item_type = db.item.item_type + fdl_item_type.writable = False + fdl_item_type.readable = False + fdl_item_type.default = 'picture' + + # and the image for the first redition + fld_redition = db.plugin_picture_rendition.picture + fld_redition.uploadfolder = os.path.join(request.folder, 'uploads') + fld_redition.label = T('Select the first rendition of the picture') + fld_redition.comment = T(""" + Normally the raw version of the image. You may add other renditions as + needed after form submition.. + """) + fld_redition.requires = IS_IMAGE() + fields.append(fld_redition) + + form = SQLFORM.factory( + *fields, + table_name='plugin_picture_rendition' # to allow the correct form name + ) + + if form.process(dbio=False).accepted: + # create the item + item_id = application.createItem('picture', form.vars) + # first rendition + rend_id = db.plugin_picture_rendition.insert( + **db.plugin_picture_rendition._filter_fields(form.vars) + ) + form.vars.renditions = [rend_id] + # generate the thumbnail + rend = db.plugin_picture_rendition(rend_id) + (filename, stream) = db.plugin_picture_rendition.picture.retrieve( + rend.picture) + filename = stream.name + im = Image.open(filename) + # update rendition with image info + rend.width, rend.height = im.size + rend.format = im.format + rend.color = im.mode + rend.update_record() + # -------------------------------- + size = (500, 500) + im.thumbnail(size) + fl = NamedTemporaryFile(suffix=".jpg", delete=True) + fl.close() + im.save(fl.name, "JPEG") + form.vars.thumbnail = db.plugin_picture_info.thumbnail.store( + open(fl.name, 'rb'), fl.name) + os.unlink(fl.name) # cleanup + # create the picture main content + form.vars.item_id = item_id + info_id = db.plugin_picture_info.insert( + **db.plugin_picture_info._filter_fields(form.vars) + ) + # register document for search + application.indexItem(item_id) + # -- + # redirect to the item + redirect(URL('default', 'index')) + + return locals() diff --git a/nstock/controllers/plugin_text.py b/nstock/controllers/plugin_text.py new file mode 100644 index 0000000..2308027 --- /dev/null +++ b/nstock/controllers/plugin_text.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- +if False: + from gluon import SQLFORM, URL, A, SPAN, CAT + from gluon import current, redirect, HTTP + request = current.request + response = current.response + T = current.T + from db import db, auth + # from dc import CT_REG + from dc import application + + +@auth.requires(lambda: application.canUpdateItem(request.args(0))) +def index(): + """ + Edit content + """ + item = application.getItemByUUID(request.args(0)) + if item is None: + raise HTTP(404) + + content = db.plugin_text_text(item_id=item.unique_id) + + form = SQLFORM( + db.plugin_text_text, + record=content, + showid=False, + submit_button=T('Save')) + + if form.process().accepted: + application.notifyChanges(item.unique_id) + application.indexItem(item.unique_id) + redirect(application.getItemURL(item.unique_id)) + response.flash = T('Done') + + return dict(form=form, item=item, content=content) + + +@auth.requires(lambda: application.canReadItem(request.args(0))) +def diff(): + item = application.getItemByUUID(request.args(0)) + if item is None: + raise HTTP(404) + content = db.plugin_text_text(item_id=item.unique_id) + archive = db.plugin_text_text_archive(request.args(1)) + + fields = [] + fields_archived = [] + fields_names = [] + + for f in db.plugin_text_text: + # if values diff + if content[f.name] != archive[f.name]: + fields_names.append(f.name) + f.comment = None + fields.append(f) + db.plugin_text_text_archive[f.name].comment = None + fields_archived.append(db.plugin_text_text_archive[f.name]) + + # build two readonly forms + form_actual = SQLFORM.factory( + *fields, + record=content, + readonly=True, + showid=False, + formstyle='divs' + ) + form_archive = SQLFORM.factory( + *fields, + record=archive, + readonly=True, + showid=False, + formstyle='divs') + + return locals() + + +@auth.requires(lambda: application.canReadItem(request.args(0))) +def changelog(): + """ + Show item change log over the time + """ + item = application.getItemByUUID(request.args(0)) + if item is None: + raise HTTP(404) + content = db.plugin_text_text(item_id=item.unique_id) + + query = (db.plugin_text_text_archive.current_record == content.id) + db.plugin_text_text_archive.modified_on.label = T('Date & Time') + db.plugin_text_text_archive.modified_on.readable = True + db.plugin_text_text_archive.modified_by.label = T('User') + db.plugin_text_text_archive.modified_by.readable = True + fields = [ + db.plugin_text_text_archive.modified_on, + db.plugin_text_text_archive.modified_by + ] + + def gen_links(row): + diff = A( + SPAN(_class="glyphicon glyphicon-random"), + _href=URL( + 'diff', + args=[item.unique_id, row.id]), + _class="btn btn-default", + _title=T("Differences"), + ) + + return CAT(diff) + + links = [dict(header='', body=gen_links)] + + changes = SQLFORM.grid( + query, + orderby=[~db.plugin_text_text_archive.modified_on], + fields=fields, + args=request.args[:1], + create=False, editable=False, details=False, deletable=False, + searchable=False, + csv=False, + links=links, + ) + + return locals() + + +@auth.requires_login() +def create(): + """ + Show the creation form of the text item. + """ + + fields = [ + db.item.headline, + db.item.keywords, + db.item.genre, + db.item.item_type, + db.plugin_text_text.body + ] + db.item.item_type.default = 'text' + db.item.item_type.writable = False + db.item.item_type.readable = False + + form = SQLFORM.factory(*fields) + + if form.process().accepted: + item_id = application.createItem('text', form.vars) + form.vars.item_id = item_id + db.plugin_text_text.insert( + **db.plugin_text_text._filter_fields(form.vars)) + application.indexItem(item_id) + redirect(URL('default', 'index.html')) + + return locals() diff --git a/nstock/cron/.gitignore b/nstock/cron/.gitignore new file mode 100644 index 0000000..76bedae --- /dev/null +++ b/nstock/cron/.gitignore @@ -0,0 +1,5 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore + diff --git a/nstock/databases/.gitignore b/nstock/databases/.gitignore new file mode 100644 index 0000000..76bedae --- /dev/null +++ b/nstock/databases/.gitignore @@ -0,0 +1,5 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore + diff --git a/nstock/errors/.gitignore b/nstock/errors/.gitignore new file mode 100644 index 0000000..76bedae --- /dev/null +++ b/nstock/errors/.gitignore @@ -0,0 +1,5 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore + diff --git a/nstock/languages/default.py b/nstock/languages/default.py new file mode 100644 index 0000000..5e6e812 --- /dev/null +++ b/nstock/languages/default.py @@ -0,0 +1,122 @@ +# coding: utf8 +{ +'!langcode!': 'en-us', +'!langname!': 'English (US)', +'%s %%(shop)': '%s %%(shop)', +'%s %%(shop[0])': '%s %%(shop[0])', +'%s %%{quark[0]}': '%s %%{quark[0]}', +'%s %%{shop[0]}': '%s %%{shop[0]}', +'%s %%{shop}': '%s %%{shop}', +'%Y-%m-%d': '%Y-%m-%d', +'%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S', +'@markmin\x01**Hello World**': '**Hello World**', +'About': 'About', +'Access Control': 'Access Control', +'Administrative Interface': 'Administrative Interface', +'Ajax Recipes': 'Ajax Recipes', +'Are you sure you want to delete this object?': 'Are you sure you want to delete this object?', +'Buy this book': 'Buy this book', +'Cannot be empty': 'Cannot be empty', +'Check to delete': 'Check to delete', +'Client IP': 'Client IP', +'Community': 'Community', +'Components and Plugins': 'Components and Plugins', +'Controller': 'Controller', +'Copyright': 'Copyright', +'Created By': 'Created By', +'Created On': 'Created On', +'customize me!': 'customize me!', +'Database': 'Database', +'DB Model': 'DB Model', +'Demo': 'Demo', +'Deployment Recipes': 'Deployment Recipes', +'Description': 'Description', +'Documentation': 'Documentation', +"Don't know what to do?": "Don't know what to do?", +'Download': 'Download', +'E-mail': 'E-mail', +'Email and SMS': 'Email and SMS', +'enter an integer between %(min)g and %(max)g': 'enter an integer between %(min)g and %(max)g', +'enter date and time as %(format)s': 'enter date and time as %(format)s', +'Errors': 'Errors', +'FAQ': 'FAQ', +'First name': 'First name', +'Forms and Validators': 'Forms and Validators', +'Free Applications': 'Free Applications', +'Group %(group_id)s created': 'Group %(group_id)s created', +'Group ID': 'Group ID', +'Group uniquely assigned to user %(id)s': 'Group uniquely assigned to user %(id)s', +'Groups': 'Groups', +'Hello World': 'Hello World', +'Hello World ## comment': 'Hello World ', +'Hello World## comment': 'Hello World', +'Home': 'Home', +'How did you get here?': 'How did you get here?', +'Introduction': 'Introduction', +'Invalid email': 'Invalid email', +'Is Active': 'Is Active', +'Last name': 'Last name', +'Layout': 'Layout', +'Layout Plugins': 'Layout Plugins', +'Layouts': 'Layouts', +'Live Chat': 'Live Chat', +'Logged in': 'Logged in', +'Logged out': 'Logged out', +'Login': 'Login', +'Logout': 'Logout', +'Lost Password': 'Lost Password', +'Lost password?': 'Lost password?', +'Menu Model': 'Menu Model', +'Modified By': 'Modified By', +'Modified On': 'Modified On', +'My Sites': 'My Sites', +'Name': 'Name', +'Object or table name': 'Object or table name', +'Online examples': 'Online examples', +'Origin': 'Origin', +'Other Plugins': 'Other Plugins', +'Other Recipes': 'Other Recipes', +'Overview': 'Overview', +'Password': 'Password', +"Password fields don't match": "Password fields don't match", +'please input your password again': 'please input your password again', +'Plugins': 'Plugins', +'Powered by': 'Powered by', +'Preface': 'Preface', +'Profile': 'Profile', +'Python': 'Python', +'Quick Examples': 'Quick Examples', +'Recipes': 'Recipes', +'Record ID': 'Record ID', +'Register': 'Register', +'Registration identifier': 'Registration identifier', +'Registration key': 'Registration key', +'Registration successful': 'Registration successful', +'Remember me (for 30 days)': 'Remember me (for 30 days)', +'Reset Password key': 'Reset Password key', +'Role': 'Role', +'Semantic': 'Semantic', +'Services': 'Services', +'Stylesheet': 'Stylesheet', +'Support': 'Support', +'The Core': 'The Core', +'The output of the file is a dictionary that was rendered by the view %s': 'The output of the file is a dictionary that was rendered by the view %s', +'The Views': 'The Views', +'This App': 'This App', +'Timestamp': 'Timestamp', +'Twitter': 'Twitter', +'User %(id)s Logged-in': 'User %(id)s Logged-in', +'User %(id)s Logged-out': 'User %(id)s Logged-out', +'User %(id)s Registered': 'User %(id)s Registered', +'User ID': 'User ID', +'value already in database or empty': 'value already in database or empty', +'Verify Password': 'Verify Password', +'Videos': 'Videos', +'View': 'View', +'Welcome': 'Welcome', +'Welcome to web2py!': 'Welcome to web2py!', +'Which called the function %s located in the file %s': 'Which called the function %s located in the file %s', +'You are successfully running web2py': 'You are successfully running web2py', +'You can modify this application and adapt it to your needs': 'You can modify this application and adapt it to your needs', +'You visited the url %s': 'You visited the url %s', +} diff --git a/nstock/languages/en-us.py b/nstock/languages/en-us.py new file mode 100644 index 0000000..fefaac9 --- /dev/null +++ b/nstock/languages/en-us.py @@ -0,0 +1,232 @@ +# -*- coding: utf-8 -*- +{ +'\n It can be the name of a city or may contain details, for example: HAVANA,\n CUBA': '\n It can be the name of a city or may contain details, for example: HAVANA,\n CUBA', +'\n News organisations often use an embargo to release information in advance,\n on the strict understanding that it may not be released into the public\n domain until after the embargo time has expired, or until some other form\n of permission has been given.\n ': '\n News organisations often use an embargo to release information in advance,\n on the strict understanding that it may not be released into the public\n domain until after the embargo time has expired, or until some other form\n of permission has been given.\n ', +'!langcode!': 'en-us', +'!langname!': 'English (US)', +'%(nrows)s records found': '%(nrows)s records found', +'%d seconds ago': '%d seconds ago', +'%s %%(shop)': '%s %%(shop)', +'%s %%(shop[0])': '%s %%(shop[0])', +'%s %%{quark[0]}': '%s %%{quark[0]}', +'%s %%{shop[0]}': '%s %%{shop[0]}', +'%s %%{shop}': '%s %%{shop}', +'%Y-%m-%d': '%Y-%m-%d', +'%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S', +'+ And': '+ And', +'+ Or': '+ Or', +'1 minute ago': '1 minute ago', +'@markmin\x01**Hello World**': '**Hello World**', +'@markmin\x01An error occured, please [[reload %s]] the page': 'An error occured, please [[reload %s]] the page', +'About': 'About', +'Access Control': 'Access Control', +'Add dashboard': 'Add dashboard', +'Add Items': 'Add Items', +'Administrative Interface': 'Administrative Interface', +'Ajax Recipes': 'Ajax Recipes', +'are allowed.': 'are allowed.', +'Are you sure you want to delete this object?': 'Are you sure you want to delete this object?', +'Buy this book': 'Buy this book', +'By line': 'By line', +'Cannot be empty': 'Cannot be empty', +'Caption': 'Caption', +'CAST': 'CAST', +'Changelog': 'Changelog', +'Changes on %s': 'Changes on %s', +'Check to delete': 'Check to delete', +'Clear': 'Clear', +'Client IP': 'Client IP', +'Close': 'Close', +'Comment': 'Comment', +'Comments': 'Comments', +'Community': 'Community', +'Components and Plugins': 'Components and Plugins', +'Content': 'Content', +'Controller': 'Controller', +'Copyright': 'Copyright', +'Copyright Holder': 'Copyright Holder', +'Copyright Notice': 'Copyright Notice', +'Copyright URL': 'Copyright URL', +'Create new organization': 'Create new organization', +'Created By': 'Created By', +'Created On': 'Created On', +'Credit line': 'Credit line', +'customize me!': 'customize me!', +'Dashboard name': 'Dashboard name', +"Dashboard's": "Dashboard's", +'Database': 'Database', +'DB Model': 'DB Model', +'Delete current dashboard': 'Delete current dashboard', +'Demo': 'Demo', +'Deployment Recipes': 'Deployment Recipes', +'Description': 'Description', +'Desks': 'Desks', +'Details': 'Details', +'Documentation': 'Documentation', +"Don't know what to do?": "Don't know what to do?", +'Download': 'Download', +'E-mail': 'E-mail', +'Edit content': 'Edit content', +'Edit current dashboard': 'Edit current dashboard', +'Email and SMS': 'Email and SMS', +'Embargoed': 'Embargoed', +'Enter an integer between %(min)g and %(max)g': 'Enter an integer between %(min)g and %(max)g', +'enter an integer between %(min)g and %(max)g': 'enter an integer between %(min)g and %(max)g', +'enter date and time as %(format)s': 'enter date and time as %(format)s', +'Errors': 'Errors', +'FAQ': 'FAQ', +'First name': 'First name', +'Forms and Validators': 'Forms and Validators', +'Free Applications': 'Free Applications', +'Genre': 'Genre', +'Group %(group_id)s created': 'Group %(group_id)s created', +'Group ID': 'Group ID', +'Group uniquely assigned to user %(id)s': 'Group uniquely assigned to user %(id)s', +'Groups': 'Groups', +'has invalid extension.': 'has invalid extension.', +'has made changes to the item': 'has made changes to the item', +'has made changes to the meta-data of the item': 'has made changes to the meta-data of the item', +'has post the comment': 'has post the comment', +'Headline': 'Headline', +'Headline or descriptive title': 'Headline or descriptive title', +'Hello World': 'Hello World', +'Hello World ## comment': 'Hello World ', +'Hello World## comment': 'Hello World', +'Home': 'Home', +'How did you get here?': 'How did you get here?', +'Id': 'Id', +'Image preview': 'Image preview', +'Introduction': 'Introduction', +'Invalid email': 'Invalid email', +'Invalid login': 'Invalid login', +'Is Active': 'Is Active', +'is empty, please select files again without it.': 'is empty, please select files again without it.', +'is too large, maximum file size is': 'is too large, maximum file size is', +'is too small, minimum file size is': 'is too small, minimum file size is', +'Item': 'Item', +'Items': 'Items', +'Keywords': 'Keywords', +'Language': 'Language', +'Last name': 'Last name', +'Layout': 'Layout', +'Layout Plugins': 'Layout Plugins', +'Layouts': 'Layouts', +'Live Chat': 'Live Chat', +'Located': 'Located', +'Log In': 'Log In', +'Log Out': 'Log Out', +'Logged in': 'Logged in', +'Logged out': 'Logged out', +'Login': 'Login', +'Logout': 'Logout', +'Lost Password': 'Lost Password', +'Lost password?': 'Lost password?', +'Mark / unmark': 'Mark / unmark', +'Members': 'Members', +'Menu Model': 'Menu Model', +'Modified By': 'Modified By', +'Modified On': 'Modified On', +'My Sites': 'My Sites', +'Name': 'Name', +'New Search': 'New Search', +'No one has commented yet': 'No one has commented yet', +'Notification center': 'Notification center', +'now': 'now', +'Object or table name': 'Object or table name', +'On the item:': 'On the item:', +'Online examples': 'Online examples', +'Only': 'Only', +'Organizations': 'Organizations', +'Origin': 'Origin', +'Other Plugins': 'Other Plugins', +'Other Recipes': 'Other Recipes', +'Overview': 'Overview', +'Package': 'Package', +'Password': 'Password', +"Password fields don't match": "Password fields don't match", +'Permissions': 'Permissions', +'Personal user desk': 'Personal user desk', +'Photo Set': 'Photo Set', +'Picture': 'Picture', +'Pictures': 'Pictures', +'Please enable JavaScript to use file uploader.': 'Please enable JavaScript to use file uploader.', +'please input your password again': 'please input your password again', +'Plugins': 'Plugins', +'Post': 'Post', +'Powered by': 'Powered by', +'Preface': 'Preface', +'Profile': 'Profile', +'Provider': 'Provider', +'Provider service': 'Provider service', +'Push to': 'Push to', +'Python': 'Python', +'Quick Examples': 'Quick Examples', +'Recipes': 'Recipes', +'Record ID': 'Record ID', +'Register': 'Register', +'Registration identifier': 'Registration identifier', +'Registration key': 'Registration key', +'Registration successful': 'Registration successful', +'Remember me (for 30 days)': 'Remember me (for 30 days)', +'Remove': 'Remove', +'Rename': 'Rename', +'Renditions': 'Renditions', +'Reset Password key': 'Reset Password key', +'Role': 'Role', +'Save': 'Save', +'says': 'says', +'Search': 'Search', +'Section': 'Section', +'Section or page in with this item is intended to be used': 'Section or page in with this item is intended to be used', +'See you on eNews': 'See you on eNews', +'See you on nStock': 'See you on nStock', +'Select and upload photos': 'Select and upload photos', +'Select where to push the item': 'Select where to push the item', +'Semantic': 'Semantic', +'Send': 'Send', +'Services': 'Services', +'Settings': 'Settings', +'Share': 'Share', +'Sign Up': 'Sign Up', +'Slugline': 'Slugline', +'Status': 'Status', +'Stylesheet': 'Stylesheet', +'Submit': 'Submit', +'Success!': 'Success!', +'Support': 'Support', +'Text': 'Text', +'The Core': 'The Core', +'The files are being uploaded, if you leave now the upload will be cancelled.': 'The files are being uploaded, if you leave now the upload will be cancelled.', +'The output of the file is a dictionary that was rendered by the view %s': 'The output of the file is a dictionary that was rendered by the view %s', +'The Views': 'The Views', +'This App': 'This App', +'Timestamp': 'Timestamp', +'Toogle pin to dashboard': 'Toogle pin to dashboard', +'Twitter': 'Twitter', +'Type text to search': 'Type text to search', +'Upload the photos before submiting the form.': 'Upload the photos before submiting the form.', +'User %(id)s Logged-in': 'User %(id)s Logged-in', +'User %(id)s Logged-out': 'User %(id)s Logged-out', +'User %(id)s Registered': 'User %(id)s Registered', +'User ID': 'User ID', +'value already in database or empty': 'value already in database or empty', +'Verify Password': 'Verify Password', +'Videos': 'Videos', +'View': 'View', +'Warning !': 'Warning !', +'Warning!': 'Warning!', +'Welcome': 'Welcome', +'Welcome to web2py!': 'Welcome to web2py!', +'Which called the function %s located in the file %s': 'Which called the function %s located in the file %s', +'Working...': 'Working...', +'You are successfully running web2py': 'You are successfully running web2py', +'You can modify this application and adapt it to your needs': 'You can modify this application and adapt it to your needs', +'You can see the changes on': 'You can see the changes on', +'You can view this or others comments to this item on': 'You can view this or others comments to this item on', +"You can't push this item to any other Desk": "You can't push this item to any other Desk", +"You don't have or have joined to any organization": "You don't have or have joined to any organization", +'You have unread notifications': 'You have unread notifications', +'You visited the url %s': 'You visited the url %s', +'Your comment': 'Your comment', +'Your organizations': 'Your organizations', +} diff --git a/nstock/languages/en.py b/nstock/languages/en.py new file mode 100644 index 0000000..4ad13e3 --- /dev/null +++ b/nstock/languages/en.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- +{ +'!langcode!': 'en-us', +'!langname!': 'English (US)', +'%s %%(shop)': '%s %%(shop)', +'%s %%(shop[0])': '%s %%(shop[0])', +'%s %%{quark[0]}': '%s %%{quark[0]}', +'%s %%{shop[0]}': '%s %%{shop[0]}', +'%s %%{shop}': '%s %%{shop}', +'%Y-%m-%d': '%Y-%m-%d', +'%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S', +'@markmin\x01**Hello World**': '**Hello World**', +'About': 'About', +'Access Control': 'Access Control', +'Administrative Interface': 'Administrative Interface', +'Ajax Recipes': 'Ajax Recipes', +'Are you sure you want to delete this object?': 'Are you sure you want to delete this object?', +'Buy this book': 'Buy this book', +'Cannot be empty': 'Cannot be empty', +'Check to delete': 'Check to delete', +'Client IP': 'Client IP', +'Community': 'Community', +'Components and Plugins': 'Components and Plugins', +'Controller': 'Controller', +'Copyright': 'Copyright', +'Created By': 'Created By', +'Created On': 'Created On', +'customize me!': 'customize me!', +'Database': 'Database', +'DB Model': 'DB Model', +'Demo': 'Demo', +'Deployment Recipes': 'Deployment Recipes', +'Description': 'Description', +'Documentation': 'Documentation', +"Don't know what to do?": "Don't know what to do?", +'Download': 'Download', +'E-mail': 'E-mail', +'Email and SMS': 'Email and SMS', +'Enter an integer between %(min)g and %(max)g': 'Enter an integer between %(min)g and %(max)g', +'enter an integer between %(min)g and %(max)g': 'enter an integer between %(min)g and %(max)g', +'enter date and time as %(format)s': 'enter date and time as %(format)s', +'Errors': 'Errors', +'FAQ': 'FAQ', +'First name': 'First name', +'Forms and Validators': 'Forms and Validators', +'Free Applications': 'Free Applications', +'Group %(group_id)s created': 'Group %(group_id)s created', +'Group ID': 'Group ID', +'Group uniquely assigned to user %(id)s': 'Group uniquely assigned to user %(id)s', +'Groups': 'Groups', +'Hello World': 'Hello World', +'Hello World ## comment': 'Hello World ', +'Hello World## comment': 'Hello World', +'Home': 'Home', +'How did you get here?': 'How did you get here?', +'Introduction': 'Introduction', +'Invalid email': 'Invalid email', +'Is Active': 'Is Active', +'Last name': 'Last name', +'Layout': 'Layout', +'Layout Plugins': 'Layout Plugins', +'Layouts': 'Layouts', +'Live Chat': 'Live Chat', +'Logged in': 'Logged in', +'Logged out': 'Logged out', +'Login': 'Login', +'Logout': 'Logout', +'Lost Password': 'Lost Password', +'Lost password?': 'Lost password?', +'Menu Model': 'Menu Model', +'Modified By': 'Modified By', +'Modified On': 'Modified On', +'My Sites': 'My Sites', +'Name': 'Name', +'Object or table name': 'Object or table name', +'Online examples': 'Online examples', +'Origin': 'Origin', +'Other Plugins': 'Other Plugins', +'Other Recipes': 'Other Recipes', +'Overview': 'Overview', +'Password': 'Password', +"Password fields don't match": "Password fields don't match", +'please input your password again': 'please input your password again', +'Plugins': 'Plugins', +'Powered by': 'Powered by', +'Preface': 'Preface', +'Profile': 'Profile', +'Python': 'Python', +'Quick Examples': 'Quick Examples', +'Recipes': 'Recipes', +'Record ID': 'Record ID', +'Register': 'Register', +'Registration identifier': 'Registration identifier', +'Registration key': 'Registration key', +'Registration successful': 'Registration successful', +'Remember me (for 30 days)': 'Remember me (for 30 days)', +'Reset Password key': 'Reset Password key', +'Role': 'Role', +'Semantic': 'Semantic', +'Services': 'Services', +'Stylesheet': 'Stylesheet', +'Support': 'Support', +'The Core': 'The Core', +'The output of the file is a dictionary that was rendered by the view %s': 'The output of the file is a dictionary that was rendered by the view %s', +'The Views': 'The Views', +'This App': 'This App', +'Timestamp': 'Timestamp', +'Twitter': 'Twitter', +'User %(id)s Logged-in': 'User %(id)s Logged-in', +'User %(id)s Logged-out': 'User %(id)s Logged-out', +'User %(id)s Registered': 'User %(id)s Registered', +'User ID': 'User ID', +'value already in database or empty': 'value already in database or empty', +'Verify Password': 'Verify Password', +'Videos': 'Videos', +'View': 'View', +'Welcome': 'Welcome', +'Welcome to web2py!': 'Welcome to web2py!', +'Which called the function %s located in the file %s': 'Which called the function %s located in the file %s', +'You are successfully running web2py': 'You are successfully running web2py', +'You can modify this application and adapt it to your needs': 'You can modify this application and adapt it to your needs', +'You visited the url %s': 'You visited the url %s', +} diff --git a/nstock/languages/es-ES.py b/nstock/languages/es-ES.py new file mode 100644 index 0000000..9ad874b --- /dev/null +++ b/nstock/languages/es-ES.py @@ -0,0 +1,768 @@ +# -*- coding: utf-8 -*- +{ +'\n Allow the user to manage/administrate this desk. Use with caution.\n ': '\n Permite al usuario administrar el escritorio, usar con cuidado.\n ', +'\n Current item content version by %(first_name)s %(last_name)s on %(date_time)s\n ': ' Current item content version by %(first_name)s %(last_name)s on %(date_time)s\r\n ', +'\n Declare the group role within the package structure.\n Contain values representing “main”, “sidebar” or other editorial\n terms that express how the content in the package is intended to be\n used.\n ': 'Declare el rol del grupo dentro de la estructura del paquete. Pueden usarse términos como “principal”, “Página 2” u otros que expresen como se pretende utilizar el contenido.', +'\n It may contain any value but it is recommended to use one of the\n values: raw, web, thumbnail, print\n ': 'Puede contener cualquier valor pero se recomienda utilizar uno de los\r\n valores: raw, web, thumbnail, printer\r\n ', +'\n Current item metadata version by %(first_name)s %(last_name)s on %(date_time)s\n ': ' Versión actual de los metadatos por %(first_name)s %(last_name)s el %(date_time)s\r\n ', +'\n To create a new translation of the current item select the target\n language.\n ': 'Seleccione el lenguaje objetivo para crear una traducción del Item actual.\r\n ', +'\n Current item content version by %(first_name)s %(last_name)s on %(date_time)s\n ': 'Versión actual del contenido por %(first_name)s %(last_name)s el %(date_time)s\r\n ', +'\n It can be the name of a city or may contain details, for example: HAVANA,\n CUBA': ' It can be the name of a city or may contain details, for example: HAVANA,\r\n CUBA', +'\n It can be the name of a city or may contain details, for example: HAVANA, CUBA\n': 'Puede ser el nombre de una ciudad o puede contener más detalles, por ejemplo: LA HABANA, CUBA\r\n', +'\n News organisations often use an embargo to release information in advance,\n on the strict understanding that it may not be released into the public\n domain until after the embargo time has expired, or until some other form\n of permission has been given.\n ': 'Las organizaciones de noticias usan a menudo un embargo para divulgar la información por adelantado, bajo la estricta comprensión de que no puede ser liberado en el dominio público hasta después de que el embargo haya expirado o hasta que se haya dado otra forma de permiso.', +'\n Normally the raw version of the image. You may add other renditions as\n needed after form submition..\n ': 'Normalmente, la versión RAW de la imagen. Puede añadir otras entregas, según sea necesario después de guardar este formulario ...\r\n ', +"\n Within a package items they can be grouped according to different purposes. A default group is created with name 'main'.\n ": 'Dentro de un paquete, los artículos se pueden agrupar de acuerdo con diferentes propósitos. Un grupo predeterminado se crea con el nombre de "main".\r\n ', +'\nAllows the provider to declare which of its services, if any, delivered\nthis package.\n': 'Permite que el proveedor de declarar cuál de sus servicios, si existe, entrega este Item.\r\n', +'\nIt can be a descriptive name for the news provider or URL associated with it.\n': 'Puede ser un nombre descriptivo para el proveedor de noticias o URL asociado con él.\r\n', +'\nNews organisations often use an embargo to release information in advance, on the\nstrict understanding that it may not be released into the public domain until\nafter the embargo time has expired, or until some other form of permission has\nbeen given.\n': 'Las organizaciones de noticias a menudo utilizan un plazo de embargo al divulgar información por adelantado, en el\r\nestricto supuesto de que no puede ser liberado al dominio público hasta\r\ndespués de que el tiempo de embargo ha expirado, o hasta que alguna otra forma de permiso se de.\r\n', +'!=': '!=', +'!langcode!': 'es', +'!langname!': 'Español', +'"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"actualice" es una expresión opcional como "campo1=\'nuevo_valor\'". No se puede actualizar o eliminar resultados de un JOIN', +'%(nrows)s records found': '%(nrows)s registros encontrados', +'%d days ago': 'hace %d días', +'%d hours ago': 'hace %d horas', +'%d minutes ago': 'hace %d minutos', +'%d seconds ago': 'hace %d segundos', +'%s %%{position}': '%s %%{posición}', +'%s %%{row} deleted': '%s %%{fila} %%{eliminada}', +'%s %%{row} updated': '%s %%{fila} %%{actualizada}', +'%s desk': 'Escritorio de %s', +'%s selected': '%s %%{seleccionado}', +'%Y-%m-%d': '%d/%m/%Y', +'%Y-%m-%d %H:%M:%S': '%d/%m/%Y %H:%M:%S', +'(**%.0d MB**)': '(**%.0d MB**)', +'(something like "it-it")': '(algo como "es-ES")', +'**%(items)s** %%{item(items)}, **%(bytes)s** %%{byte(bytes)}': '**%(items)s** %%{item(items)}, **%(bytes)s** %%{byte(bytes)}', +'**%(items)s** items, **%(bytes)s** %%{byte(bytes)}': '**%(items)s** items, **%(bytes)s** %%{byte(bytes)}', +'**not available** (requires the Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] library)': '**not available** (requires the Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] library)', +'+ And': '+ Y', +'+ Or': '+ O', +'1 day ago': 'hace 1 día', +'1 hour ago': 'hace 1 hora', +'1 minute ago': 'hace 1 minuto', +'1 second ago': 'hace 1 segundo', +'1 week ago': '1 week ago', +'<': '<', +'<=': '<=', +'=': '=', +'>': '>', +'>=': '>=', +'?': '?', +'@markmin\x01An error occured, please [[reload %s]] the page': 'Ha ocurrido un error, por favor [[recargar %s]] la página', +'@markmin\x01Number of entries: **%s**': 'Número de entradas: **%s**', +'``**not available**``:red (requires the Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] library)': '``**not available**``:red (requires the Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] library)', +'A new version of web2py is available': 'Hay una nueva versión de web2py disponible', +'A new version of web2py is available: %s': 'Hay una nueva versión de web2py disponible: %s', +'About': 'Acerca de', +'about': 'acerca de', +'About application': 'Acerca de la aplicación', +'Access Control': 'Control de Acceso', +'Activate?': '¿Activar?', +'Actual': 'Actual', +'Add': 'Añadir', +'Add dashboard': 'Agregar tablero', +'Add Items': 'Agregar Items', +'Add items': 'Agregar Items', +'Add new desk': 'Agregar escritorio', +'Add Record': 'Agregar registro', +'Add record to database': 'Agregar registro', +'Add rendition': 'Agregar entrega', +'Add this to the search as an AND term': 'Agregue esto a la búsqueda como un término Y', +'Add this to the search as an OR term': 'Agregue esto a la búsqueda como un término O', +'Add user': 'Agregar usuario', +'additional code for your application': 'código adicional para su aplicación', +'admin': 'admin', +'admin disabled because no admin password': 'admin deshabilitado por falta de contraseña', +'admin disabled because not supported on google app engine': 'admin deshabilitado, no es soportado en GAE', +'admin disabled because unable to access password file': 'admin deshabilitado, imposible acceder al archivo con la contraseña', +'Admin is disabled because insecure channel': 'Admin deshabilitado, el canal no es seguro', +'Admin is disabled because unsecure channel': 'Admin deshabilitado, el canal no es seguro', +'Administrative interface': 'Interfaz administrativa', +'Administrative Interface': 'Interfaz Administrativa', +'Administrator Password:': 'Contraseña del Administrador:', +'Ajax Recipes': 'Recetas AJAX', +'All items': 'Todos los Items', +'Allow the user make modifications to the items in the desk.': 'Permite hacer modificaciones a los Items en el escritorio.', +'Allow the user move items into the desk.': 'Permite al usuario enviar Items a este escritorio.', +'Allow the user read only access to the desk item list.': 'Perminte leer todos los Items en el escritorio', +'An error occured, please %s the page': 'Ha ocurrido un error, por favor %s la página', +'An error occured, please [[reload %s]] the page': 'Ocurrió un error, [[recargue %s]] la página', +'An Organization witch that name is allready in nStock': 'Ya existe una organización con ese nombre', +'and': 'y', +'And': 'Y', +'and rename it (required):': 'y renómbrela (requerido):', +'and rename it:': ' y renómbrelo:', +'appadmin': 'appadmin', +'appadmin is disabled because insecure channel': 'admin deshabilitado, el canal no es seguro', +'application "%s" uninstalled': 'aplicación "%s" desinstalada', +'application compiled': 'aplicación compilada', +'application is compiled and cannot be designed': 'la aplicación está compilada y no puede ser modificada', +'Apply changes': 'Aplicar cambios', +'Appointment': 'Nombramiento', +'are allowed.': 'son permitidos.', +'Are you sure you want to delete file "%s"?': '¿Está seguro que desea eliminar el archivo "%s"?', +'Are you sure you want to delete this object?': '¿Está seguro que desea borrar este objeto?', +'Are you sure you want to uninstall application "%s"': '¿Está seguro que desea desinstalar la aplicación "%s"', +'Are you sure you want to uninstall application "%s"?': '¿Está seguro que desea desinstalar la aplicación "%s"?', +'at': 'en', +'Attach to current dashboard': 'Adjuntar al tablero actual', +'ATTENTION: Login requires a secure (HTTPS) connection or running on localhost.': 'ATENCION: Inicio de sesión requiere una conexión segura (HTTPS) o localhost.', +'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'ATENCION: NO EJECUTE VARIAS PRUEBAS SIMULTANEAMENTE, NO SON THREAD SAFE.', +'ATTENTION: you cannot edit the running application!': 'ATENCION: no puede modificar la aplicación que está ejecutandose!', +'Authentication': 'Autenticación', +'Authentication failed at client DB!': '¡La autenticación ha fallado en la BDD cliente!', +'Authentication failed at main DB!': '¡La autenticación ha fallado en la BDD principal!', +'Automatic form PIL': 'Obtenido de PIL', +'Available Databases and Tables': 'Bases de datos y tablas disponibles', +'Back': 'Atrás', +'Before': 'Antes', +'Body': 'Body', +'Buy this book': 'Compra este libro', +"Buy web2py's book": "Buy web2py's book", +'By line': 'Credito', +'Byline': 'Byline', +'Cache': 'Caché', +'cache': 'caché', +'Cache Cleared': 'Chache limpiada', +'Cache contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.': 'Cache contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.', +'Cache Keys': 'Llaves de la Caché', +'cache, errors and sessions cleaned': 'caché, errores y sesiones eliminados', +'Cancel': 'Cancelar', +'Cannot be empty': 'No puede estar vacío', +'Cannot compile: there are errors in your app. Debug it, correct errors and try again.': 'No se puede compilar: hay errores en su aplicación. Depure, corrija errores y vuelva a intentarlo.', +'cannot create file': 'no es posible crear archivo', +'cannot upload file "%(filename)s"': 'no es posible subir archivo "%(filename)s"', +'Caption': 'Subtítulo', +'CAST': 'CAST', +'Change': 'Cambio', +'Change password': 'Cambie la contraseña', +'change password': 'cambie la contraseña', +'Change Password': 'Cambie la Contraseña', +'Changelog': 'Chambios', +'Changes': 'Cambios', +'Changes on %s': 'Cambios en %s', +'check all': 'marcar todos', +'Check to delete': 'Marque para eliminar', +'choose one': 'escoja uno', +'clean': 'limpiar', +'Clear': 'Limpiar', +'Clear CACHE?': '¿Limpiar CACHÉ?', +'Clear DISK': 'Limpiar DISCO', +'Clear RAM': 'Limpiar RAM', +'Click on the link %(link)s to reset your password': 'Pulse en el enlace %(link)s para reiniciar su contraseña', +'click to check for upgrades': 'haga clic para buscar actualizaciones', +'client': 'cliente', +'Client IP': 'IP del Cliente', +'Close': 'Cerrar', +'collaborator': 'colaborador', +'Collaborator - Give read only permissions.': 'Colaborador - Otorga permiso de solo lectura', +'Color space': 'Espacio de colores', +'Comma-separated export including columns not shown; fields from other tables are exported as raw values for faster export': 'Comma-separated export including columns not shown; fields from other tables are exported as raw values for faster export', +'Comma-separated export of visible columns. Fields from other tables are exported as they appear on-screen but this may be slow for many rows': 'Comma-separated export of visible columns. Fields from other tables are exported as they appear on-screen but this may be slow for many rows', +'Comment': 'Comentario', +'Comment posted': 'Compentario publicado', +'Comments': 'Comentarios', +'Comments on %s': 'Comentarios en %s', +'Community': 'Comunidad', +'compile': 'compilar', +'compiled application removed': 'aplicación compilada eliminada', +'Components and Plugins': 'Componentes y Plugins', +'Config.ini': 'Config.ini', +'Confirm Password': 'Confirmar contraseña', +'contains': 'contiene', +'Content': 'Contenido', +'Content changelog': 'Cambios en el contenido', +'Content changes': 'Cambios en el contenido', +'Content differences': 'Diferencias de contenido', +'Contributors': 'Colaboradores', +'Controller': 'Controlador', +'Controllers': 'Controladores', +'controllers': 'controladores', +'Copyright': 'Copyright', +'Copyright Holder': 'Titular de derechos de autor', +'Copyright Notice': 'Aviso de derechos de autor', +'Copyright Url': 'Derechos de autor - Url', +'Copyright URL': 'Derechos de autor - URL', +'create file with filename:': 'cree archivo con nombre:', +'Create Items': 'Crear Items', +'Create new application': 'Cree una nueva aplicación', +'create new application:': 'nombre de la nueva aplicación:', +'Create new group': 'Crear grupo', +'Create new organization': 'Crear nueva organización', +'Create news item': 'Crear Item noticioso', +'Created by': 'Creado por', +'Created By': 'Creado Por', +'Created On': 'Creado En', +'Created on': 'Creado en', +'Credit line': 'Crédito', +'CSV': 'CSV', +'CSV (hidden cols)': 'CSV (columnas ocultas)', +'Current': 'Actual', +'Current language is': 'El lenguaje actual es', +'Current Record': 'Registro actual', +'Current request': 'Solicitud en curso', +'Current response': 'Respuesta en curso', +'Current session': 'Sesión en curso', +'currently saved or': 'actualmente guardado o', +'Currrent': 'Actual', +'customize me!': '¡Adáptame!', +'Dashboard name': 'Nombre de carpeta', +"Dashboard's": 'Carpetas', +'data uploaded': 'datos subidos', +'Database': 'Base de datos', +'Database %s select': 'selección en base de datos %s', +'database administration': 'administración de base de datos', +'Database Administration (appadmin)': 'Administración de Base de Datos (appadmin)', +'Date': 'Fecha', +'Date & Time': 'Fecha y hora', +'Date and Time': 'Fecha y Hora', +'DB': 'BDD', +'db': 'bdd', +'DB Model': 'Modelo BDD', +'defines tables': 'define tablas', +'Delete': 'Eliminar', +'delete': 'eliminar', +'delete all checked': 'eliminar marcados', +'Delete current dashboard': 'Borrar tablero actual', +'Delete:': 'Eliminar:', +'Demo': 'Demostración', +'Deploy on Google App Engine': 'Despliegue en Google App Engine', +'Deployment Recipes': 'Recetas de despliegue', +'Description': 'Descripción', +'design': 'diseño', +'DESIGN': 'DISEÑO', +'Design': 'Design', +'Design for': 'Diseño por', +'desk': 'desk', +'Desks': 'Escritorios', +'Details': 'Detalles', +'detecting': 'detectando', +'Differences': 'Diferencias', +'DISK': 'DISCO', +'Disk Cache Keys': 'Llaves de Caché en Disco', +'Disk Cleared': 'Disco limpiado', +'DISK contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.': 'DISK contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.', +'Documentation': 'Documentación', +"Don't know what to do?": '¿No sabe que hacer?', +'Done': 'Hecho', +'done!': '¡hecho!', +'Download': 'Descarga', +'E-mail': 'Correo electrónico', +'e-mail address': 'correo electrónico', +'edit': 'editar', +'EDIT': 'EDITAR', +'Edit': 'Editar', +'Edit application': 'Editar aplicación', +'Edit content': 'Editar contenido', +'edit controller': 'editar controlador', +'Edit current dashboard': 'Editar carpeta actual', +'Edit current record': 'Edite el registro actual', +'Edit metadata': 'Editar metadatos', +'Edit Profile': 'Editar Perfil', +'edit profile': 'editar perfil', +'Edit This App': 'Edite esta App', +'Editing file': 'Editando archivo', +'Editing file "%s"': 'Editando archivo "%s"', +'email': 'email', +'Email': 'Correo electrónico', +'Email and SMS': 'Correo electrónico y SMS', +'Email sent': 'Se ha enviado un correo a su dirección, por favor reviselo.', +'Email verification': 'Verificación del correo electrónico', +'Email verified': 'Correo vereficado', +'Embargoed': 'Embargado', +'End of impersonation': 'Fin de suplantación', +'eNews - CAST': 'eNews - CAST', +'enter a number between %(min)g and %(max)g': 'introduzca un número entre %(min)g y %(max)g', +'Enter a valid email address': 'Entre una dirección de correo valida', +'enter a value': 'introduzca un valor', +'Enter a value': 'Entre un valor', +'Enter an integer between %(min)g and %(max)g': 'Enter an integer between %(min)g and %(max)g', +'enter an integer between %(min)g and %(max)g': 'introduzca un entero entre %(min)g y %(max)g', +'enter date and time as %(format)s': 'introduzca fecha y hora como %(format)s', +'Error logs for "%(app)s"': 'Bitácora de errores en "%(app)s"', +'errors': 'errores', +'Errors': 'Errores', +'Errors in form, please check it out.': 'Hay errores en el formulario, por favor comprúebelo.', +'export as csv file': 'exportar como archivo CSV', +'Export:': 'Exportar:', +'exposes': 'expone', +'extends': 'extiende', +'failed to reload module': 'la recarga del módulo ha fallado', +'FAQ': 'FAQ', +'file "%(filename)s" created': 'archivo "%(filename)s" creado', +'file "%(filename)s" deleted': 'archivo "%(filename)s" eliminado', +'file "%(filename)s" uploaded': 'archivo "%(filename)s" subido', +'file "%(filename)s" was not deleted': 'archivo "%(filename)s" no fué eliminado', +'file "%s" of %s restored': 'archivo "%s" de %s restaurado', +'file changed on disk': 'archivo modificado en el disco', +'file does not exist': 'archivo no existe', +'file saved on %(time)s': 'archivo guardado %(time)s', +'file saved on %s': 'archivo guardado %s', +'First name': 'Nombre', +'Forgot username?': '¿Olvidó el nombre de usuario?', +'Format': 'Formato', +'Forms and Validators': 'Formularios y validadores', +'Free Applications': 'Aplicaciones Libres', +'From': 'De', +'from current dashboard': 'de la carpeta actual', +'From User': 'From User', +'Functions with no doctests will result in [passed] tests.': 'Funciones sin doctests equivalen a pruebas [aceptadas].', +'Genre': 'Género', +'Graph Model': 'Graph Model', +'Group %(group_id)s created': 'Grupo %(group_id)s creado', +'Group ID': 'ID de Grupo', +'Group uniquely assigned to user %(id)s': 'Grupo asignado únicamente al usuario %(id)s', +'Groups': 'Grupos', +'has been translated into the fallowing languages': 'a sido traducido a los siguientes lenguaje', +'has created a translation of the item': 'ha creado una traducción del item', +'has invalid extension.': 'extensión no permitida.', +'has made changes to the item': 'ha hecho cambios en el Item', +'has not been translated': 'no ha sido traducido', +'has post the comment': 'ha comentado', +'has share the item': 'ha compartido el item', +'Headline': 'Titular', +'Headline or descriptive title': 'Titular o titulo descriptivo', +'Height': 'Altura', +'Hello World': 'Hola Mundo', +'help': 'ayuda', +'Helping web2py': 'Helping web2py', +'Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses)})': 'Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses)})', +'Home': 'Inicio', +'How did you get here?': '¿Cómo llegaste aquí?', +'HTML': 'HTML', +'HTML export of visible columns': 'HTML export of visible columns', +'htmledit': 'htmledit', +'Id': 'Id', +'Image preview': 'Vista previa', +'Impersonate': 'Suplantar', +'import': 'importar', +'Import/Export': 'Importar/Exportar', +'in': 'en', +'includes': 'incluye', +'Index': 'Índice', +'insert new': 'inserte nuevo', +'insert new %s': 'inserte nuevo %s', +'Installed applications': 'Aplicaciones instaladas', +'Insufficient privileges': 'Privilegios insuficientes', +'internal error': 'error interno', +'Internal State': 'Estado Interno', +'Introduction': 'Introducción', +'Invalid action': 'Acción inválida', +'Invalid email': 'Correo electrónico inválido', +'invalid expression': 'expresión inválida', +'Invalid image': 'La imagen no es valida', +'Invalid login': 'Inicio de sesión inválido', +'invalid password': 'contraseña inválida', +'Invalid Query': 'Consulta inválida', +'invalid request': 'solicitud inválida', +'Invalid reset password': 'Reinicio de contraseña inválido', +'invalid ticket': 'tiquete inválido', +'Is Active': 'Está Activo', +'is empty, please select files again without it.': 'esta vacío, seleccione los archivos de nuevo sin incluirlos.', +'is too large, maximum file size is': 'Es muy largo, el máximo permitido es', +'is too small, minimum file size is': 'es muy pequeño, el mínimo permitido es', +'Item': 'Item', +'Item Type': 'Tipo de Item', +'Items': 'Items', +'Items on the package': 'Elementos en el paquete', +'JSON': 'JSON', +'JSON export of visible columns': 'JSON export of visible columns', +'Key': 'Llave', +'Keywords': 'Palabras clave', +'Language': 'Lenguaje', +'language file "%(filename)s" created/updated': 'archivo de lenguaje "%(filename)s" creado/actualizado', +'Language files (static strings) updated': 'Archivos de lenguaje (cadenas estáticas) actualizados', +'Language Tag': 'Etiqueta de lenguaje', +'languages': 'lenguajes', +'Languages': 'Lenguajes', +'languages updated': 'lenguajes actualizados', +'Last name': 'Apellido', +'Last saved on:': 'Guardado en:', +'Layout': 'Diseño de página', +'Layout Plugins': 'Plugins de diseño', +'Layouts': 'Diseños de páginas', +'License for': 'Licencia para', +"list for a simple reference of 'language-country' codes.": "list for a simple reference of 'language-country' codes.", +'Live Chat': 'Chat en vivo', +'loading...': 'cargando...', +'Located': 'Lugar', +'Log In': 'Entrar', +'Log Out': 'Salir', +'Logged in': 'Sesión iniciada', +'Logged out': 'Sesión finalizada', +'Login': 'Inicio de sesión', +'login': 'inicio de sesión', +'Login disabled by administrator': 'Inicio de sesión deshabilitado por el administrador', +'Login to comment': 'Entrar para comentar', +'Login to the Administrative Interface': 'Inicio de sesión para la Interfaz Administrativa', +'logout': 'fin de sesión', +'Logout': 'Fin de sesión', +'Lost Password': 'Contraseña perdida', +'Lost password?': '¿Olvidó la contraseña?', +'lost password?': '¿olvidó la contraseña?', +'Main item group': 'Grupo principal de items', +'Main Menu': 'Menú principal', +'Manage %(action)s': 'Manejar %(action)s', +'Manage Access Control': 'Manejar control de acceso', +'Manage Cache': 'Gestionar la Caché', +'Mark / unmark': 'Mark / unmark', +'Members': 'Miembros', +'Memberships': 'Membresía', +'Menu Model': 'Modelo "menu"', +'merge': 'combinar', +'Message': 'Mensaje', +'Message Content': 'Mensaje', +'META': 'META', +'META changelog': 'META cambios', +'Metadata changes': 'Cambios (Metadatos)', +'Mode': 'Modo', +'Models': 'Modelos', +'models': 'modelos', +'Modified By': 'Modificado Por', +'Modified On': 'Modificado En', +'Modules': 'Módulos', +'modules': 'módulos', +'must be YYYY-MM-DD HH:MM:SS!': '¡debe ser DD/MM/YYYY HH:MM:SS!', +'must be YYYY-MM-DD!': '¡debe ser DD/MM/YYYY!', +'My Dashboard': 'Mi carpeta', +'My Desk': 'Mi Escritorio', +'My Sites': 'Mis Sitios', +'name': 'name', +'Name': 'Nombre', +'New': 'Nuevo', +'New %(entity)s': 'Nuevo %(entity)s', +'new application "%s" created': 'nueva aplicación "%s" creada', +'New item': 'Nuevo Item', +'New password': 'Contraseña nueva', +'New Record': 'Registro nuevo', +'new record inserted': 'nuevo registro insertado', +'New rendition': 'Nueva entrega', +'New Search': 'Nueva búsqueda', +'next %s rows': 'next %s rows', +'next 100 rows': '100 filas siguientes', +'NO': 'NO', +'No databases in this application': 'No hay bases de datos en esta aplicación', +'No one has commented yet': 'Nadie ha comentado todavía', +'No records found': 'No se han encontrado registros', +'Not Authorized': 'No autorizado', +'Not authorized': 'No autorizado', +'not authorized': 'no autorizado', +'not in': 'no en', +'Notification center': 'Centro de notificaciones', +'Notifications': 'Notificaciones', +'now': 'ahora', +'Number of entries: **%s**': 'Número de entradas: **%s**', +'Object or table name': 'Nombre del objeto o tabla', +'Ok, item is shared with %s': 'Item compartido con %s', +'Old password': 'Contraseña vieja', +'on': 'on', +'On the item:': 'Sobre el Item:', +'One keyword per line': 'Una palabra clave por línea', +'Online book': 'Libro online', +'Online examples': 'Ejemplos en línea', +'Only': 'Only', +'Open': 'Abrir', +'Or': 'O', +'or import from csv file': 'o importar desde archivo CSV', +'or provide application url:': 'o provea URL de la aplicación:', +'Organization users': 'Organization users', +'Organizations': 'Organizaciones', +'Origin': 'Origen', +'Original/Translation': 'Original/Traducción', +'Other Plugins': 'Otros Plugins', +'Other Recipes': 'Otras Recetas', +'Overview': 'Resumen', +'owner': 'propietario', +'Owner - Give all permissions to the user': 'Propietario - Otorga todo los permisos al usuario', +'pack all': 'empaquetar todo', +'pack compiled': 'empaquetar compilados', +'Package': 'Paquete', +'package': 'package', +'Package from dashboard': 'Paquete desde carpeta', +'Package groups': 'Grupos', +'Password': 'Contraseña', +'Password changed': 'Contraseña cambiada', +"Password fields don't match": 'Los campos de contraseña no coinciden', +'Password reset': 'Reinicio de contraseña', +'Peeking at file': 'Visualizando archivo', +'People': 'People', +'Permission': 'Permiso', +'Permissions': 'Permisos', +'permissions on': 'permisos en', +'Personal user desk': 'Escritorio personal', +'Phone': 'Teléfono', +'Photo Set': 'Set de fotos', +'photoset': 'fotos', +'Picture': 'Foto', +'picture': 'imagen', +'Pictures': 'Pictures', +'Plain Text': 'Texto plano', +'Please enable JavaScript to use file uploader.': 'Debe habilitar JavaScript para subir archivos.', +'please input your password again': 'por favor introduzca su contraseña otra vez', +'Plugins': 'Plugins', +'Post': 'Enviar comentario', +'Post a new comment': 'Escriba un comentario', +'Powered by': 'Este sitio usa', +'Preface': 'Prefacio', +'Preview': 'Preview', +'previous %s rows': 'previous %s rows', +'previous 100 rows': '100 filas anteriores', +'Profile': 'Perfil', +'Profile updated': 'Perfil actualizado', +'Provider': 'Proveedor', +'Provider service': 'Servicio del provedor', +'Provider Service': 'Servicio del proveedor', +'Purpose': 'Propósito', +"Push items into '%s'": "Enviar Items a '%s'", +'Push to': 'Enviar a', +'pygraphviz library not found': 'pygraphviz library not found', +'Python': 'Python', +'Query Not Supported: %s': 'Consulta No Soportada: %s', +'Query:': 'Consulta:', +'Quick Examples': 'Ejemplos Rápidos', +'RAM': 'RAM', +'RAM Cache Keys': 'Llaves de la Caché en RAM', +'Ram Cleared': 'Ram Limpiada', +'RAM contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.': 'RAM contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.', +"Read '%s' content": "Leer el contenido de '%s'", +'Read desk content': 'Read desk content', +"Read/Update items in '%s'": "Leer/Modificar Items en '%s'", +'Recipes': 'Recetas', +'Record': 'Registro', +'Record %(id)s created': 'Registro %(id)s creado', +'Record Created': 'Registro Creado', +'record does not exist': 'el registro no existe', +'Record ID': 'ID de Registro', +'Record id': 'Id de registro', +'register': 'regístrese', +'Register': 'Regístrese', +'Registration identifier': 'Identificador de Registro', +'Registration key': 'Llave de registro', +'Registration successful': 'Registro con éxito', +'reload': 'recargar', +'Remember me (for 30 days)': 'Recuérdame (durante 30 días)', +'remove compiled': 'eliminar compiladas', +'Removed': 'Eliminado', +'Rename': 'Renombrar', +'Rendition': 'Entrega', +'Renditions': 'Entregas', +'Request Reset Password': 'Pedir cambio de contraseña', +'Request reset password': 'Solicitar reinicio de contraseña', +'Reset': 'Resetear', +'Reset password': 'Reiniciar contraseña', +'Reset Password key': 'Restaurar Llave de la Contraseña', +'Resolve Conflict file': 'archivo Resolución de Conflicto', +'restore': 'restaurar', +'Retrieve username': 'Recuperar nombre de usuario', +'revert': 'revertir', +'Role': 'Rol', +'Roles': 'Roles', +'Rows in Table': 'Filas en la tabla', +'Rows selected': 'Filas seleccionadas', +'Save': 'Guardar', +'save': 'guardar', +'Save model as...': 'Guardar como...', +'Saved': 'Guardado', +'Saved file hash:': 'Hash del archivo guardado:', +'says': 'dice', +'Search': 'Buscar', +'Section': 'Sección', +'Section or page in with this item is intended to be used': 'Sección o página donde se tiene intensión de ser usado el Item', +'See': 'Ver', +'See you on eNews': 'Nos vemos en eNews', +'See you on nStock': 'See you on nStock', +'Seen': 'Visto', +'Select and upload more photos': 'Seleccionar y subir más fotos', +'Select and upload photos': 'Seleccionar y subir fotos', +'Select the first rendition of the picture': 'Seleccionar primera entrega de la fotografía.', +'Select where to push the item': 'Seleccione el escritorio a donde se va a enviar el Item', +'Semantic': 'Semántica', +'Send': 'Enviar', +'Services': 'Servicios', +'session expired': 'sesión expirada', +'Settings': 'Configuración', +'Share': 'Compartir', +'Share of %s': 'Comparticiones de %s', +'Share this item': 'Compartir este Item', +'Share with': 'Compartido con', +'shares': 'Compartido', +'Shares': '', +'Shares with': 'Compartido con', +'shell': 'terminal', +'Sign Up': 'Registrarse', +'site': 'sitio', +'Size': 'Tamaño', +'Size of cache:': 'Tamaño de la Caché:', +'Slugline': 'Slugline', +'some files could not be removed': 'algunos archivos no pudieron ser removidos', +'Spreadsheet-optimised export of tab-separated content including hidden columns. May be slow': 'Spreadsheet-optimised export of tab-separated content including hidden columns. May be slow', +'Spreadsheet-optimised export of tab-separated content, visible columns only. May be slow.': 'Spreadsheet-optimised export of tab-separated content, visible columns only. May be slow.', +'start': 'inicio', +'Start building a new search': 'Construir nueva busqueda', +'starts with': 'comienza por', +'state': 'estado', +'static': 'estáticos', +'Static files': 'Archivos estáticos', +'Statistics': 'Estadísticas', +'Status': 'Estado', +'Stylesheet': 'Hoja de estilo', +'Subject': 'Asunto', +'Submit': 'Guardar', +'submit': 'guardar', +'Success!': '¡Correcto!', +'Support': 'Soporte', +'Sure you want to delete this object?': '¿Está seguro que desea eliminar este objeto?', +'Table': 'tabla', +'Table name': 'Nombre de la tabla', +'Target language': 'Lenguage objetivo', +'test': 'probar', +'Testing application': 'Probando aplicación', +'Text': 'Texto', +'text': 'texto', +'That user is the owner of the item': 'Ese usuario es el propietario', +'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'La "consulta" es una condición como "db.tabla1.campo1==\'valor\'". Algo como "db.tabla1.campo1==db.tabla2.campo2" resulta en un JOIN SQL.', +'the application logic, each URL path is mapped in one exposed function in the controller': 'la lógica de la aplicación, cada ruta URL se mapea en una función expuesta en el controlador', +'The Core': 'El Núcleo', +'The current dashboard is empty': 'La carpeta activa esta vacia', +'the data representation, define database tables and sets': 'la representación de datos, define tablas y conjuntos de base de datos', +'The files are being uploaded, if you leave now the upload will be cancelled.': 'Los archivos están cargando, si sale ahora la carga se cancelará.', +'The group is not empty. Can not be deleted': 'El grupo no esta vacío. No pude ser borrado ', +'The output of the file is a dictionary that was rendered by the view %s': 'La salida de dicha función es un diccionario que es desplegado por la vista %s', +'the presentations layer, views are also known as templates': 'la capa de presentación, las vistas también son llamadas plantillas', +"The user don't exists on this system": 'El usuario no existe en el sistema', +'The user is already in the organization': 'El usuario ya es parte de la organización', +'The Views': 'Las Vistas', +'There are no controllers': 'No hay controladores', +'There are no models': 'No hay modelos', +'There are no modules': 'No hay módulos', +'There are no static files': 'No hay archivos estáticos', +'There are no translators, only default language is supported': 'No hay traductores, sólo el lenguaje por defecto es soportado', +'There are no views': 'No hay vistas', +'these files are served without processing, your images go here': 'estos archivos son servidos sin procesar, sus imágenes van aquí', +'this': 'esto', +'This App': 'Esta Aplicación', +'This email already has an account': 'Este correo electrónico ya tiene una cuenta', +'This is a copy of the scaffolding application': 'Esta es una copia de la aplicación de andamiaje', +'This is the %(filename)s template': 'Esta es la plantilla %(filename)s', +'This item is a translation': 'Este Item es una traducción', +'This item is a translation of': 'Este Item es una traducción de', +'This item is a translation of another !': 'Este Item es una traducción de otro Item !', +'This item is shared with you': 'Este item es compartido contigo', +'This item was created by you': 'Este item fue creado por ti', +'Ticket': 'Tiquete', +'Time in Cache (h:m:s)': 'Tiempo en Caché (h:m:s)', +'Timestamp': 'Marca de tiempo', +'to previous version.': 'a la versión previa.', +'To emulate a breakpoint programatically, write:': 'Emular un punto de ruptura programáticamente, escribir:', +'to use the debugger!': '¡usar el depurador!', +'To User': 'To User', +'toggle breakpoint': 'alternar punto de ruptura', +'Toggle comment': 'Alternar comentario', +'Toggle Fullscreen': 'Alternar pantalla completa', +'too short': 'demasiado corto', +'Too short': 'Muy corto', +'Toogle pin to dashboard': 'Encajar/Soltar de la carpeta', +'Tools': 'Herramientas', +'Traceback': 'Traceback', +'Translate': 'Traducir', +'Translate this item': 'Traducir', +'Translation of %s': 'Traducción de %s', +'translation strings for the application': 'cadenas de caracteres de traducción para la aplicación', +'try': 'intente', +'try something like': 'intente algo como', +'TSV (Excel compatible)': 'TSV (compatible Excel)', +'TSV (Excel compatible, hidden cols)': 'TSV (compatible Excel, columnas ocultas)', +'TSV (Spreadsheets)': 'TSV (Spreadsheets)', +'TSV (Spreadsheets, hidden cols)': 'TSV (Spreadsheets, hidden cols)', +'Twitter': 'Twitter', +'Type': 'Tipo', +'Type text to search': 'Escribir texto a buscar', +'Unable to check for upgrades': 'No es posible verificar la existencia de actualizaciones', +'unable to create application "%s"': 'no es posible crear la aplicación "%s"', +'unable to delete file "%(filename)s"': 'no es posible eliminar el archivo "%(filename)s"', +'Unable to download': 'No es posible la descarga', +'Unable to download app': 'No es posible descarga la aplicación', +'unable to parse csv file': 'no es posible analizar el archivo CSV', +'unable to uninstall "%s"': 'no es posible instalar "%s"', +'Unattach from current dashboard': 'Desacoplar del tablero actual', +'uncheck all': 'desmarcar todos', +'uninstall': 'desinstalar', +'unknown': 'desconocido', +'update': 'actualizar', +'update all languages': 'actualizar todos los lenguajes', +"Update/Manage '%s'": "Administrar '%s'", +'Update:': 'Actualice:', +'upload application:': 'subir aplicación:', +'Upload existing application': 'Suba esta aplicación', +'upload file:': 'suba archivo:', +'Upload more photos': 'Subir más fotos', +'Upload photos': 'Subir fotos', +'Upload the photos before submiting the form.': 'Subir las fotos antes de guargar el formulario', +'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Use (...)&(...) para AND, (...)|(...) para OR, y ~(...) para NOT, para crear consultas más complejas.', +'User': 'Usuario', +'User %(id)s is impersonating %(other_id)s': 'El usuario %(id)s está suplantando %(other_id)s', +'User %(id)s Logged-in': 'El usuario %(id)s inició la sesión', +'User %(id)s Logged-out': 'El usuario %(id)s finalizó la sesión', +'User %(id)s Password changed': 'Contraseña del usuario %(id)s cambiada', +'User %(id)s Password reset': 'Contraseña del usuario %(id)s reiniciada', +'User %(id)s Profile updated': 'Actualizado el perfil del usuario %(id)s', +'User %(id)s Registered': 'Usuario %(id)s Registrado', +'User %(id)s Username retrieved': 'Se ha recuperado el nombre de usuario del usuario %(id)s', +'User %(username)s Logged-in': 'El usuario %(username)s inició la sesión', +"User '%(username)s' Logged-in": "El usuario '%(username)s' inició la sesión", +"User '%(username)s' Logged-out": "El usuario '%(username)s' finalizó la sesión", +'User Id': 'Id de Usuario', +'User ID': 'ID de Usuario', +'User Logged-out': 'El usuario finalizó la sesión', +'Username': 'Nombre de usuario', +'Username retrieve': 'Recuperar nombre de usuario', +'Users': 'Usuarios', +'Value already in database or empty': 'El valor ya existe en la base de datos o está vacío', +'value not allowed': 'valor no permitido', +'Value not allowed': 'Value not allowed', +'value not in database': 'el valor no está en la base de datos', +'Verify Password': 'Verificar Contraseña', +'Version': 'Versión', +'versioning': 'versiones', +'Videos': 'Vídeos', +'View': 'Vista', +'view': 'vista', +'View %(entity)s': 'Ver %(entity)s', +'Views': 'Vistas', +'views': 'vistas', +'Warning!': '¡Aviso!', +'Warning !': '¡Aviso!', +'web2py is up to date': 'web2py está actualizado', +'web2py Recent Tweets': 'Tweets Recientes de web2py', +'Welcome': 'Bienvenido', +'Welcome %(username)s! Click on the link %(link)s to verify your email': 'Bienvenido %(username)s! Use este enlace %(link)s para verificar su dirección de correo', +'Welcome %s': 'Bienvenido %s', +'Welcome to web2py': 'Bienvenido a web2py', +'Welcome to web2py!': '¡Bienvenido a web2py!', +'Which called the function %s located in the file %s': 'La cual llamó la función %s localizada en el archivo %s', +'Width': 'Ancho', +'With': 'Con', +'With you': 'Contigo', +'Working...': 'Trabajando...', +'XML': 'XML', +'XML export of columns shown': 'XML export of columns shown', +'YES': 'SÍ', +'You are successfully running web2py': 'Usted está ejecutando web2py exitosamente', +'You can access to the translation with this link': 'Puedes acceder a la traducción con el siguiente enlace', +'You can modify this application and adapt it to your needs': 'Usted puede modificar esta aplicación y adaptarla a sus necesidades', +'You can see the changes on': 'Puedes ver los cambios en', +'You can view this or others comments to this item on': 'Puedes ver este u otros comentarios a este Item en', +"You can't push this item to any Desk": "No puedes enviar el Item a ningún Escritorio", +"You can't push this item to any other Desk": "No puedes enviar el Item a ningún Escritorio", +"You don't have access to any desk yet.": "Todavía no tienes acceso a ningún otro Escritorio", +"You don't have or have joined to any organization": 'No te has unido a ninguna organización', +'You have unread notifications': 'Tienes notificaciones sin leer', +'You must activate some dashboard first': 'Debe activar primero una carpeta', +'You must mark some items first': 'You must mark some items first', +'You visited the url %s': 'Usted visitó la url %s', +'Your comment': 'Tú comentario', +"Your organization don't have members yet.": 'Esta organización no tiene ningún miembro todavía.', +'Your organizations': 'Tus organizaciones', +'Your username is: %(username)s': 'Su nombre de usuario es: %(username)s', +} diff --git a/nstock/languages/es.py b/nstock/languages/es.py new file mode 100644 index 0000000..d3b9e14 --- /dev/null +++ b/nstock/languages/es.py @@ -0,0 +1,772 @@ +# -*- coding: utf-8 -*- +{ +'\n Allow the user to manage/administrate this desk. Use with caution.\n ': '\n Permite al usuario administrar el escritorio, usar con cuidado.\n ', +'\n Current item content version by %(first_name)s %(last_name)s on %(date_time)s\n ': ' Current item content version by %(first_name)s %(last_name)s on %(date_time)s\r\n ', +'\n Declare the group role within the package structure.\n Contain values representing “main”, “sidebar” or other editorial\n terms that express how the content in the package is intended to be\n used.\n ': 'Declare el rol del grupo dentro de la estructura del paquete. Pueden usarse términos como “principal”, “Página 2” u otros que expresen como se pretende utilizar el contenido.', +'\n It may contain any value but it is recommended to use one of the\n values: raw, web, thumbnail, print\n ': 'Puede contener cualquier valor pero se recomienda utilizar uno de los\r\n valores: raw, web, thumbnail, printer\r\n ', +'\n Current item metadata version by %(first_name)s %(last_name)s on %(date_time)s\n ': ' Versión actual de los metadatos por %(first_name)s %(last_name)s el %(date_time)s\r\n ', +'\n To create a new translation of the current item select the target\n language.\n ': 'Seleccione el lenguaje objetivo para crear una traducción del Item actual.\r\n ', +'\n Current item content version by %(first_name)s %(last_name)s on %(date_time)s\n ': 'Versión actual del contenido por %(first_name)s %(last_name)s el %(date_time)s\r\n ', +'\n It can be the name of a city or may contain details, for example: HAVANA,\n CUBA': ' It can be the name of a city or may contain details, for example: HAVANA,\r\n CUBA', +'\n It can be the name of a city or may contain details, for example: HAVANA, CUBA\n': 'Puede ser el nombre de una ciudad o puede contener más detalles, por ejemplo: LA HABANA, CUBA\r\n', +'\n News organisations often use an embargo to release information in advance,\n on the strict understanding that it may not be released into the public\n domain until after the embargo time has expired, or until some other form\n of permission has been given.\n ': 'Las organizaciones de noticias usan a menudo un embargo para divulgar la información por adelantado, bajo la estricta comprensión de que no puede ser liberado en el dominio público hasta después de que el embargo haya expirado o hasta que se haya dado otra forma de permiso.', +'\n Normally the raw version of the image. You may add other renditions as\n needed after form submition..\n ': 'Normalmente, la versión RAW de la imagen. Puede añadir otras entregas, según sea necesario después de guardar este formulario ...\r\n ', +"\n Within a package items they can be grouped according to different purposes. A default group is created with name 'main'.\n ": 'Dentro de un paquete, los artículos se pueden agrupar de acuerdo con diferentes propósitos. Un grupo predeterminado se crea con el nombre de "main".\r\n ', +'\nAllows the provider to declare which of its services, if any, delivered\nthis package.\n': 'Permite que el proveedor de declarar cuál de sus servicios, si existe, entrega este Item.\r\n', +'\nIt can be a descriptive name for the news provider or URL associated with it.\n': 'Puede ser un nombre descriptivo para el proveedor de noticias o URL asociado con él.\r\n', +'\nNews organisations often use an embargo to release information in advance, on the\nstrict understanding that it may not be released into the public domain until\nafter the embargo time has expired, or until some other form of permission has\nbeen given.\n': 'Las organizaciones de noticias a menudo utilizan un plazo de embargo al divulgar información por adelantado, en el\r\nestricto supuesto de que no puede ser liberado al dominio público hasta\r\ndespués de que el tiempo de embargo ha expirado, o hasta que alguna otra forma de permiso se de.\r\n', +'!=': '!=', +'!langcode!': 'es', +'!langname!': 'Español', +'"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"actualice" es una expresión opcional como "campo1=\'nuevo_valor\'". No se puede actualizar o eliminar resultados de un JOIN', +'%(nrows)s records found': '%(nrows)s registros encontrados', +'%d days ago': 'hace %d días', +'%d hours ago': 'hace %d horas', +'%d minutes ago': 'hace %d minutos', +'%d seconds ago': 'hace %d segundos', +'%s %%{position}': '%s %%{posición}', +'%s %%{row} deleted': '%s %%{fila} %%{eliminada}', +'%s %%{row} updated': '%s %%{fila} %%{actualizada}', +'%s desk': 'Escritorio de %s', +'%s selected': '%s %%{seleccionado}', +'%Y-%m-%d': '%d/%m/%Y', +'%Y-%m-%d %H:%M:%S': '%d/%m/%Y %H:%M:%S', +'(**%.0d MB**)': '(**%.0d MB**)', +'(something like "it-it")': '(algo como "es-ES")', +'**%(items)s** %%{item(items)}, **%(bytes)s** %%{byte(bytes)}': '**%(items)s** %%{item(items)}, **%(bytes)s** %%{byte(bytes)}', +'**%(items)s** items, **%(bytes)s** %%{byte(bytes)}': '**%(items)s** items, **%(bytes)s** %%{byte(bytes)}', +'**not available** (requires the Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] library)': '**not available** (requires the Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] library)', +'+ And': '+ Y', +'+ Or': '+ O', +'1 day ago': 'hace 1 día', +'1 hour ago': 'hace 1 hora', +'1 minute ago': 'hace 1 minuto', +'1 second ago': 'hace 1 segundo', +'1 week ago': '1 week ago', +'<': '<', +'<=': '<=', +'=': '=', +'>': '>', +'>=': '>=', +'?': '?', +'@markmin\x01An error occured, please [[reload %s]] the page': 'Ha ocurrido un error, por favor [[recargar %s]] la página', +'@markmin\x01Number of entries: **%s**': 'Número de entradas: **%s**', +'``**not available**``:red (requires the Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] library)': '``**not available**``:red (requires the Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] library)', +'A new version of web2py is available': 'Hay una nueva versión de web2py disponible', +'A new version of web2py is available: %s': 'Hay una nueva versión de web2py disponible: %s', +'About': 'Acerca de', +'about': 'acerca de', +'About application': 'Acerca de la aplicación', +'Access Control': 'Control de Acceso', +'Activate?': '¿Activar?', +'Actual': 'Actual', +'Add': 'Añadir', +'Add dashboard': 'Agregar tablero', +'Add Items': 'Agregar Items', +'Add items': 'Agregar Items', +'Add new desk': 'Agregar escritorio', +'Add Record': 'Agregar registro', +'Add record to database': 'Agregar registro', +'Add rendition': 'Agregar entrega', +'Add this to the search as an AND term': 'Agregue esto a la búsqueda como un término Y', +'Add this to the search as an OR term': 'Agregue esto a la búsqueda como un término O', +'Add user': 'Agregar usuario', +'additional code for your application': 'código adicional para su aplicación', +'admin': 'admin', +'admin disabled because no admin password': 'admin deshabilitado por falta de contraseña', +'admin disabled because not supported on google app engine': 'admin deshabilitado, no es soportado en GAE', +'admin disabled because unable to access password file': 'admin deshabilitado, imposible acceder al archivo con la contraseña', +'Admin is disabled because insecure channel': 'Admin deshabilitado, el canal no es seguro', +'Admin is disabled because unsecure channel': 'Admin deshabilitado, el canal no es seguro', +'Administrative interface': 'Interfaz administrativa', +'Administrative Interface': 'Interfaz Administrativa', +'Administrator Password:': 'Contraseña del Administrador:', +'Ajax Recipes': 'Recetas AJAX', +'All items': 'Todos los Items', +'Allow the user make modifications to the items in the desk.': 'Permite hacer modificaciones a los Items en el escritorio.', +'Allow the user move items into the desk.': 'Permite al usuario enviar Items a este escritorio.', +'Allow the user read only access to the desk item list.': 'Perminte leer todos los Items en el escritorio', +'An error occured, please %s the page': 'Ha ocurrido un error, por favor %s la página', +'An error occured, please [[reload %s]] the page': 'Ocurrió un error, [[recargue %s]] la página', +'An Organization witch that name is allready in nStock': 'Ya existe una organización con ese nombre', +'and': 'y', +'And': 'Y', +'and rename it (required):': 'y renómbrela (requerido):', +'and rename it:': ' y renómbrelo:', +'appadmin': 'appadmin', +'appadmin is disabled because insecure channel': 'admin deshabilitado, el canal no es seguro', +'application "%s" uninstalled': 'aplicación "%s" desinstalada', +'application compiled': 'aplicación compilada', +'application is compiled and cannot be designed': 'la aplicación está compilada y no puede ser modificada', +'Apply changes': 'Aplicar cambios', +'Appointment': 'Nombramiento', +'are allowed.': 'son permitidos.', +'Are you sure you want to delete file "%s"?': '¿Está seguro que desea eliminar el archivo "%s"?', +'Are you sure you want to delete this object?': '¿Está seguro que desea borrar este objeto?', +'Are you sure you want to uninstall application "%s"': '¿Está seguro que desea desinstalar la aplicación "%s"', +'Are you sure you want to uninstall application "%s"?': '¿Está seguro que desea desinstalar la aplicación "%s"?', +'Are you sure?': '¿Está seguro?', +'at': 'en', +'Attach to current dashboard': 'Adjuntar al tablero actual', +'ATTENTION: Login requires a secure (HTTPS) connection or running on localhost.': 'ATENCION: Inicio de sesión requiere una conexión segura (HTTPS) o localhost.', +'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'ATENCION: NO EJECUTE VARIAS PRUEBAS SIMULTANEAMENTE, NO SON THREAD SAFE.', +'ATTENTION: you cannot edit the running application!': 'ATENCION: no puede modificar la aplicación que está ejecutandose!', +'Authentication': 'Autenticación', +'Authentication failed at client DB!': '¡La autenticación ha fallado en la BDD cliente!', +'Authentication failed at main DB!': '¡La autenticación ha fallado en la BDD principal!', +'Automatic form PIL': 'Obtenido de PIL', +'Available Databases and Tables': 'Bases de datos y tablas disponibles', +'Back': 'Atrás', +'Before': 'Antes', +'Body': 'Body', +'Buy this book': 'Compra este libro', +"Buy web2py's book": "Buy web2py's book", +'By line': 'Credito', +'Byline': 'Byline', +'Cache': 'Caché', +'cache': 'caché', +'Cache Cleared': 'Chache limpiada', +'Cache contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.': 'Cache contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.', +'Cache Keys': 'Llaves de la Caché', +'cache, errors and sessions cleaned': 'caché, errores y sesiones eliminados', +'Cancel': 'Cancelar', +'Cannot be empty': 'No puede estar vacío', +'Cannot compile: there are errors in your app. Debug it, correct errors and try again.': 'No se puede compilar: hay errores en su aplicación. Depure, corrija errores y vuelva a intentarlo.', +'cannot create file': 'no es posible crear archivo', +'cannot upload file "%(filename)s"': 'no es posible subir archivo "%(filename)s"', +'Caption': 'Subtítulo', +'CAST': 'CAST', +'Change': 'Cambio', +'Change password': 'Cambie la contraseña', +'change password': 'cambie la contraseña', +'Change Password': 'Cambie la Contraseña', +'Changelog': 'Chambios', +'Changes': 'Cambios', +'Changes on %s': 'Cambios en %s', +'check all': 'marcar todos', +'Check to delete': 'Marque para eliminar', +'choose one': 'escoja uno', +'clean': 'limpiar', +'Clear': 'Limpiar', +'Clear CACHE?': '¿Limpiar CACHÉ?', +'Clear DISK': 'Limpiar DISCO', +'Clear RAM': 'Limpiar RAM', +'Click on the link %(link)s to reset your password': 'Pulse en el enlace %(link)s para reiniciar su contraseña', +'click to check for upgrades': 'haga clic para buscar actualizaciones', +'client': 'cliente', +'Client IP': 'IP del Cliente', +'Close': 'Cerrar', +'collaborator': 'colaborador', +'Collaborator - Give read only permissions.': 'Colaborador - Otorga permiso de solo lectura', +'Color space': 'Espacio de colores', +'Comma-separated export including columns not shown; fields from other tables are exported as raw values for faster export': 'Comma-separated export including columns not shown; fields from other tables are exported as raw values for faster export', +'Comma-separated export of visible columns. Fields from other tables are exported as they appear on-screen but this may be slow for many rows': 'Comma-separated export of visible columns. Fields from other tables are exported as they appear on-screen but this may be slow for many rows', +'Comment': 'Comentario', +'Comment posted': 'Compentario publicado', +'Comments': 'Comentarios', +'Comments on %s': 'Comentarios en %s', +'Community': 'Comunidad', +'compile': 'compilar', +'compiled application removed': 'aplicación compilada eliminada', +'Components and Plugins': 'Componentes y Plugins', +'Config.ini': 'Config.ini', +'Confirm Password': 'Confirmar contraseña', +'contains': 'contiene', +'Content': 'Contenido', +'Content changelog': 'Cambios en el contenido', +'Content changes': 'Cambios en el contenido', +'Content differences': 'Diferencias de contenido', +'Contributors': 'Colaboradores', +'Controller': 'Controlador', +'Controllers': 'Controladores', +'controllers': 'controladores', +'Copyright': 'Copyright', +'Copyright Holder': 'Titular de derechos de autor', +'Copyright Notice': 'Aviso de derechos de autor', +'Copyright Url': 'Derechos de autor - Url', +'Copyright URL': 'Derechos de autor - URL', +'create file with filename:': 'cree archivo con nombre:', +'Create Items': 'Crear Items', +'Create new application': 'Cree una nueva aplicación', +'create new application:': 'nombre de la nueva aplicación:', +'Create new group': 'Crear grupo', +'Create new organization': 'Crear nueva organización', +'Create news item': 'Crear Item noticioso', +'Created by': 'Creado por', +'Created By': 'Creado Por', +'Created On': 'Creado En', +'Created on': 'Creado en', +'Credit line': 'Crédito', +'CSV': 'CSV', +'CSV (hidden cols)': 'CSV (columnas ocultas)', +'Current': 'Actual', +'Current language is': 'El lenguaje actual es', +'Current Record': 'Registro actual', +'Current request': 'Solicitud en curso', +'Current response': 'Respuesta en curso', +'Current session': 'Sesión en curso', +'currently saved or': 'actualmente guardado o', +'Currrent': 'Actual', +'customize me!': '¡Adáptame!', +'Dashboard name': 'Nombre de carpeta', +"Dashboard's": 'Carpetas', +'data uploaded': 'datos subidos', +'Database': 'Base de datos', +'Database %s select': 'selección en base de datos %s', +'database administration': 'administración de base de datos', +'Database Administration (appadmin)': 'Administración de Base de Datos (appadmin)', +'Date': 'Fecha', +'Date & Time': 'Fecha y hora', +'Date and Time': 'Fecha y Hora', +'DB': 'BDD', +'db': 'bdd', +'DB Model': 'Modelo BDD', +'defines tables': 'define tablas', +'Delete': 'Eliminar', +'delete': 'eliminar', +'delete all checked': 'eliminar marcados', +'Delete current dashboard': 'Borrar tablero actual', +'Delete:': 'Eliminar:', +"Deleting this desk will push all the Items to the author's desk's": "Eliminar este escritorio enviara todos los Items a los escritorios de los autores originales.", +'Demo': 'Demostración', +'Deploy on Google App Engine': 'Despliegue en Google App Engine', +'Deployment Recipes': 'Recetas de despliegue', +'Description': 'Descripción', +'design': 'diseño', +'DESIGN': 'DISEÑO', +'Design': 'Design', +'Design for': 'Diseño por', +'desk': 'desk', +'Desks': 'Escritorios', +'Details': 'Detalles', +'detecting': 'detectando', +'Differences': 'Diferencias', +'DISK': 'DISCO', +'Disk Cache Keys': 'Llaves de Caché en Disco', +'Disk Cleared': 'Disco limpiado', +'DISK contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.': 'DISK contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.', +'Documentation': 'Documentación', +"Don't know what to do?": '¿No sabe que hacer?', +'Done': 'Hecho', +'done!': '¡hecho!', +'Download': 'Descarga', +'E-mail': 'Correo electrónico', +'e-mail address': 'correo electrónico', +'edit': 'editar', +'EDIT': 'EDITAR', +'Edit': 'Editar', +'Edit application': 'Editar aplicación', +'Edit content': 'Editar contenido', +'edit controller': 'editar controlador', +'Edit current dashboard': 'Editar carpeta actual', +'Edit current record': 'Edite el registro actual', +'Edit metadata': 'Editar metadatos', +'Edit Profile': 'Editar Perfil', +'edit profile': 'editar perfil', +'Edit This App': 'Edite esta App', +'Editing file': 'Editando archivo', +'Editing file "%s"': 'Editando archivo "%s"', +'email': 'email', +'Email': 'Correo electrónico', +'Email and SMS': 'Correo electrónico y SMS', +'Email sent': 'Se ha enviado un correo a su dirección, por favor reviselo.', +'Email verification': 'Verificación del correo electrónico', +'Email verified': 'Correo vereficado', +'Embargoed': 'Embargado', +'End of impersonation': 'Fin de suplantación', +'eNews - CAST': 'eNews - CAST', +'enter a number between %(min)g and %(max)g': 'introduzca un número entre %(min)g y %(max)g', +'Enter a valid email address': 'Entre una dirección de correo valida', +'enter a value': 'introduzca un valor', +'Enter a value': 'Entre un valor', +'Enter an integer between %(min)g and %(max)g': 'Enter an integer between %(min)g and %(max)g', +'enter an integer between %(min)g and %(max)g': 'introduzca un entero entre %(min)g y %(max)g', +'enter date and time as %(format)s': 'introduzca fecha y hora como %(format)s', +'Error logs for "%(app)s"': 'Bitácora de errores en "%(app)s"', +'errors': 'errores', +'Errors': 'Errores', +'Errors in form, please check it out.': 'Hay errores en el formulario, por favor comprúebelo.', +'export as csv file': 'exportar como archivo CSV', +'Export:': 'Exportar:', +'exposes': 'expone', +'extends': 'extiende', +'failed to reload module': 'la recarga del módulo ha fallado', +'FAQ': 'FAQ', +'file "%(filename)s" created': 'archivo "%(filename)s" creado', +'file "%(filename)s" deleted': 'archivo "%(filename)s" eliminado', +'file "%(filename)s" uploaded': 'archivo "%(filename)s" subido', +'file "%(filename)s" was not deleted': 'archivo "%(filename)s" no fué eliminado', +'file "%s" of %s restored': 'archivo "%s" de %s restaurado', +'file changed on disk': 'archivo modificado en el disco', +'file does not exist': 'archivo no existe', +'file saved on %(time)s': 'archivo guardado %(time)s', +'file saved on %s': 'archivo guardado %s', +'First name': 'Nombre', +'Forgot username?': '¿Olvidó el nombre de usuario?', +'Format': 'Formato', +'Forms and Validators': 'Formularios y validadores', +'Free Applications': 'Aplicaciones Libres', +'From': 'De', +'from current dashboard': 'de la carpeta actual', +'From User': 'From User', +'Functions with no doctests will result in [passed] tests.': 'Funciones sin doctests equivalen a pruebas [aceptadas].', +'Genre': 'Género', +'Graph Model': 'Graph Model', +'Group %(group_id)s created': 'Grupo %(group_id)s creado', +'Group ID': 'ID de Grupo', +'Group uniquely assigned to user %(id)s': 'Grupo asignado únicamente al usuario %(id)s', +'Groups': 'Grupos', +'has been translated into the fallowing languages': 'a sido traducido a los siguientes lenguaje', +'has created a translation of the item': 'ha creado una traducción del item', +'has invalid extension.': 'extensión no permitida.', +'has made changes to the item': 'ha hecho cambios en el Item', +'has not been translated': 'no ha sido traducido', +'has post the comment': 'ha comentado', +'has share the item': 'ha compartido el item', +'Headline': 'Titular', +'Headline or descriptive title': 'Titular o titulo descriptivo', +'Height': 'Altura', +'Hello World': 'Hola Mundo', +'help': 'ayuda', +'Helping web2py': 'Helping web2py', +'Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses)})': 'Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses)})', +'Home': 'Inicio', +'How did you get here?': '¿Cómo llegaste aquí?', +'HTML': 'HTML', +'HTML export of visible columns': 'HTML export of visible columns', +'htmledit': 'htmledit', +'Id': 'Id', +'Image preview': 'Vista previa', +'Impersonate': 'Suplantar', +'import': 'importar', +'Import/Export': 'Importar/Exportar', +'in': 'en', +'includes': 'incluye', +'Index': 'Índice', +'insert new': 'inserte nuevo', +'insert new %s': 'inserte nuevo %s', +'Installed applications': 'Aplicaciones instaladas', +'Insufficient privileges': 'Privilegios insuficientes', +'internal error': 'error interno', +'Internal State': 'Estado Interno', +'Introduction': 'Introducción', +'Invalid action': 'Acción inválida', +'Invalid email': 'Correo electrónico inválido', +'invalid expression': 'expresión inválida', +'Invalid image': 'La imagen no es valida', +'Invalid login': 'Inicio de sesión inválido', +'invalid password': 'contraseña inválida', +'Invalid Query': 'Consulta inválida', +'invalid request': 'solicitud inválida', +'Invalid reset password': 'Reinicio de contraseña inválido', +'invalid ticket': 'tiquete inválido', +'Is Active': 'Está Activo', +'is empty, please select files again without it.': 'esta vacío, seleccione los archivos de nuevo sin incluirlos.', +'is too large, maximum file size is': 'Es muy largo, el máximo permitido es', +'is too small, minimum file size is': 'es muy pequeño, el mínimo permitido es', +'Item': 'Item', +'Item Type': 'Tipo de Item', +'Items': 'Items', +'Items on the package': 'Elementos en el paquete', +'JSON': 'JSON', +'JSON export of visible columns': 'JSON export of visible columns', +'Key': 'Llave', +'Keywords': 'Palabras clave', +'Language': 'Lenguaje', +'language file "%(filename)s" created/updated': 'archivo de lenguaje "%(filename)s" creado/actualizado', +'Language files (static strings) updated': 'Archivos de lenguaje (cadenas estáticas) actualizados', +'Language Tag': 'Etiqueta de lenguaje', +'languages': 'lenguajes', +'Languages': 'Lenguajes', +'languages updated': 'lenguajes actualizados', +'Last name': 'Apellido', +'Last saved on:': 'Guardado en:', +'Layout': 'Diseño de página', +'Layout Plugins': 'Plugins de diseño', +'Layouts': 'Diseños de páginas', +'License for': 'Licencia para', +"list for a simple reference of 'language-country' codes.": "list for a simple reference of 'language-country' codes.", +'Live Chat': 'Chat en vivo', +'loading...': 'cargando...', +'Located': 'Lugar', +'Log In': 'Entrar', +'Log Out': 'Salir', +'Logged in': 'Sesión iniciada', +'Logged out': 'Sesión finalizada', +'Login': 'Inicio de sesión', +'login': 'inicio de sesión', +'Login disabled by administrator': 'Inicio de sesión deshabilitado por el administrador', +'Login to comment': 'Entrar para comentar', +'Login to the Administrative Interface': 'Inicio de sesión para la Interfaz Administrativa', +'logout': 'fin de sesión', +'Logout': 'Fin de sesión', +'Lost Password': 'Contraseña perdida', +'Lost password?': '¿Olvidó la contraseña?', +'lost password?': '¿olvidó la contraseña?', +'Main item group': 'Grupo principal de items', +'Main Menu': 'Menú principal', +'Manage %(action)s': 'Manejar %(action)s', +'Manage Access Control': 'Manejar control de acceso', +'Manage Cache': 'Gestionar la Caché', +'Mark / unmark': 'Mark / unmark', +'Members': 'Miembros', +'Memberships': 'Membresía', +'Menu Model': 'Modelo "menu"', +'merge': 'combinar', +'Message': 'Mensaje', +'Message Content': 'Mensaje', +'META': 'META', +'META changelog': 'META cambios', +'Metadata changes': 'Cambios (Metadatos)', +'Mode': 'Modo', +'Models': 'Modelos', +'models': 'modelos', +'Modified By': 'Modificado Por', +'Modified On': 'Modificado En', +'Modules': 'Módulos', +'modules': 'módulos', +'must be YYYY-MM-DD HH:MM:SS!': '¡debe ser DD/MM/YYYY HH:MM:SS!', +'must be YYYY-MM-DD!': '¡debe ser DD/MM/YYYY!', +'My Dashboard': 'Mi carpeta', +'My Desk': 'Mi Escritorio', +'My Sites': 'Mis Sitios', +'name': 'name', +'Name': 'Nombre', +'New': 'Nuevo', +'New %(entity)s': 'Nuevo %(entity)s', +'new application "%s" created': 'nueva aplicación "%s" creada', +'New item': 'Nuevo Item', +'New password': 'Contraseña nueva', +'New Record': 'Registro nuevo', +'new record inserted': 'nuevo registro insertado', +'New rendition': 'Nueva entrega', +'New Search': 'Nueva búsqueda', +'next %s rows': 'next %s rows', +'next 100 rows': '100 filas siguientes', +'NO': 'NO', +'No databases in this application': 'No hay bases de datos en esta aplicación', +'No one has commented yet': 'Nadie ha comentado todavía', +'No records found': 'No se han encontrado registros', +'Not Authorized': 'No autorizado', +'Not authorized': 'No autorizado', +'not authorized': 'no autorizado', +'not in': 'no en', +'Notification center': 'Centro de notificaciones', +'Notifications': 'Notificaciones', +'now': 'ahora', +'Number of entries: **%s**': 'Número de entradas: **%s**', +'Object or table name': 'Nombre del objeto o tabla', +'Ok, item is shared with %s': 'Item compartido con %s', +'Old password': 'Contraseña vieja', +'on': 'on', +'On the item:': 'Sobre el Item:', +'One keyword per line': 'Una palabra clave por línea', +'Online book': 'Libro online', +'Online examples': 'Ejemplos en línea', +'Only': 'Only', +'Open': 'Abrir', +'Or': 'O', +'or import from csv file': 'o importar desde archivo CSV', +'or provide application url:': 'o provea URL de la aplicación:', +'Organization users': 'Usuarios de la organización', +'Organizations': 'Organizaciones', +'Origin': 'Origen', +'Original/Translation': 'Original/Traducción', +'Other Plugins': 'Otros Plugins', +'Other Recipes': 'Otras Recetas', +'Overview': 'Resumen', +'owner': 'propietario', +'Owner - Give all permissions to the user': 'Propietario - Otorga todo los permisos al usuario', +'pack all': 'empaquetar todo', +'pack compiled': 'empaquetar compilados', +'Package': 'Paquete', +'package': 'package', +'Package from dashboard': 'Paquete desde carpeta', +'Package groups': 'Grupos', +'Password': 'Contraseña', +'Password changed': 'Contraseña cambiada', +"Password fields don't match": 'Los campos de contraseña no coinciden', +'Password reset': 'Reinicio de contraseña', +'Peeking at file': 'Visualizando archivo', +'People': 'People', +'Permission': 'Permiso', +'Permissions': 'Permisos', +'permissions on': 'permisos en', +'Personal user desk': 'Escritorio personal', +'Phone': 'Teléfono', +'Photo Set': 'Set de fotos', +'photoset': 'fotos', +'Picture': 'Foto', +'picture': 'imagen', +'Pictures': 'Pictures', +'Plain Text': 'Texto plano', +'Please enable JavaScript to use file uploader.': 'Debe habilitar JavaScript para subir archivos.', +'please input your password again': 'por favor introduzca su contraseña otra vez', +'Plugins': 'Plugins', +'Post': 'Enviar comentario', +'Post a new comment': 'Escriba un comentario', +'Powered by': 'Este sitio usa', +'Preface': 'Prefacio', +'Preview': 'Preview', +'previous %s rows': 'previous %s rows', +'previous 100 rows': '100 filas anteriores', +'Profile': 'Perfil', +'Profile updated': 'Perfil actualizado', +'Provider': 'Proveedor', +'Provider service': 'Servicio del provedor', +'Provider Service': 'Servicio del proveedor', +'Purpose': 'Propósito', +"Push items into '%s'": "Enviar Items a '%s'", +'Push to': 'Enviar a', +'pygraphviz library not found': 'pygraphviz library not found', +'Python': 'Python', +'Query Not Supported: %s': 'Consulta No Soportada: %s', +'Query:': 'Consulta:', +'Quick Examples': 'Ejemplos Rápidos', +'RAM': 'RAM', +'RAM Cache Keys': 'Llaves de la Caché en RAM', +'Ram Cleared': 'Ram Limpiada', +'RAM contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.': 'RAM contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.', +"Read '%s' content": "Leer el contenido de '%s'", +'Read desk content': 'Read desk content', +"Read/Update items in '%s'": "Leer/Modificar Items en '%s'", +'Recipes': 'Recetas', +'Record': 'Registro', +'Record %(id)s created': 'Registro %(id)s creado', +'Record Created': 'Registro Creado', +'record does not exist': 'el registro no existe', +'Record ID': 'ID de Registro', +'Record id': 'Id de registro', +'register': 'regístrese', +'Register': 'Regístrese', +'Registration identifier': 'Identificador de Registro', +'Registration key': 'Llave de registro', +'Registration successful': 'Registro con éxito', +'reload': 'recargar', +'Remember me (for 30 days)': 'Recuérdame (durante 30 días)', +'Remove': 'Remove', +'remove compiled': 'eliminar compiladas', +'Removed': 'Eliminado', +'Rename': 'Renombrar', +'Rendition': 'Entrega', +'Renditions': 'Entregas', +'Request Reset Password': 'Pedir cambio de contraseña', +'Request reset password': 'Solicitar reinicio de contraseña', +'Reset': 'Resetear', +'Reset password': 'Reiniciar contraseña', +'Reset Password key': 'Restaurar Llave de la Contraseña', +'Resolve Conflict file': 'archivo Resolución de Conflicto', +'restore': 'restaurar', +'Retrieve username': 'Recuperar nombre de usuario', +'revert': 'revertir', +'Role': 'Rol', +'Roles': 'Roles', +'Rows in Table': 'Filas en la tabla', +'Rows selected': 'Filas seleccionadas', +'Save': 'Guardar', +'save': 'guardar', +'Save model as...': 'Guardar como...', +'Saved': 'Guardado', +'Saved file hash:': 'Hash del archivo guardado:', +'says': 'dice', +'Search': 'Buscar', +'Section': 'Sección', +'Section or page in with this item is intended to be used': 'Sección o página donde se tiene intensión de ser usado el Item', +'See': 'Ver', +'See you on eNews': 'Nos vemos en eNews', +'See you on nStock': 'See you on nStock', +'Seen': 'Visto', +'Select and upload more photos': 'Seleccionar y subir más fotos', +'Select and upload photos': 'Seleccionar y subir fotos', +'Select the first rendition of the picture': 'Seleccionar primera entrega de la fotografía.', +'Select where to push the item': 'Seleccione el escritorio a donde se va a enviar el Item', +'Semantic': 'Semántica', +'Send': 'Enviar', +'Services': 'Servicios', +'session expired': 'sesión expirada', +'Settings': 'Configuración', +'Share': 'Compartir', +'Share of %s': 'Comparticiones de %s', +'Share this item': 'Compartir este Item', +'Share with': 'Compartido con', +'shares': 'Compartido', +'Shares': '', +'Shares with': 'Compartido con', +'shell': 'terminal', +'Sign Up': 'Registrarse', +'site': 'sitio', +'Size': 'Tamaño', +'Size of cache:': 'Tamaño de la Caché:', +'Slugline': 'Slugline', +'some files could not be removed': 'algunos archivos no pudieron ser removidos', +'Spreadsheet-optimised export of tab-separated content including hidden columns. May be slow': 'Spreadsheet-optimised export of tab-separated content including hidden columns. May be slow', +'Spreadsheet-optimised export of tab-separated content, visible columns only. May be slow.': 'Spreadsheet-optimised export of tab-separated content, visible columns only. May be slow.', +'start': 'inicio', +'Start building a new search': 'Construir nueva busqueda', +'starts with': 'comienza por', +'state': 'estado', +'static': 'estáticos', +'Static files': 'Archivos estáticos', +'Statistics': 'Estadísticas', +'Status': 'Estado', +'Stylesheet': 'Hoja de estilo', +'Subject': 'Asunto', +'Submit': 'Guardar', +'submit': 'guardar', +'Success!': '¡Correcto!', +'Support': 'Soporte', +'Sure you want to delete this object?': '¿Está seguro que desea eliminar este objeto?', +'Table': 'tabla', +'Table name': 'Nombre de la tabla', +'Target language': 'Lenguage objetivo', +'test': 'probar', +'Testing application': 'Probando aplicación', +'Text': 'Texto', +'text': 'texto', +'That user is the owner of the item': 'Ese usuario es el propietario', +'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'La "consulta" es una condición como "db.tabla1.campo1==\'valor\'". Algo como "db.tabla1.campo1==db.tabla2.campo2" resulta en un JOIN SQL.', +'the application logic, each URL path is mapped in one exposed function in the controller': 'la lógica de la aplicación, cada ruta URL se mapea en una función expuesta en el controlador', +'The Core': 'El Núcleo', +'The current dashboard is empty': 'La carpeta activa esta vacia', +'the data representation, define database tables and sets': 'la representación de datos, define tablas y conjuntos de base de datos', +'The files are being uploaded, if you leave now the upload will be cancelled.': 'Los archivos están cargando, si sale ahora la carga se cancelará.', +'The group is not empty. Can not be deleted': 'El grupo no esta vacío. No pude ser borrado ', +"The organization don't have any user.": 'No hay usarios en la organización.', +'The output of the file is a dictionary that was rendered by the view %s': 'La salida de dicha función es un diccionario que es desplegado por la vista %s', +'the presentations layer, views are also known as templates': 'la capa de presentación, las vistas también son llamadas plantillas', +"The user don't exists on this system": 'El usuario no existe en el sistema', +'The user is already in the organization': 'El usuario ya es parte de la organización', +'The Views': 'Las Vistas', +'There are no controllers': 'No hay controladores', +'There are no models': 'No hay modelos', +'There are no modules': 'No hay módulos', +'There are no static files': 'No hay archivos estáticos', +'There are no translators, only default language is supported': 'No hay traductores, sólo el lenguaje por defecto es soportado', +'There are no views': 'No hay vistas', +'these files are served without processing, your images go here': 'estos archivos son servidos sin procesar, sus imágenes van aquí', +'this': 'esto', +'This App': 'Esta Aplicación', +'This email already has an account': 'Este correo electrónico ya tiene una cuenta', +'This is a copy of the scaffolding application': 'Esta es una copia de la aplicación de andamiaje', +'This is the %(filename)s template': 'Esta es la plantilla %(filename)s', +'This item is a translation': 'Este Item es una traducción', +'This item is a translation of': 'Este Item es una traducción de', +'This item is a translation of another !': 'Este Item es una traducción de otro Item !', +'This item is shared with you': 'Este item es compartido contigo', +'This item was created by you': 'Este item fue creado por ti', +'Ticket': 'Tiquete', +'Time in Cache (h:m:s)': 'Tiempo en Caché (h:m:s)', +'Timestamp': 'Marca de tiempo', +'to previous version.': 'a la versión previa.', +'To emulate a breakpoint programatically, write:': 'Emular un punto de ruptura programáticamente, escribir:', +'to use the debugger!': '¡usar el depurador!', +'To User': 'To User', +'toggle breakpoint': 'alternar punto de ruptura', +'Toggle comment': 'Alternar comentario', +'Toggle Fullscreen': 'Alternar pantalla completa', +'too short': 'demasiado corto', +'Too short': 'Muy corto', +'Toogle pin to dashboard': 'Encajar/Soltar de la carpeta', +'Tools': 'Herramientas', +'Traceback': 'Traceback', +'Translate': 'Traducir', +'Translate this item': 'Traducir', +'Translation of %s': 'Traducción de %s', +'translation strings for the application': 'cadenas de caracteres de traducción para la aplicación', +'try': 'intente', +'try something like': 'intente algo como', +'TSV (Excel compatible)': 'TSV (compatible Excel)', +'TSV (Excel compatible, hidden cols)': 'TSV (compatible Excel, columnas ocultas)', +'TSV (Spreadsheets)': 'TSV (Spreadsheets)', +'TSV (Spreadsheets, hidden cols)': 'TSV (Spreadsheets, hidden cols)', +'Twitter': 'Twitter', +'Type': 'Tipo', +'Type text to search': 'Escribir texto a buscar', +'Unable to check for upgrades': 'No es posible verificar la existencia de actualizaciones', +'unable to create application "%s"': 'no es posible crear la aplicación "%s"', +'unable to delete file "%(filename)s"': 'no es posible eliminar el archivo "%(filename)s"', +'Unable to download': 'No es posible la descarga', +'Unable to download app': 'No es posible descarga la aplicación', +'unable to parse csv file': 'no es posible analizar el archivo CSV', +'unable to uninstall "%s"': 'no es posible instalar "%s"', +'Unattach from current dashboard': 'Desacoplar del tablero actual', +'uncheck all': 'desmarcar todos', +'uninstall': 'desinstalar', +'unknown': 'desconocido', +'update': 'actualizar', +'update all languages': 'actualizar todos los lenguajes', +"Update/Manage '%s'": "Administrar '%s'", +'Update:': 'Actualice:', +'upload application:': 'subir aplicación:', +'Upload existing application': 'Suba esta aplicación', +'upload file:': 'suba archivo:', +'Upload more photos': 'Subir más fotos', +'Upload photos': 'Subir fotos', +'Upload the photos before submiting the form.': 'Subir las fotos antes de guargar el formulario', +'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Use (...)&(...) para AND, (...)|(...) para OR, y ~(...) para NOT, para crear consultas más complejas.', +'User': 'Usuario', +'User %(id)s is impersonating %(other_id)s': 'El usuario %(id)s está suplantando %(other_id)s', +'User %(id)s Logged-in': 'El usuario %(id)s inició la sesión', +'User %(id)s Logged-out': 'El usuario %(id)s finalizó la sesión', +'User %(id)s Password changed': 'Contraseña del usuario %(id)s cambiada', +'User %(id)s Password reset': 'Contraseña del usuario %(id)s reiniciada', +'User %(id)s Profile updated': 'Actualizado el perfil del usuario %(id)s', +'User %(id)s Registered': 'Usuario %(id)s Registrado', +'User %(id)s Username retrieved': 'Se ha recuperado el nombre de usuario del usuario %(id)s', +'User %(username)s Logged-in': 'El usuario %(username)s inició la sesión', +"User '%(username)s' Logged-in": "El usuario '%(username)s' inició la sesión", +"User '%(username)s' Logged-out": "El usuario '%(username)s' finalizó la sesión", +'User Id': 'Id de Usuario', +'User ID': 'ID de Usuario', +'User Logged-out': 'El usuario finalizó la sesión', +'Username': 'Nombre de usuario', +'Username retrieve': 'Recuperar nombre de usuario', +'Users': 'Usuarios', +'Value already in database or empty': 'El valor ya existe en la base de datos o está vacío', +'value not allowed': 'valor no permitido', +'Value not allowed': 'Value not allowed', +'value not in database': 'el valor no está en la base de datos', +'Verify Password': 'Verificar Contraseña', +'Version': 'Versión', +'versioning': 'versiones', +'Videos': 'Vídeos', +'View': 'Vista', +'view': 'vista', +'View %(entity)s': 'Ver %(entity)s', +'Views': 'Vistas', +'views': 'vistas', +'Warning !': '¡Aviso!', +'Warning!': '¡Aviso!', +'web2py is up to date': 'web2py está actualizado', +'web2py Recent Tweets': 'Tweets Recientes de web2py', +'Welcome': 'Bienvenido', +'Welcome %(username)s! Click on the link %(link)s to verify your email': 'Bienvenido %(username)s! Use este enlace %(link)s para verificar su dirección de correo', +'Welcome %s': 'Bienvenido %s', +'Welcome to web2py': 'Bienvenido a web2py', +'Welcome to web2py!': '¡Bienvenido a web2py!', +'Which called the function %s located in the file %s': 'La cual llamó la función %s localizada en el archivo %s', +'Width': 'Ancho', +'With': 'Con', +'With you': 'Contigo', +'Working...': 'Trabajando...', +'XML': 'XML', +'XML export of columns shown': 'XML export of columns shown', +'YES': 'SÍ', +'You are successfully running web2py': 'Usted está ejecutando web2py exitosamente', +'You can access to the translation with this link': 'Puedes acceder a la traducción con el siguiente enlace', +'You can modify this application and adapt it to your needs': 'Usted puede modificar esta aplicación y adaptarla a sus necesidades', +'You can see the changes on': 'Puedes ver los cambios en', +'You can view this or others comments to this item on': 'Puedes ver este u otros comentarios a este Item en', +"You can't push this item to any Desk": 'No puedes enviar el Item a ningún Escritorio', +"You can't push this item to any other Desk": 'No puedes enviar el Item a ningún otro Escritorio', +"You don't have access to any desk yet.": 'Todavía no tienes acceso a ningún otro Escritorio', +"You don't have or have joined to any organization": 'No te has unido a ninguna organización', +'You have unread notifications': 'Tienes notificaciones sin leer', +'You must activate some dashboard first': 'Debe activar primero una carpeta', +'You must mark some items first': 'You must mark some items first', +'You visited the url %s': 'Usted visitó la url %s', +'Your comment': 'Tú comentario', +"Your organization don't have members yet.": 'Esta organización no tiene ningún miembro todavía.', +'Your organizations': 'Tus organizaciones', +'Your username is: %(username)s': 'Su nombre de usuario es: %(username)s', +} diff --git a/nstock/languages/plural-en.py b/nstock/languages/plural-en.py new file mode 100644 index 0000000..151346a --- /dev/null +++ b/nstock/languages/plural-en.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +{ +# "singular form (0)": ["first plural form (1)", "second plural form (2)", ...], +'account': ['accounts'], +'book': ['books'], +'is': ['are'], +'man': ['men'], +'miss': ['misses'], +'person': ['people'], +'quark': ['quarks'], +'row': ['rows'], +'shop': ['shops'], +'this': ['these'], +'was': ['were'], +'woman': ['women'], +} diff --git a/nstock/languages/plural-es.py b/nstock/languages/plural-es.py new file mode 100644 index 0000000..5e3c9e1 --- /dev/null +++ b/nstock/languages/plural-es.py @@ -0,0 +1,8 @@ +# coding: utf-8 +{ +# "singular form (0)": ["first plural form (1)", "second plural form (2)", ...], +'fila': ['filas'], +'eliminada': ['eliminadas'], +'actualizada': ['actualizadas'], +'seleccionado': ['seleccionados'], +} diff --git a/nstock/models/db.py b/nstock/models/db.py new file mode 100644 index 0000000..320f5df --- /dev/null +++ b/nstock/models/db.py @@ -0,0 +1,132 @@ +# -*- coding: utf-8 -*- + +# ------------------------------------------------------------------------- +# This scaffolding model makes your app work on Google App Engine too +# File is released under public domain and you can use without limitations +# ------------------------------------------------------------------------- + +if request.global_settings.web2py_version < "2.14.1": + raise HTTP(500, "Requires web2py 2.13.3 or newer") + +# ------------------------------------------------------------------------- +# if SSL/HTTPS is properly configured and you want all HTTP requests to +# be redirected to HTTPS, uncomment the line below: +# ------------------------------------------------------------------------- +# request.requires_https() + +# ------------------------------------------------------------------------- +# app configuration made easy. Look inside private/appconfig.ini +# ------------------------------------------------------------------------- +from gluon.contrib.appconfig import AppConfig + +# ------------------------------------------------------------------------- +# once in production, remove reload=True to gain full speed +# ------------------------------------------------------------------------- +myconf = AppConfig(reload=True) + +if not request.env.web2py_runtime_gae: + # --------------------------------------------------------------------- + # if NOT running on Google App Engine use SQLite or other DB + # --------------------------------------------------------------------- + db = DAL(myconf.get('db.uri'), + pool_size=myconf.get('db.pool_size'), + migrate_enabled=myconf.get('db.migrate'), + check_reserved=['all']) +else: + # --------------------------------------------------------------------- + # connect to Google BigTable (optional 'google:datastore://namespace') + # --------------------------------------------------------------------- + db = DAL('google:datastore+ndb') + # --------------------------------------------------------------------- + # store sessions and tickets there + # --------------------------------------------------------------------- + session.connect(request, response, db=db) + # --------------------------------------------------------------------- + # or store session in Memcache, Redis, etc. + # from gluon.contrib.memdb import MEMDB + # from google.appengine.api.memcache import Client + # session.connect(request, response, db = MEMDB(Client())) + # --------------------------------------------------------------------- + +# ------------------------------------------------------------------------- +# by default give a view/generic.extension to all actions from localhost +# none otherwise. a pattern can be 'controller/function.extension' +# ------------------------------------------------------------------------- +response.generic_patterns = ['*'] if request.is_local else [] +# ------------------------------------------------------------------------- +# choose a style for forms +# ------------------------------------------------------------------------- +response.formstyle = myconf.get('forms.formstyle') # or 'bootstrap3_stacked' or 'bootstrap2' or other +response.form_label_separator = myconf.get('forms.separator') or '' + +# ------------------------------------------------------------------------- +# (optional) optimize handling of static files +# ------------------------------------------------------------------------- +# response.optimize_css = 'concat,minify,inline' +# response.optimize_js = 'concat,minify,inline' + +# ------------------------------------------------------------------------- +# (optional) static assets folder versioning +# ------------------------------------------------------------------------- +# response.static_version = '0.0.0' + +# ------------------------------------------------------------------------- +# Here is sample code if you need for +# - email capabilities +# - authentication (registration, login, logout, ... ) +# - authorization (role based authorization) +# - services (xml, csv, json, xmlrpc, jsonrpc, amf, rss) +# - old style crud actions +# (more options discussed in gluon/tools.py) +# ------------------------------------------------------------------------- + +from gluon.tools import Auth, Service, PluginManager + +# host names must be a list of allowed host names (glob syntax allowed) +auth = Auth(db, host_names=myconf.get('host.names')) +service = Service() +plugins = PluginManager() + +# ------------------------------------------------------------------------- +# create all tables needed by auth if not custom tables +# ------------------------------------------------------------------------- +auth.define_tables(username=False, signature=False) + +# ------------------------------------------------------------------------- +# configure email +# ------------------------------------------------------------------------- +mail = auth.settings.mailer +mail.settings.server = 'logging' if request.is_local else myconf.get('smtp.server') +mail.settings.sender = myconf.get('smtp.sender') +mail.settings.login = myconf.get('smtp.login') +mail.settings.tls = myconf.get('smtp.tls') or False +mail.settings.ssl = myconf.get('smtp.ssl') or False + +# ------------------------------------------------------------------------- +# configure auth policy +# ------------------------------------------------------------------------- +auth.settings.registration_requires_verification = not request.is_local +auth.settings.registration_requires_approval = False +auth.settings.reset_password_requires_verification = True + +# ------------------------------------------------------------------------- +# Define your tables below (or better in another model file) for example +# +# >>> db.define_table('mytable', Field('myfield', 'string')) +# +# Fields can be 'string','text','password','integer','double','boolean' +# 'date','time','datetime','blob','upload', 'reference TABLENAME' +# There is an implicit 'id integer autoincrement' field +# Consult manual for more options, validators, etc. +# +# More API examples for controllers: +# +# >>> db.mytable.insert(myfield='value') +# >>> rows = db(db.mytable.myfield == 'value').select(db.mytable.ALL) +# >>> for row in rows: print row.id, row.myfield +# ------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- +# after defining tables, uncomment below to enable auditing +# ------------------------------------------------------------------------- +# auth.enable_record_versioning(db) diff --git a/nstock/models/dc.py b/nstock/models/dc.py new file mode 100644 index 0000000..a84415a --- /dev/null +++ b/nstock/models/dc.py @@ -0,0 +1,219 @@ +# -*- coding: utf-8 -*- +from app import Application +from gluon.storage import Storage +from gluon import current +from slugify import slugify +import uuid + +if False: + from gluon import Field, T, IS_NOT_EMPTY, IS_IN_SET, LOAD + from db import db, auth, mail, myconf, plugins + request = current.request + + +# configure global context +def _(): + current.auth = auth + current.db = db + current.mail = mail + current.conf = myconf + # set the language with dont need translation + T.set_current_languages('en', 'en-en') +_() + +# each content plugin must register here, for example for a text plugin: +# CT_REG.text = ContentPlugin() +# +# where ContentPlugin should be the text content-type implementation of +# ContentPlugin +CT_REG = Storage() + +PUB_STATUS = ( + 'canceled', # canceled + 'usable', # usable + 'withheld', # withheld +) + + +def _get_slugline(f): + f['slugline'] = slugify(f['headline']) + + return None + + +def _update_slugline(s, f): + if 'headline' in f.keys(): + f['slugline'] = slugify(f['headline']) + + return None + + +db.define_table( + 'item', + # content metadata + Field('headline', 'string', length=512, default=''), + Field('slugline', 'string', length=512, default=''), + Field('keywords', 'list:string', default=''), + Field('located', 'string', length=200, default=''), + Field('genre', 'string', length=100, default=''), + Field('section_page', 'string', length=100, default=''), + # language of the item it self not the lenguage of the content + Field( + 'language_tag', + 'string', + default=T.accepted_language.split('-')[0], + length=2), + # item metadata + Field('provider', 'string', length=100, default=''), + Field('provider_service', 'string', default=''), + Field('pubstatus', 'string', length=10, default='usable'), + Field('embargoed', 'datetime', default=None), + auth.signature, + # copyright info. + Field('copyright_holder', 'string', length=100, default=''), + Field('copyright_url', 'string', length=512, default=''), + Field('copyright_notice', 'text', default=''), + # the item_type will be of use for searching the actions asociate with a + # item in CONTENT_TYPE_REG, it should not be readed or writed by users + # and should be writen only one, in the creation of the item. + Field('item_type', 'string', length='100', default='text'), + Field( + 'unique_id', 'string', length=64, default=uuid.uuid4(), + writable=False, readable=False + ), +) +db.item._before_insert.append(_get_slugline) +db.item._before_update.append(_update_slugline) +db.item.id.readable = False +db.item.id.writable = False +db.item.item_type.readable = False +db.item.item_type.writable = False +db.item.copyright_url.label = T('Copyright URL') +db.item.pubstatus.requires = IS_IN_SET(PUB_STATUS, zero=None) +db.item.pubstatus.label = T('Status') +db.item.headline.requires = IS_NOT_EMPTY() +db.item.headline.label = T('Headline') +db.item.headline.comment = T('Headline or descriptive title') +db.item.headline.requires = IS_NOT_EMPTY() +db.item.language_tag.label = T('Language') +db.item.keywords.label = T("Keywords") +db.item.keywords.requires = IS_NOT_EMPTY() +db.item.keywords.comment = T("One keyword per line") +db.item.section_page.label = T("Section") +db.item.section_page.comment = T( + "Section or page in with this item is intended to be used") +db.item.located.label = T("Located") +db.item.located.comment = T( + """ + It can be the name of a city or may contain details, for example: HAVANA, + CUBA""") +db.item.genre.label = T('Genre') +db.item.genre.requires = IS_NOT_EMPTY() +db.item.provider.label = T("Provider") +db.item.provider.comment = T(""" +It can be a descriptive name for the news provider or URL associated with it. +""") +db.item.provider_service.label = T("Provider service") +db.item.provider_service.comment = T(""" +Allows the provider to declare which of its services, if any, delivered +this package. +""") +db.item.copyright_notice.label = T("Copyright Notice") +db.item.copyright_holder.label = T("Copyright Holder") +db.item.embargoed.label = T('Embargoed') +db.item.embargoed.comment = T( + """ + News organisations often use an embargo to release information in advance, + on the strict understanding that it may not be released into the public + domain until after the embargo time has expired, or until some other form + of permission has been given. + """) + +db.item._enable_record_versioning() + +db.define_table( + 'languages', + Field('language_tag', 'string', length=10), + Field('english_name', 'string', length=30) +) + + +def _(): + """ + load language file into language table + """ + import os + import csv + f_name = os.path.join( + request.folder, + os.path.join('private', 'language-codes.csv')) + with open(f_name) as lang_codes: + reader = csv.DictReader(lang_codes) + for row in reader: + db.languages.insert( + language_tag=row['alpha2'], + english_name=row['English'] + ) +if db(db.languages.id > 0).count() == 0: + _() + + +def _ltag_represent(v, r): + value = db.languages(language_tag=v) + if value is not None: + return value.english_name + + return v +db.item.language_tag.represent = _ltag_represent + + +# notification center +def _(): + tbl = db.define_table( + 'notification', + Field('subject', 'string', length=500), + Field('message_content', 'text'), + Field('from_user', 'reference auth_user'), + Field('to_user', 'reference auth_user'), + Field('seen', 'boolean', default=False), + Field('msg_date', 'datetime', default=request.now) + ) + tbl.subject.label = T('Subject') + tbl.message_content.label = T('Message') + tbl.from_user.label = T('From') + tbl.msg_date.label = T('Date and Time') + tbl.seen.label = T('Seen') + tbl.to_user.readable = False + tbl.id.readable = False +_() + + +# orgs are going here +def _(): + # don't polute globals() + tbl = db.define_table( + 'desk', + Field('name', 'string', length=100), + Field('item_list', 'list:reference item', default=[]) + ) + tbl.name.label = T('Name') + tbl.item_list.readable = False + + tbl = db.define_table( + 'organization', + Field('name', 'string', length=100), + Field('description', 'text'), + Field('users', 'list:reference auth_user', default=[]), + Field('desks', 'list:reference desk', default=[]) + ) + tbl.name.label = T('Name') + tbl.description.label = T('Description') + tbl.users.label = T('Users') +_() + +# register content type plugins +application = Application() +plugins.text.app = application +plugins.picture.app = application +plugins.photoset.app = application +plugins.package.app = application diff --git a/nstock/models/desk/z_menu.py b/nstock/models/desk/z_menu.py new file mode 100644 index 0000000..4cd80f0 --- /dev/null +++ b/nstock/models/desk/z_menu.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +if False: + from gluon import current + response = current.response + request = current.request + T = current.T + from dc import application + from db import auth + + +def _(): + # add items menu + create_items = [] + registry = application.registry + for content_type in registry: + url, title = registry[content_type].create_item_url() + create_items.append( + (title, False, url, []) + ) + response.menu += [(T('Add Items'), False, "#", create_items)] + +if auth.user: + _() diff --git a/nstock/models/menu.py b/nstock/models/menu.py new file mode 100644 index 0000000..b91aa70 --- /dev/null +++ b/nstock/models/menu.py @@ -0,0 +1,178 @@ +# -*- coding: utf-8 -*- +# this file is released under public domain and you can use without limitations + +# ---------------------------------------------------------------------------------------------------------------------- +# Customize your APP title, subtitle and menus here +# ---------------------------------------------------------------------------------------------------------------------- + +response.logo = A('nStock', + _class="navbar-brand", _href=URL('default', 'index'), + _id="web2py-logo") +response.title = request.application.replace('_', ' ').title() +response.subtitle = '' + +# ---------------------------------------------------------------------------------------------------------------------- +# read more at http://dev.w3.org/html5/markup/meta.name.html +# ---------------------------------------------------------------------------------------------------------------------- +response.meta.author = myconf.get('app.author') +response.meta.description = myconf.get('app.description') +response.meta.keywords = myconf.get('app.keywords') +response.meta.generator = myconf.get('app.generator') + +# ---------------------------------------------------------------------------------------------------------------------- +# your http://google.com/analytics id +# ---------------------------------------------------------------------------------------------------------------------- +response.google_analytics_id = None + +# ---------------------------------------------------------------------------------------------------------------------- +# this is the main application menu add/remove items as required +# ---------------------------------------------------------------------------------------------------------------------- +response.menu = [] + + +# prepare dashboard menu +def _(): + query = (db.dashboard.id > 0) + query &= (db.dashboard.created_by == auth.user.id) + dash_list = db(query).select(db.dashboard.ALL) + + if not dash_list: + # make a new dashboard + name = T('My Dashboard', lazy=False) + d_id = db.dashboard.insert( + name=name, item_list=[]) + query = (db.dashboard.id > 0) + query &= (db.dashboard.created_by == auth.user.id) + dash_list = db(query).select(db.dashboard.ALL) + auth.add_permission(0, 'owner', db.dashboard, d_id) + + submenu = [] + submenu.append(("CAST", False, URL('default', 'index'), [])) + for dash in dash_list: + submenu.append( + (dash.name, False, URL('dashboard', 'index', args=[dash.id]), []) + ) + response.menu += [ + (T("Dashboard's"), False, URL('default', 'index'), submenu) + ] +if auth.user: + #_() + pass + +DEVELOPMENT_MENU = False + + +# ---------------------------------------------------------------------------------------------------------------------- +# provide shortcuts for development. remove in production +# ---------------------------------------------------------------------------------------------------------------------- + +def _(): + # ------------------------------------------------------------------------------------------------------------------ + # shortcuts + # ------------------------------------------------------------------------------------------------------------------ + app = request.application + ctr = request.controller + # ------------------------------------------------------------------------------------------------------------------ + # useful links to internal and external resources + # ------------------------------------------------------------------------------------------------------------------ + response.menu += [ + (T('My Sites'), False, URL('admin', 'default', 'site')), + (T('This App'), False, '#', [ + (T('Design'), False, URL('admin', 'default', 'design/%s' % app)), + LI(_class="divider"), + (T('Controller'), False, + URL( + 'admin', 'default', 'edit/%s/controllers/%s.py' % (app, ctr))), + (T('View'), False, + URL( + 'admin', 'default', 'edit/%s/views/%s' % (app, response.view))), + (T('DB Model'), False, + URL( + 'admin', 'default', 'edit/%s/models/db.py' % app)), + (T('Menu Model'), False, + URL( + 'admin', 'default', 'edit/%s/models/menu.py' % app)), + (T('Config.ini'), False, + URL( + 'admin', 'default', 'edit/%s/private/appconfig.ini' % app)), + (T('Layout'), False, + URL( + 'admin', 'default', 'edit/%s/views/layout.html' % app)), + (T('Stylesheet'), False, + URL( + 'admin', 'default', 'edit/%s/static/css/web2py-bootstrap3.css' % app)), + (T('Database'), False, URL(app, 'appadmin', 'index')), + (T('Errors'), False, URL( + 'admin', 'default', 'errors/' + app)), + (T('About'), False, URL( + 'admin', 'default', 'about/' + app)), + ]), + ('web2py.com', False, '#', [ + (T('Download'), False, + 'http://www.web2py.com/examples/default/download'), + (T('Support'), False, + 'http://www.web2py.com/examples/default/support'), + (T('Demo'), False, 'http://web2py.com/demo_admin'), + (T('Quick Examples'), False, + 'http://web2py.com/examples/default/examples'), + (T('FAQ'), False, 'http://web2py.com/AlterEgo'), + (T('Videos'), False, + 'http://www.web2py.com/examples/default/videos/'), + (T('Free Applications'), + False, 'http://web2py.com/appliances'), + (T('Plugins'), False, 'http://web2py.com/plugins'), + (T('Recipes'), False, 'http://web2pyslices.com/'), + ]), + (T('Documentation'), False, '#', [ + (T('Online book'), False, 'http://www.web2py.com/book'), + LI(_class="divider"), + (T('Preface'), False, + 'http://www.web2py.com/book/default/chapter/00'), + (T('Introduction'), False, + 'http://www.web2py.com/book/default/chapter/01'), + (T('Python'), False, + 'http://www.web2py.com/book/default/chapter/02'), + (T('Overview'), False, + 'http://www.web2py.com/book/default/chapter/03'), + (T('The Core'), False, + 'http://www.web2py.com/book/default/chapter/04'), + (T('The Views'), False, + 'http://www.web2py.com/book/default/chapter/05'), + (T('Database'), False, + 'http://www.web2py.com/book/default/chapter/06'), + (T('Forms and Validators'), False, + 'http://www.web2py.com/book/default/chapter/07'), + (T('Email and SMS'), False, + 'http://www.web2py.com/book/default/chapter/08'), + (T('Access Control'), False, + 'http://www.web2py.com/book/default/chapter/09'), + (T('Services'), False, + 'http://www.web2py.com/book/default/chapter/10'), + (T('Ajax Recipes'), False, + 'http://www.web2py.com/book/default/chapter/11'), + (T('Components and Plugins'), False, + 'http://www.web2py.com/book/default/chapter/12'), + (T('Deployment Recipes'), False, + 'http://www.web2py.com/book/default/chapter/13'), + (T('Other Recipes'), False, + 'http://www.web2py.com/book/default/chapter/14'), + (T('Helping web2py'), False, + 'http://www.web2py.com/book/default/chapter/15'), + (T("Buy web2py's book"), False, + 'http://stores.lulu.com/web2py'), + ]), + (T('Community'), False, None, [ + (T('Groups'), False, + 'http://www.web2py.com/examples/default/usergroups'), + (T('Twitter'), False, 'http://twitter.com/web2py'), + (T('Live Chat'), False, + 'http://webchat.freenode.net/?channels=web2py'), + ]), + ] + + +if DEVELOPMENT_MENU: + _() + +if "auth" in locals(): + auth.wikimenu() diff --git a/nstock/models/plugin_comment.py b/nstock/models/plugin_comment.py new file mode 100644 index 0000000..c31d463 --- /dev/null +++ b/nstock/models/plugin_comment.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +if False: + from gluon import Field, LOAD, IS_NOT_EMPTY + from gluon import current + T = current.T + from db import db, auth +""" +Define the tables for the editorials commentary system +""" + + +def _(): + tbl = db.define_table( + 'plugin_comment_comment', + Field('body', 'text', label=T('Your comment')), + Field('item_id', 'string', length=64), + auth.signature, + ) + tbl.item_id.readable = False + tbl.item_id.writable = False + tbl.body.requires = IS_NOT_EMPTY() + + return lambda item_id: LOAD( + 'plugin_comment', 'index.load', args=[item_id], ajax=True) + +plugin_comment = _() + + +def _(): + return lambda item_id: LOAD( + 'plugin_comment', + 'index.load', + args=[item_id], + vars=dict(short=True), + ajax=True) +plugin_comment_short = _() diff --git a/nstock/models/plugin_package.py b/nstock/models/plugin_package.py new file mode 100644 index 0000000..d44717d --- /dev/null +++ b/nstock/models/plugin_package.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- + +from plugin_package.content_package import ContentPackage +from gluon.tools import PluginManager +from plugin_ckeditor import CKEditor + +if False: + from gluon import current + from gluon import Field + response = current.response + request = current.request + T = current.T + from db import db, auth + + +def _(): + plugins = PluginManager('package', app=None) + if plugins.package.app is not None: + # this will register the the application on content/type + plugins.package.app.registerContentType('package', ContentPackage()) + + if not hasattr(db, 'plugin_package_content'): + editor = CKEditor(db=db) + tbl = db.define_table( + 'plugin_package_content', + Field('item_list', 'list:string'), + Field('description', 'text'), + Field('item_id', 'string', length=64), + auth.signature, + ) + tbl.item_id.writable = False + tbl.item_id.readable = False + tbl.item_list.writable = False + tbl.item_list.readable = False + tbl.description.label = T('Description') + tbl.description.widget = editor.widget + tbl._enable_record_versioning() + +_() diff --git a/nstock/models/plugin_photoset.py b/nstock/models/plugin_photoset.py new file mode 100644 index 0000000..b7862ee --- /dev/null +++ b/nstock/models/plugin_photoset.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +from plugin_photoset.content_photoset import ContentPhotoset +from gluon.tools import PluginManager +from plugin_ckeditor import CKEditor + +if False: + from gluon import current, Field + response = current.response + request = current.request + T = current.T + from db import db, auth + + +def _(): + plugins = PluginManager('photoset', app=None) + if plugins.photoset.app is not None: + plugins.photoset.app.registerContentType('photoset', ContentPhotoset()) + editor = CKEditor(db=db) + if not hasattr(db, 'plugin_photoset_photo'): + db.define_table( + 'plugin_photoset_photo', + Field( + 'thumbnail', 'upload', + uploadseparate=True, + autodelete=True, + default=None + ), + Field( + 'picture', 'upload', + uploadseparate=True, + autodelete=True + ), + ) + + if not hasattr(db, 'plugin_photoset_content'): + tbl = db.define_table( + 'plugin_photoset_content', + Field('credit_line', 'string', length=250, default=''), + Field( + 'description', 'text', + label=T('Description'), + default='' + ), + Field('photoset', 'list:reference plugin_photoset_photo'), + Field('item_id', 'string', length=64), + auth.signature, + ) + tbl.credit_line.label = T("Credit line") + tbl.description.label = T('Description') + tbl.description.widget = editor.widget + tbl._enable_record_versioning() +_() diff --git a/nstock/models/plugin_picture.py b/nstock/models/plugin_picture.py new file mode 100644 index 0000000..4ea97a9 --- /dev/null +++ b/nstock/models/plugin_picture.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- + +from plugin_picture.content_picture import ContentPicture +from gluon.tools import PluginManager +from plugin_ckeditor import CKEditor + +if False: + from gluon import current + from gluon import Field, IS_NOT_EMPTY, IS_IMAGE + response = current.response + request = current.request + T = current.T + from db import db, auth + + +def _(): + plugins = PluginManager('picture', app=None) + # this will register the content/type on the application + if plugins.picture.app is not None: + editor = CKEditor(db=db) + plugins.picture.app.registerContentType('picture', ContentPicture()) + if not hasattr(db, 'plugin_picture_rendition'): + tbl = db.define_table( + 'plugin_picture_rendition', + Field( + 'picture', 'upload', uploadseparate=True, autodelete=True + ), + Field('purpose', 'string', length=50, default='raw'), + Field( + 'height', 'integer', default=0, readable=False, + writable=False + ), + Field( + 'width', 'integer', default=0, readable=False, + writable=False + ), + Field( + 'color', 'string', length=20, readable=False, + writable=False + ), + Field( + 'format', 'string', length=10, readable=False, + writable=False + ) + ) + tbl.purpose.comment = T(''' + It may contain any value but it is recommended to use one of the + values: raw, web, thumbnail, print + ''') + tbl.purpose.label = T('Purpose') + tbl.height.label = T('Height') + tbl.width.label = T('Width') + tbl.color.label = T('Color space') + tbl.format.label = T('Format') + tbl.format.comment = T('Automatic form PIL') + tbl.picture.label = T('Picture') + tbl.picture.requires = [IS_IMAGE(), IS_NOT_EMPTY()] + + if not hasattr(db, 'plugin_picture_info'): + # definimos la BD + tbl = db.define_table( + 'plugin_picture_info', + Field('credit_line', 'string', length=250, default=''), + Field( + 'description', 'text', + label=T('Description'), + default='' + ), + Field( + 'caption', 'string', + length=250, + default='' + ), + Field( + 'thumbnail', 'upload', + uploadseparate=True, + autodelete=True, + default=None + ), + Field('renditions', 'list:reference plugin_picture_rendition'), + Field('item_id', 'string', length=64), + auth.signature, + ) + tbl.credit_line.label = T("Credit line") + tbl.description.label = T('Description') + tbl.description.widget = editor.widget + tbl.caption.label = T("Caption") + tbl.renditions.label = T("Renditions") + tbl.item_id.readable = False + tbl.item_id.writable = False + + # enable record versioning + tbl._enable_record_versioning() + + return +_() diff --git a/nstock/models/plugin_text.py b/nstock/models/plugin_text.py new file mode 100644 index 0000000..8190a08 --- /dev/null +++ b/nstock/models/plugin_text.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +from plugin_text.content_text import ContentText +from plugin_ckeditor import CKEditor +from gluon import Field, IS_NOT_EMPTY +from gluon.tools import PluginManager + +if False: + from gluon import current + response = current.response + request = current.request + T = current.T + from db import db, auth + + +# define tables of this plugin +def _(): + plugins = PluginManager('text', app=None) + if plugins.text.app is not None: + # this will register the content/type on the application + plugins.text.app.registerContentType('text', ContentText()) + if not hasattr(db, 'plugin_text_text'): + # configure ckeditor + editor = CKEditor(db=db) + # definimos la BD + tbl = db.define_table( + 'plugin_text_text', + Field('byline', 'string', length=250, default=''), + Field('body', 'text', label=T('Content')), + Field('item_id', 'string', length=64), + auth.signature, + ) + tbl.byline.label = T('By line') + tbl.item_id.readable = False + tbl.item_id.writable = False + tbl.body.requires = IS_NOT_EMPTY() + tbl.body.widget = editor.widget + + # enable record versioning + tbl._enable_record_versioning() + + return +_() diff --git a/nstock/modules/__init__.py b/nstock/modules/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/nstock/modules/__init__.py @@ -0,0 +1 @@ + diff --git a/nstock/modules/app.py b/nstock/modules/app.py new file mode 100644 index 0000000..69527b0 --- /dev/null +++ b/nstock/modules/app.py @@ -0,0 +1,212 @@ +# coding: utf-8 +from content_plugin import ContentPlugin +from z_whoosh import Whoosh +from gluon import current, URL +from gluon.storage import Storage +from gluon.cache import Cache +import perms + + +class Application(object): + + def __init__(self): + super(Application, self).__init__() + + # copy current context + self.db = current.db + self.T = current.T + self.auth = current.auth + self.request = current.request + self.response = current.response + self.session = current.session + self.mail = current.mail + self.conf = current.conf + self.registry = Storage() + self.cache = Cache(self.request) + + def registerContentType(self, item_type, plug): + """ + Register a ContentPlugin for an Item Type + """ + assert isinstance(plug, ContentPlugin) + + self.registry[item_type] = plug + plug.setController(self) + + def getContentType(self, item_type): + return self.registry[item_type] + + def getItemByUUID(self, unique_id): + db = self.db + query = (db.item.unique_id == unique_id) + item = db(query).select().first() + return item + + def canUpdateItem(self, unique_id, user=None): + item = self.getItemByUUID(unique_id) + desk = self.db( + self.db.desk.item_list.contains(item.id)).select().first() + is_owner = self.isOwner(unique_id, user=user) and ( + desk.id == self.getUserDesk().id) + can_update_desk = self.auth.has_permission( + 'update_items', self.db.desk, desk.id) or self.auth.has_permission( + 'owner', self.db.desk, desk.id) or self.auth.has_permission( + 'update', self.db.desk, desk.id) + + return (is_owner or can_update_desk) and (item.id in desk.item_list) + + def canReadItem(self, unique_id, user=None): + item = self.getItemByUUID(unique_id) + desk = self.db( + self.db.desk.item_list.contains(item.id)).select().first() + can_read_desk = self.auth.has_permission( + 'read', self.db.desk, desk.id) or self.auth.has_permission( + 'owner', self.db.desk, desk.id) or self.auth.has_permission( + 'update', self.db.desk, desk.id) + + return can_read_desk and (item.id in desk.item_list) + + def isOwner(self, unique_id, user=None): + """ + Returns True if user is the owner of the item + """ + item = self.getItemByUUID(unique_id) + + if item is None: + return False + + if user is None: + return perms.isOwner(item.id) + + return self.auth.has_permission( + 'owner', self.db.item, record_id=item.id, user_id=user.id) + + def getUserDesk(self, user=None): + db = self.db + auth = self.auth + if user is None: + user = auth.user + + # setup user desk if necessary. + user_desk = db( + auth.accessible_query('owner', db.desk, user.id)).select().first() + if user_desk is None: + name = self.T("%s desk", (auth.user.first_name,)) + desk_id = db.desk.insert(name=name) + g_id = auth.user_group(auth.user.id) + auth.add_permission(g_id, 'owner', db.desk, desk_id) + user_desk = db.desk(desk_id) + + return user_desk + + def indexItem(self, item_id, user=None): + """ + Add/update item to the user search index + """ + if user is None: + user = self.auth.user + item = self.getItemByUUID(item_id) + ct = self.getContentType(item.item_type) + text = ct.get_full_text(item) + w = Whoosh(str(user.id)) + w.add_to_index(unicode(item_id), text) + + def createItem(self, content_type, values): + db = self.db + auth = self.auth + values['item_type'] = content_type + + item_id = db.item.insert(**db.item._filter_fields(values)) + # give owner perm to the item + auth.add_permission(0, 'owner', db.item, item_id) + # add the item to the user desk + user_desk = self.getUserDesk() + item_list = user_desk.item_list + item_list.insert(0, item_id) + user_desk.update_record(item_list=item_list) + # -- + return db.item(item_id).unique_id + + def getItemURL(self, unique_id): + item = self.getItemByUUID(unique_id) + c = "plugin_{}".format(item.item_type) + f = "index.html" + return URL(c=c, f=f, args=[item.unique_id]) + + def getContentChangesURL(self, unique_id): + item = self.getItemByUUID(unique_id) + c = "plugin_{}".format(item.item_type) + f = "changelog.html" + return URL(c=c, f=f, args=[item.unique_id]) + + def notifyChanges(self, item_id): + response = self.response + auth = self.auth + T = self.T + item = self.getItemByUUID(item_id) + + message = response.render( + 'changes_email.txt', + dict(item=item, user=auth.user) + ) + subject = T("Changes on %s") % (item.headline,) + + self.notifyCollaborators( + item.unique_id, + subject, + message + ) + + def getCollaborators(self, item_id, exclude_current=True): + """ + Given a item returns the list of user who have access to item. + """ + db = self.db + auth = self.auth + item = self.getItemByUUID(item_id) + desk = self.db( + self.db.desk.item_list.contains(item.id)).select().first() + + query = (db.auth_permission.record_id == desk.id) + query &= (db.auth_permission.name != 'push_items') + query &= (db.auth_permission.table_name == db.desk) + query &= (db.auth_permission.group_id == db.auth_membership.group_id) + query &= (db.auth_user.id == db.auth_membership.user_id) + if exclude_current: + query &= (db.auth_user.id != auth.user.id) + return db(query).select( + db.auth_user.ALL, + distinct=True, + cache=(self.cache.ram, 30), + cacheable=True) + + def notifyCollaborators(self, item_id, subject, message): + db = self.db + auth = self.auth + item = self.getItemByUUID(item_id) + + myusers = self.getCollaborators(item.unique_id) + for u in myusers: + db.notification.insert( + subject=subject, + message_content=message, + from_user=auth.user.id, + to_user=u.id + ) + + def shareItem(self, item_id, src_desk, dst_desk): + """ + Move item_id from src_desk to dst_desk + """ + item = self.getItemByUUID(item_id) + src = self.db.desk(src_desk) + dst = self.db.desk(dst_desk) + src_list = src.item_list + src_list.remove(item.id) + src.update_record(item_list=src_list) + dst_list = dst.item_list + dst_list.insert(0, item.id) + dst.update_record(item_list=dst_list) + self.notifyChanges(item_id) + + return diff --git a/nstock/modules/content_plugin.py b/nstock/modules/content_plugin.py new file mode 100644 index 0000000..f325411 --- /dev/null +++ b/nstock/modules/content_plugin.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- + + +class ContentPlugin(object): + + def __init__(self): + super(ContentPlugin, self).__init__() + self.configured = False + + def setController(self, app): + self.app = app + self.T = app.T + self.db = app.db + self.response = app.response + self.request = app.request + self.auth = app.auth + self.mail = app.mail + self.configured = True + + def get_item_url(self, item): + raise NotImplementedError + + def preview(self, item): + """ + Show the item preview on list's or in packages. + """ + return '' + + def create_item_url(self): + """ + Return a tuple in with the first element is the link to create a new + item of this Content-Type and the second is the text to use as title. + """ + raise NotImplementedError + + def get_changelog_url(self, item): + return None + + def get_full_text(self, item): + """Return full text document, mean for plugins""" + raise NotImplementedError + + def shareItem(self, item_id, src_desk, dst_desk): + """Share item with user, given the perms""" + self.app.shareItem(item_id, src_desk, dst_desk) + # some content plugins may whant to do some stuff before or after + # sharing an item. For example package-type items. Remember call + # super. diff --git a/nstock/modules/html2text.py b/nstock/modules/html2text.py new file mode 100644 index 0000000..1752890 --- /dev/null +++ b/nstock/modules/html2text.py @@ -0,0 +1,914 @@ +#!/usr/bin/env python +"""html2text: Turn HTML into equivalent Markdown-structured text.""" +__version__ = "3.200.3" +__author__ = "Aaron Swartz (me@aaronsw.com)" +__copyright__ = "(C) 2004-2008 Aaron Swartz. GNU GPL 3." +__contributors__ = ["Martin 'Joey' Schulze", "Ricardo Reyes", "Kevin Jay North"] + +# TODO: +# Support decoded entities with unifiable. + +try: + True +except NameError: + setattr(__builtins__, 'True', 1) + setattr(__builtins__, 'False', 0) + +def has_key(x, y): + if hasattr(x, 'has_key'): return x.has_key(y) + else: return y in x + +try: + import htmlentitydefs + import urlparse + import HTMLParser +except ImportError: #Python3 + import html.entities as htmlentitydefs + import urllib.parse as urlparse + import html.parser as HTMLParser +try: #Python3 + import urllib.request as urllib +except: + import urllib +import optparse, re, sys, codecs, types + +try: from textwrap import wrap +except: pass + +# Use Unicode characters instead of their ascii psuedo-replacements +UNICODE_SNOB = 0 + +# Escape all special characters. Output is less readable, but avoids corner case formatting issues. +ESCAPE_SNOB = 0 + +# Put the links after each paragraph instead of at the end. +LINKS_EACH_PARAGRAPH = 0 + +# Wrap long lines at position. 0 for no wrapping. (Requires Python 2.3.) +BODY_WIDTH = 78 + +# Don't show internal links (href="#local-anchor") -- corresponding link targets +# won't be visible in the plain text file anyway. +SKIP_INTERNAL_LINKS = True + +# Use inline, rather than reference, formatting for images and links +INLINE_LINKS = True + +# Number of pixels Google indents nested lists +GOOGLE_LIST_INDENT = 36 + +IGNORE_ANCHORS = False +IGNORE_IMAGES = False +IGNORE_EMPHASIS = False + +### Entity Nonsense ### + +def name2cp(k): + if k == 'apos': return ord("'") + if hasattr(htmlentitydefs, "name2codepoint"): # requires Python 2.3 + return htmlentitydefs.name2codepoint[k] + else: + k = htmlentitydefs.entitydefs[k] + if k.startswith("&#") and k.endswith(";"): return int(k[2:-1]) # not in latin-1 + return ord(codecs.latin_1_decode(k)[0]) + +unifiable = {'rsquo':"'", 'lsquo':"'", 'rdquo':'"', 'ldquo':'"', +'copy':'(C)', 'mdash':'--', 'nbsp':' ', 'rarr':'->', 'larr':'<-', 'middot':'*', +'ndash':'-', 'oelig':'oe', 'aelig':'ae', +'agrave':'a', 'aacute':'a', 'acirc':'a', 'atilde':'a', 'auml':'a', 'aring':'a', +'egrave':'e', 'eacute':'e', 'ecirc':'e', 'euml':'e', +'igrave':'i', 'iacute':'i', 'icirc':'i', 'iuml':'i', +'ograve':'o', 'oacute':'o', 'ocirc':'o', 'otilde':'o', 'ouml':'o', +'ugrave':'u', 'uacute':'u', 'ucirc':'u', 'uuml':'u', +'lrm':'', 'rlm':''} + +unifiable_n = {} + +for k in unifiable.keys(): + unifiable_n[name2cp(k)] = unifiable[k] + +### End Entity Nonsense ### + +def onlywhite(line): + """Return true if the line does only consist of whitespace characters.""" + for c in line: + if c is not ' ' and c is not ' ': + return c is ' ' + return line + +def hn(tag): + if tag[0] == 'h' and len(tag) == 2: + try: + n = int(tag[1]) + if n in range(1, 10): return n + except ValueError: return 0 + +def dumb_property_dict(style): + """returns a hash of css attributes""" + return dict([(x.strip(), y.strip()) for x, y in [z.split(':', 1) for z in style.split(';') if ':' in z]]); + +def dumb_css_parser(data): + """returns a hash of css selectors, each of which contains a hash of css attributes""" + # remove @import sentences + data += ';' + importIndex = data.find('@import') + while importIndex != -1: + data = data[0:importIndex] + data[data.find(';', importIndex) + 1:] + importIndex = data.find('@import') + + # parse the css. reverted from dictionary compehension in order to support older pythons + elements = [x.split('{') for x in data.split('}') if '{' in x.strip()] + try: + elements = dict([(a.strip(), dumb_property_dict(b)) for a, b in elements]) + except ValueError: + elements = {} # not that important + + return elements + +def element_style(attrs, style_def, parent_style): + """returns a hash of the 'final' style attributes of the element""" + style = parent_style.copy() + if 'class' in attrs: + for css_class in attrs['class'].split(): + css_style = style_def['.' + css_class] + style.update(css_style) + if 'style' in attrs: + immediate_style = dumb_property_dict(attrs['style']) + style.update(immediate_style) + return style + +def google_list_style(style): + """finds out whether this is an ordered or unordered list""" + if 'list-style-type' in style: + list_style = style['list-style-type'] + if list_style in ['disc', 'circle', 'square', 'none']: + return 'ul' + return 'ol' + +def google_has_height(style): + """check if the style of the element has the 'height' attribute explicitly defined""" + if 'height' in style: + return True + return False + +def google_text_emphasis(style): + """return a list of all emphasis modifiers of the element""" + emphasis = [] + if 'text-decoration' in style: + emphasis.append(style['text-decoration']) + if 'font-style' in style: + emphasis.append(style['font-style']) + if 'font-weight' in style: + emphasis.append(style['font-weight']) + return emphasis + +def google_fixed_width_font(style): + """check if the css of the current element defines a fixed width font""" + font_family = '' + if 'font-family' in style: + font_family = style['font-family'] + if 'Courier New' == font_family or 'Consolas' == font_family: + return True + return False + +def list_numbering_start(attrs): + """extract numbering from list element attributes""" + if 'start' in attrs: + return int(attrs['start']) - 1 + else: + return 0 + +class HTML2Text(HTMLParser.HTMLParser): + def __init__(self, out=None, baseurl=''): + HTMLParser.HTMLParser.__init__(self) + + # Config options + self.unicode_snob = UNICODE_SNOB + self.escape_snob = ESCAPE_SNOB + self.links_each_paragraph = LINKS_EACH_PARAGRAPH + self.body_width = BODY_WIDTH + self.skip_internal_links = SKIP_INTERNAL_LINKS + self.inline_links = INLINE_LINKS + self.google_list_indent = GOOGLE_LIST_INDENT + self.ignore_links = IGNORE_ANCHORS + self.ignore_images = IGNORE_IMAGES + self.ignore_emphasis = IGNORE_EMPHASIS + self.google_doc = False + self.ul_item_mark = '*' + self.emphasis_mark = '_' + self.strong_mark = '**' + + if out is None: + self.out = self.outtextf + else: + self.out = out + + self.outtextlist = [] # empty list to store output characters before they are "joined" + + try: + self.outtext = unicode() + except NameError: # Python3 + self.outtext = str() + + self.quiet = 0 + self.p_p = 0 # number of newline character to print before next output + self.outcount = 0 + self.start = 1 + self.space = 0 + self.a = [] + self.astack = [] + self.maybe_automatic_link = None + self.absolute_url_matcher = re.compile(r'^[a-zA-Z+]+://') + self.acount = 0 + self.list = [] + self.blockquote = 0 + self.pre = 0 + self.startpre = 0 + self.code = False + self.br_toggle = '' + self.lastWasNL = 0 + self.lastWasList = False + self.style = 0 + self.style_def = {} + self.tag_stack = [] + self.emphasis = 0 + self.drop_white_space = 0 + self.inheader = False + self.abbr_title = None # current abbreviation definition + self.abbr_data = None # last inner HTML (for abbr being defined) + self.abbr_list = {} # stack of abbreviations to write later + self.baseurl = baseurl + + try: del unifiable_n[name2cp('nbsp')] + except KeyError: pass + unifiable['nbsp'] = ' _place_holder;' + + + def feed(self, data): + data = data.replace("", "") + HTMLParser.HTMLParser.feed(self, data) + + def handle(self, data): + self.feed(data) + self.feed("") + return self.optwrap(self.close()) + + def outtextf(self, s): + self.outtextlist.append(s) + if s: self.lastWasNL = s[-1] == '\n' + + def close(self): + HTMLParser.HTMLParser.close(self) + + self.pbr() + self.o('', 0, 'end') + + self.outtext = self.outtext.join(self.outtextlist) + if self.unicode_snob: + nbsp = unichr(name2cp('nbsp')) + else: + nbsp = u' ' + self.outtext = self.outtext.replace(u' _place_holder;', nbsp) + + return self.outtext + + def handle_charref(self, c): + self.o(self.charref(c), 1) + + def handle_entityref(self, c): + self.o(self.entityref(c), 1) + + def handle_starttag(self, tag, attrs): + self.handle_tag(tag, attrs, 1) + + def handle_endtag(self, tag): + self.handle_tag(tag, None, 0) + + def previousIndex(self, attrs): + """ returns the index of certain set of attributes (of a link) in the + self.a list + + If the set of attributes is not found, returns None + """ + if not has_key(attrs, 'href'): return None + + i = -1 + for a in self.a: + i += 1 + match = 0 + + if has_key(a, 'href') and a['href'] == attrs['href']: + if has_key(a, 'title') or has_key(attrs, 'title'): + if (has_key(a, 'title') and has_key(attrs, 'title') and + a['title'] == attrs['title']): + match = True + else: + match = True + + if match: return i + + def drop_last(self, nLetters): + if not self.quiet: + self.outtext = self.outtext[:-nLetters] + + def handle_emphasis(self, start, tag_style, parent_style): + """handles various text emphases""" + tag_emphasis = google_text_emphasis(tag_style) + parent_emphasis = google_text_emphasis(parent_style) + + # handle Google's text emphasis + strikethrough = 'line-through' in tag_emphasis and self.hide_strikethrough + bold = 'bold' in tag_emphasis and not 'bold' in parent_emphasis + italic = 'italic' in tag_emphasis and not 'italic' in parent_emphasis + fixed = google_fixed_width_font(tag_style) and not \ + google_fixed_width_font(parent_style) and not self.pre + + if start: + # crossed-out text must be handled before other attributes + # in order not to output qualifiers unnecessarily + if bold or italic or fixed: + self.emphasis += 1 + if strikethrough: + self.quiet += 1 + if italic: + self.o(self.emphasis_mark) + self.drop_white_space += 1 + if bold: + self.o(self.strong_mark) + self.drop_white_space += 1 + if fixed: + self.o('`') + self.drop_white_space += 1 + self.code = True + else: + if bold or italic or fixed: + # there must not be whitespace before closing emphasis mark + self.emphasis -= 1 + self.space = 0 + self.outtext = self.outtext.rstrip() + if fixed: + if self.drop_white_space: + # empty emphasis, drop it + self.drop_last(1) + self.drop_white_space -= 1 + else: + self.o('`') + self.code = False + if bold: + if self.drop_white_space: + # empty emphasis, drop it + self.drop_last(2) + self.drop_white_space -= 1 + else: + self.o(self.strong_mark) + if italic: + if self.drop_white_space: + # empty emphasis, drop it + self.drop_last(1) + self.drop_white_space -= 1 + else: + self.o(self.emphasis_mark) + # space is only allowed after *all* emphasis marks + if (bold or italic) and not self.emphasis: + self.o(" ") + if strikethrough: + self.quiet -= 1 + + def handle_tag(self, tag, attrs, start): + #attrs = fixattrs(attrs) + if attrs is None: + attrs = {} + else: + attrs = dict(attrs) + + if self.google_doc: + # the attrs parameter is empty for a closing tag. in addition, we + # need the attributes of the parent nodes in order to get a + # complete style description for the current element. we assume + # that google docs export well formed html. + parent_style = {} + if start: + if self.tag_stack: + parent_style = self.tag_stack[-1][2] + tag_style = element_style(attrs, self.style_def, parent_style) + self.tag_stack.append((tag, attrs, tag_style)) + else: + dummy, attrs, tag_style = self.tag_stack.pop() + if self.tag_stack: + parent_style = self.tag_stack[-1][2] + + if hn(tag): + self.p() + if start: + self.inheader = True + self.o(hn(tag)*"#" + ' ') + else: + self.inheader = False + return # prevent redundant emphasis marks on headers + + if tag in ['p', 'div']: + if self.google_doc: + if start and google_has_height(tag_style): + self.p() + else: + self.soft_br() + else: + self.p() + + if tag == "br" and start: self.o(" \n") + + if tag == "hr" and start: + self.p() + self.o("* * *") + self.p() + + if tag in ["head", "style", 'script']: + if start: self.quiet += 1 + else: self.quiet -= 1 + + if tag == "style": + if start: self.style += 1 + else: self.style -= 1 + + if tag in ["body"]: + self.quiet = 0 # sites like 9rules.com never close + + if tag == "blockquote": + if start: + self.p(); self.o('> ', 0, 1); self.start = 1 + self.blockquote += 1 + else: + self.blockquote -= 1 + self.p() + + if tag in ['em', 'i', 'u'] and not self.ignore_emphasis: self.o(self.emphasis_mark) + if tag in ['strong', 'b'] and not self.ignore_emphasis: self.o(self.strong_mark) + if tag in ['del', 'strike', 's']: + if start: + self.o("<"+tag+">") + else: + self.o("") + + if self.google_doc: + if not self.inheader: + # handle some font attributes, but leave headers clean + self.handle_emphasis(start, tag_style, parent_style) + + if tag in ["code", "tt"] and not self.pre: self.o('`') #TODO: `` `this` `` + if tag == "abbr": + if start: + self.abbr_title = None + self.abbr_data = '' + if has_key(attrs, 'title'): + self.abbr_title = attrs['title'] + else: + if self.abbr_title != None: + self.abbr_list[self.abbr_data] = self.abbr_title + self.abbr_title = None + self.abbr_data = '' + + if tag == "a" and not self.ignore_links: + if start: + if has_key(attrs, 'href') and not (self.skip_internal_links and attrs['href'].startswith('#')): + self.astack.append(attrs) + self.maybe_automatic_link = attrs['href'] + else: + self.astack.append(None) + else: + if self.astack: + a = self.astack.pop() + if self.maybe_automatic_link: + self.maybe_automatic_link = None + elif a: + if self.inline_links: + self.o("](" + escape_md(a['href']) + ")") + else: + i = self.previousIndex(a) + if i is not None: + a = self.a[i] + else: + self.acount += 1 + a['count'] = self.acount + a['outcount'] = self.outcount + self.a.append(a) + self.o("][" + str(a['count']) + "]") + + if tag == "img" and start and not self.ignore_images: + if has_key(attrs, 'src'): + attrs['href'] = attrs['src'] + alt = attrs.get('alt', '') + self.o("![" + escape_md(alt) + "]") + + if self.inline_links: + self.o("(" + escape_md(attrs['href']) + ")") + else: + i = self.previousIndex(attrs) + if i is not None: + attrs = self.a[i] + else: + self.acount += 1 + attrs['count'] = self.acount + attrs['outcount'] = self.outcount + self.a.append(attrs) + self.o("[" + str(attrs['count']) + "]") + + if tag == 'dl' and start: self.p() + if tag == 'dt' and not start: self.pbr() + if tag == 'dd' and start: self.o(' ') + if tag == 'dd' and not start: self.pbr() + + if tag in ["ol", "ul"]: + # Google Docs create sub lists as top level lists + if (not self.list) and (not self.lastWasList): + self.p() + if start: + if self.google_doc: + list_style = google_list_style(tag_style) + else: + list_style = tag + numbering_start = list_numbering_start(attrs) + self.list.append({'name':list_style, 'num':numbering_start}) + else: + if self.list: self.list.pop() + self.lastWasList = True + else: + self.lastWasList = False + + if tag == 'li': + self.pbr() + if start: + if self.list: li = self.list[-1] + else: li = {'name':'ul', 'num':0} + if self.google_doc: + nest_count = self.google_nest_count(tag_style) + else: + nest_count = len(self.list) + self.o(" " * nest_count) #TODO: line up
  1. s > 9 correctly. + if li['name'] == "ul": self.o(self.ul_item_mark + " ") + elif li['name'] == "ol": + li['num'] += 1 + self.o(str(li['num'])+". ") + self.start = 1 + + if tag in ["table", "tr"] and start: self.p() + if tag == 'td': self.pbr() + + if tag == "pre": + if start: + self.startpre = 1 + self.pre = 1 + else: + self.pre = 0 + self.p() + + def pbr(self): + if self.p_p == 0: + self.p_p = 1 + + def p(self): + self.p_p = 2 + + def soft_br(self): + self.pbr() + self.br_toggle = ' ' + + def o(self, data, puredata=0, force=0): + if self.abbr_data is not None: + self.abbr_data += data + + if not self.quiet: + if self.google_doc: + # prevent white space immediately after 'begin emphasis' marks ('**' and '_') + lstripped_data = data.lstrip() + if self.drop_white_space and not (self.pre or self.code): + data = lstripped_data + if lstripped_data != '': + self.drop_white_space = 0 + + if puredata and not self.pre: + data = re.sub('\s+', ' ', data) + if data and data[0] == ' ': + self.space = 1 + data = data[1:] + if not data and not force: return + + if self.startpre: + #self.out(" :") #TODO: not output when already one there + if not data.startswith("\n"): #
    stuff...
    +                    data = "\n" + data
    +
    +            bq = (">" * self.blockquote)
    +            if not (force and data and data[0] == ">") and self.blockquote: bq += " "
    +
    +            if self.pre:
    +                if not self.list:
    +                    bq += "    "
    +                #else: list content is already partially indented
    +                for i in xrange(len(self.list)):
    +                    bq += "    "
    +                data = data.replace("\n", "\n"+bq)
    +
    +            if self.startpre:
    +                self.startpre = 0
    +                if self.list:
    +                    data = data.lstrip("\n") # use existing initial indentation
    +
    +            if self.start:
    +                self.space = 0
    +                self.p_p = 0
    +                self.start = 0
    +
    +            if force == 'end':
    +                # It's the end.
    +                self.p_p = 0
    +                self.out("\n")
    +                self.space = 0
    +
    +            if self.p_p:
    +                self.out((self.br_toggle+'\n'+bq)*self.p_p)
    +                self.space = 0
    +                self.br_toggle = ''
    +
    +            if self.space:
    +                if not self.lastWasNL: self.out(' ')
    +                self.space = 0
    +
    +            if self.a and ((self.p_p == 2 and self.links_each_paragraph) or force == "end"):
    +                if force == "end": self.out("\n")
    +
    +                newa = []
    +                for link in self.a:
    +                    if self.outcount > link['outcount']:
    +                        self.out("   ["+ str(link['count']) +"]: " + urlparse.urljoin(self.baseurl, link['href']))
    +                        if has_key(link, 'title'): self.out(" ("+link['title']+")")
    +                        self.out("\n")
    +                    else:
    +                        newa.append(link)
    +
    +                if self.a != newa: self.out("\n") # Don't need an extra line when nothing was done.
    +
    +                self.a = newa
    +
    +            if self.abbr_list and force == "end":
    +                for abbr, definition in self.abbr_list.items():
    +                    self.out("  *[" + abbr + "]: " + definition + "\n")
    +
    +            self.p_p = 0
    +            self.out(data)
    +            self.outcount += 1
    +
    +    def handle_data(self, data):
    +        if r'\/script>' in data: self.quiet -= 1
    +
    +        if self.style:
    +            self.style_def.update(dumb_css_parser(data))
    +
    +        if not self.maybe_automatic_link is None:
    +            href = self.maybe_automatic_link
    +            if href == data and self.absolute_url_matcher.match(href):
    +                self.o("<" + data + ">")
    +                return
    +            else:
    +                self.o("[")
    +                self.maybe_automatic_link = None
    +
    +        if not self.code and not self.pre:
    +            data = escape_md_section(data, snob=self.escape_snob)
    +        self.o(data, 1)
    +
    +    def unknown_decl(self, data): pass
    +
    +    def charref(self, name):
    +        if name[0] in ['x','X']:
    +            c = int(name[1:], 16)
    +        else:
    +            c = int(name)
    +
    +        if not self.unicode_snob and c in unifiable_n.keys():
    +            return unifiable_n[c]
    +        else:
    +            try:
    +                return unichr(c)
    +            except NameError: #Python3
    +                return chr(c)
    +
    +    def entityref(self, c):
    +        if not self.unicode_snob and c in unifiable.keys():
    +            return unifiable[c]
    +        else:
    +            try: name2cp(c)
    +            except KeyError: return "&" + c + ';'
    +            else:
    +                try:
    +                    return unichr(name2cp(c))
    +                except NameError: #Python3
    +                    return chr(name2cp(c))
    +
    +    def replaceEntities(self, s):
    +        s = s.group(1)
    +        if s[0] == "#":
    +            return self.charref(s[1:])
    +        else: return self.entityref(s)
    +
    +    r_unescape = re.compile(r"&(#?[xX]?(?:[0-9a-fA-F]+|\w{1,8}));")
    +    def unescape(self, s):
    +        return self.r_unescape.sub(self.replaceEntities, s)
    +
    +    def google_nest_count(self, style):
    +        """calculate the nesting count of google doc lists"""
    +        nest_count = 0
    +        if 'margin-left' in style:
    +            nest_count = int(style['margin-left'][:-2]) / self.google_list_indent
    +        return nest_count
    +
    +
    +    def optwrap(self, text):
    +        """Wrap all paragraphs in the provided text."""
    +        if not self.body_width:
    +            return text
    +
    +        assert wrap, "Requires Python 2.3."
    +        result = ''
    +        newlines = 0
    +        for para in text.split("\n"):
    +            if len(para) > 0:
    +                if not skipwrap(para):
    +                    result += "\n".join(wrap(para, self.body_width))
    +                    if para.endswith('  '):
    +                        result += "  \n"
    +                        newlines = 1
    +                    else:
    +                        result += "\n\n"
    +                        newlines = 2
    +                else:
    +                    if not onlywhite(para):
    +                        result += para + "\n"
    +                        newlines = 1
    +            else:
    +                if newlines < 2:
    +                    result += "\n"
    +                    newlines += 1
    +        return result
    +
    +ordered_list_matcher = re.compile(r'\d+\.\s')
    +unordered_list_matcher = re.compile(r'[-\*\+]\s')
    +md_chars_matcher = re.compile(r"([\\\[\]\(\)])")
    +md_chars_matcher_all = re.compile(r"([`\*_{}\[\]\(\)#!])")
    +md_dot_matcher = re.compile(r"""
    +    ^             # start of line
    +    (\s*\d+)      # optional whitespace and a number
    +    (\.)          # dot
    +    (?=\s)        # lookahead assert whitespace
    +    """, re.MULTILINE | re.VERBOSE)
    +md_plus_matcher = re.compile(r"""
    +    ^
    +    (\s*)
    +    (\+)
    +    (?=\s)
    +    """, flags=re.MULTILINE | re.VERBOSE)
    +md_dash_matcher = re.compile(r"""
    +    ^
    +    (\s*)
    +    (-)
    +    (?=\s|\-)     # followed by whitespace (bullet list, or spaced out hr)
    +                  # or another dash (header or hr)
    +    """, flags=re.MULTILINE | re.VERBOSE)
    +slash_chars = r'\`*_{}[]()#+-.!'
    +md_backslash_matcher = re.compile(r'''
    +    (\\)          # match one slash
    +    (?=[%s])      # followed by a char that requires escaping
    +    ''' % re.escape(slash_chars),
    +    flags=re.VERBOSE)
    +
    +def skipwrap(para):
    +    # If the text begins with four spaces or one tab, it's a code block; don't wrap
    +    if para[0:4] == '    ' or para[0] == '\t':
    +        return True
    +    # If the text begins with only two "--", possibly preceded by whitespace, that's
    +    # an emdash; so wrap.
    +    stripped = para.lstrip()
    +    if stripped[0:2] == "--" and len(stripped) > 2 and stripped[2] != "-":
    +        return False
    +    # I'm not sure what this is for; I thought it was to detect lists, but there's
    +    # a 
    -inside- case in one of the tests that also depends upon it. + if stripped[0:1] == '-' or stripped[0:1] == '*': + return True + # If the text begins with a single -, *, or +, followed by a space, or an integer, + # followed by a ., followed by a space (in either case optionally preceeded by + # whitespace), it's a list; don't wrap. + if ordered_list_matcher.match(stripped) or unordered_list_matcher.match(stripped): + return True + return False + +def wrapwrite(text): + text = text.encode('utf-8') + try: #Python3 + sys.stdout.buffer.write(text) + except AttributeError: + sys.stdout.write(text) + +def html2text(html, baseurl=''): + h = HTML2Text(baseurl=baseurl) + return h.handle(html) + +def unescape(s, unicode_snob=False): + h = HTML2Text() + h.unicode_snob = unicode_snob + return h.unescape(s) + +def escape_md(text): + """Escapes markdown-sensitive characters within other markdown constructs.""" + return md_chars_matcher.sub(r"\\\1", text) + +def escape_md_section(text, snob=False): + """Escapes markdown-sensitive characters across whole document sections.""" + text = md_backslash_matcher.sub(r"\\\1", text) + if snob: + text = md_chars_matcher_all.sub(r"\\\1", text) + text = md_dot_matcher.sub(r"\1\\\2", text) + text = md_plus_matcher.sub(r"\1\\\2", text) + text = md_dash_matcher.sub(r"\1\\\2", text) + return text + + +def main(): + baseurl = '' + + p = optparse.OptionParser('%prog [(filename|url) [encoding]]', + version='%prog ' + __version__) + p.add_option("--ignore-emphasis", dest="ignore_emphasis", action="store_true", + default=IGNORE_EMPHASIS, help="don't include any formatting for emphasis") + p.add_option("--ignore-links", dest="ignore_links", action="store_true", + default=IGNORE_ANCHORS, help="don't include any formatting for links") + p.add_option("--ignore-images", dest="ignore_images", action="store_true", + default=IGNORE_IMAGES, help="don't include any formatting for images") + p.add_option("-g", "--google-doc", action="store_true", dest="google_doc", + default=False, help="convert an html-exported Google Document") + p.add_option("-d", "--dash-unordered-list", action="store_true", dest="ul_style_dash", + default=False, help="use a dash rather than a star for unordered list items") + p.add_option("-e", "--asterisk-emphasis", action="store_true", dest="em_style_asterisk", + default=False, help="use an asterisk rather than an underscore for emphasized text") + p.add_option("-b", "--body-width", dest="body_width", action="store", type="int", + default=BODY_WIDTH, help="number of characters per output line, 0 for no wrap") + p.add_option("-i", "--google-list-indent", dest="list_indent", action="store", type="int", + default=GOOGLE_LIST_INDENT, help="number of pixels Google indents nested lists") + p.add_option("-s", "--hide-strikethrough", action="store_true", dest="hide_strikethrough", + default=False, help="hide strike-through text. only relevant when -g is specified as well") + p.add_option("--escape-all", action="store_true", dest="escape_snob", + default=False, help="Escape all special characters. Output is less readable, but avoids corner case formatting issues.") + (options, args) = p.parse_args() + + # process input + encoding = "utf-8" + if len(args) > 0: + file_ = args[0] + if len(args) == 2: + encoding = args[1] + if len(args) > 2: + p.error('Too many arguments') + + if file_.startswith('http://') or file_.startswith('https://'): + baseurl = file_ + j = urllib.urlopen(baseurl) + data = j.read() + if encoding is None: + try: + from feedparser import _getCharacterEncoding as enc + except ImportError: + enc = lambda x, y: ('utf-8', 1) + encoding = enc(j.headers, data)[0] + if encoding == 'us-ascii': + encoding = 'utf-8' + else: + data = open(file_, 'rb').read() + if encoding is None: + try: + from chardet import detect + except ImportError: + detect = lambda x: {'encoding': 'utf-8'} + encoding = detect(data)['encoding'] + else: + data = sys.stdin.read() + + data = data.decode(encoding) + h = HTML2Text(baseurl=baseurl) + # handle options + if options.ul_style_dash: h.ul_item_mark = '-' + if options.em_style_asterisk: + h.emphasis_mark = '*' + h.strong_mark = '__' + + h.body_width = options.body_width + h.list_indent = options.list_indent + h.ignore_emphasis = options.ignore_emphasis + h.ignore_links = options.ignore_links + h.ignore_images = options.ignore_images + h.google_doc = options.google_doc + h.hide_strikethrough = options.hide_strikethrough + h.escape_snob = options.escape_snob + + wrapwrite(h.handle(data)) + + +if __name__ == "__main__": + main() diff --git a/nstock/modules/mail.py b/nstock/modules/mail.py new file mode 100644 index 0000000..f905f9f --- /dev/null +++ b/nstock/modules/mail.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +from gluon import current + + +def item_notify_users(item_id, subject='None', message='None'): + """ + Notify all users who has access to item_id + """ + db = current.db + mail = current.mail + auth = current.auth + + item = db.item(item_id) + + # i need all user who have some permission over current item + query = (db.auth_permission.record_id == item.id) + query &= (db.auth_permission.table_name == db.item) + query &= (db.auth_permission.group_id == db.auth_membership.group_id) + query &= (db.auth_user.id == db.auth_membership.user_id) + # except the user who active this action + query &= (db.auth_user.id != auth.user.id) + + for u in db(query).select(db.auth_user.ALL, distinct=True): + mail.send( + to=[u.email], + subject=subject, + message=message + ) diff --git a/nstock/modules/perms.py b/nstock/modules/perms.py new file mode 100644 index 0000000..b7f495f --- /dev/null +++ b/nstock/modules/perms.py @@ -0,0 +1,35 @@ +# coding=utf-8 +from gluon import current + + +def isOwnerOrCollaborator(item_id=None): + """ + Returns True if the current user is the owner or has collaborator + permission + """ + request = current.request + + if not item_id: + item_id = request.args(0) + + return (isOwner(item_id) or isCollaborator(item_id)) + + +def isOwner(item_id): + """ + Returns True only if the current user is the owner of the item + """ + auth = current.auth + db = current.db + + return auth.has_permission('owner', db.item, record_id=item_id) + + +def isCollaborator(item_id): + """ + Returns True if the current user has collaborator permission over item_id + """ + auth = current.auth + db = current.db + + return auth.has_permission('collaborator', db.item, record_id=item_id) diff --git a/nstock/modules/plugin_ckeditor.py b/nstock/modules/plugin_ckeditor.py new file mode 100644 index 0000000..6f4e08b --- /dev/null +++ b/nstock/modules/plugin_ckeditor.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +web2py_ckeditor4: web2py plugin for CKEditor v4: http://ckeditor.com/ +""" + +__author__ = 'Tim Richardson' +__email__ = 'tim@growthpath.com.au' +__copyright__ = 'Copyright(c) 2012-2014, Ross Peoples, Bruno Rocha, ' \ + 'Tim Richardson' +__license__ = 'LGPLv3' +__version__ = '1.1' +# possible options: Prototype, Development, Production +__status__ = 'Development' + +import os +from gluon import * +from gluon.storage import Storage +from gluon.sqlhtml import FormWidget + +class CKEditor(object): + """ + Integrates CKEditor nicely into web2py. + """ + def __init__(self, db, download_url=('default','download')): + """ + Initializes the CKEditor module. Requires a DAL instance. + """ + + self.db = db + + self.settings = Storage() + self.settings.table_upload = None + self.settings.uploadfs = None + self.settings.table_upload_name = 'plugin_ckeditor_upload' + self.settings.extra_fields = {} + self.settings.url_upload = URL('plugin_ckeditor', 'upload') + self.settings.url_browse = URL('plugin_ckeditor', 'browse') + self.settings.browse_filter = {} + self.settings.file_length_max = 10485760 # 10 MB + self.settings.file_length_min = 0 # no minimum + self.settings.spellcheck_while_typing = False + + self.settings.download_url = download_url + current.plugin_ckeditor = self + + def define_tables(self, migrate=True, fake_migrate=False): + """ + Called after settings are set to create the required tables for dealing + with file uploads from CKEditor. + """ + upload_name = self.settings.table_upload_name + + self.settings.table_upload = self.db.define_table(upload_name, + Field('title', length=255), + Field('filename', length=255), + Field('flength', 'integer'), + Field('mime_type', length=128), + Field('upload', 'upload', uploadfs=self.settings.uploadfs, requires=[IS_NOT_EMPTY(), IS_LENGTH(maxsize=self.settings.file_length_max, minsize=self.settings.file_length_min)]), + *self.settings.extra_fields.get(upload_name, []), + migrate = migrate, + fake_migrate = fake_migrate, + format = '%(title)s' + ) + + + def widget(self, field, value, **attributes): + """ + To be used with db.table.field.widget to set CKEditor as the desired + widget for the field. Simply set + db.table.field.widget = ckeditor.widget to use the CKEditor widget. + """ + default = dict( + value = value, + _cols = 80, + _rows = 10 + ) + + attributes = FormWidget._attributes(field, default, **attributes) + attributes['_class'] = 'text plugin_ckeditor' + + textarea = TEXTAREA(**attributes) + javascript = self.load('#' + textarea.attributes['_id'], + use_caching=False) + result = CAT(textarea, javascript) + + return result + + def handle_upload(self): + """ + Gets an upload from CKEditor and returns the new filename that + can then be inserted into a database. Returns (new_filename, + old_filename, length, mime_type) + """ + upload = current.request.vars.upload + path = os.path.join(current.request.folder, 'uploads') + + if upload != None: + if hasattr(upload, 'file'): + form = SQLFORM.factory( + Field('upload', 'upload', requires=IS_NOT_EMPTY(), + uploadfs=self.settings.uploadfs, + uploadfolder=path), + table_name=self.settings.table_upload_name, + + ) + + old_filename = upload.filename + new_filename = form.table.upload.store(upload.file, + upload.filename) + if self.settings.uploadfs: + length = self.settings.uploadfs.getsize(new_filename) + else: + length = os.path.getsize(os.path.join(path, new_filename)) + mime_type = upload.headers['content-type'] + + return (new_filename, old_filename, length, mime_type) + else: + raise HTTP(401, 'Upload is not proper type.') + else: + raise HTTP(401, 'Missing required upload.') + + def unlink(self, filename): + """ + Unlink file from storage. It can be an local storage or a filesystem. + Using self.unlink and clean file with filename. + """ + if self.settings.uploadfs: + self.settings.uploadfs.remove(filename) + else: + filepath = os.path.join(current.request.folder, 'uploads', filename) + os.unlink(filepath) + + def load(self, selector=None, use_caching=True): + """ + Generates the required JavaScript for CKEditor. If selector is set, + then immediately turns the selected HTML element(s) into CKEditor + instances. Otherwise, a manual JavaScript call to plugin_ckeditor_init() + is required with the desired selector. + """ + if self.settings.loaded and use_caching: + return XML('') + else: + self.settings.loaded = True + + upload_url = self.settings.url_upload + browse_url = self.settings.url_browse + ckeditor_js = URL('static', 'plugin_ckeditor/ckeditor.js') + jquery_js = URL('static', 'plugin_ckeditor/adapters/jquery.js') + + # contents_css = "['%s']" % URL('static', 'plugin_ckeditor/contents.css') + contents_css = "['%s']" % URL('static', 'plugin_ckeditor/style.css') + + immediate = '' + if selector: + immediate = """ + jQuery(function() { + CKEDITOR.timestamp='ABCD'; + var config = ckeditor_config(); + jQuery('%s').ckeditor(config); + }); + """ % selector + + scayt = 'false' + if self.settings.spellcheck_while_typing: + scayt = 'true' + + return XML( + """ + + + + + + """ % dict( + ckeditor_js = ckeditor_js, + jquery_js = jquery_js, + + contents_css = contents_css, + upload_url = upload_url, + browse_url = browse_url, + scayt = scayt, + immediate = immediate, + ) + ) + + def filetype(self, filename): + """ + Takes a filename and returns a category based on the file type. + Categories: word, excel, powerpoint, flash, pdf, image, video, audio, archive, other. + """ + parts = os.path.splitext(filename) + if len(parts) < 2: + return 'other' + else: + ext = parts[1][1:].lower() + if ext == 'png' or ext == 'jpg' or ext == 'jpeg' or ext == 'gif': + return 'image' + elif ext == 'avi' or ext == 'mp4' or ext == 'm4v' or ext == 'ogv' or ext == 'wmv' or ext == 'mpg' or ext == 'mpeg': + return 'video' + elif ext == 'mp3' or ext == 'm4a' or ext == 'wav' or ext == 'ogg' or ext == 'aiff': + return 'audio' + elif ext == 'zip' or ext == '7z' or ext == 'tar' or ext == 'gz' or ext == 'tgz' or ext == 'bz2' or ext == 'rar': + return 'archive' + elif ext == 'doc' or ext == 'docx' or ext == 'dot' or ext == 'dotx' or ext == 'rtf': + return 'word' + elif ext == 'xls' or ext == 'xlsx' or ext == 'xlt' or ext == 'xltx' or ext == 'csv': + return 'excel' + elif ext == 'ppt' or ext == 'pptx': + return 'powerpoint' + elif ext == 'flv' or ext == 'swf': + return 'flash' + elif ext == 'pdf': + return 'pdf' + else: + return 'other' diff --git a/nstock/modules/plugin_package/__init__.py b/nstock/modules/plugin_package/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/nstock/modules/plugin_package/content_package.py b/nstock/modules/plugin_package/content_package.py new file mode 100644 index 0000000..a014133 --- /dev/null +++ b/nstock/modules/plugin_package/content_package.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +from content_plugin import ContentPlugin +from gluon import URL, CAT, I, XML + + +class ContentPackage(ContentPlugin): + """docstring for ContentPackage.""" + + def get_item_url(self, item): + return URL('plugin_package', 'index.html', args=[item.unique_id]) + + def preview(self, item): + super(ContentPackage, self).preview(item) + content = self.db.plugin_package_content(item_id=item.unique_id) + return XML( + self.response.render( + 'plugin_package/preview.html', + dict(item=item, p_content=content)) + ) + + def create_item_url(self): + return ( + URL('plugin_package', 'create.html'), + CAT(I(_class='fa fa-file-archive-o'), ' ', self.T('Package'))) + + def get_full_text(self, item): + """Return full text document, mean for plugins""" + content = self.db.plugin_package_content(item_id=item.unique_id) + output = self.response.render( + 'plugin_package/full_text.txt', + dict(item=item, content=content)) + return unicode(output.decode('utf-8')) + + def get_changelog_url(self, item): + return URL('plugin_package', 'changelog', args=[item.unique_id]) + + def shareItem(self, item_id, src_desk, dst_desk): + """Share package to user""" + super(ContentPackage, self).shareItem(item_id, src_desk, dst_desk) + # on packages, we share each item on the package, and then + # the package it self + pkg_item = self.app.getItemByUUID(item_id) + pkg_content = self.db.plugin_package_content( + item_id=pkg_item.unique_id) + for c_item in pkg_content.item_list: + p_c_item = self.app.getItemByUUID(c_item) + src = self.db.desk(src_desk) + if p_c_item.id in src.item_list: + ct = self.app.getContentType(p_c_item.item_type) + ct.shareItem(c_item, src_desk, dst_desk) diff --git a/nstock/modules/plugin_photoset/__init__.py b/nstock/modules/plugin_photoset/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/nstock/modules/plugin_photoset/content_photoset.py b/nstock/modules/plugin_photoset/content_photoset.py new file mode 100644 index 0000000..375d9e7 --- /dev/null +++ b/nstock/modules/plugin_photoset/content_photoset.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +from content_plugin import ContentPlugin +from gluon import URL, XML, CAT, I + + +class ContentPhotoset(ContentPlugin): + """ + Photo set item + """ + + def create_item_url(self): + return ( + URL('plugin_photoset', 'create.html'), + CAT(I(_class="fa fa-object-group"), ' ', self.T('Photo Set')) + ) + + def get_item_url(self, item): + return URL('plugin_photoset', 'index.html', args=[item.unique_id]) + + def get_changelog_url(self, item): + return URL('plugin_photoset', 'changelog', args=[item.unique_id]) + + def get_full_text(self, item): + """Return full text document, mean for plugins""" + photoset_content = self.db.plugin_photoset_content( + item_id=item.unique_id) + output = self.response.render( + 'plugin_photoset/full_text.txt', + dict(photoset_content=photoset_content, item=item)) + return unicode(output.decode('utf-8')) + + def preview(self, item): + super(ContentPhotoset, self).preview(item) + photoset_content = self.db.plugin_photoset_content( + item_id=item.unique_id + ) + return XML( + self.response.render( + 'plugin_photoset/preview.html', + dict(item=item, photoset_content=photoset_content)) + ) diff --git a/nstock/modules/plugin_picture/__init__.py b/nstock/modules/plugin_picture/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/nstock/modules/plugin_picture/content_picture.py b/nstock/modules/plugin_picture/content_picture.py new file mode 100644 index 0000000..fd1d314 --- /dev/null +++ b/nstock/modules/plugin_picture/content_picture.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +from content_plugin import ContentPlugin +from gluon import URL, XML, CAT, I + + +class ContentPicture(ContentPlugin): + + def create_item_url(self): + return ( + URL('plugin_picture', 'create.html'), + CAT(I(_class='fa fa-picture-o'), ' ', self.T('Picture')) + ) + + def get_item_url(self, item): + return URL('plugin_picture', 'index.html', args=[item.unique_id]) + + def get_full_text(self, item): + """Return full text document, mean for plugins""" + pic_info = self.db.plugin_picture_info(item_id=item.unique_id) + output = self.response.render( + 'plugin_picture/full_text.txt', + dict(pic_info=pic_info, item=item)) + return unicode(output.decode('utf-8')) + + def get_changelog_url(self, item): + return URL('plugin_picture', 'changelog', args=[item.unique_id]) + + def preview(self, item): + super(ContentPicture, self).preview(item) + info = self.db.plugin_picture_info(item_id=item.unique_id) + return XML( + self.response.render( + 'plugin_picture/preview.html', + dict(item=item, info=info))) diff --git a/nstock/modules/plugin_text/__init__.py b/nstock/modules/plugin_text/__init__.py new file mode 100644 index 0000000..40a96af --- /dev/null +++ b/nstock/modules/plugin_text/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/nstock/modules/plugin_text/content_text.py b/nstock/modules/plugin_text/content_text.py new file mode 100644 index 0000000..f3d6241 --- /dev/null +++ b/nstock/modules/plugin_text/content_text.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +from content_plugin import ContentPlugin +from gluon import URL, XML, CAT, I + + +class ContentText(ContentPlugin): + + def create_item_url(self): + return ( + URL('plugin_text', 'create.html'), + CAT(I(_class="fa fa-file-text-o"), ' ', self.T('Text'))) + + def get_item_url(self, item): + return URL('plugin_text', 'index.html', args=[item.unique_id]) + + def get_changelog_url(self, item): + return URL('plugin_text', 'changelog', args=[item.unique_id]) + + def get_full_text(self, item): + """Return full text document, mean for plugins""" + text_content = self.db.plugin_text_text(item_id=item.unique_id) + output = self.response.render( + 'plugin_text/full_text.txt', + dict(text_content=text_content, item=item)) + return unicode(output.decode('utf-8')) + + def preview(self, item): + super(ContentText, self).preview(item) + content = self.db.plugin_text_text(item_id=item.unique_id) + return XML(self.response.render( + 'plugin_text/preview.html', + dict(item=item, p_content=content))) diff --git a/nstock/modules/slugify/__init__.py b/nstock/modules/slugify/__init__.py new file mode 100644 index 0000000..8b20b5f --- /dev/null +++ b/nstock/modules/slugify/__init__.py @@ -0,0 +1,6 @@ +from .slugify import * + + +__author__ = 'Val Neekman @ Neekware Inc. [@vneekman]' +__description__ = 'A Python slugify application that also handles Unicode' +__version__ = '1.2.0' diff --git a/nstock/modules/slugify/slugify.py b/nstock/modules/slugify/slugify.py new file mode 100644 index 0000000..113afdd --- /dev/null +++ b/nstock/modules/slugify/slugify.py @@ -0,0 +1,160 @@ +import re +import unicodedata +import types +import sys + +try: + from htmlentitydefs import name2codepoint + _unicode = unicode + _unicode_type = types.UnicodeType +except ImportError: + from html.entities import name2codepoint + _unicode = str + _unicode_type = str + unichr = chr + +import unidecode + + +__all__ = ['slugify'] + + +CHAR_ENTITY_PATTERN = re.compile('&(%s);' % '|'.join(name2codepoint)) +DECIMAL_PATTERN = re.compile('&#(\d+);') +HEX_PATTERN = re.compile('&#x([\da-fA-F]+);') +QUOTE_PATTERN = re.compile(r'[\']+') +ALLOWED_CHARS_PATTERN = re.compile(r'[^-a-z0-9]+') +DUPLICATE_DASH_PATTERN = re.compile('-{2,}') +NUMBERS_PATTERN = re.compile('(?<=\d),(?=\d)') + + +def smart_truncate(string, max_length=0, word_boundaries=False, separator=' ', save_order=False): + """ + Truncate a string. + :param string (str): string for modification + :param max_length (int): output string length + :param word_boundaries (bool): + :param save_order (bool): if True then word order of output string is like input string + :param separator (str): separator between words + :return: + """ + + string = string.strip(separator) + + if not max_length: + return string + + if len(string) < max_length: + return string + + if not word_boundaries: + return string[:max_length].strip(separator) + + if separator not in string: + return string[:max_length] + + truncated = '' + for word in string.split(separator): + if word: + next_len = len(truncated) + len(word) + if next_len < max_length: + truncated += '{0}{1}'.format(word, separator) + elif next_len == max_length: + truncated += '{0}'.format(word) + break + else: + if save_order: + break + if not truncated: + truncated = string[:max_length] + return truncated.strip(separator) + + +def slugify(text, entities=True, decimal=True, hexadecimal=True, max_length=0, word_boundary=False, + separator='-', save_order=False, stopwords=()): + """ + Make a slug from the given text. + :param text (str): initial text + :param entities (bool): + :param decimal (bool): + :param hexadecimal (bool): + :param max_length (int): output string length + :param word_boundary (bool): + :param save_order (bool): if parameter is True and max_length > 0 return whole words in the initial order + :param separator (str): separator between words + :param stopwords (iterable): words to discount + :return (str): + """ + + # ensure text is unicode + if not isinstance(text, _unicode_type): + text = _unicode(text, 'utf-8', 'ignore') + + # replace quotes with dashes - pre-process + text = QUOTE_PATTERN.sub('-', text) + + # decode unicode + text = unidecode.unidecode(text) + + # ensure text is still in unicode + if not isinstance(text, _unicode_type): + text = _unicode(text, 'utf-8', 'ignore') + + # character entity reference + if entities: + text = CHAR_ENTITY_PATTERN.sub(lambda m: unichr(name2codepoint[m.group(1)]), text) + + # decimal character reference + if decimal: + try: + text = DECIMAL_PATTERN.sub(lambda m: unichr(int(m.group(1))), text) + except: + pass + + # hexadecimal character reference + if hexadecimal: + try: + text = HEX_PATTERN.sub(lambda m: unichr(int(m.group(1), 16)), text) + except: + pass + + # translate + text = unicodedata.normalize('NFKD', text) + if sys.version_info < (3,): + text = text.encode('ascii', 'ignore') + + # make the text lowercase + text = text.lower() + + # remove generated quotes -- post-process + text = QUOTE_PATTERN.sub('', text) + + # replace unwanted characters + text = NUMBERS_PATTERN.sub('', text) + text = ALLOWED_CHARS_PATTERN.sub('-', text) + + # remove redundant - + text = DUPLICATE_DASH_PATTERN.sub('-', text).strip('-') + + # remove stopwords + if stopwords: + stopwords_lower = [s.lower() for s in stopwords] + words = [w for w in text.split('-') if w not in stopwords_lower] + text = '-'.join(words) + + # smart truncate if requested + if max_length > 0: + text = smart_truncate(text, max_length, word_boundary, '-', save_order) + + if separator != '-': + text = text.replace('-', separator) + + return text + + +def main(): + if len(sys.argv) < 2: + print("Usage %s TEXT TO SLUGIFY" % sys.argv[0]) + else: + text = ' '.join(sys.argv[1:]) + print(slugify(text)) diff --git a/nstock/modules/unidecode/__init__.py b/nstock/modules/unidecode/__init__.py new file mode 100644 index 0000000..3b68de4 --- /dev/null +++ b/nstock/modules/unidecode/__init__.py @@ -0,0 +1,103 @@ +# -*- coding: utf-8 -*- +# vi:tabstop=4:expandtab:sw=4 +"""Transliterate Unicode text into plain 7-bit ASCII. + +Example usage: +>>> from unidecode import unidecode: +>>> unidecode(u"\u5317\u4EB0") +"Bei Jing " + +The transliteration uses a straightforward map, and doesn't have alternatives +for the same character based on language, position, or anything else. + +In Python 3, a standard string object will be returned. If you need bytes, use: +>>> unidecode("Κνωσός").encode("ascii") +b'Knosos' +""" +import warnings +from sys import version_info + +Cache = {} + + +def _warn_if_not_unicode(string): + if version_info[0] < 3 and not isinstance(string, unicode): + warnings.warn( "Argument %r is not an unicode object. " + "Passing an encoded string will likely have " + "unexpected results." % (type(string),), + RuntimeWarning, 2) + + +def unidecode_expect_ascii(string): + """Transliterate an Unicode object into an ASCII string + + >>> unidecode(u"\u5317\u4EB0") + "Bei Jing " + + This function first tries to convert the string using ASCII codec. + If it fails (because of non-ASCII characters), it falls back to + transliteration using the character tables. + + This is approx. five times faster if the string only contains ASCII + characters, but slightly slower than using unidecode directly if non-ASCII + chars are present. + """ + + _warn_if_not_unicode(string) + try: + bytestring = string.encode('ASCII') + except UnicodeEncodeError: + return _unidecode(string) + if version_info[0] >= 3: + return string + else: + return bytestring + +def unidecode_expect_nonascii(string): + """Transliterate an Unicode object into an ASCII string + + >>> unidecode(u"\u5317\u4EB0") + "Bei Jing " + """ + + _warn_if_not_unicode(string) + return _unidecode(string) + +unidecode = unidecode_expect_ascii + +def _unidecode(string): + retval = [] + + for char in string: + codepoint = ord(char) + + if codepoint < 0x80: # Basic ASCII + retval.append(str(char)) + continue + + if codepoint > 0xeffff: + continue # Characters in Private Use Area and above are ignored + + if 0xd800 <= codepoint <= 0xdfff: + warnings.warn( "Surrogate character %r will be ignored. " + "You might be using a narrow Python build." % (char,), + RuntimeWarning, 2) + + section = codepoint >> 8 # Chop off the last two hex digits + position = codepoint % 256 # Last two hex digits + + try: + table = Cache[section] + except KeyError: + try: + mod = __import__('unidecode.x%03x'%(section), globals(), locals(), ['data']) + except ImportError: + Cache[section] = None + continue # No match: ignore this character and carry on. + + Cache[section] = table = mod.data + + if table and len(table) > position: + retval.append( table[position] ) + + return ''.join(retval) diff --git a/nstock/modules/unidecode/util.py b/nstock/modules/unidecode/util.py new file mode 100644 index 0000000..477280d --- /dev/null +++ b/nstock/modules/unidecode/util.py @@ -0,0 +1,58 @@ +# vim:ts=4 sw=4 expandtab softtabstop=4 +from __future__ import print_function +import optparse +import locale +import os +import sys +import warnings + +from unidecode import unidecode + +PY3 = sys.version_info[0] >= 3 + +def fatal(msg): + sys.stderr.write(msg + "\n") + sys.exit(1) + +def main(): + default_encoding = locale.getpreferredencoding() + + parser = optparse.OptionParser('%prog [options] [FILE]', + description="Transliterate Unicode text into ASCII. FILE is path to file to transliterate. " + "Standard input is used if FILE is omitted and -c is not specified.") + parser.add_option('-e', '--encoding', metavar='ENCODING', default=default_encoding, + help='Specify an encoding (default is %s)' % (default_encoding,)) + parser.add_option('-c', metavar='TEXT', dest='text', + help='Transliterate TEXT instead of FILE') + + options, args = parser.parse_args() + + encoding = options.encoding + + if args: + if options.text: + fatal("Can't use both FILE and -c option") + else: + with open(args[0], 'rb') as f: + stream = f.read() + elif options.text: + if PY3: + stream = os.fsencode(options.text) + else: + stream = options.text + # add a newline to the string if it comes from the + # command line so that the result is printed nicely + # on the console. + stream += '\n'.encode('ascii') + else: + if PY3: + stream = sys.stdin.buffer.read() + else: + stream = sys.stdin.read() + + try: + stream = stream.decode(encoding) + except UnicodeDecodeError as e: + fatal('Unable to decode input: %s, start: %d, end: %d' % (e.reason, e.start, e.end)) + + sys.stdout.write(unidecode(stream)) diff --git a/nstock/modules/unidecode/x000.py b/nstock/modules/unidecode/x000.py new file mode 100644 index 0000000..c3f8f51 --- /dev/null +++ b/nstock/modules/unidecode/x000.py @@ -0,0 +1,165 @@ +data = ( +# Code points u+007f and below are equivalent to ASCII and are handled by a +# special case in the code. Hence they are not present in this table. +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + +'', # 0x80 +'', # 0x81 +'', # 0x82 +'', # 0x83 +'', # 0x84 +'', # 0x85 +'', # 0x86 +'', # 0x87 +'', # 0x88 +'', # 0x89 +'', # 0x8a +'', # 0x8b +'', # 0x8c +'', # 0x8d +'', # 0x8e +'', # 0x8f +'', # 0x90 +'', # 0x91 +'', # 0x92 +'', # 0x93 +'', # 0x94 +'', # 0x95 +'', # 0x96 +'', # 0x97 +'', # 0x98 +'', # 0x99 +'', # 0x9a +'', # 0x9b +'', # 0x9c +'', # 0x9d +'', # 0x9e +'', # 0x9f +' ', # 0xa0 +'!', # 0xa1 +'C/', # 0xa2 + +# Not "GBP" - Pound Sign is used for more than just British Pounds. +'PS', # 0xa3 + +'$?', # 0xa4 +'Y=', # 0xa5 +'|', # 0xa6 +'SS', # 0xa7 +'"', # 0xa8 +'(c)', # 0xa9 +'a', # 0xaa +'<<', # 0xab +'!', # 0xac +'', # 0xad +'(r)', # 0xae +'-', # 0xaf +'deg', # 0xb0 +'+-', # 0xb1 + +# These might be combined with other superscript digits (u+2070 - u+2079) +'2', # 0xb2 +'3', # 0xb3 + +'\'', # 0xb4 +'u', # 0xb5 +'P', # 0xb6 +'*', # 0xb7 +',', # 0xb8 +'1', # 0xb9 +'o', # 0xba +'>>', # 0xbb +'1/4', # 0xbc +'1/2', # 0xbd +'3/4', # 0xbe +'?', # 0xbf +'A', # 0xc0 +'A', # 0xc1 +'A', # 0xc2 +'A', # 0xc3 + +# Not "AE" - used in languages other than German +'A', # 0xc4 + +'A', # 0xc5 +'AE', # 0xc6 +'C', # 0xc7 +'E', # 0xc8 +'E', # 0xc9 +'E', # 0xca +'E', # 0xcb +'I', # 0xcc +'I', # 0xcd +'I', # 0xce +'I', # 0xcf +'D', # 0xd0 +'N', # 0xd1 +'O', # 0xd2 +'O', # 0xd3 +'O', # 0xd4 +'O', # 0xd5 + +# Not "OE" - used in languages other than German +'O', # 0xd6 + +'x', # 0xd7 +'O', # 0xd8 +'U', # 0xd9 +'U', # 0xda +'U', # 0xdb + +# Not "UE" - used in languages other than German +'U', # 0xdc + +'Y', # 0xdd +'Th', # 0xde +'ss', # 0xdf +'a', # 0xe0 +'a', # 0xe1 +'a', # 0xe2 +'a', # 0xe3 + +# Not "ae" - used in languages other than German +'a', # 0xe4 + +'a', # 0xe5 +'ae', # 0xe6 +'c', # 0xe7 +'e', # 0xe8 +'e', # 0xe9 +'e', # 0xea +'e', # 0xeb +'i', # 0xec +'i', # 0xed +'i', # 0xee +'i', # 0xef +'d', # 0xf0 +'n', # 0xf1 +'o', # 0xf2 +'o', # 0xf3 +'o', # 0xf4 +'o', # 0xf5 + +# Not "oe" - used in languages other than German +'o', # 0xf6 + +'/', # 0xf7 +'o', # 0xf8 +'u', # 0xf9 +'u', # 0xfa +'u', # 0xfb + +# Not "ue" - used in languages other than German +'u', # 0xfc + +'y', # 0xfd +'th', # 0xfe +'y', # 0xff +) diff --git a/nstock/modules/unidecode/x001.py b/nstock/modules/unidecode/x001.py new file mode 100644 index 0000000..212c2d1 --- /dev/null +++ b/nstock/modules/unidecode/x001.py @@ -0,0 +1,258 @@ +data = ( +'A', # 0x00 +'a', # 0x01 +'A', # 0x02 +'a', # 0x03 +'A', # 0x04 +'a', # 0x05 +'C', # 0x06 +'c', # 0x07 +'C', # 0x08 +'c', # 0x09 +'C', # 0x0a +'c', # 0x0b +'C', # 0x0c +'c', # 0x0d +'D', # 0x0e +'d', # 0x0f +'D', # 0x10 +'d', # 0x11 +'E', # 0x12 +'e', # 0x13 +'E', # 0x14 +'e', # 0x15 +'E', # 0x16 +'e', # 0x17 +'E', # 0x18 +'e', # 0x19 +'E', # 0x1a +'e', # 0x1b +'G', # 0x1c +'g', # 0x1d +'G', # 0x1e +'g', # 0x1f +'G', # 0x20 +'g', # 0x21 +'G', # 0x22 +'g', # 0x23 +'H', # 0x24 +'h', # 0x25 +'H', # 0x26 +'h', # 0x27 +'I', # 0x28 +'i', # 0x29 +'I', # 0x2a +'i', # 0x2b +'I', # 0x2c +'i', # 0x2d +'I', # 0x2e +'i', # 0x2f +'I', # 0x30 +'i', # 0x31 +'IJ', # 0x32 +'ij', # 0x33 +'J', # 0x34 +'j', # 0x35 +'K', # 0x36 +'k', # 0x37 +'k', # 0x38 +'L', # 0x39 +'l', # 0x3a +'L', # 0x3b +'l', # 0x3c +'L', # 0x3d +'l', # 0x3e +'L', # 0x3f +'l', # 0x40 +'L', # 0x41 +'l', # 0x42 +'N', # 0x43 +'n', # 0x44 +'N', # 0x45 +'n', # 0x46 +'N', # 0x47 +'n', # 0x48 +'\'n', # 0x49 +'ng', # 0x4a +'NG', # 0x4b +'O', # 0x4c +'o', # 0x4d +'O', # 0x4e +'o', # 0x4f +'O', # 0x50 +'o', # 0x51 +'OE', # 0x52 +'oe', # 0x53 +'R', # 0x54 +'r', # 0x55 +'R', # 0x56 +'r', # 0x57 +'R', # 0x58 +'r', # 0x59 +'S', # 0x5a +'s', # 0x5b +'S', # 0x5c +'s', # 0x5d +'S', # 0x5e +'s', # 0x5f +'S', # 0x60 +'s', # 0x61 +'T', # 0x62 +'t', # 0x63 +'T', # 0x64 +'t', # 0x65 +'T', # 0x66 +'t', # 0x67 +'U', # 0x68 +'u', # 0x69 +'U', # 0x6a +'u', # 0x6b +'U', # 0x6c +'u', # 0x6d +'U', # 0x6e +'u', # 0x6f +'U', # 0x70 +'u', # 0x71 +'U', # 0x72 +'u', # 0x73 +'W', # 0x74 +'w', # 0x75 +'Y', # 0x76 +'y', # 0x77 +'Y', # 0x78 +'Z', # 0x79 +'z', # 0x7a +'Z', # 0x7b +'z', # 0x7c +'Z', # 0x7d +'z', # 0x7e +'s', # 0x7f +'b', # 0x80 +'B', # 0x81 +'B', # 0x82 +'b', # 0x83 +'6', # 0x84 +'6', # 0x85 +'O', # 0x86 +'C', # 0x87 +'c', # 0x88 +'D', # 0x89 +'D', # 0x8a +'D', # 0x8b +'d', # 0x8c +'d', # 0x8d +'3', # 0x8e +'@', # 0x8f +'E', # 0x90 +'F', # 0x91 +'f', # 0x92 +'G', # 0x93 +'G', # 0x94 +'hv', # 0x95 +'I', # 0x96 +'I', # 0x97 +'K', # 0x98 +'k', # 0x99 +'l', # 0x9a +'l', # 0x9b +'W', # 0x9c +'N', # 0x9d +'n', # 0x9e +'O', # 0x9f +'O', # 0xa0 +'o', # 0xa1 +'OI', # 0xa2 +'oi', # 0xa3 +'P', # 0xa4 +'p', # 0xa5 +'YR', # 0xa6 +'2', # 0xa7 +'2', # 0xa8 +'SH', # 0xa9 +'sh', # 0xaa +'t', # 0xab +'T', # 0xac +'t', # 0xad +'T', # 0xae +'U', # 0xaf +'u', # 0xb0 +'Y', # 0xb1 +'V', # 0xb2 +'Y', # 0xb3 +'y', # 0xb4 +'Z', # 0xb5 +'z', # 0xb6 +'ZH', # 0xb7 +'ZH', # 0xb8 +'zh', # 0xb9 +'zh', # 0xba +'2', # 0xbb +'5', # 0xbc +'5', # 0xbd +'ts', # 0xbe +'w', # 0xbf +'|', # 0xc0 +'||', # 0xc1 +'|=', # 0xc2 +'!', # 0xc3 +'DZ', # 0xc4 +'Dz', # 0xc5 +'dz', # 0xc6 +'LJ', # 0xc7 +'Lj', # 0xc8 +'lj', # 0xc9 +'NJ', # 0xca +'Nj', # 0xcb +'nj', # 0xcc +'A', # 0xcd +'a', # 0xce +'I', # 0xcf +'i', # 0xd0 +'O', # 0xd1 +'o', # 0xd2 +'U', # 0xd3 +'u', # 0xd4 +'U', # 0xd5 +'u', # 0xd6 +'U', # 0xd7 +'u', # 0xd8 +'U', # 0xd9 +'u', # 0xda +'U', # 0xdb +'u', # 0xdc +'@', # 0xdd +'A', # 0xde +'a', # 0xdf +'A', # 0xe0 +'a', # 0xe1 +'AE', # 0xe2 +'ae', # 0xe3 +'G', # 0xe4 +'g', # 0xe5 +'G', # 0xe6 +'g', # 0xe7 +'K', # 0xe8 +'k', # 0xe9 +'O', # 0xea +'o', # 0xeb +'O', # 0xec +'o', # 0xed +'ZH', # 0xee +'zh', # 0xef +'j', # 0xf0 +'DZ', # 0xf1 +'Dz', # 0xf2 +'dz', # 0xf3 +'G', # 0xf4 +'g', # 0xf5 +'HV', # 0xf6 +'W', # 0xf7 +'N', # 0xf8 +'n', # 0xf9 +'A', # 0xfa +'a', # 0xfb +'AE', # 0xfc +'ae', # 0xfd +'O', # 0xfe +'o', # 0xff +) diff --git a/nstock/modules/unidecode/x002.py b/nstock/modules/unidecode/x002.py new file mode 100644 index 0000000..ea45441 --- /dev/null +++ b/nstock/modules/unidecode/x002.py @@ -0,0 +1,257 @@ +data = ( +'A', # 0x00 +'a', # 0x01 +'A', # 0x02 +'a', # 0x03 +'E', # 0x04 +'e', # 0x05 +'E', # 0x06 +'e', # 0x07 +'I', # 0x08 +'i', # 0x09 +'I', # 0x0a +'i', # 0x0b +'O', # 0x0c +'o', # 0x0d +'O', # 0x0e +'o', # 0x0f +'R', # 0x10 +'r', # 0x11 +'R', # 0x12 +'r', # 0x13 +'U', # 0x14 +'u', # 0x15 +'U', # 0x16 +'u', # 0x17 +'S', # 0x18 +'s', # 0x19 +'T', # 0x1a +'t', # 0x1b +'Y', # 0x1c +'y', # 0x1d +'H', # 0x1e +'h', # 0x1f +'N', # 0x20 +'d', # 0x21 +'OU', # 0x22 +'ou', # 0x23 +'Z', # 0x24 +'z', # 0x25 +'A', # 0x26 +'a', # 0x27 +'E', # 0x28 +'e', # 0x29 +'O', # 0x2a +'o', # 0x2b +'O', # 0x2c +'o', # 0x2d +'O', # 0x2e +'o', # 0x2f +'O', # 0x30 +'o', # 0x31 +'Y', # 0x32 +'y', # 0x33 +'l', # 0x34 +'n', # 0x35 +'t', # 0x36 +'j', # 0x37 +'db', # 0x38 +'qp', # 0x39 +'A', # 0x3a +'C', # 0x3b +'c', # 0x3c +'L', # 0x3d +'T', # 0x3e +'s', # 0x3f +'z', # 0x40 +'[?]', # 0x41 +'[?]', # 0x42 +'B', # 0x43 +'U', # 0x44 +'^', # 0x45 +'E', # 0x46 +'e', # 0x47 +'J', # 0x48 +'j', # 0x49 +'q', # 0x4a +'q', # 0x4b +'R', # 0x4c +'r', # 0x4d +'Y', # 0x4e +'y', # 0x4f +'a', # 0x50 +'a', # 0x51 +'a', # 0x52 +'b', # 0x53 +'o', # 0x54 +'c', # 0x55 +'d', # 0x56 +'d', # 0x57 +'e', # 0x58 +'@', # 0x59 +'@', # 0x5a +'e', # 0x5b +'e', # 0x5c +'e', # 0x5d +'e', # 0x5e +'j', # 0x5f +'g', # 0x60 +'g', # 0x61 +'g', # 0x62 +'g', # 0x63 +'u', # 0x64 +'Y', # 0x65 +'h', # 0x66 +'h', # 0x67 +'i', # 0x68 +'i', # 0x69 +'I', # 0x6a +'l', # 0x6b +'l', # 0x6c +'l', # 0x6d +'lZ', # 0x6e +'W', # 0x6f +'W', # 0x70 +'m', # 0x71 +'n', # 0x72 +'n', # 0x73 +'n', # 0x74 +'o', # 0x75 +'OE', # 0x76 +'O', # 0x77 +'F', # 0x78 +'r', # 0x79 +'r', # 0x7a +'r', # 0x7b +'r', # 0x7c +'r', # 0x7d +'r', # 0x7e +'r', # 0x7f +'R', # 0x80 +'R', # 0x81 +'s', # 0x82 +'S', # 0x83 +'j', # 0x84 +'S', # 0x85 +'S', # 0x86 +'t', # 0x87 +'t', # 0x88 +'u', # 0x89 +'U', # 0x8a +'v', # 0x8b +'^', # 0x8c +'w', # 0x8d +'y', # 0x8e +'Y', # 0x8f +'z', # 0x90 +'z', # 0x91 +'Z', # 0x92 +'Z', # 0x93 +'?', # 0x94 +'?', # 0x95 +'?', # 0x96 +'C', # 0x97 +'@', # 0x98 +'B', # 0x99 +'E', # 0x9a +'G', # 0x9b +'H', # 0x9c +'j', # 0x9d +'k', # 0x9e +'L', # 0x9f +'q', # 0xa0 +'?', # 0xa1 +'?', # 0xa2 +'dz', # 0xa3 +'dZ', # 0xa4 +'dz', # 0xa5 +'ts', # 0xa6 +'tS', # 0xa7 +'tC', # 0xa8 +'fN', # 0xa9 +'ls', # 0xaa +'lz', # 0xab +'WW', # 0xac +']]', # 0xad +'h', # 0xae +'h', # 0xaf +'k', # 0xb0 +'h', # 0xb1 +'j', # 0xb2 +'r', # 0xb3 +'r', # 0xb4 +'r', # 0xb5 +'r', # 0xb6 +'w', # 0xb7 +'y', # 0xb8 +'\'', # 0xb9 +'"', # 0xba +'`', # 0xbb +'\'', # 0xbc +'`', # 0xbd +'`', # 0xbe +'\'', # 0xbf +'?', # 0xc0 +'?', # 0xc1 +'<', # 0xc2 +'>', # 0xc3 +'^', # 0xc4 +'V', # 0xc5 +'^', # 0xc6 +'V', # 0xc7 +'\'', # 0xc8 +'-', # 0xc9 +'/', # 0xca +'\\', # 0xcb +',', # 0xcc +'_', # 0xcd +'\\', # 0xce +'/', # 0xcf +':', # 0xd0 +'.', # 0xd1 +'`', # 0xd2 +'\'', # 0xd3 +'^', # 0xd4 +'V', # 0xd5 +'+', # 0xd6 +'-', # 0xd7 +'V', # 0xd8 +'.', # 0xd9 +'@', # 0xda +',', # 0xdb +'~', # 0xdc +'"', # 0xdd +'R', # 0xde +'X', # 0xdf +'G', # 0xe0 +'l', # 0xe1 +'s', # 0xe2 +'x', # 0xe3 +'?', # 0xe4 +'', # 0xe5 +'', # 0xe6 +'', # 0xe7 +'', # 0xe8 +'', # 0xe9 +'', # 0xea +'', # 0xeb +'V', # 0xec +'=', # 0xed +'"', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x003.py b/nstock/modules/unidecode/x003.py new file mode 100644 index 0000000..4ba8d72 --- /dev/null +++ b/nstock/modules/unidecode/x003.py @@ -0,0 +1,257 @@ +data = ( +'', # 0x00 +'', # 0x01 +'', # 0x02 +'', # 0x03 +'', # 0x04 +'', # 0x05 +'', # 0x06 +'', # 0x07 +'', # 0x08 +'', # 0x09 +'', # 0x0a +'', # 0x0b +'', # 0x0c +'', # 0x0d +'', # 0x0e +'', # 0x0f +'', # 0x10 +'', # 0x11 +'', # 0x12 +'', # 0x13 +'', # 0x14 +'', # 0x15 +'', # 0x16 +'', # 0x17 +'', # 0x18 +'', # 0x19 +'', # 0x1a +'', # 0x1b +'', # 0x1c +'', # 0x1d +'', # 0x1e +'', # 0x1f +'', # 0x20 +'', # 0x21 +'', # 0x22 +'', # 0x23 +'', # 0x24 +'', # 0x25 +'', # 0x26 +'', # 0x27 +'', # 0x28 +'', # 0x29 +'', # 0x2a +'', # 0x2b +'', # 0x2c +'', # 0x2d +'', # 0x2e +'', # 0x2f +'', # 0x30 +'', # 0x31 +'', # 0x32 +'', # 0x33 +'', # 0x34 +'', # 0x35 +'', # 0x36 +'', # 0x37 +'', # 0x38 +'', # 0x39 +'', # 0x3a +'', # 0x3b +'', # 0x3c +'', # 0x3d +'', # 0x3e +'', # 0x3f +'', # 0x40 +'', # 0x41 +'', # 0x42 +'', # 0x43 +'', # 0x44 +'', # 0x45 +'', # 0x46 +'', # 0x47 +'', # 0x48 +'', # 0x49 +'', # 0x4a +'', # 0x4b +'', # 0x4c +'', # 0x4d +'', # 0x4e +'[?]', # 0x4f +'[?]', # 0x50 +'[?]', # 0x51 +'[?]', # 0x52 +'[?]', # 0x53 +'[?]', # 0x54 +'[?]', # 0x55 +'[?]', # 0x56 +'[?]', # 0x57 +'[?]', # 0x58 +'[?]', # 0x59 +'[?]', # 0x5a +'[?]', # 0x5b +'[?]', # 0x5c +'[?]', # 0x5d +'[?]', # 0x5e +'[?]', # 0x5f +'', # 0x60 +'', # 0x61 +'', # 0x62 +'a', # 0x63 +'e', # 0x64 +'i', # 0x65 +'o', # 0x66 +'u', # 0x67 +'c', # 0x68 +'d', # 0x69 +'h', # 0x6a +'m', # 0x6b +'r', # 0x6c +'t', # 0x6d +'v', # 0x6e +'x', # 0x6f +'[?]', # 0x70 +'[?]', # 0x71 +'[?]', # 0x72 +'[?]', # 0x73 +'\'', # 0x74 +',', # 0x75 +'[?]', # 0x76 +'[?]', # 0x77 +'[?]', # 0x78 +'[?]', # 0x79 +'', # 0x7a +'[?]', # 0x7b +'[?]', # 0x7c +'[?]', # 0x7d +'?', # 0x7e +'[?]', # 0x7f +'[?]', # 0x80 +'[?]', # 0x81 +'[?]', # 0x82 +'[?]', # 0x83 +'', # 0x84 +'', # 0x85 +'A', # 0x86 +';', # 0x87 +'E', # 0x88 +'E', # 0x89 +'I', # 0x8a +'[?]', # 0x8b +'O', # 0x8c +'[?]', # 0x8d +'U', # 0x8e +'O', # 0x8f +'I', # 0x90 +'A', # 0x91 +'B', # 0x92 +'G', # 0x93 +'D', # 0x94 +'E', # 0x95 +'Z', # 0x96 +'E', # 0x97 +'Th', # 0x98 +'I', # 0x99 +'K', # 0x9a +'L', # 0x9b +'M', # 0x9c +'N', # 0x9d +'Ks', # 0x9e +'O', # 0x9f +'P', # 0xa0 +'R', # 0xa1 +'[?]', # 0xa2 +'S', # 0xa3 +'T', # 0xa4 +'U', # 0xa5 +'Ph', # 0xa6 +'Kh', # 0xa7 +'Ps', # 0xa8 +'O', # 0xa9 +'I', # 0xaa +'U', # 0xab +'a', # 0xac +'e', # 0xad +'e', # 0xae +'i', # 0xaf +'u', # 0xb0 +'a', # 0xb1 +'b', # 0xb2 +'g', # 0xb3 +'d', # 0xb4 +'e', # 0xb5 +'z', # 0xb6 +'e', # 0xb7 +'th', # 0xb8 +'i', # 0xb9 +'k', # 0xba +'l', # 0xbb +'m', # 0xbc +'n', # 0xbd +'x', # 0xbe +'o', # 0xbf +'p', # 0xc0 +'r', # 0xc1 +'s', # 0xc2 +'s', # 0xc3 +'t', # 0xc4 +'u', # 0xc5 +'ph', # 0xc6 +'kh', # 0xc7 +'ps', # 0xc8 +'o', # 0xc9 +'i', # 0xca +'u', # 0xcb +'o', # 0xcc +'u', # 0xcd +'o', # 0xce +'[?]', # 0xcf +'b', # 0xd0 +'th', # 0xd1 +'U', # 0xd2 +'U', # 0xd3 +'U', # 0xd4 +'ph', # 0xd5 +'p', # 0xd6 +'&', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'St', # 0xda +'st', # 0xdb +'W', # 0xdc +'w', # 0xdd +'Q', # 0xde +'q', # 0xdf +'Sp', # 0xe0 +'sp', # 0xe1 +'Sh', # 0xe2 +'sh', # 0xe3 +'F', # 0xe4 +'f', # 0xe5 +'Kh', # 0xe6 +'kh', # 0xe7 +'H', # 0xe8 +'h', # 0xe9 +'G', # 0xea +'g', # 0xeb +'CH', # 0xec +'ch', # 0xed +'Ti', # 0xee +'ti', # 0xef +'k', # 0xf0 +'r', # 0xf1 +'c', # 0xf2 +'j', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x004.py b/nstock/modules/unidecode/x004.py new file mode 100644 index 0000000..1cc3dbc --- /dev/null +++ b/nstock/modules/unidecode/x004.py @@ -0,0 +1,257 @@ +data = ( +'Ie', # 0x00 +'Io', # 0x01 +'Dj', # 0x02 +'Gj', # 0x03 +'Ie', # 0x04 +'Dz', # 0x05 +'I', # 0x06 +'Yi', # 0x07 +'J', # 0x08 +'Lj', # 0x09 +'Nj', # 0x0a +'Tsh', # 0x0b +'Kj', # 0x0c +'I', # 0x0d +'U', # 0x0e +'Dzh', # 0x0f +'A', # 0x10 +'B', # 0x11 +'V', # 0x12 +'G', # 0x13 +'D', # 0x14 +'E', # 0x15 +'Zh', # 0x16 +'Z', # 0x17 +'I', # 0x18 +'I', # 0x19 +'K', # 0x1a +'L', # 0x1b +'M', # 0x1c +'N', # 0x1d +'O', # 0x1e +'P', # 0x1f +'R', # 0x20 +'S', # 0x21 +'T', # 0x22 +'U', # 0x23 +'F', # 0x24 +'Kh', # 0x25 +'Ts', # 0x26 +'Ch', # 0x27 +'Sh', # 0x28 +'Shch', # 0x29 +'\'', # 0x2a +'Y', # 0x2b +'\'', # 0x2c +'E', # 0x2d +'Iu', # 0x2e +'Ia', # 0x2f +'a', # 0x30 +'b', # 0x31 +'v', # 0x32 +'g', # 0x33 +'d', # 0x34 +'e', # 0x35 +'zh', # 0x36 +'z', # 0x37 +'i', # 0x38 +'i', # 0x39 +'k', # 0x3a +'l', # 0x3b +'m', # 0x3c +'n', # 0x3d +'o', # 0x3e +'p', # 0x3f +'r', # 0x40 +'s', # 0x41 +'t', # 0x42 +'u', # 0x43 +'f', # 0x44 +'kh', # 0x45 +'ts', # 0x46 +'ch', # 0x47 +'sh', # 0x48 +'shch', # 0x49 +'\'', # 0x4a +'y', # 0x4b +'\'', # 0x4c +'e', # 0x4d +'iu', # 0x4e +'ia', # 0x4f +'ie', # 0x50 +'io', # 0x51 +'dj', # 0x52 +'gj', # 0x53 +'ie', # 0x54 +'dz', # 0x55 +'i', # 0x56 +'yi', # 0x57 +'j', # 0x58 +'lj', # 0x59 +'nj', # 0x5a +'tsh', # 0x5b +'kj', # 0x5c +'i', # 0x5d +'u', # 0x5e +'dzh', # 0x5f +'O', # 0x60 +'o', # 0x61 +'E', # 0x62 +'e', # 0x63 +'Ie', # 0x64 +'ie', # 0x65 +'E', # 0x66 +'e', # 0x67 +'Ie', # 0x68 +'ie', # 0x69 +'O', # 0x6a +'o', # 0x6b +'Io', # 0x6c +'io', # 0x6d +'Ks', # 0x6e +'ks', # 0x6f +'Ps', # 0x70 +'ps', # 0x71 +'F', # 0x72 +'f', # 0x73 +'Y', # 0x74 +'y', # 0x75 +'Y', # 0x76 +'y', # 0x77 +'u', # 0x78 +'u', # 0x79 +'O', # 0x7a +'o', # 0x7b +'O', # 0x7c +'o', # 0x7d +'Ot', # 0x7e +'ot', # 0x7f +'Q', # 0x80 +'q', # 0x81 +'*1000*', # 0x82 +'', # 0x83 +'', # 0x84 +'', # 0x85 +'', # 0x86 +'[?]', # 0x87 +'*100.000*', # 0x88 +'*1.000.000*', # 0x89 +'[?]', # 0x8a +'[?]', # 0x8b +'"', # 0x8c +'"', # 0x8d +'R\'', # 0x8e +'r\'', # 0x8f +'G\'', # 0x90 +'g\'', # 0x91 +'G\'', # 0x92 +'g\'', # 0x93 +'G\'', # 0x94 +'g\'', # 0x95 +'Zh\'', # 0x96 +'zh\'', # 0x97 +'Z\'', # 0x98 +'z\'', # 0x99 +'K\'', # 0x9a +'k\'', # 0x9b +'K\'', # 0x9c +'k\'', # 0x9d +'K\'', # 0x9e +'k\'', # 0x9f +'K\'', # 0xa0 +'k\'', # 0xa1 +'N\'', # 0xa2 +'n\'', # 0xa3 +'Ng', # 0xa4 +'ng', # 0xa5 +'P\'', # 0xa6 +'p\'', # 0xa7 +'Kh', # 0xa8 +'kh', # 0xa9 +'S\'', # 0xaa +'s\'', # 0xab +'T\'', # 0xac +'t\'', # 0xad +'U', # 0xae +'u', # 0xaf +'U\'', # 0xb0 +'u\'', # 0xb1 +'Kh\'', # 0xb2 +'kh\'', # 0xb3 +'Tts', # 0xb4 +'tts', # 0xb5 +'Ch\'', # 0xb6 +'ch\'', # 0xb7 +'Ch\'', # 0xb8 +'ch\'', # 0xb9 +'H', # 0xba +'h', # 0xbb +'Ch', # 0xbc +'ch', # 0xbd +'Ch\'', # 0xbe +'ch\'', # 0xbf +'`', # 0xc0 +'Zh', # 0xc1 +'zh', # 0xc2 +'K\'', # 0xc3 +'k\'', # 0xc4 +'[?]', # 0xc5 +'[?]', # 0xc6 +'N\'', # 0xc7 +'n\'', # 0xc8 +'[?]', # 0xc9 +'[?]', # 0xca +'Ch', # 0xcb +'ch', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'a', # 0xd0 +'a', # 0xd1 +'A', # 0xd2 +'a', # 0xd3 +'Ae', # 0xd4 +'ae', # 0xd5 +'Ie', # 0xd6 +'ie', # 0xd7 +'@', # 0xd8 +'@', # 0xd9 +'@', # 0xda +'@', # 0xdb +'Zh', # 0xdc +'zh', # 0xdd +'Z', # 0xde +'z', # 0xdf +'Dz', # 0xe0 +'dz', # 0xe1 +'I', # 0xe2 +'i', # 0xe3 +'I', # 0xe4 +'i', # 0xe5 +'O', # 0xe6 +'o', # 0xe7 +'O', # 0xe8 +'o', # 0xe9 +'O', # 0xea +'o', # 0xeb +'E', # 0xec +'e', # 0xed +'U', # 0xee +'u', # 0xef +'U', # 0xf0 +'u', # 0xf1 +'U', # 0xf2 +'u', # 0xf3 +'Ch', # 0xf4 +'ch', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'Y', # 0xf8 +'y', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x005.py b/nstock/modules/unidecode/x005.py new file mode 100644 index 0000000..2913fff --- /dev/null +++ b/nstock/modules/unidecode/x005.py @@ -0,0 +1,257 @@ +data = ( +'[?]', # 0x00 +'[?]', # 0x01 +'[?]', # 0x02 +'[?]', # 0x03 +'[?]', # 0x04 +'[?]', # 0x05 +'[?]', # 0x06 +'[?]', # 0x07 +'[?]', # 0x08 +'[?]', # 0x09 +'[?]', # 0x0a +'[?]', # 0x0b +'[?]', # 0x0c +'[?]', # 0x0d +'[?]', # 0x0e +'[?]', # 0x0f +'[?]', # 0x10 +'[?]', # 0x11 +'[?]', # 0x12 +'[?]', # 0x13 +'[?]', # 0x14 +'[?]', # 0x15 +'[?]', # 0x16 +'[?]', # 0x17 +'[?]', # 0x18 +'[?]', # 0x19 +'[?]', # 0x1a +'[?]', # 0x1b +'[?]', # 0x1c +'[?]', # 0x1d +'[?]', # 0x1e +'[?]', # 0x1f +'[?]', # 0x20 +'[?]', # 0x21 +'[?]', # 0x22 +'[?]', # 0x23 +'[?]', # 0x24 +'[?]', # 0x25 +'[?]', # 0x26 +'[?]', # 0x27 +'[?]', # 0x28 +'[?]', # 0x29 +'[?]', # 0x2a +'[?]', # 0x2b +'[?]', # 0x2c +'[?]', # 0x2d +'[?]', # 0x2e +'[?]', # 0x2f +'[?]', # 0x30 +'A', # 0x31 +'B', # 0x32 +'G', # 0x33 +'D', # 0x34 +'E', # 0x35 +'Z', # 0x36 +'E', # 0x37 +'E', # 0x38 +'T`', # 0x39 +'Zh', # 0x3a +'I', # 0x3b +'L', # 0x3c +'Kh', # 0x3d +'Ts', # 0x3e +'K', # 0x3f +'H', # 0x40 +'Dz', # 0x41 +'Gh', # 0x42 +'Ch', # 0x43 +'M', # 0x44 +'Y', # 0x45 +'N', # 0x46 +'Sh', # 0x47 +'O', # 0x48 +'Ch`', # 0x49 +'P', # 0x4a +'J', # 0x4b +'Rh', # 0x4c +'S', # 0x4d +'V', # 0x4e +'T', # 0x4f +'R', # 0x50 +'Ts`', # 0x51 +'W', # 0x52 +'P`', # 0x53 +'K`', # 0x54 +'O', # 0x55 +'F', # 0x56 +'[?]', # 0x57 +'[?]', # 0x58 +'<', # 0x59 +'\'', # 0x5a +'/', # 0x5b +'!', # 0x5c +',', # 0x5d +'?', # 0x5e +'.', # 0x5f +'[?]', # 0x60 +'a', # 0x61 +'b', # 0x62 +'g', # 0x63 +'d', # 0x64 +'e', # 0x65 +'z', # 0x66 +'e', # 0x67 +'e', # 0x68 +'t`', # 0x69 +'zh', # 0x6a +'i', # 0x6b +'l', # 0x6c +'kh', # 0x6d +'ts', # 0x6e +'k', # 0x6f +'h', # 0x70 +'dz', # 0x71 +'gh', # 0x72 +'ch', # 0x73 +'m', # 0x74 +'y', # 0x75 +'n', # 0x76 +'sh', # 0x77 +'o', # 0x78 +'ch`', # 0x79 +'p', # 0x7a +'j', # 0x7b +'rh', # 0x7c +'s', # 0x7d +'v', # 0x7e +'t', # 0x7f +'r', # 0x80 +'ts`', # 0x81 +'w', # 0x82 +'p`', # 0x83 +'k`', # 0x84 +'o', # 0x85 +'f', # 0x86 +'ew', # 0x87 +'[?]', # 0x88 +':', # 0x89 +'-', # 0x8a +'[?]', # 0x8b +'[?]', # 0x8c +'[?]', # 0x8d +'[?]', # 0x8e +'[?]', # 0x8f +'[?]', # 0x90 +'', # 0x91 +'', # 0x92 +'', # 0x93 +'', # 0x94 +'', # 0x95 +'', # 0x96 +'', # 0x97 +'', # 0x98 +'', # 0x99 +'', # 0x9a +'', # 0x9b +'', # 0x9c +'', # 0x9d +'', # 0x9e +'', # 0x9f +'', # 0xa0 +'', # 0xa1 +'[?]', # 0xa2 +'', # 0xa3 +'', # 0xa4 +'', # 0xa5 +'', # 0xa6 +'', # 0xa7 +'', # 0xa8 +'', # 0xa9 +'', # 0xaa +'', # 0xab +'', # 0xac +'', # 0xad +'', # 0xae +'', # 0xaf +'@', # 0xb0 +'e', # 0xb1 +'a', # 0xb2 +'o', # 0xb3 +'i', # 0xb4 +'e', # 0xb5 +'e', # 0xb6 +'a', # 0xb7 +'a', # 0xb8 +'o', # 0xb9 +'[?]', # 0xba +'u', # 0xbb +'\'', # 0xbc +'', # 0xbd +'', # 0xbe +'', # 0xbf +'|', # 0xc0 +'', # 0xc1 +'', # 0xc2 +':', # 0xc3 +'', # 0xc4 +'[?]', # 0xc5 +'[?]', # 0xc6 +'[?]', # 0xc7 +'[?]', # 0xc8 +'[?]', # 0xc9 +'[?]', # 0xca +'[?]', # 0xcb +'[?]', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'', # 0xd0 +'b', # 0xd1 +'g', # 0xd2 +'d', # 0xd3 +'h', # 0xd4 +'v', # 0xd5 +'z', # 0xd6 +'kh', # 0xd7 +'t', # 0xd8 +'y', # 0xd9 +'k', # 0xda +'k', # 0xdb +'l', # 0xdc +'m', # 0xdd +'m', # 0xde +'n', # 0xdf +'n', # 0xe0 +'s', # 0xe1 +'`', # 0xe2 +'p', # 0xe3 +'p', # 0xe4 +'ts', # 0xe5 +'ts', # 0xe6 +'q', # 0xe7 +'r', # 0xe8 +'sh', # 0xe9 +'t', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'V', # 0xf0 +'oy', # 0xf1 +'i', # 0xf2 +'\'', # 0xf3 +'"', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x006.py b/nstock/modules/unidecode/x006.py new file mode 100644 index 0000000..09440b2 --- /dev/null +++ b/nstock/modules/unidecode/x006.py @@ -0,0 +1,257 @@ +data = ( +'[?]', # 0x00 +'[?]', # 0x01 +'[?]', # 0x02 +'[?]', # 0x03 +'[?]', # 0x04 +'[?]', # 0x05 +'[?]', # 0x06 +'[?]', # 0x07 +'[?]', # 0x08 +'[?]', # 0x09 +'[?]', # 0x0a +'[?]', # 0x0b +',', # 0x0c +'[?]', # 0x0d +'[?]', # 0x0e +'[?]', # 0x0f +'[?]', # 0x10 +'[?]', # 0x11 +'[?]', # 0x12 +'[?]', # 0x13 +'[?]', # 0x14 +'[?]', # 0x15 +'[?]', # 0x16 +'[?]', # 0x17 +'[?]', # 0x18 +'[?]', # 0x19 +'[?]', # 0x1a +';', # 0x1b +'[?]', # 0x1c +'[?]', # 0x1d +'[?]', # 0x1e +'?', # 0x1f +'[?]', # 0x20 +'', # 0x21 +'a', # 0x22 +'\'', # 0x23 +'w\'', # 0x24 +'', # 0x25 +'y\'', # 0x26 +'', # 0x27 +'b', # 0x28 +'@', # 0x29 +'t', # 0x2a +'th', # 0x2b +'j', # 0x2c +'H', # 0x2d +'kh', # 0x2e +'d', # 0x2f +'dh', # 0x30 +'r', # 0x31 +'z', # 0x32 +'s', # 0x33 +'sh', # 0x34 +'S', # 0x35 +'D', # 0x36 +'T', # 0x37 +'Z', # 0x38 +'`', # 0x39 +'G', # 0x3a +'[?]', # 0x3b +'[?]', # 0x3c +'[?]', # 0x3d +'[?]', # 0x3e +'[?]', # 0x3f +'', # 0x40 +'f', # 0x41 +'q', # 0x42 +'k', # 0x43 +'l', # 0x44 +'m', # 0x45 +'n', # 0x46 +'h', # 0x47 +'w', # 0x48 +'~', # 0x49 +'y', # 0x4a +'an', # 0x4b +'un', # 0x4c +'in', # 0x4d +'a', # 0x4e +'u', # 0x4f +'i', # 0x50 +'W', # 0x51 +'', # 0x52 +'', # 0x53 +'\'', # 0x54 +'\'', # 0x55 +'[?]', # 0x56 +'[?]', # 0x57 +'[?]', # 0x58 +'[?]', # 0x59 +'[?]', # 0x5a +'[?]', # 0x5b +'[?]', # 0x5c +'[?]', # 0x5d +'[?]', # 0x5e +'[?]', # 0x5f +'0', # 0x60 +'1', # 0x61 +'2', # 0x62 +'3', # 0x63 +'4', # 0x64 +'5', # 0x65 +'6', # 0x66 +'7', # 0x67 +'8', # 0x68 +'9', # 0x69 +'%', # 0x6a +'.', # 0x6b +',', # 0x6c +'*', # 0x6d +'[?]', # 0x6e +'[?]', # 0x6f +'', # 0x70 +'\'', # 0x71 +'\'', # 0x72 +'\'', # 0x73 +'', # 0x74 +'\'', # 0x75 +'\'w', # 0x76 +'\'u', # 0x77 +'\'y', # 0x78 +'tt', # 0x79 +'tth', # 0x7a +'b', # 0x7b +'t', # 0x7c +'T', # 0x7d +'p', # 0x7e +'th', # 0x7f +'bh', # 0x80 +'\'h', # 0x81 +'H', # 0x82 +'ny', # 0x83 +'dy', # 0x84 +'H', # 0x85 +'ch', # 0x86 +'cch', # 0x87 +'dd', # 0x88 +'D', # 0x89 +'D', # 0x8a +'Dt', # 0x8b +'dh', # 0x8c +'ddh', # 0x8d +'d', # 0x8e +'D', # 0x8f +'D', # 0x90 +'rr', # 0x91 +'R', # 0x92 +'R', # 0x93 +'R', # 0x94 +'R', # 0x95 +'R', # 0x96 +'R', # 0x97 +'j', # 0x98 +'R', # 0x99 +'S', # 0x9a +'S', # 0x9b +'S', # 0x9c +'S', # 0x9d +'S', # 0x9e +'T', # 0x9f +'GH', # 0xa0 +'F', # 0xa1 +'F', # 0xa2 +'F', # 0xa3 +'v', # 0xa4 +'f', # 0xa5 +'ph', # 0xa6 +'Q', # 0xa7 +'Q', # 0xa8 +'kh', # 0xa9 +'k', # 0xaa +'K', # 0xab +'K', # 0xac +'ng', # 0xad +'K', # 0xae +'g', # 0xaf +'G', # 0xb0 +'N', # 0xb1 +'G', # 0xb2 +'G', # 0xb3 +'G', # 0xb4 +'L', # 0xb5 +'L', # 0xb6 +'L', # 0xb7 +'L', # 0xb8 +'N', # 0xb9 +'N', # 0xba +'N', # 0xbb +'N', # 0xbc +'N', # 0xbd +'h', # 0xbe +'Ch', # 0xbf +'hy', # 0xc0 +'h', # 0xc1 +'H', # 0xc2 +'@', # 0xc3 +'W', # 0xc4 +'oe', # 0xc5 +'oe', # 0xc6 +'u', # 0xc7 +'yu', # 0xc8 +'yu', # 0xc9 +'W', # 0xca +'v', # 0xcb +'y', # 0xcc +'Y', # 0xcd +'Y', # 0xce +'W', # 0xcf +'', # 0xd0 +'', # 0xd1 +'y', # 0xd2 +'y\'', # 0xd3 +'.', # 0xd4 +'ae', # 0xd5 +'', # 0xd6 +'', # 0xd7 +'', # 0xd8 +'', # 0xd9 +'', # 0xda +'', # 0xdb +'', # 0xdc +'@', # 0xdd +'#', # 0xde +'', # 0xdf +'', # 0xe0 +'', # 0xe1 +'', # 0xe2 +'', # 0xe3 +'', # 0xe4 +'', # 0xe5 +'', # 0xe6 +'', # 0xe7 +'', # 0xe8 +'^', # 0xe9 +'', # 0xea +'', # 0xeb +'', # 0xec +'', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'0', # 0xf0 +'1', # 0xf1 +'2', # 0xf2 +'3', # 0xf3 +'4', # 0xf4 +'5', # 0xf5 +'6', # 0xf6 +'7', # 0xf7 +'8', # 0xf8 +'9', # 0xf9 +'Sh', # 0xfa +'D', # 0xfb +'Gh', # 0xfc +'&', # 0xfd +'+m', # 0xfe +) diff --git a/nstock/modules/unidecode/x007.py b/nstock/modules/unidecode/x007.py new file mode 100644 index 0000000..d2c0021 --- /dev/null +++ b/nstock/modules/unidecode/x007.py @@ -0,0 +1,257 @@ +data = ( +'//', # 0x00 +'/', # 0x01 +',', # 0x02 +'!', # 0x03 +'!', # 0x04 +'-', # 0x05 +',', # 0x06 +',', # 0x07 +';', # 0x08 +'?', # 0x09 +'~', # 0x0a +'{', # 0x0b +'}', # 0x0c +'*', # 0x0d +'[?]', # 0x0e +'', # 0x0f +'\'', # 0x10 +'', # 0x11 +'b', # 0x12 +'g', # 0x13 +'g', # 0x14 +'d', # 0x15 +'d', # 0x16 +'h', # 0x17 +'w', # 0x18 +'z', # 0x19 +'H', # 0x1a +'t', # 0x1b +'t', # 0x1c +'y', # 0x1d +'yh', # 0x1e +'k', # 0x1f +'l', # 0x20 +'m', # 0x21 +'n', # 0x22 +'s', # 0x23 +'s', # 0x24 +'`', # 0x25 +'p', # 0x26 +'p', # 0x27 +'S', # 0x28 +'q', # 0x29 +'r', # 0x2a +'sh', # 0x2b +'t', # 0x2c +'[?]', # 0x2d +'[?]', # 0x2e +'[?]', # 0x2f +'a', # 0x30 +'a', # 0x31 +'a', # 0x32 +'A', # 0x33 +'A', # 0x34 +'A', # 0x35 +'e', # 0x36 +'e', # 0x37 +'e', # 0x38 +'E', # 0x39 +'i', # 0x3a +'i', # 0x3b +'u', # 0x3c +'u', # 0x3d +'u', # 0x3e +'o', # 0x3f +'', # 0x40 +'`', # 0x41 +'\'', # 0x42 +'', # 0x43 +'', # 0x44 +'X', # 0x45 +'Q', # 0x46 +'@', # 0x47 +'@', # 0x48 +'|', # 0x49 +'+', # 0x4a +'[?]', # 0x4b +'[?]', # 0x4c +'[?]', # 0x4d +'[?]', # 0x4e +'[?]', # 0x4f +'[?]', # 0x50 +'[?]', # 0x51 +'[?]', # 0x52 +'[?]', # 0x53 +'[?]', # 0x54 +'[?]', # 0x55 +'[?]', # 0x56 +'[?]', # 0x57 +'[?]', # 0x58 +'[?]', # 0x59 +'[?]', # 0x5a +'[?]', # 0x5b +'[?]', # 0x5c +'[?]', # 0x5d +'[?]', # 0x5e +'[?]', # 0x5f +'[?]', # 0x60 +'[?]', # 0x61 +'[?]', # 0x62 +'[?]', # 0x63 +'[?]', # 0x64 +'[?]', # 0x65 +'[?]', # 0x66 +'[?]', # 0x67 +'[?]', # 0x68 +'[?]', # 0x69 +'[?]', # 0x6a +'[?]', # 0x6b +'[?]', # 0x6c +'[?]', # 0x6d +'[?]', # 0x6e +'[?]', # 0x6f +'[?]', # 0x70 +'[?]', # 0x71 +'[?]', # 0x72 +'[?]', # 0x73 +'[?]', # 0x74 +'[?]', # 0x75 +'[?]', # 0x76 +'[?]', # 0x77 +'[?]', # 0x78 +'[?]', # 0x79 +'[?]', # 0x7a +'[?]', # 0x7b +'[?]', # 0x7c +'[?]', # 0x7d +'[?]', # 0x7e +'[?]', # 0x7f +'h', # 0x80 +'sh', # 0x81 +'n', # 0x82 +'r', # 0x83 +'b', # 0x84 +'L', # 0x85 +'k', # 0x86 +'\'', # 0x87 +'v', # 0x88 +'m', # 0x89 +'f', # 0x8a +'dh', # 0x8b +'th', # 0x8c +'l', # 0x8d +'g', # 0x8e +'ny', # 0x8f +'s', # 0x90 +'d', # 0x91 +'z', # 0x92 +'t', # 0x93 +'y', # 0x94 +'p', # 0x95 +'j', # 0x96 +'ch', # 0x97 +'tt', # 0x98 +'hh', # 0x99 +'kh', # 0x9a +'th', # 0x9b +'z', # 0x9c +'sh', # 0x9d +'s', # 0x9e +'d', # 0x9f +'t', # 0xa0 +'z', # 0xa1 +'`', # 0xa2 +'gh', # 0xa3 +'q', # 0xa4 +'w', # 0xa5 +'a', # 0xa6 +'aa', # 0xa7 +'i', # 0xa8 +'ee', # 0xa9 +'u', # 0xaa +'oo', # 0xab +'e', # 0xac +'ey', # 0xad +'o', # 0xae +'oa', # 0xaf +'', # 0xb0 +'[?]', # 0xb1 +'[?]', # 0xb2 +'[?]', # 0xb3 +'[?]', # 0xb4 +'[?]', # 0xb5 +'[?]', # 0xb6 +'[?]', # 0xb7 +'[?]', # 0xb8 +'[?]', # 0xb9 +'[?]', # 0xba +'[?]', # 0xbb +'[?]', # 0xbc +'[?]', # 0xbd +'[?]', # 0xbe +'[?]', # 0xbf +'[?]', # 0xc0 +'[?]', # 0xc1 +'[?]', # 0xc2 +'[?]', # 0xc3 +'[?]', # 0xc4 +'[?]', # 0xc5 +'[?]', # 0xc6 +'[?]', # 0xc7 +'[?]', # 0xc8 +'[?]', # 0xc9 +'[?]', # 0xca +'[?]', # 0xcb +'[?]', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'[?]', # 0xd0 +'[?]', # 0xd1 +'[?]', # 0xd2 +'[?]', # 0xd3 +'[?]', # 0xd4 +'[?]', # 0xd5 +'[?]', # 0xd6 +'[?]', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'[?]', # 0xdc +'[?]', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'[?]', # 0xe0 +'[?]', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'[?]', # 0xe6 +'[?]', # 0xe7 +'[?]', # 0xe8 +'[?]', # 0xe9 +'[?]', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x009.py b/nstock/modules/unidecode/x009.py new file mode 100644 index 0000000..564ec78 --- /dev/null +++ b/nstock/modules/unidecode/x009.py @@ -0,0 +1,257 @@ +data = ( +'[?]', # 0x00 +'N', # 0x01 +'N', # 0x02 +'H', # 0x03 +'[?]', # 0x04 +'a', # 0x05 +'aa', # 0x06 +'i', # 0x07 +'ii', # 0x08 +'u', # 0x09 +'uu', # 0x0a +'R', # 0x0b +'L', # 0x0c +'eN', # 0x0d +'e', # 0x0e +'e', # 0x0f +'ai', # 0x10 +'oN', # 0x11 +'o', # 0x12 +'o', # 0x13 +'au', # 0x14 +'k', # 0x15 +'kh', # 0x16 +'g', # 0x17 +'gh', # 0x18 +'ng', # 0x19 +'c', # 0x1a +'ch', # 0x1b +'j', # 0x1c +'jh', # 0x1d +'ny', # 0x1e +'tt', # 0x1f +'tth', # 0x20 +'dd', # 0x21 +'ddh', # 0x22 +'nn', # 0x23 +'t', # 0x24 +'th', # 0x25 +'d', # 0x26 +'dh', # 0x27 +'n', # 0x28 +'nnn', # 0x29 +'p', # 0x2a +'ph', # 0x2b +'b', # 0x2c +'bh', # 0x2d +'m', # 0x2e +'y', # 0x2f +'r', # 0x30 +'rr', # 0x31 +'l', # 0x32 +'l', # 0x33 +'lll', # 0x34 +'v', # 0x35 +'sh', # 0x36 +'ss', # 0x37 +'s', # 0x38 +'h', # 0x39 +'[?]', # 0x3a +'[?]', # 0x3b +'\'', # 0x3c +'\'', # 0x3d +'aa', # 0x3e +'i', # 0x3f +'ii', # 0x40 +'u', # 0x41 +'uu', # 0x42 +'R', # 0x43 +'RR', # 0x44 +'eN', # 0x45 +'e', # 0x46 +'e', # 0x47 +'ai', # 0x48 +'oN', # 0x49 +'o', # 0x4a +'o', # 0x4b +'au', # 0x4c +'', # 0x4d +'[?]', # 0x4e +'[?]', # 0x4f +'AUM', # 0x50 +'\'', # 0x51 +'\'', # 0x52 +'`', # 0x53 +'\'', # 0x54 +'[?]', # 0x55 +'[?]', # 0x56 +'[?]', # 0x57 +'q', # 0x58 +'khh', # 0x59 +'ghh', # 0x5a +'z', # 0x5b +'dddh', # 0x5c +'rh', # 0x5d +'f', # 0x5e +'yy', # 0x5f +'RR', # 0x60 +'LL', # 0x61 +'L', # 0x62 +'LL', # 0x63 +' / ', # 0x64 +' // ', # 0x65 +'0', # 0x66 +'1', # 0x67 +'2', # 0x68 +'3', # 0x69 +'4', # 0x6a +'5', # 0x6b +'6', # 0x6c +'7', # 0x6d +'8', # 0x6e +'9', # 0x6f +'.', # 0x70 +'[?]', # 0x71 +'[?]', # 0x72 +'[?]', # 0x73 +'[?]', # 0x74 +'[?]', # 0x75 +'[?]', # 0x76 +'[?]', # 0x77 +'[?]', # 0x78 +'[?]', # 0x79 +'[?]', # 0x7a +'[?]', # 0x7b +'[?]', # 0x7c +'[?]', # 0x7d +'[?]', # 0x7e +'[?]', # 0x7f +'[?]', # 0x80 +'N', # 0x81 +'N', # 0x82 +'H', # 0x83 +'[?]', # 0x84 +'a', # 0x85 +'aa', # 0x86 +'i', # 0x87 +'ii', # 0x88 +'u', # 0x89 +'uu', # 0x8a +'R', # 0x8b +'RR', # 0x8c +'[?]', # 0x8d +'[?]', # 0x8e +'e', # 0x8f +'ai', # 0x90 +'[?]', # 0x91 +'[?]', # 0x92 +'o', # 0x93 +'au', # 0x94 +'k', # 0x95 +'kh', # 0x96 +'g', # 0x97 +'gh', # 0x98 +'ng', # 0x99 +'c', # 0x9a +'ch', # 0x9b +'j', # 0x9c +'jh', # 0x9d +'ny', # 0x9e +'tt', # 0x9f +'tth', # 0xa0 +'dd', # 0xa1 +'ddh', # 0xa2 +'nn', # 0xa3 +'t', # 0xa4 +'th', # 0xa5 +'d', # 0xa6 +'dh', # 0xa7 +'n', # 0xa8 +'[?]', # 0xa9 +'p', # 0xaa +'ph', # 0xab +'b', # 0xac +'bh', # 0xad +'m', # 0xae +'y', # 0xaf +'r', # 0xb0 +'[?]', # 0xb1 +'l', # 0xb2 +'[?]', # 0xb3 +'[?]', # 0xb4 +'[?]', # 0xb5 +'sh', # 0xb6 +'ss', # 0xb7 +'s', # 0xb8 +'h', # 0xb9 +'[?]', # 0xba +'[?]', # 0xbb +'\'', # 0xbc +'[?]', # 0xbd +'aa', # 0xbe +'i', # 0xbf +'ii', # 0xc0 +'u', # 0xc1 +'uu', # 0xc2 +'R', # 0xc3 +'RR', # 0xc4 +'[?]', # 0xc5 +'[?]', # 0xc6 +'e', # 0xc7 +'ai', # 0xc8 +'[?]', # 0xc9 +'[?]', # 0xca +'o', # 0xcb +'au', # 0xcc +'', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'[?]', # 0xd0 +'[?]', # 0xd1 +'[?]', # 0xd2 +'[?]', # 0xd3 +'[?]', # 0xd4 +'[?]', # 0xd5 +'[?]', # 0xd6 +'+', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'rr', # 0xdc +'rh', # 0xdd +'[?]', # 0xde +'yy', # 0xdf +'RR', # 0xe0 +'LL', # 0xe1 +'L', # 0xe2 +'LL', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'0', # 0xe6 +'1', # 0xe7 +'2', # 0xe8 +'3', # 0xe9 +'4', # 0xea +'5', # 0xeb +'6', # 0xec +'7', # 0xed +'8', # 0xee +'9', # 0xef +'r\'', # 0xf0 +'r`', # 0xf1 +'Rs', # 0xf2 +'Rs', # 0xf3 +'1/', # 0xf4 +'2/', # 0xf5 +'3/', # 0xf6 +'4/', # 0xf7 +' 1 - 1/', # 0xf8 +'/16', # 0xf9 +'', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x00a.py b/nstock/modules/unidecode/x00a.py new file mode 100644 index 0000000..1ccd9df --- /dev/null +++ b/nstock/modules/unidecode/x00a.py @@ -0,0 +1,257 @@ +data = ( +'[?]', # 0x00 +'[?]', # 0x01 +'N', # 0x02 +'[?]', # 0x03 +'[?]', # 0x04 +'a', # 0x05 +'aa', # 0x06 +'i', # 0x07 +'ii', # 0x08 +'u', # 0x09 +'uu', # 0x0a +'[?]', # 0x0b +'[?]', # 0x0c +'[?]', # 0x0d +'[?]', # 0x0e +'ee', # 0x0f +'ai', # 0x10 +'[?]', # 0x11 +'[?]', # 0x12 +'oo', # 0x13 +'au', # 0x14 +'k', # 0x15 +'kh', # 0x16 +'g', # 0x17 +'gh', # 0x18 +'ng', # 0x19 +'c', # 0x1a +'ch', # 0x1b +'j', # 0x1c +'jh', # 0x1d +'ny', # 0x1e +'tt', # 0x1f +'tth', # 0x20 +'dd', # 0x21 +'ddh', # 0x22 +'nn', # 0x23 +'t', # 0x24 +'th', # 0x25 +'d', # 0x26 +'dh', # 0x27 +'n', # 0x28 +'[?]', # 0x29 +'p', # 0x2a +'ph', # 0x2b +'b', # 0x2c +'bb', # 0x2d +'m', # 0x2e +'y', # 0x2f +'r', # 0x30 +'[?]', # 0x31 +'l', # 0x32 +'ll', # 0x33 +'[?]', # 0x34 +'v', # 0x35 +'sh', # 0x36 +'[?]', # 0x37 +'s', # 0x38 +'h', # 0x39 +'[?]', # 0x3a +'[?]', # 0x3b +'\'', # 0x3c +'[?]', # 0x3d +'aa', # 0x3e +'i', # 0x3f +'ii', # 0x40 +'u', # 0x41 +'uu', # 0x42 +'[?]', # 0x43 +'[?]', # 0x44 +'[?]', # 0x45 +'[?]', # 0x46 +'ee', # 0x47 +'ai', # 0x48 +'[?]', # 0x49 +'[?]', # 0x4a +'oo', # 0x4b +'au', # 0x4c +'', # 0x4d +'[?]', # 0x4e +'[?]', # 0x4f +'[?]', # 0x50 +'[?]', # 0x51 +'[?]', # 0x52 +'[?]', # 0x53 +'[?]', # 0x54 +'[?]', # 0x55 +'[?]', # 0x56 +'[?]', # 0x57 +'[?]', # 0x58 +'khh', # 0x59 +'ghh', # 0x5a +'z', # 0x5b +'rr', # 0x5c +'[?]', # 0x5d +'f', # 0x5e +'[?]', # 0x5f +'[?]', # 0x60 +'[?]', # 0x61 +'[?]', # 0x62 +'[?]', # 0x63 +'[?]', # 0x64 +'[?]', # 0x65 +'0', # 0x66 +'1', # 0x67 +'2', # 0x68 +'3', # 0x69 +'4', # 0x6a +'5', # 0x6b +'6', # 0x6c +'7', # 0x6d +'8', # 0x6e +'9', # 0x6f +'N', # 0x70 +'H', # 0x71 +'', # 0x72 +'', # 0x73 +'G.E.O.', # 0x74 +'[?]', # 0x75 +'[?]', # 0x76 +'[?]', # 0x77 +'[?]', # 0x78 +'[?]', # 0x79 +'[?]', # 0x7a +'[?]', # 0x7b +'[?]', # 0x7c +'[?]', # 0x7d +'[?]', # 0x7e +'[?]', # 0x7f +'[?]', # 0x80 +'N', # 0x81 +'N', # 0x82 +'H', # 0x83 +'[?]', # 0x84 +'a', # 0x85 +'aa', # 0x86 +'i', # 0x87 +'ii', # 0x88 +'u', # 0x89 +'uu', # 0x8a +'R', # 0x8b +'[?]', # 0x8c +'eN', # 0x8d +'[?]', # 0x8e +'e', # 0x8f +'ai', # 0x90 +'oN', # 0x91 +'[?]', # 0x92 +'o', # 0x93 +'au', # 0x94 +'k', # 0x95 +'kh', # 0x96 +'g', # 0x97 +'gh', # 0x98 +'ng', # 0x99 +'c', # 0x9a +'ch', # 0x9b +'j', # 0x9c +'jh', # 0x9d +'ny', # 0x9e +'tt', # 0x9f +'tth', # 0xa0 +'dd', # 0xa1 +'ddh', # 0xa2 +'nn', # 0xa3 +'t', # 0xa4 +'th', # 0xa5 +'d', # 0xa6 +'dh', # 0xa7 +'n', # 0xa8 +'[?]', # 0xa9 +'p', # 0xaa +'ph', # 0xab +'b', # 0xac +'bh', # 0xad +'m', # 0xae +'ya', # 0xaf +'r', # 0xb0 +'[?]', # 0xb1 +'l', # 0xb2 +'ll', # 0xb3 +'[?]', # 0xb4 +'v', # 0xb5 +'sh', # 0xb6 +'ss', # 0xb7 +'s', # 0xb8 +'h', # 0xb9 +'[?]', # 0xba +'[?]', # 0xbb +'\'', # 0xbc +'\'', # 0xbd +'aa', # 0xbe +'i', # 0xbf +'ii', # 0xc0 +'u', # 0xc1 +'uu', # 0xc2 +'R', # 0xc3 +'RR', # 0xc4 +'eN', # 0xc5 +'[?]', # 0xc6 +'e', # 0xc7 +'ai', # 0xc8 +'oN', # 0xc9 +'[?]', # 0xca +'o', # 0xcb +'au', # 0xcc +'', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'AUM', # 0xd0 +'[?]', # 0xd1 +'[?]', # 0xd2 +'[?]', # 0xd3 +'[?]', # 0xd4 +'[?]', # 0xd5 +'[?]', # 0xd6 +'[?]', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'[?]', # 0xdc +'[?]', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'RR', # 0xe0 +'[?]', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'0', # 0xe6 +'1', # 0xe7 +'2', # 0xe8 +'3', # 0xe9 +'4', # 0xea +'5', # 0xeb +'6', # 0xec +'7', # 0xed +'8', # 0xee +'9', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x00b.py b/nstock/modules/unidecode/x00b.py new file mode 100644 index 0000000..19d1848 --- /dev/null +++ b/nstock/modules/unidecode/x00b.py @@ -0,0 +1,257 @@ +data = ( +'[?]', # 0x00 +'N', # 0x01 +'N', # 0x02 +'H', # 0x03 +'[?]', # 0x04 +'a', # 0x05 +'aa', # 0x06 +'i', # 0x07 +'ii', # 0x08 +'u', # 0x09 +'uu', # 0x0a +'R', # 0x0b +'L', # 0x0c +'[?]', # 0x0d +'[?]', # 0x0e +'e', # 0x0f +'ai', # 0x10 +'[?]', # 0x11 +'[?]', # 0x12 +'o', # 0x13 +'au', # 0x14 +'k', # 0x15 +'kh', # 0x16 +'g', # 0x17 +'gh', # 0x18 +'ng', # 0x19 +'c', # 0x1a +'ch', # 0x1b +'j', # 0x1c +'jh', # 0x1d +'ny', # 0x1e +'tt', # 0x1f +'tth', # 0x20 +'dd', # 0x21 +'ddh', # 0x22 +'nn', # 0x23 +'t', # 0x24 +'th', # 0x25 +'d', # 0x26 +'dh', # 0x27 +'n', # 0x28 +'[?]', # 0x29 +'p', # 0x2a +'ph', # 0x2b +'b', # 0x2c +'bh', # 0x2d +'m', # 0x2e +'y', # 0x2f +'r', # 0x30 +'[?]', # 0x31 +'l', # 0x32 +'ll', # 0x33 +'[?]', # 0x34 +'', # 0x35 +'sh', # 0x36 +'ss', # 0x37 +'s', # 0x38 +'h', # 0x39 +'[?]', # 0x3a +'[?]', # 0x3b +'\'', # 0x3c +'\'', # 0x3d +'aa', # 0x3e +'i', # 0x3f +'ii', # 0x40 +'u', # 0x41 +'uu', # 0x42 +'R', # 0x43 +'[?]', # 0x44 +'[?]', # 0x45 +'[?]', # 0x46 +'e', # 0x47 +'ai', # 0x48 +'[?]', # 0x49 +'[?]', # 0x4a +'o', # 0x4b +'au', # 0x4c +'', # 0x4d +'[?]', # 0x4e +'[?]', # 0x4f +'[?]', # 0x50 +'[?]', # 0x51 +'[?]', # 0x52 +'[?]', # 0x53 +'[?]', # 0x54 +'[?]', # 0x55 +'+', # 0x56 +'+', # 0x57 +'[?]', # 0x58 +'[?]', # 0x59 +'[?]', # 0x5a +'[?]', # 0x5b +'rr', # 0x5c +'rh', # 0x5d +'[?]', # 0x5e +'yy', # 0x5f +'RR', # 0x60 +'LL', # 0x61 +'[?]', # 0x62 +'[?]', # 0x63 +'[?]', # 0x64 +'[?]', # 0x65 +'0', # 0x66 +'1', # 0x67 +'2', # 0x68 +'3', # 0x69 +'4', # 0x6a +'5', # 0x6b +'6', # 0x6c +'7', # 0x6d +'8', # 0x6e +'9', # 0x6f +'', # 0x70 +'[?]', # 0x71 +'[?]', # 0x72 +'[?]', # 0x73 +'[?]', # 0x74 +'[?]', # 0x75 +'[?]', # 0x76 +'[?]', # 0x77 +'[?]', # 0x78 +'[?]', # 0x79 +'[?]', # 0x7a +'[?]', # 0x7b +'[?]', # 0x7c +'[?]', # 0x7d +'[?]', # 0x7e +'[?]', # 0x7f +'[?]', # 0x80 +'[?]', # 0x81 +'N', # 0x82 +'H', # 0x83 +'[?]', # 0x84 +'a', # 0x85 +'aa', # 0x86 +'i', # 0x87 +'ii', # 0x88 +'u', # 0x89 +'uu', # 0x8a +'[?]', # 0x8b +'[?]', # 0x8c +'[?]', # 0x8d +'e', # 0x8e +'ee', # 0x8f +'ai', # 0x90 +'[?]', # 0x91 +'o', # 0x92 +'oo', # 0x93 +'au', # 0x94 +'k', # 0x95 +'[?]', # 0x96 +'[?]', # 0x97 +'[?]', # 0x98 +'ng', # 0x99 +'c', # 0x9a +'[?]', # 0x9b +'j', # 0x9c +'[?]', # 0x9d +'ny', # 0x9e +'tt', # 0x9f +'[?]', # 0xa0 +'[?]', # 0xa1 +'[?]', # 0xa2 +'nn', # 0xa3 +'t', # 0xa4 +'[?]', # 0xa5 +'[?]', # 0xa6 +'[?]', # 0xa7 +'n', # 0xa8 +'nnn', # 0xa9 +'p', # 0xaa +'[?]', # 0xab +'[?]', # 0xac +'[?]', # 0xad +'m', # 0xae +'y', # 0xaf +'r', # 0xb0 +'rr', # 0xb1 +'l', # 0xb2 +'ll', # 0xb3 +'lll', # 0xb4 +'v', # 0xb5 +'[?]', # 0xb6 +'ss', # 0xb7 +'s', # 0xb8 +'h', # 0xb9 +'[?]', # 0xba +'[?]', # 0xbb +'[?]', # 0xbc +'[?]', # 0xbd +'aa', # 0xbe +'i', # 0xbf +'ii', # 0xc0 +'u', # 0xc1 +'uu', # 0xc2 +'[?]', # 0xc3 +'[?]', # 0xc4 +'[?]', # 0xc5 +'e', # 0xc6 +'ee', # 0xc7 +'ai', # 0xc8 +'[?]', # 0xc9 +'o', # 0xca +'oo', # 0xcb +'au', # 0xcc +'', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'[?]', # 0xd0 +'[?]', # 0xd1 +'[?]', # 0xd2 +'[?]', # 0xd3 +'[?]', # 0xd4 +'[?]', # 0xd5 +'[?]', # 0xd6 +'+', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'[?]', # 0xdc +'[?]', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'[?]', # 0xe0 +'[?]', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'0', # 0xe6 +'1', # 0xe7 +'2', # 0xe8 +'3', # 0xe9 +'4', # 0xea +'5', # 0xeb +'6', # 0xec +'7', # 0xed +'8', # 0xee +'9', # 0xef +'+10+', # 0xf0 +'+100+', # 0xf1 +'+1000+', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x00c.py b/nstock/modules/unidecode/x00c.py new file mode 100644 index 0000000..56f3654 --- /dev/null +++ b/nstock/modules/unidecode/x00c.py @@ -0,0 +1,257 @@ +data = ( +'[?]', # 0x00 +'N', # 0x01 +'N', # 0x02 +'H', # 0x03 +'[?]', # 0x04 +'a', # 0x05 +'aa', # 0x06 +'i', # 0x07 +'ii', # 0x08 +'u', # 0x09 +'uu', # 0x0a +'R', # 0x0b +'L', # 0x0c +'[?]', # 0x0d +'e', # 0x0e +'ee', # 0x0f +'ai', # 0x10 +'[?]', # 0x11 +'o', # 0x12 +'oo', # 0x13 +'au', # 0x14 +'k', # 0x15 +'kh', # 0x16 +'g', # 0x17 +'gh', # 0x18 +'ng', # 0x19 +'c', # 0x1a +'ch', # 0x1b +'j', # 0x1c +'jh', # 0x1d +'ny', # 0x1e +'tt', # 0x1f +'tth', # 0x20 +'dd', # 0x21 +'ddh', # 0x22 +'nn', # 0x23 +'t', # 0x24 +'th', # 0x25 +'d', # 0x26 +'dh', # 0x27 +'n', # 0x28 +'[?]', # 0x29 +'p', # 0x2a +'ph', # 0x2b +'b', # 0x2c +'bh', # 0x2d +'m', # 0x2e +'y', # 0x2f +'r', # 0x30 +'rr', # 0x31 +'l', # 0x32 +'ll', # 0x33 +'[?]', # 0x34 +'v', # 0x35 +'sh', # 0x36 +'ss', # 0x37 +'s', # 0x38 +'h', # 0x39 +'[?]', # 0x3a +'[?]', # 0x3b +'[?]', # 0x3c +'[?]', # 0x3d +'aa', # 0x3e +'i', # 0x3f +'ii', # 0x40 +'u', # 0x41 +'uu', # 0x42 +'R', # 0x43 +'RR', # 0x44 +'[?]', # 0x45 +'e', # 0x46 +'ee', # 0x47 +'ai', # 0x48 +'[?]', # 0x49 +'o', # 0x4a +'oo', # 0x4b +'au', # 0x4c +'', # 0x4d +'[?]', # 0x4e +'[?]', # 0x4f +'[?]', # 0x50 +'[?]', # 0x51 +'[?]', # 0x52 +'[?]', # 0x53 +'[?]', # 0x54 +'+', # 0x55 +'+', # 0x56 +'[?]', # 0x57 +'[?]', # 0x58 +'[?]', # 0x59 +'[?]', # 0x5a +'[?]', # 0x5b +'[?]', # 0x5c +'[?]', # 0x5d +'[?]', # 0x5e +'[?]', # 0x5f +'RR', # 0x60 +'LL', # 0x61 +'[?]', # 0x62 +'[?]', # 0x63 +'[?]', # 0x64 +'[?]', # 0x65 +'0', # 0x66 +'1', # 0x67 +'2', # 0x68 +'3', # 0x69 +'4', # 0x6a +'5', # 0x6b +'6', # 0x6c +'7', # 0x6d +'8', # 0x6e +'9', # 0x6f +'[?]', # 0x70 +'[?]', # 0x71 +'[?]', # 0x72 +'[?]', # 0x73 +'[?]', # 0x74 +'[?]', # 0x75 +'[?]', # 0x76 +'[?]', # 0x77 +'[?]', # 0x78 +'[?]', # 0x79 +'[?]', # 0x7a +'[?]', # 0x7b +'[?]', # 0x7c +'[?]', # 0x7d +'[?]', # 0x7e +'[?]', # 0x7f +'[?]', # 0x80 +'[?]', # 0x81 +'N', # 0x82 +'H', # 0x83 +'[?]', # 0x84 +'a', # 0x85 +'aa', # 0x86 +'i', # 0x87 +'ii', # 0x88 +'u', # 0x89 +'uu', # 0x8a +'R', # 0x8b +'L', # 0x8c +'[?]', # 0x8d +'e', # 0x8e +'ee', # 0x8f +'ai', # 0x90 +'[?]', # 0x91 +'o', # 0x92 +'oo', # 0x93 +'au', # 0x94 +'k', # 0x95 +'kh', # 0x96 +'g', # 0x97 +'gh', # 0x98 +'ng', # 0x99 +'c', # 0x9a +'ch', # 0x9b +'j', # 0x9c +'jh', # 0x9d +'ny', # 0x9e +'tt', # 0x9f +'tth', # 0xa0 +'dd', # 0xa1 +'ddh', # 0xa2 +'nn', # 0xa3 +'t', # 0xa4 +'th', # 0xa5 +'d', # 0xa6 +'dh', # 0xa7 +'n', # 0xa8 +'[?]', # 0xa9 +'p', # 0xaa +'ph', # 0xab +'b', # 0xac +'bh', # 0xad +'m', # 0xae +'y', # 0xaf +'r', # 0xb0 +'rr', # 0xb1 +'l', # 0xb2 +'ll', # 0xb3 +'[?]', # 0xb4 +'v', # 0xb5 +'sh', # 0xb6 +'ss', # 0xb7 +'s', # 0xb8 +'h', # 0xb9 +'[?]', # 0xba +'[?]', # 0xbb +'[?]', # 0xbc +'[?]', # 0xbd +'aa', # 0xbe +'i', # 0xbf +'ii', # 0xc0 +'u', # 0xc1 +'uu', # 0xc2 +'R', # 0xc3 +'RR', # 0xc4 +'[?]', # 0xc5 +'e', # 0xc6 +'ee', # 0xc7 +'ai', # 0xc8 +'[?]', # 0xc9 +'o', # 0xca +'oo', # 0xcb +'au', # 0xcc +'', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'[?]', # 0xd0 +'[?]', # 0xd1 +'[?]', # 0xd2 +'[?]', # 0xd3 +'[?]', # 0xd4 +'+', # 0xd5 +'+', # 0xd6 +'[?]', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'[?]', # 0xdc +'[?]', # 0xdd +'lll', # 0xde +'[?]', # 0xdf +'RR', # 0xe0 +'LL', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'0', # 0xe6 +'1', # 0xe7 +'2', # 0xe8 +'3', # 0xe9 +'4', # 0xea +'5', # 0xeb +'6', # 0xec +'7', # 0xed +'8', # 0xee +'9', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x00d.py b/nstock/modules/unidecode/x00d.py new file mode 100644 index 0000000..d105c43 --- /dev/null +++ b/nstock/modules/unidecode/x00d.py @@ -0,0 +1,257 @@ +data = ( +'[?]', # 0x00 +'[?]', # 0x01 +'N', # 0x02 +'H', # 0x03 +'[?]', # 0x04 +'a', # 0x05 +'aa', # 0x06 +'i', # 0x07 +'ii', # 0x08 +'u', # 0x09 +'uu', # 0x0a +'R', # 0x0b +'L', # 0x0c +'[?]', # 0x0d +'e', # 0x0e +'ee', # 0x0f +'ai', # 0x10 +'[?]', # 0x11 +'o', # 0x12 +'oo', # 0x13 +'au', # 0x14 +'k', # 0x15 +'kh', # 0x16 +'g', # 0x17 +'gh', # 0x18 +'ng', # 0x19 +'c', # 0x1a +'ch', # 0x1b +'j', # 0x1c +'jh', # 0x1d +'ny', # 0x1e +'tt', # 0x1f +'tth', # 0x20 +'dd', # 0x21 +'ddh', # 0x22 +'nn', # 0x23 +'t', # 0x24 +'th', # 0x25 +'d', # 0x26 +'dh', # 0x27 +'n', # 0x28 +'[?]', # 0x29 +'p', # 0x2a +'ph', # 0x2b +'b', # 0x2c +'bh', # 0x2d +'m', # 0x2e +'y', # 0x2f +'r', # 0x30 +'rr', # 0x31 +'l', # 0x32 +'ll', # 0x33 +'lll', # 0x34 +'v', # 0x35 +'sh', # 0x36 +'ss', # 0x37 +'s', # 0x38 +'h', # 0x39 +'[?]', # 0x3a +'[?]', # 0x3b +'[?]', # 0x3c +'[?]', # 0x3d +'aa', # 0x3e +'i', # 0x3f +'ii', # 0x40 +'u', # 0x41 +'uu', # 0x42 +'R', # 0x43 +'[?]', # 0x44 +'[?]', # 0x45 +'e', # 0x46 +'ee', # 0x47 +'ai', # 0x48 +'', # 0x49 +'o', # 0x4a +'oo', # 0x4b +'au', # 0x4c +'', # 0x4d +'[?]', # 0x4e +'[?]', # 0x4f +'[?]', # 0x50 +'[?]', # 0x51 +'[?]', # 0x52 +'[?]', # 0x53 +'[?]', # 0x54 +'[?]', # 0x55 +'[?]', # 0x56 +'+', # 0x57 +'[?]', # 0x58 +'[?]', # 0x59 +'[?]', # 0x5a +'[?]', # 0x5b +'[?]', # 0x5c +'[?]', # 0x5d +'[?]', # 0x5e +'[?]', # 0x5f +'RR', # 0x60 +'LL', # 0x61 +'[?]', # 0x62 +'[?]', # 0x63 +'[?]', # 0x64 +'[?]', # 0x65 +'0', # 0x66 +'1', # 0x67 +'2', # 0x68 +'3', # 0x69 +'4', # 0x6a +'5', # 0x6b +'6', # 0x6c +'7', # 0x6d +'8', # 0x6e +'9', # 0x6f +'[?]', # 0x70 +'[?]', # 0x71 +'[?]', # 0x72 +'[?]', # 0x73 +'[?]', # 0x74 +'[?]', # 0x75 +'[?]', # 0x76 +'[?]', # 0x77 +'[?]', # 0x78 +'[?]', # 0x79 +'[?]', # 0x7a +'[?]', # 0x7b +'[?]', # 0x7c +'[?]', # 0x7d +'[?]', # 0x7e +'[?]', # 0x7f +'[?]', # 0x80 +'[?]', # 0x81 +'N', # 0x82 +'H', # 0x83 +'[?]', # 0x84 +'a', # 0x85 +'aa', # 0x86 +'ae', # 0x87 +'aae', # 0x88 +'i', # 0x89 +'ii', # 0x8a +'u', # 0x8b +'uu', # 0x8c +'R', # 0x8d +'RR', # 0x8e +'L', # 0x8f +'LL', # 0x90 +'e', # 0x91 +'ee', # 0x92 +'ai', # 0x93 +'o', # 0x94 +'oo', # 0x95 +'au', # 0x96 +'[?]', # 0x97 +'[?]', # 0x98 +'[?]', # 0x99 +'k', # 0x9a +'kh', # 0x9b +'g', # 0x9c +'gh', # 0x9d +'ng', # 0x9e +'nng', # 0x9f +'c', # 0xa0 +'ch', # 0xa1 +'j', # 0xa2 +'jh', # 0xa3 +'ny', # 0xa4 +'jny', # 0xa5 +'nyj', # 0xa6 +'tt', # 0xa7 +'tth', # 0xa8 +'dd', # 0xa9 +'ddh', # 0xaa +'nn', # 0xab +'nndd', # 0xac +'t', # 0xad +'th', # 0xae +'d', # 0xaf +'dh', # 0xb0 +'n', # 0xb1 +'[?]', # 0xb2 +'nd', # 0xb3 +'p', # 0xb4 +'ph', # 0xb5 +'b', # 0xb6 +'bh', # 0xb7 +'m', # 0xb8 +'mb', # 0xb9 +'y', # 0xba +'r', # 0xbb +'[?]', # 0xbc +'l', # 0xbd +'[?]', # 0xbe +'[?]', # 0xbf +'v', # 0xc0 +'sh', # 0xc1 +'ss', # 0xc2 +'s', # 0xc3 +'h', # 0xc4 +'ll', # 0xc5 +'f', # 0xc6 +'[?]', # 0xc7 +'[?]', # 0xc8 +'[?]', # 0xc9 +'', # 0xca +'[?]', # 0xcb +'[?]', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'aa', # 0xcf +'ae', # 0xd0 +'aae', # 0xd1 +'i', # 0xd2 +'ii', # 0xd3 +'u', # 0xd4 +'[?]', # 0xd5 +'uu', # 0xd6 +'[?]', # 0xd7 +'R', # 0xd8 +'e', # 0xd9 +'ee', # 0xda +'ai', # 0xdb +'o', # 0xdc +'oo', # 0xdd +'au', # 0xde +'L', # 0xdf +'[?]', # 0xe0 +'[?]', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'[?]', # 0xe6 +'[?]', # 0xe7 +'[?]', # 0xe8 +'[?]', # 0xe9 +'[?]', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'RR', # 0xf2 +'LL', # 0xf3 +' . ', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x00e.py b/nstock/modules/unidecode/x00e.py new file mode 100644 index 0000000..775b5f4 --- /dev/null +++ b/nstock/modules/unidecode/x00e.py @@ -0,0 +1,257 @@ +data = ( +'[?]', # 0x00 +'k', # 0x01 +'kh', # 0x02 +'kh', # 0x03 +'kh', # 0x04 +'kh', # 0x05 +'kh', # 0x06 +'ng', # 0x07 +'cch', # 0x08 +'ch', # 0x09 +'ch', # 0x0a +'ch', # 0x0b +'ch', # 0x0c +'y', # 0x0d +'d', # 0x0e +'t', # 0x0f +'th', # 0x10 +'th', # 0x11 +'th', # 0x12 +'n', # 0x13 +'d', # 0x14 +'t', # 0x15 +'th', # 0x16 +'th', # 0x17 +'th', # 0x18 +'n', # 0x19 +'b', # 0x1a +'p', # 0x1b +'ph', # 0x1c +'f', # 0x1d +'ph', # 0x1e +'f', # 0x1f +'ph', # 0x20 +'m', # 0x21 +'y', # 0x22 +'r', # 0x23 +'R', # 0x24 +'l', # 0x25 +'L', # 0x26 +'w', # 0x27 +'s', # 0x28 +'s', # 0x29 +'s', # 0x2a +'h', # 0x2b +'l', # 0x2c +'`', # 0x2d +'h', # 0x2e +'~', # 0x2f +'a', # 0x30 +'a', # 0x31 +'aa', # 0x32 +'am', # 0x33 +'i', # 0x34 +'ii', # 0x35 +'ue', # 0x36 +'uue', # 0x37 +'u', # 0x38 +'uu', # 0x39 +'\'', # 0x3a +'[?]', # 0x3b +'[?]', # 0x3c +'[?]', # 0x3d +'[?]', # 0x3e +'Bh.', # 0x3f +'e', # 0x40 +'ae', # 0x41 +'o', # 0x42 +'ai', # 0x43 +'ai', # 0x44 +'ao', # 0x45 +'+', # 0x46 +'', # 0x47 +'', # 0x48 +'', # 0x49 +'', # 0x4a +'', # 0x4b +'', # 0x4c +'M', # 0x4d +'', # 0x4e +' * ', # 0x4f +'0', # 0x50 +'1', # 0x51 +'2', # 0x52 +'3', # 0x53 +'4', # 0x54 +'5', # 0x55 +'6', # 0x56 +'7', # 0x57 +'8', # 0x58 +'9', # 0x59 +' // ', # 0x5a +' /// ', # 0x5b +'[?]', # 0x5c +'[?]', # 0x5d +'[?]', # 0x5e +'[?]', # 0x5f +'[?]', # 0x60 +'[?]', # 0x61 +'[?]', # 0x62 +'[?]', # 0x63 +'[?]', # 0x64 +'[?]', # 0x65 +'[?]', # 0x66 +'[?]', # 0x67 +'[?]', # 0x68 +'[?]', # 0x69 +'[?]', # 0x6a +'[?]', # 0x6b +'[?]', # 0x6c +'[?]', # 0x6d +'[?]', # 0x6e +'[?]', # 0x6f +'[?]', # 0x70 +'[?]', # 0x71 +'[?]', # 0x72 +'[?]', # 0x73 +'[?]', # 0x74 +'[?]', # 0x75 +'[?]', # 0x76 +'[?]', # 0x77 +'[?]', # 0x78 +'[?]', # 0x79 +'[?]', # 0x7a +'[?]', # 0x7b +'[?]', # 0x7c +'[?]', # 0x7d +'[?]', # 0x7e +'[?]', # 0x7f +'[?]', # 0x80 +'k', # 0x81 +'kh', # 0x82 +'[?]', # 0x83 +'kh', # 0x84 +'[?]', # 0x85 +'[?]', # 0x86 +'ng', # 0x87 +'ch', # 0x88 +'[?]', # 0x89 +'s', # 0x8a +'[?]', # 0x8b +'[?]', # 0x8c +'ny', # 0x8d +'[?]', # 0x8e +'[?]', # 0x8f +'[?]', # 0x90 +'[?]', # 0x91 +'[?]', # 0x92 +'[?]', # 0x93 +'d', # 0x94 +'h', # 0x95 +'th', # 0x96 +'th', # 0x97 +'[?]', # 0x98 +'n', # 0x99 +'b', # 0x9a +'p', # 0x9b +'ph', # 0x9c +'f', # 0x9d +'ph', # 0x9e +'f', # 0x9f +'[?]', # 0xa0 +'m', # 0xa1 +'y', # 0xa2 +'r', # 0xa3 +'[?]', # 0xa4 +'l', # 0xa5 +'[?]', # 0xa6 +'w', # 0xa7 +'[?]', # 0xa8 +'[?]', # 0xa9 +'s', # 0xaa +'h', # 0xab +'[?]', # 0xac +'`', # 0xad +'', # 0xae +'~', # 0xaf +'a', # 0xb0 +'', # 0xb1 +'aa', # 0xb2 +'am', # 0xb3 +'i', # 0xb4 +'ii', # 0xb5 +'y', # 0xb6 +'yy', # 0xb7 +'u', # 0xb8 +'uu', # 0xb9 +'[?]', # 0xba +'o', # 0xbb +'l', # 0xbc +'ny', # 0xbd +'[?]', # 0xbe +'[?]', # 0xbf +'e', # 0xc0 +'ei', # 0xc1 +'o', # 0xc2 +'ay', # 0xc3 +'ai', # 0xc4 +'[?]', # 0xc5 +'+', # 0xc6 +'[?]', # 0xc7 +'', # 0xc8 +'', # 0xc9 +'', # 0xca +'', # 0xcb +'', # 0xcc +'M', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'0', # 0xd0 +'1', # 0xd1 +'2', # 0xd2 +'3', # 0xd3 +'4', # 0xd4 +'5', # 0xd5 +'6', # 0xd6 +'7', # 0xd7 +'8', # 0xd8 +'9', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'hn', # 0xdc +'hm', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'[?]', # 0xe0 +'[?]', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'[?]', # 0xe6 +'[?]', # 0xe7 +'[?]', # 0xe8 +'[?]', # 0xe9 +'[?]', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x00f.py b/nstock/modules/unidecode/x00f.py new file mode 100644 index 0000000..4c2410e --- /dev/null +++ b/nstock/modules/unidecode/x00f.py @@ -0,0 +1,257 @@ +data = ( +'AUM', # 0x00 +'', # 0x01 +'', # 0x02 +'', # 0x03 +'', # 0x04 +'', # 0x05 +'', # 0x06 +'', # 0x07 +' // ', # 0x08 +' * ', # 0x09 +'', # 0x0a +'-', # 0x0b +' / ', # 0x0c +' / ', # 0x0d +' // ', # 0x0e +' -/ ', # 0x0f +' +/ ', # 0x10 +' X/ ', # 0x11 +' /XX/ ', # 0x12 +' /X/ ', # 0x13 +', ', # 0x14 +'', # 0x15 +'', # 0x16 +'', # 0x17 +'', # 0x18 +'', # 0x19 +'', # 0x1a +'', # 0x1b +'', # 0x1c +'', # 0x1d +'', # 0x1e +'', # 0x1f +'0', # 0x20 +'1', # 0x21 +'2', # 0x22 +'3', # 0x23 +'4', # 0x24 +'5', # 0x25 +'6', # 0x26 +'7', # 0x27 +'8', # 0x28 +'9', # 0x29 +'.5', # 0x2a +'1.5', # 0x2b +'2.5', # 0x2c +'3.5', # 0x2d +'4.5', # 0x2e +'5.5', # 0x2f +'6.5', # 0x30 +'7.5', # 0x31 +'8.5', # 0x32 +'-.5', # 0x33 +'+', # 0x34 +'*', # 0x35 +'^', # 0x36 +'_', # 0x37 +'', # 0x38 +'~', # 0x39 +'[?]', # 0x3a +']', # 0x3b +'[[', # 0x3c +']]', # 0x3d +'', # 0x3e +'', # 0x3f +'k', # 0x40 +'kh', # 0x41 +'g', # 0x42 +'gh', # 0x43 +'ng', # 0x44 +'c', # 0x45 +'ch', # 0x46 +'j', # 0x47 +'[?]', # 0x48 +'ny', # 0x49 +'tt', # 0x4a +'tth', # 0x4b +'dd', # 0x4c +'ddh', # 0x4d +'nn', # 0x4e +'t', # 0x4f +'th', # 0x50 +'d', # 0x51 +'dh', # 0x52 +'n', # 0x53 +'p', # 0x54 +'ph', # 0x55 +'b', # 0x56 +'bh', # 0x57 +'m', # 0x58 +'ts', # 0x59 +'tsh', # 0x5a +'dz', # 0x5b +'dzh', # 0x5c +'w', # 0x5d +'zh', # 0x5e +'z', # 0x5f +'\'', # 0x60 +'y', # 0x61 +'r', # 0x62 +'l', # 0x63 +'sh', # 0x64 +'ssh', # 0x65 +'s', # 0x66 +'h', # 0x67 +'a', # 0x68 +'kss', # 0x69 +'r', # 0x6a +'[?]', # 0x6b +'[?]', # 0x6c +'[?]', # 0x6d +'[?]', # 0x6e +'[?]', # 0x6f +'[?]', # 0x70 +'aa', # 0x71 +'i', # 0x72 +'ii', # 0x73 +'u', # 0x74 +'uu', # 0x75 +'R', # 0x76 +'RR', # 0x77 +'L', # 0x78 +'LL', # 0x79 +'e', # 0x7a +'ee', # 0x7b +'o', # 0x7c +'oo', # 0x7d +'M', # 0x7e +'H', # 0x7f +'i', # 0x80 +'ii', # 0x81 +'', # 0x82 +'', # 0x83 +'', # 0x84 +'', # 0x85 +'', # 0x86 +'', # 0x87 +'', # 0x88 +'', # 0x89 +'', # 0x8a +'', # 0x8b +'[?]', # 0x8c +'[?]', # 0x8d +'[?]', # 0x8e +'[?]', # 0x8f +'k', # 0x90 +'kh', # 0x91 +'g', # 0x92 +'gh', # 0x93 +'ng', # 0x94 +'c', # 0x95 +'ch', # 0x96 +'j', # 0x97 +'[?]', # 0x98 +'ny', # 0x99 +'tt', # 0x9a +'tth', # 0x9b +'dd', # 0x9c +'ddh', # 0x9d +'nn', # 0x9e +'t', # 0x9f +'th', # 0xa0 +'d', # 0xa1 +'dh', # 0xa2 +'n', # 0xa3 +'p', # 0xa4 +'ph', # 0xa5 +'b', # 0xa6 +'bh', # 0xa7 +'m', # 0xa8 +'ts', # 0xa9 +'tsh', # 0xaa +'dz', # 0xab +'dzh', # 0xac +'w', # 0xad +'zh', # 0xae +'z', # 0xaf +'\'', # 0xb0 +'y', # 0xb1 +'r', # 0xb2 +'l', # 0xb3 +'sh', # 0xb4 +'ss', # 0xb5 +'s', # 0xb6 +'h', # 0xb7 +'a', # 0xb8 +'kss', # 0xb9 +'w', # 0xba +'y', # 0xbb +'r', # 0xbc +'[?]', # 0xbd +'X', # 0xbe +' :X: ', # 0xbf +' /O/ ', # 0xc0 +' /o/ ', # 0xc1 +' \\o\\ ', # 0xc2 +' (O) ', # 0xc3 +'', # 0xc4 +'', # 0xc5 +'', # 0xc6 +'', # 0xc7 +'', # 0xc8 +'', # 0xc9 +'', # 0xca +'', # 0xcb +'', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'', # 0xcf +'[?]', # 0xd0 +'[?]', # 0xd1 +'[?]', # 0xd2 +'[?]', # 0xd3 +'[?]', # 0xd4 +'[?]', # 0xd5 +'[?]', # 0xd6 +'[?]', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'[?]', # 0xdc +'[?]', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'[?]', # 0xe0 +'[?]', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'[?]', # 0xe6 +'[?]', # 0xe7 +'[?]', # 0xe8 +'[?]', # 0xe9 +'[?]', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x010.py b/nstock/modules/unidecode/x010.py new file mode 100644 index 0000000..aaf820d --- /dev/null +++ b/nstock/modules/unidecode/x010.py @@ -0,0 +1,257 @@ +data = ( +'k', # 0x00 +'kh', # 0x01 +'g', # 0x02 +'gh', # 0x03 +'ng', # 0x04 +'c', # 0x05 +'ch', # 0x06 +'j', # 0x07 +'jh', # 0x08 +'ny', # 0x09 +'nny', # 0x0a +'tt', # 0x0b +'tth', # 0x0c +'dd', # 0x0d +'ddh', # 0x0e +'nn', # 0x0f +'tt', # 0x10 +'th', # 0x11 +'d', # 0x12 +'dh', # 0x13 +'n', # 0x14 +'p', # 0x15 +'ph', # 0x16 +'b', # 0x17 +'bh', # 0x18 +'m', # 0x19 +'y', # 0x1a +'r', # 0x1b +'l', # 0x1c +'w', # 0x1d +'s', # 0x1e +'h', # 0x1f +'ll', # 0x20 +'a', # 0x21 +'[?]', # 0x22 +'i', # 0x23 +'ii', # 0x24 +'u', # 0x25 +'uu', # 0x26 +'e', # 0x27 +'[?]', # 0x28 +'o', # 0x29 +'au', # 0x2a +'[?]', # 0x2b +'aa', # 0x2c +'i', # 0x2d +'ii', # 0x2e +'u', # 0x2f +'uu', # 0x30 +'e', # 0x31 +'ai', # 0x32 +'[?]', # 0x33 +'[?]', # 0x34 +'[?]', # 0x35 +'N', # 0x36 +'\'', # 0x37 +':', # 0x38 +'', # 0x39 +'[?]', # 0x3a +'[?]', # 0x3b +'[?]', # 0x3c +'[?]', # 0x3d +'[?]', # 0x3e +'[?]', # 0x3f +'0', # 0x40 +'1', # 0x41 +'2', # 0x42 +'3', # 0x43 +'4', # 0x44 +'5', # 0x45 +'6', # 0x46 +'7', # 0x47 +'8', # 0x48 +'9', # 0x49 +' / ', # 0x4a +' // ', # 0x4b +'n*', # 0x4c +'r*', # 0x4d +'l*', # 0x4e +'e*', # 0x4f +'sh', # 0x50 +'ss', # 0x51 +'R', # 0x52 +'RR', # 0x53 +'L', # 0x54 +'LL', # 0x55 +'R', # 0x56 +'RR', # 0x57 +'L', # 0x58 +'LL', # 0x59 +'[?]', # 0x5a +'[?]', # 0x5b +'[?]', # 0x5c +'[?]', # 0x5d +'[?]', # 0x5e +'[?]', # 0x5f +'[?]', # 0x60 +'[?]', # 0x61 +'[?]', # 0x62 +'[?]', # 0x63 +'[?]', # 0x64 +'[?]', # 0x65 +'[?]', # 0x66 +'[?]', # 0x67 +'[?]', # 0x68 +'[?]', # 0x69 +'[?]', # 0x6a +'[?]', # 0x6b +'[?]', # 0x6c +'[?]', # 0x6d +'[?]', # 0x6e +'[?]', # 0x6f +'[?]', # 0x70 +'[?]', # 0x71 +'[?]', # 0x72 +'[?]', # 0x73 +'[?]', # 0x74 +'[?]', # 0x75 +'[?]', # 0x76 +'[?]', # 0x77 +'[?]', # 0x78 +'[?]', # 0x79 +'[?]', # 0x7a +'[?]', # 0x7b +'[?]', # 0x7c +'[?]', # 0x7d +'[?]', # 0x7e +'[?]', # 0x7f +'[?]', # 0x80 +'[?]', # 0x81 +'[?]', # 0x82 +'[?]', # 0x83 +'[?]', # 0x84 +'[?]', # 0x85 +'[?]', # 0x86 +'[?]', # 0x87 +'[?]', # 0x88 +'[?]', # 0x89 +'[?]', # 0x8a +'[?]', # 0x8b +'[?]', # 0x8c +'[?]', # 0x8d +'[?]', # 0x8e +'[?]', # 0x8f +'[?]', # 0x90 +'[?]', # 0x91 +'[?]', # 0x92 +'[?]', # 0x93 +'[?]', # 0x94 +'[?]', # 0x95 +'[?]', # 0x96 +'[?]', # 0x97 +'[?]', # 0x98 +'[?]', # 0x99 +'[?]', # 0x9a +'[?]', # 0x9b +'[?]', # 0x9c +'[?]', # 0x9d +'[?]', # 0x9e +'[?]', # 0x9f +'A', # 0xa0 +'B', # 0xa1 +'G', # 0xa2 +'D', # 0xa3 +'E', # 0xa4 +'V', # 0xa5 +'Z', # 0xa6 +'T`', # 0xa7 +'I', # 0xa8 +'K', # 0xa9 +'L', # 0xaa +'M', # 0xab +'N', # 0xac +'O', # 0xad +'P', # 0xae +'Zh', # 0xaf +'R', # 0xb0 +'S', # 0xb1 +'T', # 0xb2 +'U', # 0xb3 +'P`', # 0xb4 +'K`', # 0xb5 +'G\'', # 0xb6 +'Q', # 0xb7 +'Sh', # 0xb8 +'Ch`', # 0xb9 +'C`', # 0xba +'Z\'', # 0xbb +'C', # 0xbc +'Ch', # 0xbd +'X', # 0xbe +'J', # 0xbf +'H', # 0xc0 +'E', # 0xc1 +'Y', # 0xc2 +'W', # 0xc3 +'Xh', # 0xc4 +'OE', # 0xc5 +'[?]', # 0xc6 +'[?]', # 0xc7 +'[?]', # 0xc8 +'[?]', # 0xc9 +'[?]', # 0xca +'[?]', # 0xcb +'[?]', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'a', # 0xd0 +'b', # 0xd1 +'g', # 0xd2 +'d', # 0xd3 +'e', # 0xd4 +'v', # 0xd5 +'z', # 0xd6 +'t`', # 0xd7 +'i', # 0xd8 +'k', # 0xd9 +'l', # 0xda +'m', # 0xdb +'n', # 0xdc +'o', # 0xdd +'p', # 0xde +'zh', # 0xdf +'r', # 0xe0 +'s', # 0xe1 +'t', # 0xe2 +'u', # 0xe3 +'p`', # 0xe4 +'k`', # 0xe5 +'g\'', # 0xe6 +'q', # 0xe7 +'sh', # 0xe8 +'ch`', # 0xe9 +'c`', # 0xea +'z\'', # 0xeb +'c', # 0xec +'ch', # 0xed +'x', # 0xee +'j', # 0xef +'h', # 0xf0 +'e', # 0xf1 +'y', # 0xf2 +'w', # 0xf3 +'xh', # 0xf4 +'oe', # 0xf5 +'f', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +' // ', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x011.py b/nstock/modules/unidecode/x011.py new file mode 100644 index 0000000..f0d8f92 --- /dev/null +++ b/nstock/modules/unidecode/x011.py @@ -0,0 +1,257 @@ +data = ( +'g', # 0x00 +'gg', # 0x01 +'n', # 0x02 +'d', # 0x03 +'dd', # 0x04 +'r', # 0x05 +'m', # 0x06 +'b', # 0x07 +'bb', # 0x08 +'s', # 0x09 +'ss', # 0x0a +'', # 0x0b +'j', # 0x0c +'jj', # 0x0d +'c', # 0x0e +'k', # 0x0f +'t', # 0x10 +'p', # 0x11 +'h', # 0x12 +'ng', # 0x13 +'nn', # 0x14 +'nd', # 0x15 +'nb', # 0x16 +'dg', # 0x17 +'rn', # 0x18 +'rr', # 0x19 +'rh', # 0x1a +'rN', # 0x1b +'mb', # 0x1c +'mN', # 0x1d +'bg', # 0x1e +'bn', # 0x1f +'', # 0x20 +'bs', # 0x21 +'bsg', # 0x22 +'bst', # 0x23 +'bsb', # 0x24 +'bss', # 0x25 +'bsj', # 0x26 +'bj', # 0x27 +'bc', # 0x28 +'bt', # 0x29 +'bp', # 0x2a +'bN', # 0x2b +'bbN', # 0x2c +'sg', # 0x2d +'sn', # 0x2e +'sd', # 0x2f +'sr', # 0x30 +'sm', # 0x31 +'sb', # 0x32 +'sbg', # 0x33 +'sss', # 0x34 +'s', # 0x35 +'sj', # 0x36 +'sc', # 0x37 +'sk', # 0x38 +'st', # 0x39 +'sp', # 0x3a +'sh', # 0x3b +'', # 0x3c +'', # 0x3d +'', # 0x3e +'', # 0x3f +'Z', # 0x40 +'g', # 0x41 +'d', # 0x42 +'m', # 0x43 +'b', # 0x44 +'s', # 0x45 +'Z', # 0x46 +'', # 0x47 +'j', # 0x48 +'c', # 0x49 +'t', # 0x4a +'p', # 0x4b +'N', # 0x4c +'j', # 0x4d +'', # 0x4e +'', # 0x4f +'', # 0x50 +'', # 0x51 +'ck', # 0x52 +'ch', # 0x53 +'', # 0x54 +'', # 0x55 +'pb', # 0x56 +'pN', # 0x57 +'hh', # 0x58 +'Q', # 0x59 +'[?]', # 0x5a +'[?]', # 0x5b +'[?]', # 0x5c +'[?]', # 0x5d +'[?]', # 0x5e +'', # 0x5f +'', # 0x60 +'a', # 0x61 +'ae', # 0x62 +'ya', # 0x63 +'yae', # 0x64 +'eo', # 0x65 +'e', # 0x66 +'yeo', # 0x67 +'ye', # 0x68 +'o', # 0x69 +'wa', # 0x6a +'wae', # 0x6b +'oe', # 0x6c +'yo', # 0x6d +'u', # 0x6e +'weo', # 0x6f +'we', # 0x70 +'wi', # 0x71 +'yu', # 0x72 +'eu', # 0x73 +'yi', # 0x74 +'i', # 0x75 +'a-o', # 0x76 +'a-u', # 0x77 +'ya-o', # 0x78 +'ya-yo', # 0x79 +'eo-o', # 0x7a +'eo-u', # 0x7b +'eo-eu', # 0x7c +'yeo-o', # 0x7d +'yeo-u', # 0x7e +'o-eo', # 0x7f +'o-e', # 0x80 +'o-ye', # 0x81 +'o-o', # 0x82 +'o-u', # 0x83 +'yo-ya', # 0x84 +'yo-yae', # 0x85 +'yo-yeo', # 0x86 +'yo-o', # 0x87 +'yo-i', # 0x88 +'u-a', # 0x89 +'u-ae', # 0x8a +'u-eo-eu', # 0x8b +'u-ye', # 0x8c +'u-u', # 0x8d +'yu-a', # 0x8e +'yu-eo', # 0x8f +'yu-e', # 0x90 +'yu-yeo', # 0x91 +'yu-ye', # 0x92 +'yu-u', # 0x93 +'yu-i', # 0x94 +'eu-u', # 0x95 +'eu-eu', # 0x96 +'yi-u', # 0x97 +'i-a', # 0x98 +'i-ya', # 0x99 +'i-o', # 0x9a +'i-u', # 0x9b +'i-eu', # 0x9c +'i-U', # 0x9d +'U', # 0x9e +'U-eo', # 0x9f +'U-u', # 0xa0 +'U-i', # 0xa1 +'UU', # 0xa2 +'[?]', # 0xa3 +'[?]', # 0xa4 +'[?]', # 0xa5 +'[?]', # 0xa6 +'[?]', # 0xa7 +'g', # 0xa8 +'gg', # 0xa9 +'gs', # 0xaa +'n', # 0xab +'nj', # 0xac +'nh', # 0xad +'d', # 0xae +'l', # 0xaf +'lg', # 0xb0 +'lm', # 0xb1 +'lb', # 0xb2 +'ls', # 0xb3 +'lt', # 0xb4 +'lp', # 0xb5 +'lh', # 0xb6 +'m', # 0xb7 +'b', # 0xb8 +'bs', # 0xb9 +'s', # 0xba +'ss', # 0xbb +'ng', # 0xbc +'j', # 0xbd +'c', # 0xbe +'k', # 0xbf +'t', # 0xc0 +'p', # 0xc1 +'h', # 0xc2 +'gl', # 0xc3 +'gsg', # 0xc4 +'ng', # 0xc5 +'nd', # 0xc6 +'ns', # 0xc7 +'nZ', # 0xc8 +'nt', # 0xc9 +'dg', # 0xca +'tl', # 0xcb +'lgs', # 0xcc +'ln', # 0xcd +'ld', # 0xce +'lth', # 0xcf +'ll', # 0xd0 +'lmg', # 0xd1 +'lms', # 0xd2 +'lbs', # 0xd3 +'lbh', # 0xd4 +'rNp', # 0xd5 +'lss', # 0xd6 +'lZ', # 0xd7 +'lk', # 0xd8 +'lQ', # 0xd9 +'mg', # 0xda +'ml', # 0xdb +'mb', # 0xdc +'ms', # 0xdd +'mss', # 0xde +'mZ', # 0xdf +'mc', # 0xe0 +'mh', # 0xe1 +'mN', # 0xe2 +'bl', # 0xe3 +'bp', # 0xe4 +'ph', # 0xe5 +'pN', # 0xe6 +'sg', # 0xe7 +'sd', # 0xe8 +'sl', # 0xe9 +'sb', # 0xea +'Z', # 0xeb +'g', # 0xec +'ss', # 0xed +'', # 0xee +'kh', # 0xef +'N', # 0xf0 +'Ns', # 0xf1 +'NZ', # 0xf2 +'pb', # 0xf3 +'pN', # 0xf4 +'hn', # 0xf5 +'hl', # 0xf6 +'hm', # 0xf7 +'hb', # 0xf8 +'Q', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x012.py b/nstock/modules/unidecode/x012.py new file mode 100644 index 0000000..f267065 --- /dev/null +++ b/nstock/modules/unidecode/x012.py @@ -0,0 +1,258 @@ +data = ( +'ha', # 0x00 +'hu', # 0x01 +'hi', # 0x02 +'haa', # 0x03 +'hee', # 0x04 +'he', # 0x05 +'ho', # 0x06 +'[?]', # 0x07 +'la', # 0x08 +'lu', # 0x09 +'li', # 0x0a +'laa', # 0x0b +'lee', # 0x0c +'le', # 0x0d +'lo', # 0x0e +'lwa', # 0x0f +'hha', # 0x10 +'hhu', # 0x11 +'hhi', # 0x12 +'hhaa', # 0x13 +'hhee', # 0x14 +'hhe', # 0x15 +'hho', # 0x16 +'hhwa', # 0x17 +'ma', # 0x18 +'mu', # 0x19 +'mi', # 0x1a +'maa', # 0x1b +'mee', # 0x1c +'me', # 0x1d +'mo', # 0x1e +'mwa', # 0x1f +'sza', # 0x20 +'szu', # 0x21 +'szi', # 0x22 +'szaa', # 0x23 +'szee', # 0x24 +'sze', # 0x25 +'szo', # 0x26 +'szwa', # 0x27 +'ra', # 0x28 +'ru', # 0x29 +'ri', # 0x2a +'raa', # 0x2b +'ree', # 0x2c +'re', # 0x2d +'ro', # 0x2e +'rwa', # 0x2f +'sa', # 0x30 +'su', # 0x31 +'si', # 0x32 +'saa', # 0x33 +'see', # 0x34 +'se', # 0x35 +'so', # 0x36 +'swa', # 0x37 +'sha', # 0x38 +'shu', # 0x39 +'shi', # 0x3a +'shaa', # 0x3b +'shee', # 0x3c +'she', # 0x3d +'sho', # 0x3e +'shwa', # 0x3f +'qa', # 0x40 +'qu', # 0x41 +'qi', # 0x42 +'qaa', # 0x43 +'qee', # 0x44 +'qe', # 0x45 +'qo', # 0x46 +'[?]', # 0x47 +'qwa', # 0x48 +'[?]', # 0x49 +'qwi', # 0x4a +'qwaa', # 0x4b +'qwee', # 0x4c +'qwe', # 0x4d +'[?]', # 0x4e +'[?]', # 0x4f +'qha', # 0x50 +'qhu', # 0x51 +'qhi', # 0x52 +'qhaa', # 0x53 +'qhee', # 0x54 +'qhe', # 0x55 +'qho', # 0x56 +'[?]', # 0x57 +'qhwa', # 0x58 +'[?]', # 0x59 +'qhwi', # 0x5a +'qhwaa', # 0x5b +'qhwee', # 0x5c +'qhwe', # 0x5d +'[?]', # 0x5e +'[?]', # 0x5f +'ba', # 0x60 +'bu', # 0x61 +'bi', # 0x62 +'baa', # 0x63 +'bee', # 0x64 +'be', # 0x65 +'bo', # 0x66 +'bwa', # 0x67 +'va', # 0x68 +'vu', # 0x69 +'vi', # 0x6a +'vaa', # 0x6b +'vee', # 0x6c +'ve', # 0x6d +'vo', # 0x6e +'vwa', # 0x6f +'ta', # 0x70 +'tu', # 0x71 +'ti', # 0x72 +'taa', # 0x73 +'tee', # 0x74 +'te', # 0x75 +'to', # 0x76 +'twa', # 0x77 +'ca', # 0x78 +'cu', # 0x79 +'ci', # 0x7a +'caa', # 0x7b +'cee', # 0x7c +'ce', # 0x7d +'co', # 0x7e +'cwa', # 0x7f +'xa', # 0x80 +'xu', # 0x81 +'xi', # 0x82 +'xaa', # 0x83 +'xee', # 0x84 +'xe', # 0x85 +'xo', # 0x86 +'[?]', # 0x87 +'xwa', # 0x88 +'[?]', # 0x89 +'xwi', # 0x8a +'xwaa', # 0x8b +'xwee', # 0x8c +'xwe', # 0x8d +'[?]', # 0x8e +'[?]', # 0x8f +'na', # 0x90 +'nu', # 0x91 +'ni', # 0x92 +'naa', # 0x93 +'nee', # 0x94 +'ne', # 0x95 +'no', # 0x96 +'nwa', # 0x97 +'nya', # 0x98 +'nyu', # 0x99 +'nyi', # 0x9a +'nyaa', # 0x9b +'nyee', # 0x9c +'nye', # 0x9d +'nyo', # 0x9e +'nywa', # 0x9f +'\'a', # 0xa0 +'\'u', # 0xa1 +'[?]', # 0xa2 +'\'aa', # 0xa3 +'\'ee', # 0xa4 +'\'e', # 0xa5 +'\'o', # 0xa6 +'\'wa', # 0xa7 +'ka', # 0xa8 +'ku', # 0xa9 +'ki', # 0xaa +'kaa', # 0xab +'kee', # 0xac +'ke', # 0xad +'ko', # 0xae +'[?]', # 0xaf +'kwa', # 0xb0 +'[?]', # 0xb1 +'kwi', # 0xb2 +'kwaa', # 0xb3 +'kwee', # 0xb4 +'kwe', # 0xb5 +'[?]', # 0xb6 +'[?]', # 0xb7 +'kxa', # 0xb8 +'kxu', # 0xb9 +'kxi', # 0xba +'kxaa', # 0xbb +'kxee', # 0xbc +'kxe', # 0xbd +'kxo', # 0xbe +'[?]', # 0xbf +'kxwa', # 0xc0 +'[?]', # 0xc1 +'kxwi', # 0xc2 +'kxwaa', # 0xc3 +'kxwee', # 0xc4 +'kxwe', # 0xc5 +'[?]', # 0xc6 +'[?]', # 0xc7 +'wa', # 0xc8 +'wu', # 0xc9 +'wi', # 0xca +'waa', # 0xcb +'wee', # 0xcc +'we', # 0xcd +'wo', # 0xce +'[?]', # 0xcf +'`a', # 0xd0 +'`u', # 0xd1 +'`i', # 0xd2 +'`aa', # 0xd3 +'`ee', # 0xd4 +'`e', # 0xd5 +'`o', # 0xd6 +'[?]', # 0xd7 +'za', # 0xd8 +'zu', # 0xd9 +'zi', # 0xda +'zaa', # 0xdb +'zee', # 0xdc +'ze', # 0xdd +'zo', # 0xde +'zwa', # 0xdf +'zha', # 0xe0 +'zhu', # 0xe1 +'zhi', # 0xe2 +'zhaa', # 0xe3 +'zhee', # 0xe4 +'zhe', # 0xe5 +'zho', # 0xe6 +'zhwa', # 0xe7 +'ya', # 0xe8 +'yu', # 0xe9 +'yi', # 0xea +'yaa', # 0xeb +'yee', # 0xec +'ye', # 0xed +'yo', # 0xee +'[?]', # 0xef +'da', # 0xf0 +'du', # 0xf1 +'di', # 0xf2 +'daa', # 0xf3 +'dee', # 0xf4 +'de', # 0xf5 +'do', # 0xf6 +'dwa', # 0xf7 +'dda', # 0xf8 +'ddu', # 0xf9 +'ddi', # 0xfa +'ddaa', # 0xfb +'ddee', # 0xfc +'dde', # 0xfd +'ddo', # 0xfe +'ddwa', # 0xff +) diff --git a/nstock/modules/unidecode/x013.py b/nstock/modules/unidecode/x013.py new file mode 100644 index 0000000..8a8c3f9 --- /dev/null +++ b/nstock/modules/unidecode/x013.py @@ -0,0 +1,257 @@ +data = ( +'ja', # 0x00 +'ju', # 0x01 +'ji', # 0x02 +'jaa', # 0x03 +'jee', # 0x04 +'je', # 0x05 +'jo', # 0x06 +'jwa', # 0x07 +'ga', # 0x08 +'gu', # 0x09 +'gi', # 0x0a +'gaa', # 0x0b +'gee', # 0x0c +'ge', # 0x0d +'go', # 0x0e +'[?]', # 0x0f +'gwa', # 0x10 +'[?]', # 0x11 +'gwi', # 0x12 +'gwaa', # 0x13 +'gwee', # 0x14 +'gwe', # 0x15 +'[?]', # 0x16 +'[?]', # 0x17 +'gga', # 0x18 +'ggu', # 0x19 +'ggi', # 0x1a +'ggaa', # 0x1b +'ggee', # 0x1c +'gge', # 0x1d +'ggo', # 0x1e +'[?]', # 0x1f +'tha', # 0x20 +'thu', # 0x21 +'thi', # 0x22 +'thaa', # 0x23 +'thee', # 0x24 +'the', # 0x25 +'tho', # 0x26 +'thwa', # 0x27 +'cha', # 0x28 +'chu', # 0x29 +'chi', # 0x2a +'chaa', # 0x2b +'chee', # 0x2c +'che', # 0x2d +'cho', # 0x2e +'chwa', # 0x2f +'pha', # 0x30 +'phu', # 0x31 +'phi', # 0x32 +'phaa', # 0x33 +'phee', # 0x34 +'phe', # 0x35 +'pho', # 0x36 +'phwa', # 0x37 +'tsa', # 0x38 +'tsu', # 0x39 +'tsi', # 0x3a +'tsaa', # 0x3b +'tsee', # 0x3c +'tse', # 0x3d +'tso', # 0x3e +'tswa', # 0x3f +'tza', # 0x40 +'tzu', # 0x41 +'tzi', # 0x42 +'tzaa', # 0x43 +'tzee', # 0x44 +'tze', # 0x45 +'tzo', # 0x46 +'[?]', # 0x47 +'fa', # 0x48 +'fu', # 0x49 +'fi', # 0x4a +'faa', # 0x4b +'fee', # 0x4c +'fe', # 0x4d +'fo', # 0x4e +'fwa', # 0x4f +'pa', # 0x50 +'pu', # 0x51 +'pi', # 0x52 +'paa', # 0x53 +'pee', # 0x54 +'pe', # 0x55 +'po', # 0x56 +'pwa', # 0x57 +'rya', # 0x58 +'mya', # 0x59 +'fya', # 0x5a +'[?]', # 0x5b +'[?]', # 0x5c +'[?]', # 0x5d +'[?]', # 0x5e +'[?]', # 0x5f +'[?]', # 0x60 +' ', # 0x61 +'.', # 0x62 +',', # 0x63 +';', # 0x64 +':', # 0x65 +':: ', # 0x66 +'?', # 0x67 +'//', # 0x68 +'1', # 0x69 +'2', # 0x6a +'3', # 0x6b +'4', # 0x6c +'5', # 0x6d +'6', # 0x6e +'7', # 0x6f +'8', # 0x70 +'9', # 0x71 +'10+', # 0x72 +'20+', # 0x73 +'30+', # 0x74 +'40+', # 0x75 +'50+', # 0x76 +'60+', # 0x77 +'70+', # 0x78 +'80+', # 0x79 +'90+', # 0x7a +'100+', # 0x7b +'10,000+', # 0x7c +'[?]', # 0x7d +'[?]', # 0x7e +'[?]', # 0x7f +'[?]', # 0x80 +'[?]', # 0x81 +'[?]', # 0x82 +'[?]', # 0x83 +'[?]', # 0x84 +'[?]', # 0x85 +'[?]', # 0x86 +'[?]', # 0x87 +'[?]', # 0x88 +'[?]', # 0x89 +'[?]', # 0x8a +'[?]', # 0x8b +'[?]', # 0x8c +'[?]', # 0x8d +'[?]', # 0x8e +'[?]', # 0x8f +'[?]', # 0x90 +'[?]', # 0x91 +'[?]', # 0x92 +'[?]', # 0x93 +'[?]', # 0x94 +'[?]', # 0x95 +'[?]', # 0x96 +'[?]', # 0x97 +'[?]', # 0x98 +'[?]', # 0x99 +'[?]', # 0x9a +'[?]', # 0x9b +'[?]', # 0x9c +'[?]', # 0x9d +'[?]', # 0x9e +'[?]', # 0x9f +'a', # 0xa0 +'e', # 0xa1 +'i', # 0xa2 +'o', # 0xa3 +'u', # 0xa4 +'v', # 0xa5 +'ga', # 0xa6 +'ka', # 0xa7 +'ge', # 0xa8 +'gi', # 0xa9 +'go', # 0xaa +'gu', # 0xab +'gv', # 0xac +'ha', # 0xad +'he', # 0xae +'hi', # 0xaf +'ho', # 0xb0 +'hu', # 0xb1 +'hv', # 0xb2 +'la', # 0xb3 +'le', # 0xb4 +'li', # 0xb5 +'lo', # 0xb6 +'lu', # 0xb7 +'lv', # 0xb8 +'ma', # 0xb9 +'me', # 0xba +'mi', # 0xbb +'mo', # 0xbc +'mu', # 0xbd +'na', # 0xbe +'hna', # 0xbf +'nah', # 0xc0 +'ne', # 0xc1 +'ni', # 0xc2 +'no', # 0xc3 +'nu', # 0xc4 +'nv', # 0xc5 +'qua', # 0xc6 +'que', # 0xc7 +'qui', # 0xc8 +'quo', # 0xc9 +'quu', # 0xca +'quv', # 0xcb +'sa', # 0xcc +'s', # 0xcd +'se', # 0xce +'si', # 0xcf +'so', # 0xd0 +'su', # 0xd1 +'sv', # 0xd2 +'da', # 0xd3 +'ta', # 0xd4 +'de', # 0xd5 +'te', # 0xd6 +'di', # 0xd7 +'ti', # 0xd8 +'do', # 0xd9 +'du', # 0xda +'dv', # 0xdb +'dla', # 0xdc +'tla', # 0xdd +'tle', # 0xde +'tli', # 0xdf +'tlo', # 0xe0 +'tlu', # 0xe1 +'tlv', # 0xe2 +'tsa', # 0xe3 +'tse', # 0xe4 +'tsi', # 0xe5 +'tso', # 0xe6 +'tsu', # 0xe7 +'tsv', # 0xe8 +'wa', # 0xe9 +'we', # 0xea +'wi', # 0xeb +'wo', # 0xec +'wu', # 0xed +'wv', # 0xee +'ya', # 0xef +'ye', # 0xf0 +'yi', # 0xf1 +'yo', # 0xf2 +'yu', # 0xf3 +'yv', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x014.py b/nstock/modules/unidecode/x014.py new file mode 100644 index 0000000..e8c0180 --- /dev/null +++ b/nstock/modules/unidecode/x014.py @@ -0,0 +1,258 @@ +data = ( +'[?]', # 0x00 +'e', # 0x01 +'aai', # 0x02 +'i', # 0x03 +'ii', # 0x04 +'o', # 0x05 +'oo', # 0x06 +'oo', # 0x07 +'ee', # 0x08 +'i', # 0x09 +'a', # 0x0a +'aa', # 0x0b +'we', # 0x0c +'we', # 0x0d +'wi', # 0x0e +'wi', # 0x0f +'wii', # 0x10 +'wii', # 0x11 +'wo', # 0x12 +'wo', # 0x13 +'woo', # 0x14 +'woo', # 0x15 +'woo', # 0x16 +'wa', # 0x17 +'wa', # 0x18 +'waa', # 0x19 +'waa', # 0x1a +'waa', # 0x1b +'ai', # 0x1c +'w', # 0x1d +'\'', # 0x1e +'t', # 0x1f +'k', # 0x20 +'sh', # 0x21 +'s', # 0x22 +'n', # 0x23 +'w', # 0x24 +'n', # 0x25 +'[?]', # 0x26 +'w', # 0x27 +'c', # 0x28 +'?', # 0x29 +'l', # 0x2a +'en', # 0x2b +'in', # 0x2c +'on', # 0x2d +'an', # 0x2e +'pe', # 0x2f +'paai', # 0x30 +'pi', # 0x31 +'pii', # 0x32 +'po', # 0x33 +'poo', # 0x34 +'poo', # 0x35 +'hee', # 0x36 +'hi', # 0x37 +'pa', # 0x38 +'paa', # 0x39 +'pwe', # 0x3a +'pwe', # 0x3b +'pwi', # 0x3c +'pwi', # 0x3d +'pwii', # 0x3e +'pwii', # 0x3f +'pwo', # 0x40 +'pwo', # 0x41 +'pwoo', # 0x42 +'pwoo', # 0x43 +'pwa', # 0x44 +'pwa', # 0x45 +'pwaa', # 0x46 +'pwaa', # 0x47 +'pwaa', # 0x48 +'p', # 0x49 +'p', # 0x4a +'h', # 0x4b +'te', # 0x4c +'taai', # 0x4d +'ti', # 0x4e +'tii', # 0x4f +'to', # 0x50 +'too', # 0x51 +'too', # 0x52 +'dee', # 0x53 +'di', # 0x54 +'ta', # 0x55 +'taa', # 0x56 +'twe', # 0x57 +'twe', # 0x58 +'twi', # 0x59 +'twi', # 0x5a +'twii', # 0x5b +'twii', # 0x5c +'two', # 0x5d +'two', # 0x5e +'twoo', # 0x5f +'twoo', # 0x60 +'twa', # 0x61 +'twa', # 0x62 +'twaa', # 0x63 +'twaa', # 0x64 +'twaa', # 0x65 +'t', # 0x66 +'tte', # 0x67 +'tti', # 0x68 +'tto', # 0x69 +'tta', # 0x6a +'ke', # 0x6b +'kaai', # 0x6c +'ki', # 0x6d +'kii', # 0x6e +'ko', # 0x6f +'koo', # 0x70 +'koo', # 0x71 +'ka', # 0x72 +'kaa', # 0x73 +'kwe', # 0x74 +'kwe', # 0x75 +'kwi', # 0x76 +'kwi', # 0x77 +'kwii', # 0x78 +'kwii', # 0x79 +'kwo', # 0x7a +'kwo', # 0x7b +'kwoo', # 0x7c +'kwoo', # 0x7d +'kwa', # 0x7e +'kwa', # 0x7f +'kwaa', # 0x80 +'kwaa', # 0x81 +'kwaa', # 0x82 +'k', # 0x83 +'kw', # 0x84 +'keh', # 0x85 +'kih', # 0x86 +'koh', # 0x87 +'kah', # 0x88 +'ce', # 0x89 +'caai', # 0x8a +'ci', # 0x8b +'cii', # 0x8c +'co', # 0x8d +'coo', # 0x8e +'coo', # 0x8f +'ca', # 0x90 +'caa', # 0x91 +'cwe', # 0x92 +'cwe', # 0x93 +'cwi', # 0x94 +'cwi', # 0x95 +'cwii', # 0x96 +'cwii', # 0x97 +'cwo', # 0x98 +'cwo', # 0x99 +'cwoo', # 0x9a +'cwoo', # 0x9b +'cwa', # 0x9c +'cwa', # 0x9d +'cwaa', # 0x9e +'cwaa', # 0x9f +'cwaa', # 0xa0 +'c', # 0xa1 +'th', # 0xa2 +'me', # 0xa3 +'maai', # 0xa4 +'mi', # 0xa5 +'mii', # 0xa6 +'mo', # 0xa7 +'moo', # 0xa8 +'moo', # 0xa9 +'ma', # 0xaa +'maa', # 0xab +'mwe', # 0xac +'mwe', # 0xad +'mwi', # 0xae +'mwi', # 0xaf +'mwii', # 0xb0 +'mwii', # 0xb1 +'mwo', # 0xb2 +'mwo', # 0xb3 +'mwoo', # 0xb4 +'mwoo', # 0xb5 +'mwa', # 0xb6 +'mwa', # 0xb7 +'mwaa', # 0xb8 +'mwaa', # 0xb9 +'mwaa', # 0xba +'m', # 0xbb +'m', # 0xbc +'mh', # 0xbd +'m', # 0xbe +'m', # 0xbf +'ne', # 0xc0 +'naai', # 0xc1 +'ni', # 0xc2 +'nii', # 0xc3 +'no', # 0xc4 +'noo', # 0xc5 +'noo', # 0xc6 +'na', # 0xc7 +'naa', # 0xc8 +'nwe', # 0xc9 +'nwe', # 0xca +'nwa', # 0xcb +'nwa', # 0xcc +'nwaa', # 0xcd +'nwaa', # 0xce +'nwaa', # 0xcf +'n', # 0xd0 +'ng', # 0xd1 +'nh', # 0xd2 +'le', # 0xd3 +'laai', # 0xd4 +'li', # 0xd5 +'lii', # 0xd6 +'lo', # 0xd7 +'loo', # 0xd8 +'loo', # 0xd9 +'la', # 0xda +'laa', # 0xdb +'lwe', # 0xdc +'lwe', # 0xdd +'lwi', # 0xde +'lwi', # 0xdf +'lwii', # 0xe0 +'lwii', # 0xe1 +'lwo', # 0xe2 +'lwo', # 0xe3 +'lwoo', # 0xe4 +'lwoo', # 0xe5 +'lwa', # 0xe6 +'lwa', # 0xe7 +'lwaa', # 0xe8 +'lwaa', # 0xe9 +'l', # 0xea +'l', # 0xeb +'l', # 0xec +'se', # 0xed +'saai', # 0xee +'si', # 0xef +'sii', # 0xf0 +'so', # 0xf1 +'soo', # 0xf2 +'soo', # 0xf3 +'sa', # 0xf4 +'saa', # 0xf5 +'swe', # 0xf6 +'swe', # 0xf7 +'swi', # 0xf8 +'swi', # 0xf9 +'swii', # 0xfa +'swii', # 0xfb +'swo', # 0xfc +'swo', # 0xfd +'swoo', # 0xfe +'swoo', # 0xff +) diff --git a/nstock/modules/unidecode/x015.py b/nstock/modules/unidecode/x015.py new file mode 100644 index 0000000..5ac22cb --- /dev/null +++ b/nstock/modules/unidecode/x015.py @@ -0,0 +1,258 @@ +data = ( +'swa', # 0x00 +'swa', # 0x01 +'swaa', # 0x02 +'swaa', # 0x03 +'swaa', # 0x04 +'s', # 0x05 +'s', # 0x06 +'sw', # 0x07 +'s', # 0x08 +'sk', # 0x09 +'skw', # 0x0a +'sW', # 0x0b +'spwa', # 0x0c +'stwa', # 0x0d +'skwa', # 0x0e +'scwa', # 0x0f +'she', # 0x10 +'shi', # 0x11 +'shii', # 0x12 +'sho', # 0x13 +'shoo', # 0x14 +'sha', # 0x15 +'shaa', # 0x16 +'shwe', # 0x17 +'shwe', # 0x18 +'shwi', # 0x19 +'shwi', # 0x1a +'shwii', # 0x1b +'shwii', # 0x1c +'shwo', # 0x1d +'shwo', # 0x1e +'shwoo', # 0x1f +'shwoo', # 0x20 +'shwa', # 0x21 +'shwa', # 0x22 +'shwaa', # 0x23 +'shwaa', # 0x24 +'sh', # 0x25 +'ye', # 0x26 +'yaai', # 0x27 +'yi', # 0x28 +'yii', # 0x29 +'yo', # 0x2a +'yoo', # 0x2b +'yoo', # 0x2c +'ya', # 0x2d +'yaa', # 0x2e +'ywe', # 0x2f +'ywe', # 0x30 +'ywi', # 0x31 +'ywi', # 0x32 +'ywii', # 0x33 +'ywii', # 0x34 +'ywo', # 0x35 +'ywo', # 0x36 +'ywoo', # 0x37 +'ywoo', # 0x38 +'ywa', # 0x39 +'ywa', # 0x3a +'ywaa', # 0x3b +'ywaa', # 0x3c +'ywaa', # 0x3d +'y', # 0x3e +'y', # 0x3f +'y', # 0x40 +'yi', # 0x41 +'re', # 0x42 +'re', # 0x43 +'le', # 0x44 +'raai', # 0x45 +'ri', # 0x46 +'rii', # 0x47 +'ro', # 0x48 +'roo', # 0x49 +'lo', # 0x4a +'ra', # 0x4b +'raa', # 0x4c +'la', # 0x4d +'rwaa', # 0x4e +'rwaa', # 0x4f +'r', # 0x50 +'r', # 0x51 +'r', # 0x52 +'fe', # 0x53 +'faai', # 0x54 +'fi', # 0x55 +'fii', # 0x56 +'fo', # 0x57 +'foo', # 0x58 +'fa', # 0x59 +'faa', # 0x5a +'fwaa', # 0x5b +'fwaa', # 0x5c +'f', # 0x5d +'the', # 0x5e +'the', # 0x5f +'thi', # 0x60 +'thi', # 0x61 +'thii', # 0x62 +'thii', # 0x63 +'tho', # 0x64 +'thoo', # 0x65 +'tha', # 0x66 +'thaa', # 0x67 +'thwaa', # 0x68 +'thwaa', # 0x69 +'th', # 0x6a +'tthe', # 0x6b +'tthi', # 0x6c +'ttho', # 0x6d +'ttha', # 0x6e +'tth', # 0x6f +'tye', # 0x70 +'tyi', # 0x71 +'tyo', # 0x72 +'tya', # 0x73 +'he', # 0x74 +'hi', # 0x75 +'hii', # 0x76 +'ho', # 0x77 +'hoo', # 0x78 +'ha', # 0x79 +'haa', # 0x7a +'h', # 0x7b +'h', # 0x7c +'hk', # 0x7d +'qaai', # 0x7e +'qi', # 0x7f +'qii', # 0x80 +'qo', # 0x81 +'qoo', # 0x82 +'qa', # 0x83 +'qaa', # 0x84 +'q', # 0x85 +'tlhe', # 0x86 +'tlhi', # 0x87 +'tlho', # 0x88 +'tlha', # 0x89 +'re', # 0x8a +'ri', # 0x8b +'ro', # 0x8c +'ra', # 0x8d +'ngaai', # 0x8e +'ngi', # 0x8f +'ngii', # 0x90 +'ngo', # 0x91 +'ngoo', # 0x92 +'nga', # 0x93 +'ngaa', # 0x94 +'ng', # 0x95 +'nng', # 0x96 +'she', # 0x97 +'shi', # 0x98 +'sho', # 0x99 +'sha', # 0x9a +'the', # 0x9b +'thi', # 0x9c +'tho', # 0x9d +'tha', # 0x9e +'th', # 0x9f +'lhi', # 0xa0 +'lhii', # 0xa1 +'lho', # 0xa2 +'lhoo', # 0xa3 +'lha', # 0xa4 +'lhaa', # 0xa5 +'lh', # 0xa6 +'the', # 0xa7 +'thi', # 0xa8 +'thii', # 0xa9 +'tho', # 0xaa +'thoo', # 0xab +'tha', # 0xac +'thaa', # 0xad +'th', # 0xae +'b', # 0xaf +'e', # 0xb0 +'i', # 0xb1 +'o', # 0xb2 +'a', # 0xb3 +'we', # 0xb4 +'wi', # 0xb5 +'wo', # 0xb6 +'wa', # 0xb7 +'ne', # 0xb8 +'ni', # 0xb9 +'no', # 0xba +'na', # 0xbb +'ke', # 0xbc +'ki', # 0xbd +'ko', # 0xbe +'ka', # 0xbf +'he', # 0xc0 +'hi', # 0xc1 +'ho', # 0xc2 +'ha', # 0xc3 +'ghu', # 0xc4 +'gho', # 0xc5 +'ghe', # 0xc6 +'ghee', # 0xc7 +'ghi', # 0xc8 +'gha', # 0xc9 +'ru', # 0xca +'ro', # 0xcb +'re', # 0xcc +'ree', # 0xcd +'ri', # 0xce +'ra', # 0xcf +'wu', # 0xd0 +'wo', # 0xd1 +'we', # 0xd2 +'wee', # 0xd3 +'wi', # 0xd4 +'wa', # 0xd5 +'hwu', # 0xd6 +'hwo', # 0xd7 +'hwe', # 0xd8 +'hwee', # 0xd9 +'hwi', # 0xda +'hwa', # 0xdb +'thu', # 0xdc +'tho', # 0xdd +'the', # 0xde +'thee', # 0xdf +'thi', # 0xe0 +'tha', # 0xe1 +'ttu', # 0xe2 +'tto', # 0xe3 +'tte', # 0xe4 +'ttee', # 0xe5 +'tti', # 0xe6 +'tta', # 0xe7 +'pu', # 0xe8 +'po', # 0xe9 +'pe', # 0xea +'pee', # 0xeb +'pi', # 0xec +'pa', # 0xed +'p', # 0xee +'gu', # 0xef +'go', # 0xf0 +'ge', # 0xf1 +'gee', # 0xf2 +'gi', # 0xf3 +'ga', # 0xf4 +'khu', # 0xf5 +'kho', # 0xf6 +'khe', # 0xf7 +'khee', # 0xf8 +'khi', # 0xf9 +'kha', # 0xfa +'kku', # 0xfb +'kko', # 0xfc +'kke', # 0xfd +'kkee', # 0xfe +'kki', # 0xff +) diff --git a/nstock/modules/unidecode/x016.py b/nstock/modules/unidecode/x016.py new file mode 100644 index 0000000..613d1e9 --- /dev/null +++ b/nstock/modules/unidecode/x016.py @@ -0,0 +1,257 @@ +data = ( +'kka', # 0x00 +'kk', # 0x01 +'nu', # 0x02 +'no', # 0x03 +'ne', # 0x04 +'nee', # 0x05 +'ni', # 0x06 +'na', # 0x07 +'mu', # 0x08 +'mo', # 0x09 +'me', # 0x0a +'mee', # 0x0b +'mi', # 0x0c +'ma', # 0x0d +'yu', # 0x0e +'yo', # 0x0f +'ye', # 0x10 +'yee', # 0x11 +'yi', # 0x12 +'ya', # 0x13 +'ju', # 0x14 +'ju', # 0x15 +'jo', # 0x16 +'je', # 0x17 +'jee', # 0x18 +'ji', # 0x19 +'ji', # 0x1a +'ja', # 0x1b +'jju', # 0x1c +'jjo', # 0x1d +'jje', # 0x1e +'jjee', # 0x1f +'jji', # 0x20 +'jja', # 0x21 +'lu', # 0x22 +'lo', # 0x23 +'le', # 0x24 +'lee', # 0x25 +'li', # 0x26 +'la', # 0x27 +'dlu', # 0x28 +'dlo', # 0x29 +'dle', # 0x2a +'dlee', # 0x2b +'dli', # 0x2c +'dla', # 0x2d +'lhu', # 0x2e +'lho', # 0x2f +'lhe', # 0x30 +'lhee', # 0x31 +'lhi', # 0x32 +'lha', # 0x33 +'tlhu', # 0x34 +'tlho', # 0x35 +'tlhe', # 0x36 +'tlhee', # 0x37 +'tlhi', # 0x38 +'tlha', # 0x39 +'tlu', # 0x3a +'tlo', # 0x3b +'tle', # 0x3c +'tlee', # 0x3d +'tli', # 0x3e +'tla', # 0x3f +'zu', # 0x40 +'zo', # 0x41 +'ze', # 0x42 +'zee', # 0x43 +'zi', # 0x44 +'za', # 0x45 +'z', # 0x46 +'z', # 0x47 +'dzu', # 0x48 +'dzo', # 0x49 +'dze', # 0x4a +'dzee', # 0x4b +'dzi', # 0x4c +'dza', # 0x4d +'su', # 0x4e +'so', # 0x4f +'se', # 0x50 +'see', # 0x51 +'si', # 0x52 +'sa', # 0x53 +'shu', # 0x54 +'sho', # 0x55 +'she', # 0x56 +'shee', # 0x57 +'shi', # 0x58 +'sha', # 0x59 +'sh', # 0x5a +'tsu', # 0x5b +'tso', # 0x5c +'tse', # 0x5d +'tsee', # 0x5e +'tsi', # 0x5f +'tsa', # 0x60 +'chu', # 0x61 +'cho', # 0x62 +'che', # 0x63 +'chee', # 0x64 +'chi', # 0x65 +'cha', # 0x66 +'ttsu', # 0x67 +'ttso', # 0x68 +'ttse', # 0x69 +'ttsee', # 0x6a +'ttsi', # 0x6b +'ttsa', # 0x6c +'X', # 0x6d +'.', # 0x6e +'qai', # 0x6f +'ngai', # 0x70 +'nngi', # 0x71 +'nngii', # 0x72 +'nngo', # 0x73 +'nngoo', # 0x74 +'nnga', # 0x75 +'nngaa', # 0x76 +'[?]', # 0x77 +'[?]', # 0x78 +'[?]', # 0x79 +'[?]', # 0x7a +'[?]', # 0x7b +'[?]', # 0x7c +'[?]', # 0x7d +'[?]', # 0x7e +'[?]', # 0x7f +' ', # 0x80 +'b', # 0x81 +'l', # 0x82 +'f', # 0x83 +'s', # 0x84 +'n', # 0x85 +'h', # 0x86 +'d', # 0x87 +'t', # 0x88 +'c', # 0x89 +'q', # 0x8a +'m', # 0x8b +'g', # 0x8c +'ng', # 0x8d +'z', # 0x8e +'r', # 0x8f +'a', # 0x90 +'o', # 0x91 +'u', # 0x92 +'e', # 0x93 +'i', # 0x94 +'ch', # 0x95 +'th', # 0x96 +'ph', # 0x97 +'p', # 0x98 +'x', # 0x99 +'p', # 0x9a +'<', # 0x9b +'>', # 0x9c +'[?]', # 0x9d +'[?]', # 0x9e +'[?]', # 0x9f +'f', # 0xa0 +'v', # 0xa1 +'u', # 0xa2 +'yr', # 0xa3 +'y', # 0xa4 +'w', # 0xa5 +'th', # 0xa6 +'th', # 0xa7 +'a', # 0xa8 +'o', # 0xa9 +'ac', # 0xaa +'ae', # 0xab +'o', # 0xac +'o', # 0xad +'o', # 0xae +'oe', # 0xaf +'on', # 0xb0 +'r', # 0xb1 +'k', # 0xb2 +'c', # 0xb3 +'k', # 0xb4 +'g', # 0xb5 +'ng', # 0xb6 +'g', # 0xb7 +'g', # 0xb8 +'w', # 0xb9 +'h', # 0xba +'h', # 0xbb +'h', # 0xbc +'h', # 0xbd +'n', # 0xbe +'n', # 0xbf +'n', # 0xc0 +'i', # 0xc1 +'e', # 0xc2 +'j', # 0xc3 +'g', # 0xc4 +'ae', # 0xc5 +'a', # 0xc6 +'eo', # 0xc7 +'p', # 0xc8 +'z', # 0xc9 +'s', # 0xca +'s', # 0xcb +'s', # 0xcc +'c', # 0xcd +'z', # 0xce +'t', # 0xcf +'t', # 0xd0 +'d', # 0xd1 +'b', # 0xd2 +'b', # 0xd3 +'p', # 0xd4 +'p', # 0xd5 +'e', # 0xd6 +'m', # 0xd7 +'m', # 0xd8 +'m', # 0xd9 +'l', # 0xda +'l', # 0xdb +'ng', # 0xdc +'ng', # 0xdd +'d', # 0xde +'o', # 0xdf +'ear', # 0xe0 +'ior', # 0xe1 +'qu', # 0xe2 +'qu', # 0xe3 +'qu', # 0xe4 +'s', # 0xe5 +'yr', # 0xe6 +'yr', # 0xe7 +'yr', # 0xe8 +'q', # 0xe9 +'x', # 0xea +'.', # 0xeb +':', # 0xec +'+', # 0xed +'17', # 0xee +'18', # 0xef +'19', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x017.py b/nstock/modules/unidecode/x017.py new file mode 100644 index 0000000..e0a8f44 --- /dev/null +++ b/nstock/modules/unidecode/x017.py @@ -0,0 +1,257 @@ +data = ( +'[?]', # 0x00 +'[?]', # 0x01 +'[?]', # 0x02 +'[?]', # 0x03 +'[?]', # 0x04 +'[?]', # 0x05 +'[?]', # 0x06 +'[?]', # 0x07 +'[?]', # 0x08 +'[?]', # 0x09 +'[?]', # 0x0a +'[?]', # 0x0b +'[?]', # 0x0c +'[?]', # 0x0d +'[?]', # 0x0e +'[?]', # 0x0f +'[?]', # 0x10 +'[?]', # 0x11 +'[?]', # 0x12 +'[?]', # 0x13 +'[?]', # 0x14 +'[?]', # 0x15 +'[?]', # 0x16 +'[?]', # 0x17 +'[?]', # 0x18 +'[?]', # 0x19 +'[?]', # 0x1a +'[?]', # 0x1b +'[?]', # 0x1c +'[?]', # 0x1d +'[?]', # 0x1e +'[?]', # 0x1f +'[?]', # 0x20 +'[?]', # 0x21 +'[?]', # 0x22 +'[?]', # 0x23 +'[?]', # 0x24 +'[?]', # 0x25 +'[?]', # 0x26 +'[?]', # 0x27 +'[?]', # 0x28 +'[?]', # 0x29 +'[?]', # 0x2a +'[?]', # 0x2b +'[?]', # 0x2c +'[?]', # 0x2d +'[?]', # 0x2e +'[?]', # 0x2f +'[?]', # 0x30 +'[?]', # 0x31 +'[?]', # 0x32 +'[?]', # 0x33 +'[?]', # 0x34 +'[?]', # 0x35 +'[?]', # 0x36 +'[?]', # 0x37 +'[?]', # 0x38 +'[?]', # 0x39 +'[?]', # 0x3a +'[?]', # 0x3b +'[?]', # 0x3c +'[?]', # 0x3d +'[?]', # 0x3e +'[?]', # 0x3f +'[?]', # 0x40 +'[?]', # 0x41 +'[?]', # 0x42 +'[?]', # 0x43 +'[?]', # 0x44 +'[?]', # 0x45 +'[?]', # 0x46 +'[?]', # 0x47 +'[?]', # 0x48 +'[?]', # 0x49 +'[?]', # 0x4a +'[?]', # 0x4b +'[?]', # 0x4c +'[?]', # 0x4d +'[?]', # 0x4e +'[?]', # 0x4f +'[?]', # 0x50 +'[?]', # 0x51 +'[?]', # 0x52 +'[?]', # 0x53 +'[?]', # 0x54 +'[?]', # 0x55 +'[?]', # 0x56 +'[?]', # 0x57 +'[?]', # 0x58 +'[?]', # 0x59 +'[?]', # 0x5a +'[?]', # 0x5b +'[?]', # 0x5c +'[?]', # 0x5d +'[?]', # 0x5e +'[?]', # 0x5f +'[?]', # 0x60 +'[?]', # 0x61 +'[?]', # 0x62 +'[?]', # 0x63 +'[?]', # 0x64 +'[?]', # 0x65 +'[?]', # 0x66 +'[?]', # 0x67 +'[?]', # 0x68 +'[?]', # 0x69 +'[?]', # 0x6a +'[?]', # 0x6b +'[?]', # 0x6c +'[?]', # 0x6d +'[?]', # 0x6e +'[?]', # 0x6f +'[?]', # 0x70 +'[?]', # 0x71 +'[?]', # 0x72 +'[?]', # 0x73 +'[?]', # 0x74 +'[?]', # 0x75 +'[?]', # 0x76 +'[?]', # 0x77 +'[?]', # 0x78 +'[?]', # 0x79 +'[?]', # 0x7a +'[?]', # 0x7b +'[?]', # 0x7c +'[?]', # 0x7d +'[?]', # 0x7e +'[?]', # 0x7f +'k', # 0x80 +'kh', # 0x81 +'g', # 0x82 +'gh', # 0x83 +'ng', # 0x84 +'c', # 0x85 +'ch', # 0x86 +'j', # 0x87 +'jh', # 0x88 +'ny', # 0x89 +'t', # 0x8a +'tth', # 0x8b +'d', # 0x8c +'ddh', # 0x8d +'nn', # 0x8e +'t', # 0x8f +'th', # 0x90 +'d', # 0x91 +'dh', # 0x92 +'n', # 0x93 +'p', # 0x94 +'ph', # 0x95 +'b', # 0x96 +'bh', # 0x97 +'m', # 0x98 +'y', # 0x99 +'r', # 0x9a +'l', # 0x9b +'v', # 0x9c +'sh', # 0x9d +'ss', # 0x9e +'s', # 0x9f +'h', # 0xa0 +'l', # 0xa1 +'q', # 0xa2 +'a', # 0xa3 +'aa', # 0xa4 +'i', # 0xa5 +'ii', # 0xa6 +'u', # 0xa7 +'uk', # 0xa8 +'uu', # 0xa9 +'uuv', # 0xaa +'ry', # 0xab +'ryy', # 0xac +'ly', # 0xad +'lyy', # 0xae +'e', # 0xaf +'ai', # 0xb0 +'oo', # 0xb1 +'oo', # 0xb2 +'au', # 0xb3 +'a', # 0xb4 +'aa', # 0xb5 +'aa', # 0xb6 +'i', # 0xb7 +'ii', # 0xb8 +'y', # 0xb9 +'yy', # 0xba +'u', # 0xbb +'uu', # 0xbc +'ua', # 0xbd +'oe', # 0xbe +'ya', # 0xbf +'ie', # 0xc0 +'e', # 0xc1 +'ae', # 0xc2 +'ai', # 0xc3 +'oo', # 0xc4 +'au', # 0xc5 +'M', # 0xc6 +'H', # 0xc7 +'a`', # 0xc8 +'', # 0xc9 +'', # 0xca +'', # 0xcb +'r', # 0xcc +'', # 0xcd +'!', # 0xce +'', # 0xcf +'', # 0xd0 +'', # 0xd1 +'', # 0xd2 +'', # 0xd3 +'.', # 0xd4 +' // ', # 0xd5 +':', # 0xd6 +'+', # 0xd7 +'++', # 0xd8 +' * ', # 0xd9 +' /// ', # 0xda +'KR', # 0xdb +'\'', # 0xdc +'[?]', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'0', # 0xe0 +'1', # 0xe1 +'2', # 0xe2 +'3', # 0xe3 +'4', # 0xe4 +'5', # 0xe5 +'6', # 0xe6 +'7', # 0xe7 +'8', # 0xe8 +'9', # 0xe9 +'[?]', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x018.py b/nstock/modules/unidecode/x018.py new file mode 100644 index 0000000..3162a01 --- /dev/null +++ b/nstock/modules/unidecode/x018.py @@ -0,0 +1,257 @@ +data = ( +' @ ', # 0x00 +' ... ', # 0x01 +', ', # 0x02 +'. ', # 0x03 +': ', # 0x04 +' // ', # 0x05 +'', # 0x06 +'-', # 0x07 +', ', # 0x08 +'. ', # 0x09 +'', # 0x0a +'', # 0x0b +'', # 0x0c +'', # 0x0d +'', # 0x0e +'[?]', # 0x0f +'0', # 0x10 +'1', # 0x11 +'2', # 0x12 +'3', # 0x13 +'4', # 0x14 +'5', # 0x15 +'6', # 0x16 +'7', # 0x17 +'8', # 0x18 +'9', # 0x19 +'[?]', # 0x1a +'[?]', # 0x1b +'[?]', # 0x1c +'[?]', # 0x1d +'[?]', # 0x1e +'[?]', # 0x1f +'a', # 0x20 +'e', # 0x21 +'i', # 0x22 +'o', # 0x23 +'u', # 0x24 +'O', # 0x25 +'U', # 0x26 +'ee', # 0x27 +'n', # 0x28 +'ng', # 0x29 +'b', # 0x2a +'p', # 0x2b +'q', # 0x2c +'g', # 0x2d +'m', # 0x2e +'l', # 0x2f +'s', # 0x30 +'sh', # 0x31 +'t', # 0x32 +'d', # 0x33 +'ch', # 0x34 +'j', # 0x35 +'y', # 0x36 +'r', # 0x37 +'w', # 0x38 +'f', # 0x39 +'k', # 0x3a +'kha', # 0x3b +'ts', # 0x3c +'z', # 0x3d +'h', # 0x3e +'zr', # 0x3f +'lh', # 0x40 +'zh', # 0x41 +'ch', # 0x42 +'-', # 0x43 +'e', # 0x44 +'i', # 0x45 +'o', # 0x46 +'u', # 0x47 +'O', # 0x48 +'U', # 0x49 +'ng', # 0x4a +'b', # 0x4b +'p', # 0x4c +'q', # 0x4d +'g', # 0x4e +'m', # 0x4f +'t', # 0x50 +'d', # 0x51 +'ch', # 0x52 +'j', # 0x53 +'ts', # 0x54 +'y', # 0x55 +'w', # 0x56 +'k', # 0x57 +'g', # 0x58 +'h', # 0x59 +'jy', # 0x5a +'ny', # 0x5b +'dz', # 0x5c +'e', # 0x5d +'i', # 0x5e +'iy', # 0x5f +'U', # 0x60 +'u', # 0x61 +'ng', # 0x62 +'k', # 0x63 +'g', # 0x64 +'h', # 0x65 +'p', # 0x66 +'sh', # 0x67 +'t', # 0x68 +'d', # 0x69 +'j', # 0x6a +'f', # 0x6b +'g', # 0x6c +'h', # 0x6d +'ts', # 0x6e +'z', # 0x6f +'r', # 0x70 +'ch', # 0x71 +'zh', # 0x72 +'i', # 0x73 +'k', # 0x74 +'r', # 0x75 +'f', # 0x76 +'zh', # 0x77 +'[?]', # 0x78 +'[?]', # 0x79 +'[?]', # 0x7a +'[?]', # 0x7b +'[?]', # 0x7c +'[?]', # 0x7d +'[?]', # 0x7e +'[?]', # 0x7f +'[?]', # 0x80 +'H', # 0x81 +'X', # 0x82 +'W', # 0x83 +'M', # 0x84 +' 3 ', # 0x85 +' 333 ', # 0x86 +'a', # 0x87 +'i', # 0x88 +'k', # 0x89 +'ng', # 0x8a +'c', # 0x8b +'tt', # 0x8c +'tth', # 0x8d +'dd', # 0x8e +'nn', # 0x8f +'t', # 0x90 +'d', # 0x91 +'p', # 0x92 +'ph', # 0x93 +'ss', # 0x94 +'zh', # 0x95 +'z', # 0x96 +'a', # 0x97 +'t', # 0x98 +'zh', # 0x99 +'gh', # 0x9a +'ng', # 0x9b +'c', # 0x9c +'jh', # 0x9d +'tta', # 0x9e +'ddh', # 0x9f +'t', # 0xa0 +'dh', # 0xa1 +'ss', # 0xa2 +'cy', # 0xa3 +'zh', # 0xa4 +'z', # 0xa5 +'u', # 0xa6 +'y', # 0xa7 +'bh', # 0xa8 +'\'', # 0xa9 +'[?]', # 0xaa +'[?]', # 0xab +'[?]', # 0xac +'[?]', # 0xad +'[?]', # 0xae +'[?]', # 0xaf +'[?]', # 0xb0 +'[?]', # 0xb1 +'[?]', # 0xb2 +'[?]', # 0xb3 +'[?]', # 0xb4 +'[?]', # 0xb5 +'[?]', # 0xb6 +'[?]', # 0xb7 +'[?]', # 0xb8 +'[?]', # 0xb9 +'[?]', # 0xba +'[?]', # 0xbb +'[?]', # 0xbc +'[?]', # 0xbd +'[?]', # 0xbe +'[?]', # 0xbf +'[?]', # 0xc0 +'[?]', # 0xc1 +'[?]', # 0xc2 +'[?]', # 0xc3 +'[?]', # 0xc4 +'[?]', # 0xc5 +'[?]', # 0xc6 +'[?]', # 0xc7 +'[?]', # 0xc8 +'[?]', # 0xc9 +'[?]', # 0xca +'[?]', # 0xcb +'[?]', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'[?]', # 0xd0 +'[?]', # 0xd1 +'[?]', # 0xd2 +'[?]', # 0xd3 +'[?]', # 0xd4 +'[?]', # 0xd5 +'[?]', # 0xd6 +'[?]', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'[?]', # 0xdc +'[?]', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'[?]', # 0xe0 +'[?]', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'[?]', # 0xe6 +'[?]', # 0xe7 +'[?]', # 0xe8 +'[?]', # 0xe9 +'[?]', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x01d.py b/nstock/modules/unidecode/x01d.py new file mode 100644 index 0000000..5b65906 --- /dev/null +++ b/nstock/modules/unidecode/x01d.py @@ -0,0 +1,257 @@ +data = ( +'', # 0x00 +'', # 0x01 +'', # 0x02 +'', # 0x03 +'', # 0x04 +'', # 0x05 +'', # 0x06 +'', # 0x07 +'', # 0x08 +'', # 0x09 +'', # 0x0a +'', # 0x0b +'', # 0x0c +'', # 0x0d +'', # 0x0e +'', # 0x0f +'', # 0x10 +'', # 0x11 +'', # 0x12 +'', # 0x13 +'', # 0x14 +'', # 0x15 +'', # 0x16 +'', # 0x17 +'', # 0x18 +'', # 0x19 +'', # 0x1a +'', # 0x1b +'', # 0x1c +'', # 0x1d +'', # 0x1e +'', # 0x1f +'', # 0x20 +'', # 0x21 +'', # 0x22 +'', # 0x23 +'', # 0x24 +'', # 0x25 +'', # 0x26 +'', # 0x27 +'', # 0x28 +'', # 0x29 +'', # 0x2a +'', # 0x2b +'', # 0x2c +'', # 0x2d +'', # 0x2e +'', # 0x2f +'', # 0x30 +'', # 0x31 +'', # 0x32 +'', # 0x33 +'', # 0x34 +'', # 0x35 +'', # 0x36 +'', # 0x37 +'', # 0x38 +'', # 0x39 +'', # 0x3a +'', # 0x3b +'', # 0x3c +'', # 0x3d +'', # 0x3e +'', # 0x3f +'', # 0x40 +'', # 0x41 +'', # 0x42 +'', # 0x43 +'', # 0x44 +'', # 0x45 +'', # 0x46 +'', # 0x47 +'', # 0x48 +'', # 0x49 +'', # 0x4a +'', # 0x4b +'', # 0x4c +'', # 0x4d +'', # 0x4e +'', # 0x4f +'', # 0x50 +'', # 0x51 +'', # 0x52 +'', # 0x53 +'', # 0x54 +'', # 0x55 +'', # 0x56 +'', # 0x57 +'', # 0x58 +'', # 0x59 +'', # 0x5a +'', # 0x5b +'', # 0x5c +'', # 0x5d +'', # 0x5e +'', # 0x5f +'', # 0x60 +'', # 0x61 +'', # 0x62 +'', # 0x63 +'', # 0x64 +'', # 0x65 +'', # 0x66 +'', # 0x67 +'', # 0x68 +'', # 0x69 +'', # 0x6a +'', # 0x6b +'b', # 0x6c +'d', # 0x6d +'f', # 0x6e +'m', # 0x6f +'n', # 0x70 +'p', # 0x71 +'r', # 0x72 +'r', # 0x73 +'s', # 0x74 +'t', # 0x75 +'z', # 0x76 +'g', # 0x77 +'', # 0x78 +'', # 0x79 +'', # 0x7a +'', # 0x7b +'', # 0x7c +'p', # 0x7d +'', # 0x7e +'', # 0x7f +'b', # 0x80 +'d', # 0x81 +'f', # 0x82 +'g', # 0x83 +'k', # 0x84 +'l', # 0x85 +'m', # 0x86 +'n', # 0x87 +'p', # 0x88 +'r', # 0x89 +'s', # 0x8a +'', # 0x8b +'v', # 0x8c +'x', # 0x8d +'z', # 0x8e +'', # 0x8f +'', # 0x90 +'', # 0x91 +'', # 0x92 +'', # 0x93 +'', # 0x94 +'', # 0x95 +'', # 0x96 +'', # 0x97 +'', # 0x98 +'', # 0x99 +'', # 0x9a +'', # 0x9b +'', # 0x9c +'', # 0x9d +'', # 0x9e +'', # 0x9f +'', # 0xa0 +'', # 0xa1 +'', # 0xa2 +'', # 0xa3 +'', # 0xa4 +'', # 0xa5 +'', # 0xa6 +'', # 0xa7 +'', # 0xa8 +'', # 0xa9 +'', # 0xaa +'', # 0xab +'', # 0xac +'', # 0xad +'', # 0xae +'', # 0xaf +'', # 0xb0 +'', # 0xb1 +'', # 0xb2 +'', # 0xb3 +'', # 0xb4 +'', # 0xb5 +'', # 0xb6 +'', # 0xb7 +'', # 0xb8 +'', # 0xb9 +'', # 0xba +'', # 0xbb +'', # 0xbc +'', # 0xbd +'', # 0xbe +'', # 0xbf +'', # 0xc0 +'', # 0xc1 +'', # 0xc2 +'', # 0xc3 +'', # 0xc4 +'', # 0xc5 +'', # 0xc6 +'', # 0xc7 +'', # 0xc8 +'', # 0xc9 +'', # 0xca +'', # 0xcb +'', # 0xcc +'', # 0xcd +'', # 0xce +'', # 0xcf +'', # 0xd0 +'', # 0xd1 +'', # 0xd2 +'', # 0xd3 +'', # 0xd4 +'', # 0xd5 +'', # 0xd6 +'', # 0xd7 +'', # 0xd8 +'', # 0xd9 +'', # 0xda +'', # 0xdb +'', # 0xdc +'', # 0xdd +'', # 0xde +'', # 0xdf +'', # 0xe0 +'', # 0xe1 +'', # 0xe2 +'', # 0xe3 +'', # 0xe4 +'', # 0xe5 +'', # 0xe6 +'', # 0xe7 +'', # 0xe8 +'', # 0xe9 +'', # 0xea +'', # 0xeb +'', # 0xec +'', # 0xed +'', # 0xee +'', # 0xef +'', # 0xf0 +'', # 0xf1 +'', # 0xf2 +'', # 0xf3 +'', # 0xf4 +'', # 0xf5 +'', # 0xf6 +'', # 0xf7 +'', # 0xf8 +'', # 0xf9 +'', # 0xfa +'', # 0xfb +'', # 0xfc +'', # 0xfd +'', # 0xfe +) diff --git a/nstock/modules/unidecode/x01e.py b/nstock/modules/unidecode/x01e.py new file mode 100644 index 0000000..606576b --- /dev/null +++ b/nstock/modules/unidecode/x01e.py @@ -0,0 +1,257 @@ +data = ( +'A', # 0x00 +'a', # 0x01 +'B', # 0x02 +'b', # 0x03 +'B', # 0x04 +'b', # 0x05 +'B', # 0x06 +'b', # 0x07 +'C', # 0x08 +'c', # 0x09 +'D', # 0x0a +'d', # 0x0b +'D', # 0x0c +'d', # 0x0d +'D', # 0x0e +'d', # 0x0f +'D', # 0x10 +'d', # 0x11 +'D', # 0x12 +'d', # 0x13 +'E', # 0x14 +'e', # 0x15 +'E', # 0x16 +'e', # 0x17 +'E', # 0x18 +'e', # 0x19 +'E', # 0x1a +'e', # 0x1b +'E', # 0x1c +'e', # 0x1d +'F', # 0x1e +'f', # 0x1f +'G', # 0x20 +'g', # 0x21 +'H', # 0x22 +'h', # 0x23 +'H', # 0x24 +'h', # 0x25 +'H', # 0x26 +'h', # 0x27 +'H', # 0x28 +'h', # 0x29 +'H', # 0x2a +'h', # 0x2b +'I', # 0x2c +'i', # 0x2d +'I', # 0x2e +'i', # 0x2f +'K', # 0x30 +'k', # 0x31 +'K', # 0x32 +'k', # 0x33 +'K', # 0x34 +'k', # 0x35 +'L', # 0x36 +'l', # 0x37 +'L', # 0x38 +'l', # 0x39 +'L', # 0x3a +'l', # 0x3b +'L', # 0x3c +'l', # 0x3d +'M', # 0x3e +'m', # 0x3f +'M', # 0x40 +'m', # 0x41 +'M', # 0x42 +'m', # 0x43 +'N', # 0x44 +'n', # 0x45 +'N', # 0x46 +'n', # 0x47 +'N', # 0x48 +'n', # 0x49 +'N', # 0x4a +'n', # 0x4b +'O', # 0x4c +'o', # 0x4d +'O', # 0x4e +'o', # 0x4f +'O', # 0x50 +'o', # 0x51 +'O', # 0x52 +'o', # 0x53 +'P', # 0x54 +'p', # 0x55 +'P', # 0x56 +'p', # 0x57 +'R', # 0x58 +'r', # 0x59 +'R', # 0x5a +'r', # 0x5b +'R', # 0x5c +'r', # 0x5d +'R', # 0x5e +'r', # 0x5f +'S', # 0x60 +'s', # 0x61 +'S', # 0x62 +'s', # 0x63 +'S', # 0x64 +'s', # 0x65 +'S', # 0x66 +'s', # 0x67 +'S', # 0x68 +'s', # 0x69 +'T', # 0x6a +'t', # 0x6b +'T', # 0x6c +'t', # 0x6d +'T', # 0x6e +'t', # 0x6f +'T', # 0x70 +'t', # 0x71 +'U', # 0x72 +'u', # 0x73 +'U', # 0x74 +'u', # 0x75 +'U', # 0x76 +'u', # 0x77 +'U', # 0x78 +'u', # 0x79 +'U', # 0x7a +'u', # 0x7b +'V', # 0x7c +'v', # 0x7d +'V', # 0x7e +'v', # 0x7f +'W', # 0x80 +'w', # 0x81 +'W', # 0x82 +'w', # 0x83 +'W', # 0x84 +'w', # 0x85 +'W', # 0x86 +'w', # 0x87 +'W', # 0x88 +'w', # 0x89 +'X', # 0x8a +'x', # 0x8b +'X', # 0x8c +'x', # 0x8d +'Y', # 0x8e +'y', # 0x8f +'Z', # 0x90 +'z', # 0x91 +'Z', # 0x92 +'z', # 0x93 +'Z', # 0x94 +'z', # 0x95 +'h', # 0x96 +'t', # 0x97 +'w', # 0x98 +'y', # 0x99 +'a', # 0x9a +'S', # 0x9b +'[?]', # 0x9c +'[?]', # 0x9d +'Ss', # 0x9e +'[?]', # 0x9f +'A', # 0xa0 +'a', # 0xa1 +'A', # 0xa2 +'a', # 0xa3 +'A', # 0xa4 +'a', # 0xa5 +'A', # 0xa6 +'a', # 0xa7 +'A', # 0xa8 +'a', # 0xa9 +'A', # 0xaa +'a', # 0xab +'A', # 0xac +'a', # 0xad +'A', # 0xae +'a', # 0xaf +'A', # 0xb0 +'a', # 0xb1 +'A', # 0xb2 +'a', # 0xb3 +'A', # 0xb4 +'a', # 0xb5 +'A', # 0xb6 +'a', # 0xb7 +'E', # 0xb8 +'e', # 0xb9 +'E', # 0xba +'e', # 0xbb +'E', # 0xbc +'e', # 0xbd +'E', # 0xbe +'e', # 0xbf +'E', # 0xc0 +'e', # 0xc1 +'E', # 0xc2 +'e', # 0xc3 +'E', # 0xc4 +'e', # 0xc5 +'E', # 0xc6 +'e', # 0xc7 +'I', # 0xc8 +'i', # 0xc9 +'I', # 0xca +'i', # 0xcb +'O', # 0xcc +'o', # 0xcd +'O', # 0xce +'o', # 0xcf +'O', # 0xd0 +'o', # 0xd1 +'O', # 0xd2 +'o', # 0xd3 +'O', # 0xd4 +'o', # 0xd5 +'O', # 0xd6 +'o', # 0xd7 +'O', # 0xd8 +'o', # 0xd9 +'O', # 0xda +'o', # 0xdb +'O', # 0xdc +'o', # 0xdd +'O', # 0xde +'o', # 0xdf +'O', # 0xe0 +'o', # 0xe1 +'O', # 0xe2 +'o', # 0xe3 +'U', # 0xe4 +'u', # 0xe5 +'U', # 0xe6 +'u', # 0xe7 +'U', # 0xe8 +'u', # 0xe9 +'U', # 0xea +'u', # 0xeb +'U', # 0xec +'u', # 0xed +'U', # 0xee +'u', # 0xef +'U', # 0xf0 +'u', # 0xf1 +'Y', # 0xf2 +'y', # 0xf3 +'Y', # 0xf4 +'y', # 0xf5 +'Y', # 0xf6 +'y', # 0xf7 +'Y', # 0xf8 +'y', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x01f.py b/nstock/modules/unidecode/x01f.py new file mode 100644 index 0000000..bcd2dec --- /dev/null +++ b/nstock/modules/unidecode/x01f.py @@ -0,0 +1,257 @@ +data = ( +'a', # 0x00 +'a', # 0x01 +'a', # 0x02 +'a', # 0x03 +'a', # 0x04 +'a', # 0x05 +'a', # 0x06 +'a', # 0x07 +'A', # 0x08 +'A', # 0x09 +'A', # 0x0a +'A', # 0x0b +'A', # 0x0c +'A', # 0x0d +'A', # 0x0e +'A', # 0x0f +'e', # 0x10 +'e', # 0x11 +'e', # 0x12 +'e', # 0x13 +'e', # 0x14 +'e', # 0x15 +'[?]', # 0x16 +'[?]', # 0x17 +'E', # 0x18 +'E', # 0x19 +'E', # 0x1a +'E', # 0x1b +'E', # 0x1c +'E', # 0x1d +'[?]', # 0x1e +'[?]', # 0x1f +'e', # 0x20 +'e', # 0x21 +'e', # 0x22 +'e', # 0x23 +'e', # 0x24 +'e', # 0x25 +'e', # 0x26 +'e', # 0x27 +'E', # 0x28 +'E', # 0x29 +'E', # 0x2a +'E', # 0x2b +'E', # 0x2c +'E', # 0x2d +'E', # 0x2e +'E', # 0x2f +'i', # 0x30 +'i', # 0x31 +'i', # 0x32 +'i', # 0x33 +'i', # 0x34 +'i', # 0x35 +'i', # 0x36 +'i', # 0x37 +'I', # 0x38 +'I', # 0x39 +'I', # 0x3a +'I', # 0x3b +'I', # 0x3c +'I', # 0x3d +'I', # 0x3e +'I', # 0x3f +'o', # 0x40 +'o', # 0x41 +'o', # 0x42 +'o', # 0x43 +'o', # 0x44 +'o', # 0x45 +'[?]', # 0x46 +'[?]', # 0x47 +'O', # 0x48 +'O', # 0x49 +'O', # 0x4a +'O', # 0x4b +'O', # 0x4c +'O', # 0x4d +'[?]', # 0x4e +'[?]', # 0x4f +'u', # 0x50 +'u', # 0x51 +'u', # 0x52 +'u', # 0x53 +'u', # 0x54 +'u', # 0x55 +'u', # 0x56 +'u', # 0x57 +'[?]', # 0x58 +'U', # 0x59 +'[?]', # 0x5a +'U', # 0x5b +'[?]', # 0x5c +'U', # 0x5d +'[?]', # 0x5e +'U', # 0x5f +'o', # 0x60 +'o', # 0x61 +'o', # 0x62 +'o', # 0x63 +'o', # 0x64 +'o', # 0x65 +'o', # 0x66 +'o', # 0x67 +'O', # 0x68 +'O', # 0x69 +'O', # 0x6a +'O', # 0x6b +'O', # 0x6c +'O', # 0x6d +'O', # 0x6e +'O', # 0x6f +'a', # 0x70 +'a', # 0x71 +'e', # 0x72 +'e', # 0x73 +'e', # 0x74 +'e', # 0x75 +'i', # 0x76 +'i', # 0x77 +'o', # 0x78 +'o', # 0x79 +'u', # 0x7a +'u', # 0x7b +'o', # 0x7c +'o', # 0x7d +'[?]', # 0x7e +'[?]', # 0x7f +'a', # 0x80 +'a', # 0x81 +'a', # 0x82 +'a', # 0x83 +'a', # 0x84 +'a', # 0x85 +'a', # 0x86 +'a', # 0x87 +'A', # 0x88 +'A', # 0x89 +'A', # 0x8a +'A', # 0x8b +'A', # 0x8c +'A', # 0x8d +'A', # 0x8e +'A', # 0x8f +'e', # 0x90 +'e', # 0x91 +'e', # 0x92 +'e', # 0x93 +'e', # 0x94 +'e', # 0x95 +'e', # 0x96 +'e', # 0x97 +'E', # 0x98 +'E', # 0x99 +'E', # 0x9a +'E', # 0x9b +'E', # 0x9c +'E', # 0x9d +'E', # 0x9e +'E', # 0x9f +'o', # 0xa0 +'o', # 0xa1 +'o', # 0xa2 +'o', # 0xa3 +'o', # 0xa4 +'o', # 0xa5 +'o', # 0xa6 +'o', # 0xa7 +'O', # 0xa8 +'O', # 0xa9 +'O', # 0xaa +'O', # 0xab +'O', # 0xac +'O', # 0xad +'O', # 0xae +'O', # 0xaf +'a', # 0xb0 +'a', # 0xb1 +'a', # 0xb2 +'a', # 0xb3 +'a', # 0xb4 +'[?]', # 0xb5 +'a', # 0xb6 +'a', # 0xb7 +'A', # 0xb8 +'A', # 0xb9 +'A', # 0xba +'A', # 0xbb +'A', # 0xbc +'\'', # 0xbd +'i', # 0xbe +'\'', # 0xbf +'~', # 0xc0 +'"~', # 0xc1 +'e', # 0xc2 +'e', # 0xc3 +'e', # 0xc4 +'[?]', # 0xc5 +'e', # 0xc6 +'e', # 0xc7 +'E', # 0xc8 +'E', # 0xc9 +'E', # 0xca +'E', # 0xcb +'E', # 0xcc +'\'`', # 0xcd +'\'\'', # 0xce +'\'~', # 0xcf +'i', # 0xd0 +'i', # 0xd1 +'i', # 0xd2 +'i', # 0xd3 +'[?]', # 0xd4 +'[?]', # 0xd5 +'i', # 0xd6 +'i', # 0xd7 +'I', # 0xd8 +'I', # 0xd9 +'I', # 0xda +'I', # 0xdb +'[?]', # 0xdc +'`\'', # 0xdd +'`\'', # 0xde +'`~', # 0xdf +'u', # 0xe0 +'u', # 0xe1 +'u', # 0xe2 +'u', # 0xe3 +'R', # 0xe4 +'R', # 0xe5 +'u', # 0xe6 +'u', # 0xe7 +'U', # 0xe8 +'U', # 0xe9 +'U', # 0xea +'U', # 0xeb +'R', # 0xec +'"`', # 0xed +'"\'', # 0xee +'`', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'o', # 0xf2 +'o', # 0xf3 +'o', # 0xf4 +'[?]', # 0xf5 +'o', # 0xf6 +'o', # 0xf7 +'O', # 0xf8 +'O', # 0xf9 +'O', # 0xfa +'O', # 0xfb +'O', # 0xfc +'\'', # 0xfd +'`', # 0xfe +) diff --git a/nstock/modules/unidecode/x020.py b/nstock/modules/unidecode/x020.py new file mode 100644 index 0000000..b649473 --- /dev/null +++ b/nstock/modules/unidecode/x020.py @@ -0,0 +1,257 @@ +data = ( +' ', # 0x00 +' ', # 0x01 +' ', # 0x02 +' ', # 0x03 +' ', # 0x04 +' ', # 0x05 +' ', # 0x06 +' ', # 0x07 +' ', # 0x08 +' ', # 0x09 +' ', # 0x0a +' ', # 0x0b +'', # 0x0c +'', # 0x0d +'', # 0x0e +'', # 0x0f +'-', # 0x10 +'-', # 0x11 +'-', # 0x12 +'-', # 0x13 +'--', # 0x14 +'--', # 0x15 +'||', # 0x16 +'_', # 0x17 +'\'', # 0x18 +'\'', # 0x19 +',', # 0x1a +'\'', # 0x1b +'"', # 0x1c +'"', # 0x1d +',,', # 0x1e +'"', # 0x1f +'+', # 0x20 +'++', # 0x21 +'*', # 0x22 +'*>', # 0x23 +'.', # 0x24 +'..', # 0x25 +'...', # 0x26 +'.', # 0x27 +'\x0a', # 0x28 +'\x0a\x0a', # 0x29 +'', # 0x2a +'', # 0x2b +'', # 0x2c +'', # 0x2d +'', # 0x2e +' ', # 0x2f +'%0', # 0x30 +'%00', # 0x31 +'\'', # 0x32 +'\'\'', # 0x33 +'\'\'\'', # 0x34 +'`', # 0x35 +'``', # 0x36 +'```', # 0x37 +'^', # 0x38 +'<', # 0x39 +'>', # 0x3a +'*', # 0x3b +'!!', # 0x3c +'!?', # 0x3d +'-', # 0x3e +'_', # 0x3f +'-', # 0x40 +'^', # 0x41 +'***', # 0x42 +'--', # 0x43 +'/', # 0x44 +'-[', # 0x45 +']-', # 0x46 +'??', # 0x47 +'?!', # 0x48 +'!?', # 0x49 +'7', # 0x4a +'PP', # 0x4b +'(]', # 0x4c +'[)', # 0x4d +'*', # 0x4e +'[?]', # 0x4f +'[?]', # 0x50 +'[?]', # 0x51 +'%', # 0x52 +'~', # 0x53 +'[?]', # 0x54 +'[?]', # 0x55 +'[?]', # 0x56 +"''''", # 0x57 +'[?]', # 0x58 +'[?]', # 0x59 +'[?]', # 0x5a +'[?]', # 0x5b +'[?]', # 0x5c +'[?]', # 0x5d +'[?]', # 0x5e +'[?]', # 0x5f +'', # 0x60 +'[?]', # 0x61 +'[?]', # 0x62 +'[?]', # 0x63 +'[?]', # 0x64 +'[?]', # 0x65 +'[?]', # 0x66 +'[?]', # 0x67 +'[?]', # 0x68 +'[?]', # 0x69 +'', # 0x6a +'', # 0x6b +'', # 0x6c +'', # 0x6d +'', # 0x6e +'', # 0x6f +'0', # 0x70 +'', # 0x71 +'', # 0x72 +'', # 0x73 +'4', # 0x74 +'5', # 0x75 +'6', # 0x76 +'7', # 0x77 +'8', # 0x78 +'9', # 0x79 +'+', # 0x7a +'-', # 0x7b +'=', # 0x7c +'(', # 0x7d +')', # 0x7e +'n', # 0x7f +'0', # 0x80 +'1', # 0x81 +'2', # 0x82 +'3', # 0x83 +'4', # 0x84 +'5', # 0x85 +'6', # 0x86 +'7', # 0x87 +'8', # 0x88 +'9', # 0x89 +'+', # 0x8a +'-', # 0x8b +'=', # 0x8c +'(', # 0x8d +')', # 0x8e +'[?]', # 0x8f +'[?]', # 0x90 +'[?]', # 0x91 +'[?]', # 0x92 +'[?]', # 0x93 +'[?]', # 0x94 +'[?]', # 0x95 +'[?]', # 0x96 +'[?]', # 0x97 +'[?]', # 0x98 +'[?]', # 0x99 +'[?]', # 0x9a +'[?]', # 0x9b +'[?]', # 0x9c +'[?]', # 0x9d +'[?]', # 0x9e +'[?]', # 0x9f +'ECU', # 0xa0 +'CL', # 0xa1 +'Cr', # 0xa2 +'FF', # 0xa3 +'L', # 0xa4 +'mil', # 0xa5 +'N', # 0xa6 +'Pts', # 0xa7 +'Rs', # 0xa8 +'W', # 0xa9 +'NS', # 0xaa +'D', # 0xab +'EUR', # 0xac +'K', # 0xad +'T', # 0xae +'Dr', # 0xaf +'[?]', # 0xb0 +'[?]', # 0xb1 +'[?]', # 0xb2 +'[?]', # 0xb3 +'[?]', # 0xb4 +'[?]', # 0xb5 +'[?]', # 0xb6 +'[?]', # 0xb7 +'[?]', # 0xb8 +'[?]', # 0xb9 +'[?]', # 0xba +'[?]', # 0xbb +'[?]', # 0xbc +'[?]', # 0xbd +'[?]', # 0xbe +'[?]', # 0xbf +'[?]', # 0xc0 +'[?]', # 0xc1 +'[?]', # 0xc2 +'[?]', # 0xc3 +'[?]', # 0xc4 +'[?]', # 0xc5 +'[?]', # 0xc6 +'[?]', # 0xc7 +'[?]', # 0xc8 +'[?]', # 0xc9 +'[?]', # 0xca +'[?]', # 0xcb +'[?]', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'', # 0xd0 +'', # 0xd1 +'', # 0xd2 +'', # 0xd3 +'', # 0xd4 +'', # 0xd5 +'', # 0xd6 +'', # 0xd7 +'', # 0xd8 +'', # 0xd9 +'', # 0xda +'', # 0xdb +'', # 0xdc +'', # 0xdd +'', # 0xde +'', # 0xdf +'', # 0xe0 +'', # 0xe1 +'', # 0xe2 +'', # 0xe3 +'[?]', # 0xe4 +'', # 0xe5 +'[?]', # 0xe6 +'[?]', # 0xe7 +'[?]', # 0xe8 +'[?]', # 0xe9 +'[?]', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x021.py b/nstock/modules/unidecode/x021.py new file mode 100644 index 0000000..067d9bd --- /dev/null +++ b/nstock/modules/unidecode/x021.py @@ -0,0 +1,257 @@ +data = ( +'', # 0x00 +'', # 0x01 +'C', # 0x02 +'', # 0x03 +'', # 0x04 +'', # 0x05 +'', # 0x06 +'', # 0x07 +'', # 0x08 +'', # 0x09 +'', # 0x0a +'', # 0x0b +'', # 0x0c +'H', # 0x0d +'', # 0x0e +'', # 0x0f +'', # 0x10 +'', # 0x11 +'', # 0x12 +'', # 0x13 +'', # 0x14 +'N', # 0x15 +'', # 0x16 +'', # 0x17 +'', # 0x18 +'P', # 0x19 +'Q', # 0x1a +'', # 0x1b +'', # 0x1c +'R', # 0x1d +'', # 0x1e +'', # 0x1f +'(sm)', # 0x20 +'TEL', # 0x21 +'(tm)', # 0x22 +'', # 0x23 +'Z', # 0x24 +'', # 0x25 +'', # 0x26 +'', # 0x27 +'', # 0x28 +'', # 0x29 +'K', # 0x2a +'A', # 0x2b +'', # 0x2c +'', # 0x2d +'e', # 0x2e +'e', # 0x2f +'E', # 0x30 +'F', # 0x31 +'F', # 0x32 +'M', # 0x33 +'', # 0x34 +'', # 0x35 +'', # 0x36 +'', # 0x37 +'', # 0x38 +'', # 0x39 +'', # 0x3a +'FAX', # 0x3b +'', # 0x3c +'', # 0x3d +'', # 0x3e +'', # 0x3f +'[?]', # 0x40 +'[?]', # 0x41 +'[?]', # 0x42 +'[?]', # 0x43 +'[?]', # 0x44 +'D', # 0x45 +'d', # 0x46 +'e', # 0x47 +'i', # 0x48 +'j', # 0x49 +'[?]', # 0x4a +'[?]', # 0x4b +'[?]', # 0x4c +'[?]', # 0x4d +'F', # 0x4e +'[?]', # 0x4f +'[?]', # 0x50 +'[?]', # 0x51 +'[?]', # 0x52 +' 1/3 ', # 0x53 +' 2/3 ', # 0x54 +' 1/5 ', # 0x55 +' 2/5 ', # 0x56 +' 3/5 ', # 0x57 +' 4/5 ', # 0x58 +' 1/6 ', # 0x59 +' 5/6 ', # 0x5a +' 1/8 ', # 0x5b +' 3/8 ', # 0x5c +' 5/8 ', # 0x5d +' 7/8 ', # 0x5e +' 1/', # 0x5f +'I', # 0x60 +'II', # 0x61 +'III', # 0x62 +'IV', # 0x63 +'V', # 0x64 +'VI', # 0x65 +'VII', # 0x66 +'VIII', # 0x67 +'IX', # 0x68 +'X', # 0x69 +'XI', # 0x6a +'XII', # 0x6b +'L', # 0x6c +'C', # 0x6d +'D', # 0x6e +'M', # 0x6f +'i', # 0x70 +'ii', # 0x71 +'iii', # 0x72 +'iv', # 0x73 +'v', # 0x74 +'vi', # 0x75 +'vii', # 0x76 +'viii', # 0x77 +'ix', # 0x78 +'x', # 0x79 +'xi', # 0x7a +'xii', # 0x7b +'l', # 0x7c +'c', # 0x7d +'d', # 0x7e +'m', # 0x7f +'(D', # 0x80 +'D)', # 0x81 +'((|))', # 0x82 +')', # 0x83 +'[?]', # 0x84 +'[?]', # 0x85 +'[?]', # 0x86 +'[?]', # 0x87 +'[?]', # 0x88 +'[?]', # 0x89 +'[?]', # 0x8a +'[?]', # 0x8b +'[?]', # 0x8c +'[?]', # 0x8d +'[?]', # 0x8e +'[?]', # 0x8f +'-', # 0x90 +'|', # 0x91 +'-', # 0x92 +'|', # 0x93 +'-', # 0x94 +'|', # 0x95 +'\\', # 0x96 +'/', # 0x97 +'\\', # 0x98 +'/', # 0x99 +'-', # 0x9a +'-', # 0x9b +'~', # 0x9c +'~', # 0x9d +'-', # 0x9e +'|', # 0x9f +'-', # 0xa0 +'|', # 0xa1 +'-', # 0xa2 +'-', # 0xa3 +'-', # 0xa4 +'|', # 0xa5 +'-', # 0xa6 +'|', # 0xa7 +'|', # 0xa8 +'-', # 0xa9 +'-', # 0xaa +'-', # 0xab +'-', # 0xac +'-', # 0xad +'-', # 0xae +'|', # 0xaf +'|', # 0xb0 +'|', # 0xb1 +'|', # 0xb2 +'|', # 0xb3 +'|', # 0xb4 +'|', # 0xb5 +'^', # 0xb6 +'V', # 0xb7 +'\\', # 0xb8 +'=', # 0xb9 +'V', # 0xba +'^', # 0xbb +'-', # 0xbc +'-', # 0xbd +'|', # 0xbe +'|', # 0xbf +'-', # 0xc0 +'-', # 0xc1 +'|', # 0xc2 +'|', # 0xc3 +'=', # 0xc4 +'|', # 0xc5 +'=', # 0xc6 +'=', # 0xc7 +'|', # 0xc8 +'=', # 0xc9 +'|', # 0xca +'=', # 0xcb +'=', # 0xcc +'=', # 0xcd +'=', # 0xce +'=', # 0xcf +'=', # 0xd0 +'|', # 0xd1 +'=', # 0xd2 +'|', # 0xd3 +'=', # 0xd4 +'|', # 0xd5 +'\\', # 0xd6 +'/', # 0xd7 +'\\', # 0xd8 +'/', # 0xd9 +'=', # 0xda +'=', # 0xdb +'~', # 0xdc +'~', # 0xdd +'|', # 0xde +'|', # 0xdf +'-', # 0xe0 +'|', # 0xe1 +'-', # 0xe2 +'|', # 0xe3 +'-', # 0xe4 +'-', # 0xe5 +'-', # 0xe6 +'|', # 0xe7 +'-', # 0xe8 +'|', # 0xe9 +'|', # 0xea +'|', # 0xeb +'|', # 0xec +'|', # 0xed +'|', # 0xee +'|', # 0xef +'-', # 0xf0 +'\\', # 0xf1 +'\\', # 0xf2 +'|', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x022.py b/nstock/modules/unidecode/x022.py new file mode 100644 index 0000000..e38fb5c --- /dev/null +++ b/nstock/modules/unidecode/x022.py @@ -0,0 +1,257 @@ +data = ( +'[?]', # 0x00 +'[?]', # 0x01 +'[?]', # 0x02 +'[?]', # 0x03 +'[?]', # 0x04 +'[?]', # 0x05 +'[?]', # 0x06 +'[?]', # 0x07 +'[?]', # 0x08 +'[?]', # 0x09 +'[?]', # 0x0a +'[?]', # 0x0b +'[?]', # 0x0c +'[?]', # 0x0d +'[?]', # 0x0e +'[?]', # 0x0f +'[?]', # 0x10 +'[?]', # 0x11 +'-', # 0x12 +'[?]', # 0x13 +'[?]', # 0x14 +'/', # 0x15 +'\\', # 0x16 +'*', # 0x17 +'[?]', # 0x18 +'[?]', # 0x19 +'[?]', # 0x1a +'[?]', # 0x1b +'[?]', # 0x1c +'[?]', # 0x1d +'[?]', # 0x1e +'[?]', # 0x1f +'[?]', # 0x20 +'[?]', # 0x21 +'[?]', # 0x22 +'|', # 0x23 +'[?]', # 0x24 +'[?]', # 0x25 +'[?]', # 0x26 +'[?]', # 0x27 +'[?]', # 0x28 +'[?]', # 0x29 +'[?]', # 0x2a +'[?]', # 0x2b +'[?]', # 0x2c +'[?]', # 0x2d +'[?]', # 0x2e +'[?]', # 0x2f +'[?]', # 0x30 +'[?]', # 0x31 +'[?]', # 0x32 +'[?]', # 0x33 +'[?]', # 0x34 +'[?]', # 0x35 +':', # 0x36 +'[?]', # 0x37 +'[?]', # 0x38 +'[?]', # 0x39 +'[?]', # 0x3a +'[?]', # 0x3b +'~', # 0x3c +'[?]', # 0x3d +'[?]', # 0x3e +'[?]', # 0x3f +'[?]', # 0x40 +'[?]', # 0x41 +'[?]', # 0x42 +'[?]', # 0x43 +'[?]', # 0x44 +'[?]', # 0x45 +'[?]', # 0x46 +'[?]', # 0x47 +'[?]', # 0x48 +'[?]', # 0x49 +'[?]', # 0x4a +'[?]', # 0x4b +'[?]', # 0x4c +'[?]', # 0x4d +'[?]', # 0x4e +'[?]', # 0x4f +'[?]', # 0x50 +'[?]', # 0x51 +'[?]', # 0x52 +'[?]', # 0x53 +'[?]', # 0x54 +'[?]', # 0x55 +'[?]', # 0x56 +'[?]', # 0x57 +'[?]', # 0x58 +'[?]', # 0x59 +'[?]', # 0x5a +'[?]', # 0x5b +'[?]', # 0x5c +'[?]', # 0x5d +'[?]', # 0x5e +'[?]', # 0x5f +'[?]', # 0x60 +'[?]', # 0x61 +'[?]', # 0x62 +'[?]', # 0x63 +'<=', # 0x64 +'>=', # 0x65 +'<=', # 0x66 +'>=', # 0x67 +'[?]', # 0x68 +'[?]', # 0x69 +'[?]', # 0x6a +'[?]', # 0x6b +'[?]', # 0x6c +'[?]', # 0x6d +'[?]', # 0x6e +'[?]', # 0x6f +'[?]', # 0x70 +'[?]', # 0x71 +'[?]', # 0x72 +'[?]', # 0x73 +'[?]', # 0x74 +'[?]', # 0x75 +'[?]', # 0x76 +'[?]', # 0x77 +'[?]', # 0x78 +'[?]', # 0x79 +'[?]', # 0x7a +'[?]', # 0x7b +'[?]', # 0x7c +'[?]', # 0x7d +'[?]', # 0x7e +'[?]', # 0x7f +'[?]', # 0x80 +'[?]', # 0x81 +'[?]', # 0x82 +'[?]', # 0x83 +'[?]', # 0x84 +'[?]', # 0x85 +'[?]', # 0x86 +'[?]', # 0x87 +'[?]', # 0x88 +'[?]', # 0x89 +'[?]', # 0x8a +'[?]', # 0x8b +'[?]', # 0x8c +'[?]', # 0x8d +'[?]', # 0x8e +'[?]', # 0x8f +'[?]', # 0x90 +'[?]', # 0x91 +'[?]', # 0x92 +'[?]', # 0x93 +'[?]', # 0x94 +'[?]', # 0x95 +'[?]', # 0x96 +'[?]', # 0x97 +'[?]', # 0x98 +'[?]', # 0x99 +'[?]', # 0x9a +'[?]', # 0x9b +'[?]', # 0x9c +'[?]', # 0x9d +'[?]', # 0x9e +'[?]', # 0x9f +'[?]', # 0xa0 +'[?]', # 0xa1 +'[?]', # 0xa2 +'[?]', # 0xa3 +'[?]', # 0xa4 +'[?]', # 0xa5 +'[?]', # 0xa6 +'[?]', # 0xa7 +'[?]', # 0xa8 +'[?]', # 0xa9 +'[?]', # 0xaa +'[?]', # 0xab +'[?]', # 0xac +'[?]', # 0xad +'[?]', # 0xae +'[?]', # 0xaf +'[?]', # 0xb0 +'[?]', # 0xb1 +'[?]', # 0xb2 +'[?]', # 0xb3 +'[?]', # 0xb4 +'[?]', # 0xb5 +'[?]', # 0xb6 +'[?]', # 0xb7 +'[?]', # 0xb8 +'[?]', # 0xb9 +'[?]', # 0xba +'[?]', # 0xbb +'[?]', # 0xbc +'[?]', # 0xbd +'[?]', # 0xbe +'[?]', # 0xbf +'[?]', # 0xc0 +'[?]', # 0xc1 +'[?]', # 0xc2 +'[?]', # 0xc3 +'[?]', # 0xc4 +'[?]', # 0xc5 +'[?]', # 0xc6 +'[?]', # 0xc7 +'[?]', # 0xc8 +'[?]', # 0xc9 +'[?]', # 0xca +'[?]', # 0xcb +'[?]', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'[?]', # 0xd0 +'[?]', # 0xd1 +'[?]', # 0xd2 +'[?]', # 0xd3 +'[?]', # 0xd4 +'[?]', # 0xd5 +'[?]', # 0xd6 +'[?]', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'[?]', # 0xdc +'[?]', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'[?]', # 0xe0 +'[?]', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'[?]', # 0xe6 +'[?]', # 0xe7 +'[?]', # 0xe8 +'[?]', # 0xe9 +'[?]', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x023.py b/nstock/modules/unidecode/x023.py new file mode 100644 index 0000000..3c4462e --- /dev/null +++ b/nstock/modules/unidecode/x023.py @@ -0,0 +1,257 @@ +data = ( +'[?]', # 0x00 +'[?]', # 0x01 +'[?]', # 0x02 +'^', # 0x03 +'[?]', # 0x04 +'[?]', # 0x05 +'[?]', # 0x06 +'[?]', # 0x07 +'[?]', # 0x08 +'[?]', # 0x09 +'[?]', # 0x0a +'[?]', # 0x0b +'[?]', # 0x0c +'[?]', # 0x0d +'[?]', # 0x0e +'[?]', # 0x0f +'[?]', # 0x10 +'[?]', # 0x11 +'[?]', # 0x12 +'[?]', # 0x13 +'[?]', # 0x14 +'[?]', # 0x15 +'[?]', # 0x16 +'[?]', # 0x17 +'[?]', # 0x18 +'[?]', # 0x19 +'[?]', # 0x1a +'[?]', # 0x1b +'[?]', # 0x1c +'[?]', # 0x1d +'[?]', # 0x1e +'[?]', # 0x1f +'[?]', # 0x20 +'[?]', # 0x21 +'[?]', # 0x22 +'[?]', # 0x23 +'[?]', # 0x24 +'[?]', # 0x25 +'[?]', # 0x26 +'[?]', # 0x27 +'[?]', # 0x28 +'<', # 0x29 +'> ', # 0x2a +'[?]', # 0x2b +'[?]', # 0x2c +'[?]', # 0x2d +'[?]', # 0x2e +'[?]', # 0x2f +'[?]', # 0x30 +'[?]', # 0x31 +'[?]', # 0x32 +'[?]', # 0x33 +'[?]', # 0x34 +'[?]', # 0x35 +'[?]', # 0x36 +'[?]', # 0x37 +'[?]', # 0x38 +'[?]', # 0x39 +'[?]', # 0x3a +'[?]', # 0x3b +'[?]', # 0x3c +'[?]', # 0x3d +'[?]', # 0x3e +'[?]', # 0x3f +'[?]', # 0x40 +'[?]', # 0x41 +'[?]', # 0x42 +'[?]', # 0x43 +'[?]', # 0x44 +'[?]', # 0x45 +'[?]', # 0x46 +'[?]', # 0x47 +'[?]', # 0x48 +'[?]', # 0x49 +'[?]', # 0x4a +'[?]', # 0x4b +'[?]', # 0x4c +'[?]', # 0x4d +'[?]', # 0x4e +'[?]', # 0x4f +'[?]', # 0x50 +'[?]', # 0x51 +'[?]', # 0x52 +'[?]', # 0x53 +'[?]', # 0x54 +'[?]', # 0x55 +'[?]', # 0x56 +'[?]', # 0x57 +'[?]', # 0x58 +'[?]', # 0x59 +'[?]', # 0x5a +'[?]', # 0x5b +'[?]', # 0x5c +'[?]', # 0x5d +'[?]', # 0x5e +'[?]', # 0x5f +'[?]', # 0x60 +'[?]', # 0x61 +'[?]', # 0x62 +'[?]', # 0x63 +'[?]', # 0x64 +'[?]', # 0x65 +'[?]', # 0x66 +'[?]', # 0x67 +'[?]', # 0x68 +'[?]', # 0x69 +'[?]', # 0x6a +'[?]', # 0x6b +'[?]', # 0x6c +'[?]', # 0x6d +'[?]', # 0x6e +'[?]', # 0x6f +'[?]', # 0x70 +'[?]', # 0x71 +'[?]', # 0x72 +'[?]', # 0x73 +'[?]', # 0x74 +'[?]', # 0x75 +'[?]', # 0x76 +'[?]', # 0x77 +'[?]', # 0x78 +'[?]', # 0x79 +'[?]', # 0x7a +'[?]', # 0x7b +'[?]', # 0x7c +'[?]', # 0x7d +'[?]', # 0x7e +'[?]', # 0x7f +'[?]', # 0x80 +'[?]', # 0x81 +'[?]', # 0x82 +'[?]', # 0x83 +'[?]', # 0x84 +'[?]', # 0x85 +'[?]', # 0x86 +'[?]', # 0x87 +'[?]', # 0x88 +'[?]', # 0x89 +'[?]', # 0x8a +'[?]', # 0x8b +'[?]', # 0x8c +'[?]', # 0x8d +'[?]', # 0x8e +'[?]', # 0x8f +'[?]', # 0x90 +'[?]', # 0x91 +'[?]', # 0x92 +'[?]', # 0x93 +'[?]', # 0x94 +'[?]', # 0x95 +'[?]', # 0x96 +'[?]', # 0x97 +'[?]', # 0x98 +'[?]', # 0x99 +'[?]', # 0x9a +'[?]', # 0x9b +'[?]', # 0x9c +'[?]', # 0x9d +'[?]', # 0x9e +'[?]', # 0x9f +'[?]', # 0xa0 +'[?]', # 0xa1 +'[?]', # 0xa2 +'[?]', # 0xa3 +'[?]', # 0xa4 +'[?]', # 0xa5 +'[?]', # 0xa6 +'[?]', # 0xa7 +'[?]', # 0xa8 +'[?]', # 0xa9 +'[?]', # 0xaa +'[?]', # 0xab +'[?]', # 0xac +'[?]', # 0xad +'[?]', # 0xae +'[?]', # 0xaf +'[?]', # 0xb0 +'[?]', # 0xb1 +'[?]', # 0xb2 +'[?]', # 0xb3 +'[?]', # 0xb4 +'[?]', # 0xb5 +'[?]', # 0xb6 +'[?]', # 0xb7 +'[?]', # 0xb8 +'[?]', # 0xb9 +'[?]', # 0xba +'[?]', # 0xbb +'[?]', # 0xbc +'[?]', # 0xbd +'[?]', # 0xbe +'[?]', # 0xbf +'[?]', # 0xc0 +'[?]', # 0xc1 +'[?]', # 0xc2 +'[?]', # 0xc3 +'[?]', # 0xc4 +'[?]', # 0xc5 +'[?]', # 0xc6 +'[?]', # 0xc7 +'[?]', # 0xc8 +'[?]', # 0xc9 +'[?]', # 0xca +'[?]', # 0xcb +'[?]', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'[?]', # 0xd0 +'[?]', # 0xd1 +'[?]', # 0xd2 +'[?]', # 0xd3 +'[?]', # 0xd4 +'[?]', # 0xd5 +'[?]', # 0xd6 +'[?]', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'[?]', # 0xdc +'[?]', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'[?]', # 0xe0 +'[?]', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'[?]', # 0xe6 +'[?]', # 0xe7 +'[?]', # 0xe8 +'[?]', # 0xe9 +'[?]', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x024.py b/nstock/modules/unidecode/x024.py new file mode 100644 index 0000000..20b3c8f --- /dev/null +++ b/nstock/modules/unidecode/x024.py @@ -0,0 +1,257 @@ +data = ( +'', # 0x00 +'', # 0x01 +'', # 0x02 +'', # 0x03 +'', # 0x04 +'', # 0x05 +'', # 0x06 +'', # 0x07 +'', # 0x08 +'', # 0x09 +'', # 0x0a +'', # 0x0b +'', # 0x0c +'', # 0x0d +'', # 0x0e +'', # 0x0f +'', # 0x10 +'', # 0x11 +'', # 0x12 +'', # 0x13 +'', # 0x14 +'', # 0x15 +'', # 0x16 +'', # 0x17 +'', # 0x18 +'', # 0x19 +'', # 0x1a +'', # 0x1b +'', # 0x1c +'', # 0x1d +'', # 0x1e +'', # 0x1f +'', # 0x20 +'', # 0x21 +'', # 0x22 +'', # 0x23 +'', # 0x24 +'', # 0x25 +'', # 0x26 +'[?]', # 0x27 +'[?]', # 0x28 +'[?]', # 0x29 +'[?]', # 0x2a +'[?]', # 0x2b +'[?]', # 0x2c +'[?]', # 0x2d +'[?]', # 0x2e +'[?]', # 0x2f +'[?]', # 0x30 +'[?]', # 0x31 +'[?]', # 0x32 +'[?]', # 0x33 +'[?]', # 0x34 +'[?]', # 0x35 +'[?]', # 0x36 +'[?]', # 0x37 +'[?]', # 0x38 +'[?]', # 0x39 +'[?]', # 0x3a +'[?]', # 0x3b +'[?]', # 0x3c +'[?]', # 0x3d +'[?]', # 0x3e +'[?]', # 0x3f +'', # 0x40 +'', # 0x41 +'', # 0x42 +'', # 0x43 +'', # 0x44 +'', # 0x45 +'', # 0x46 +'', # 0x47 +'', # 0x48 +'', # 0x49 +'', # 0x4a +'[?]', # 0x4b +'[?]', # 0x4c +'[?]', # 0x4d +'[?]', # 0x4e +'[?]', # 0x4f +'[?]', # 0x50 +'[?]', # 0x51 +'[?]', # 0x52 +'[?]', # 0x53 +'[?]', # 0x54 +'[?]', # 0x55 +'[?]', # 0x56 +'[?]', # 0x57 +'[?]', # 0x58 +'[?]', # 0x59 +'[?]', # 0x5a +'[?]', # 0x5b +'[?]', # 0x5c +'[?]', # 0x5d +'[?]', # 0x5e +'[?]', # 0x5f +'1', # 0x60 +'2', # 0x61 +'3', # 0x62 +'4', # 0x63 +'5', # 0x64 +'6', # 0x65 +'7', # 0x66 +'8', # 0x67 +'9', # 0x68 +'10', # 0x69 +'11', # 0x6a +'12', # 0x6b +'13', # 0x6c +'14', # 0x6d +'15', # 0x6e +'16', # 0x6f +'17', # 0x70 +'18', # 0x71 +'19', # 0x72 +'20', # 0x73 +'(1)', # 0x74 +'(2)', # 0x75 +'(3)', # 0x76 +'(4)', # 0x77 +'(5)', # 0x78 +'(6)', # 0x79 +'(7)', # 0x7a +'(8)', # 0x7b +'(9)', # 0x7c +'(10)', # 0x7d +'(11)', # 0x7e +'(12)', # 0x7f +'(13)', # 0x80 +'(14)', # 0x81 +'(15)', # 0x82 +'(16)', # 0x83 +'(17)', # 0x84 +'(18)', # 0x85 +'(19)', # 0x86 +'(20)', # 0x87 +'1.', # 0x88 +'2.', # 0x89 +'3.', # 0x8a +'4.', # 0x8b +'5.', # 0x8c +'6.', # 0x8d +'7.', # 0x8e +'8.', # 0x8f +'9.', # 0x90 +'10.', # 0x91 +'11.', # 0x92 +'12.', # 0x93 +'13.', # 0x94 +'14.', # 0x95 +'15.', # 0x96 +'16.', # 0x97 +'17.', # 0x98 +'18.', # 0x99 +'19.', # 0x9a +'20.', # 0x9b +'(a)', # 0x9c +'(b)', # 0x9d +'(c)', # 0x9e +'(d)', # 0x9f +'(e)', # 0xa0 +'(f)', # 0xa1 +'(g)', # 0xa2 +'(h)', # 0xa3 +'(i)', # 0xa4 +'(j)', # 0xa5 +'(k)', # 0xa6 +'(l)', # 0xa7 +'(m)', # 0xa8 +'(n)', # 0xa9 +'(o)', # 0xaa +'(p)', # 0xab +'(q)', # 0xac +'(r)', # 0xad +'(s)', # 0xae +'(t)', # 0xaf +'(u)', # 0xb0 +'(v)', # 0xb1 +'(w)', # 0xb2 +'(x)', # 0xb3 +'(y)', # 0xb4 +'(z)', # 0xb5 +'a', # 0xb6 +'b', # 0xb7 +'c', # 0xb8 +'d', # 0xb9 +'e', # 0xba +'f', # 0xbb +'g', # 0xbc +'h', # 0xbd +'i', # 0xbe +'j', # 0xbf +'k', # 0xc0 +'l', # 0xc1 +'m', # 0xc2 +'n', # 0xc3 +'o', # 0xc4 +'p', # 0xc5 +'q', # 0xc6 +'r', # 0xc7 +'s', # 0xc8 +'t', # 0xc9 +'u', # 0xca +'v', # 0xcb +'w', # 0xcc +'x', # 0xcd +'y', # 0xce +'z', # 0xcf +'a', # 0xd0 +'b', # 0xd1 +'c', # 0xd2 +'d', # 0xd3 +'e', # 0xd4 +'f', # 0xd5 +'g', # 0xd6 +'h', # 0xd7 +'i', # 0xd8 +'j', # 0xd9 +'k', # 0xda +'l', # 0xdb +'m', # 0xdc +'n', # 0xdd +'o', # 0xde +'p', # 0xdf +'q', # 0xe0 +'r', # 0xe1 +'s', # 0xe2 +'t', # 0xe3 +'u', # 0xe4 +'v', # 0xe5 +'w', # 0xe6 +'x', # 0xe7 +'y', # 0xe8 +'z', # 0xe9 +'0', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x025.py b/nstock/modules/unidecode/x025.py new file mode 100644 index 0000000..5a62b10 --- /dev/null +++ b/nstock/modules/unidecode/x025.py @@ -0,0 +1,257 @@ +data = ( +'-', # 0x00 +'-', # 0x01 +'|', # 0x02 +'|', # 0x03 +'-', # 0x04 +'-', # 0x05 +'|', # 0x06 +'|', # 0x07 +'-', # 0x08 +'-', # 0x09 +'|', # 0x0a +'|', # 0x0b +'+', # 0x0c +'+', # 0x0d +'+', # 0x0e +'+', # 0x0f +'+', # 0x10 +'+', # 0x11 +'+', # 0x12 +'+', # 0x13 +'+', # 0x14 +'+', # 0x15 +'+', # 0x16 +'+', # 0x17 +'+', # 0x18 +'+', # 0x19 +'+', # 0x1a +'+', # 0x1b +'+', # 0x1c +'+', # 0x1d +'+', # 0x1e +'+', # 0x1f +'+', # 0x20 +'+', # 0x21 +'+', # 0x22 +'+', # 0x23 +'+', # 0x24 +'+', # 0x25 +'+', # 0x26 +'+', # 0x27 +'+', # 0x28 +'+', # 0x29 +'+', # 0x2a +'+', # 0x2b +'+', # 0x2c +'+', # 0x2d +'+', # 0x2e +'+', # 0x2f +'+', # 0x30 +'+', # 0x31 +'+', # 0x32 +'+', # 0x33 +'+', # 0x34 +'+', # 0x35 +'+', # 0x36 +'+', # 0x37 +'+', # 0x38 +'+', # 0x39 +'+', # 0x3a +'+', # 0x3b +'+', # 0x3c +'+', # 0x3d +'+', # 0x3e +'+', # 0x3f +'+', # 0x40 +'+', # 0x41 +'+', # 0x42 +'+', # 0x43 +'+', # 0x44 +'+', # 0x45 +'+', # 0x46 +'+', # 0x47 +'+', # 0x48 +'+', # 0x49 +'+', # 0x4a +'+', # 0x4b +'-', # 0x4c +'-', # 0x4d +'|', # 0x4e +'|', # 0x4f +'-', # 0x50 +'|', # 0x51 +'+', # 0x52 +'+', # 0x53 +'+', # 0x54 +'+', # 0x55 +'+', # 0x56 +'+', # 0x57 +'+', # 0x58 +'+', # 0x59 +'+', # 0x5a +'+', # 0x5b +'+', # 0x5c +'+', # 0x5d +'+', # 0x5e +'+', # 0x5f +'+', # 0x60 +'+', # 0x61 +'+', # 0x62 +'+', # 0x63 +'+', # 0x64 +'+', # 0x65 +'+', # 0x66 +'+', # 0x67 +'+', # 0x68 +'+', # 0x69 +'+', # 0x6a +'+', # 0x6b +'+', # 0x6c +'+', # 0x6d +'+', # 0x6e +'+', # 0x6f +'+', # 0x70 +'/', # 0x71 +'\\', # 0x72 +'X', # 0x73 +'-', # 0x74 +'|', # 0x75 +'-', # 0x76 +'|', # 0x77 +'-', # 0x78 +'|', # 0x79 +'-', # 0x7a +'|', # 0x7b +'-', # 0x7c +'|', # 0x7d +'-', # 0x7e +'|', # 0x7f +'#', # 0x80 +'#', # 0x81 +'#', # 0x82 +'#', # 0x83 +'#', # 0x84 +'#', # 0x85 +'#', # 0x86 +'#', # 0x87 +'#', # 0x88 +'#', # 0x89 +'#', # 0x8a +'#', # 0x8b +'#', # 0x8c +'#', # 0x8d +'#', # 0x8e +'#', # 0x8f +'#', # 0x90 +'#', # 0x91 +'#', # 0x92 +'#', # 0x93 +'-', # 0x94 +'|', # 0x95 +'[?]', # 0x96 +'[?]', # 0x97 +'[?]', # 0x98 +'[?]', # 0x99 +'[?]', # 0x9a +'[?]', # 0x9b +'[?]', # 0x9c +'[?]', # 0x9d +'[?]', # 0x9e +'[?]', # 0x9f +'#', # 0xa0 +'#', # 0xa1 +'#', # 0xa2 +'#', # 0xa3 +'#', # 0xa4 +'#', # 0xa5 +'#', # 0xa6 +'#', # 0xa7 +'#', # 0xa8 +'#', # 0xa9 +'#', # 0xaa +'#', # 0xab +'#', # 0xac +'#', # 0xad +'#', # 0xae +'#', # 0xaf +'#', # 0xb0 +'#', # 0xb1 +'^', # 0xb2 +'^', # 0xb3 +'^', # 0xb4 +'^', # 0xb5 +'>', # 0xb6 +'>', # 0xb7 +'>', # 0xb8 +'>', # 0xb9 +'>', # 0xba +'>', # 0xbb +'V', # 0xbc +'V', # 0xbd +'V', # 0xbe +'V', # 0xbf +'<', # 0xc0 +'<', # 0xc1 +'<', # 0xc2 +'<', # 0xc3 +'<', # 0xc4 +'<', # 0xc5 +'*', # 0xc6 +'*', # 0xc7 +'*', # 0xc8 +'*', # 0xc9 +'*', # 0xca +'*', # 0xcb +'*', # 0xcc +'*', # 0xcd +'*', # 0xce +'*', # 0xcf +'*', # 0xd0 +'*', # 0xd1 +'*', # 0xd2 +'*', # 0xd3 +'*', # 0xd4 +'*', # 0xd5 +'*', # 0xd6 +'*', # 0xd7 +'*', # 0xd8 +'*', # 0xd9 +'*', # 0xda +'*', # 0xdb +'*', # 0xdc +'*', # 0xdd +'*', # 0xde +'*', # 0xdf +'*', # 0xe0 +'*', # 0xe1 +'*', # 0xe2 +'*', # 0xe3 +'*', # 0xe4 +'*', # 0xe5 +'*', # 0xe6 +'#', # 0xe7 +'#', # 0xe8 +'#', # 0xe9 +'#', # 0xea +'#', # 0xeb +'^', # 0xec +'^', # 0xed +'^', # 0xee +'O', # 0xef +'#', # 0xf0 +'#', # 0xf1 +'#', # 0xf2 +'#', # 0xf3 +'#', # 0xf4 +'#', # 0xf5 +'#', # 0xf6 +'#', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x026.py b/nstock/modules/unidecode/x026.py new file mode 100644 index 0000000..c575472 --- /dev/null +++ b/nstock/modules/unidecode/x026.py @@ -0,0 +1,257 @@ +data = ( +'', # 0x00 +'', # 0x01 +'', # 0x02 +'', # 0x03 +'', # 0x04 +'', # 0x05 +'', # 0x06 +'', # 0x07 +'', # 0x08 +'', # 0x09 +'', # 0x0a +'', # 0x0b +'', # 0x0c +'', # 0x0d +'', # 0x0e +'', # 0x0f +'', # 0x10 +'', # 0x11 +'', # 0x12 +'', # 0x13 +'[?]', # 0x14 +'[?]', # 0x15 +'[?]', # 0x16 +'[?]', # 0x17 +'[?]', # 0x18 +'', # 0x19 +'', # 0x1a +'', # 0x1b +'', # 0x1c +'', # 0x1d +'', # 0x1e +'', # 0x1f +'', # 0x20 +'', # 0x21 +'', # 0x22 +'', # 0x23 +'', # 0x24 +'', # 0x25 +'', # 0x26 +'', # 0x27 +'', # 0x28 +'', # 0x29 +'', # 0x2a +'', # 0x2b +'', # 0x2c +'', # 0x2d +'', # 0x2e +'', # 0x2f +'', # 0x30 +'', # 0x31 +'', # 0x32 +'', # 0x33 +'', # 0x34 +'', # 0x35 +'', # 0x36 +'', # 0x37 +'', # 0x38 +'', # 0x39 +'', # 0x3a +'', # 0x3b +'', # 0x3c +'', # 0x3d +'', # 0x3e +'', # 0x3f +'', # 0x40 +'', # 0x41 +'', # 0x42 +'', # 0x43 +'', # 0x44 +'', # 0x45 +'', # 0x46 +'', # 0x47 +'', # 0x48 +'', # 0x49 +'', # 0x4a +'', # 0x4b +'', # 0x4c +'', # 0x4d +'', # 0x4e +'', # 0x4f +'', # 0x50 +'', # 0x51 +'', # 0x52 +'', # 0x53 +'', # 0x54 +'', # 0x55 +'', # 0x56 +'', # 0x57 +'', # 0x58 +'', # 0x59 +'', # 0x5a +'', # 0x5b +'', # 0x5c +'', # 0x5d +'', # 0x5e +'', # 0x5f +'', # 0x60 +'', # 0x61 +'', # 0x62 +'', # 0x63 +'', # 0x64 +'', # 0x65 +'', # 0x66 +'', # 0x67 +'', # 0x68 +'', # 0x69 +'', # 0x6a +'', # 0x6b +'', # 0x6c +'', # 0x6d +'', # 0x6e +'#', # 0x6f +'', # 0x70 +'', # 0x71 +'[?]', # 0x72 +'[?]', # 0x73 +'[?]', # 0x74 +'[?]', # 0x75 +'[?]', # 0x76 +'[?]', # 0x77 +'[?]', # 0x78 +'[?]', # 0x79 +'[?]', # 0x7a +'[?]', # 0x7b +'[?]', # 0x7c +'[?]', # 0x7d +'[?]', # 0x7e +'[?]', # 0x7f +'[?]', # 0x80 +'[?]', # 0x81 +'[?]', # 0x82 +'[?]', # 0x83 +'[?]', # 0x84 +'[?]', # 0x85 +'[?]', # 0x86 +'[?]', # 0x87 +'[?]', # 0x88 +'[?]', # 0x89 +'[?]', # 0x8a +'[?]', # 0x8b +'[?]', # 0x8c +'[?]', # 0x8d +'[?]', # 0x8e +'[?]', # 0x8f +'[?]', # 0x90 +'[?]', # 0x91 +'[?]', # 0x92 +'[?]', # 0x93 +'[?]', # 0x94 +'[?]', # 0x95 +'[?]', # 0x96 +'[?]', # 0x97 +'[?]', # 0x98 +'[?]', # 0x99 +'[?]', # 0x9a +'[?]', # 0x9b +'[?]', # 0x9c +'[?]', # 0x9d +'[?]', # 0x9e +'[?]', # 0x9f +'[?]', # 0xa0 +'[?]', # 0xa1 +'[?]', # 0xa2 +'[?]', # 0xa3 +'[?]', # 0xa4 +'[?]', # 0xa5 +'[?]', # 0xa6 +'[?]', # 0xa7 +'[?]', # 0xa8 +'[?]', # 0xa9 +'[?]', # 0xaa +'[?]', # 0xab +'[?]', # 0xac +'[?]', # 0xad +'[?]', # 0xae +'[?]', # 0xaf +'[?]', # 0xb0 +'[?]', # 0xb1 +'[?]', # 0xb2 +'[?]', # 0xb3 +'[?]', # 0xb4 +'[?]', # 0xb5 +'[?]', # 0xb6 +'[?]', # 0xb7 +'[?]', # 0xb8 +'[?]', # 0xb9 +'[?]', # 0xba +'[?]', # 0xbb +'[?]', # 0xbc +'[?]', # 0xbd +'[?]', # 0xbe +'[?]', # 0xbf +'[?]', # 0xc0 +'[?]', # 0xc1 +'[?]', # 0xc2 +'[?]', # 0xc3 +'[?]', # 0xc4 +'[?]', # 0xc5 +'[?]', # 0xc6 +'[?]', # 0xc7 +'[?]', # 0xc8 +'[?]', # 0xc9 +'[?]', # 0xca +'[?]', # 0xcb +'[?]', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'[?]', # 0xd0 +'[?]', # 0xd1 +'[?]', # 0xd2 +'[?]', # 0xd3 +'[?]', # 0xd4 +'[?]', # 0xd5 +'[?]', # 0xd6 +'[?]', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'[?]', # 0xdc +'[?]', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'[?]', # 0xe0 +'[?]', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'[?]', # 0xe6 +'[?]', # 0xe7 +'[?]', # 0xe8 +'[?]', # 0xe9 +'[?]', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x027.py b/nstock/modules/unidecode/x027.py new file mode 100644 index 0000000..3c74c07 --- /dev/null +++ b/nstock/modules/unidecode/x027.py @@ -0,0 +1,257 @@ +data = ( +'[?]', # 0x00 +'', # 0x01 +'', # 0x02 +'', # 0x03 +'', # 0x04 +'', # 0x05 +'', # 0x06 +'', # 0x07 +'', # 0x08 +'', # 0x09 +'', # 0x0a +'', # 0x0b +'', # 0x0c +'', # 0x0d +'', # 0x0e +'', # 0x0f +'', # 0x10 +'', # 0x11 +'', # 0x12 +'', # 0x13 +'', # 0x14 +'', # 0x15 +'', # 0x16 +'', # 0x17 +'', # 0x18 +'', # 0x19 +'', # 0x1a +'', # 0x1b +'', # 0x1c +'', # 0x1d +'', # 0x1e +'', # 0x1f +'', # 0x20 +'', # 0x21 +'', # 0x22 +'', # 0x23 +'', # 0x24 +'', # 0x25 +'', # 0x26 +'', # 0x27 +'', # 0x28 +'', # 0x29 +'', # 0x2a +'', # 0x2b +'', # 0x2c +'', # 0x2d +'', # 0x2e +'', # 0x2f +'', # 0x30 +'*', # 0x31 +'', # 0x32 +'', # 0x33 +'', # 0x34 +'', # 0x35 +'', # 0x36 +'', # 0x37 +'', # 0x38 +'', # 0x39 +'', # 0x3a +'', # 0x3b +'', # 0x3c +'', # 0x3d +'', # 0x3e +'', # 0x3f +'', # 0x40 +'', # 0x41 +'', # 0x42 +'', # 0x43 +'', # 0x44 +'', # 0x45 +'', # 0x46 +'', # 0x47 +'', # 0x48 +'', # 0x49 +'', # 0x4a +'', # 0x4b +'', # 0x4c +'', # 0x4d +'', # 0x4e +'', # 0x4f +'', # 0x50 +'', # 0x51 +'', # 0x52 +'', # 0x53 +'', # 0x54 +'', # 0x55 +'', # 0x56 +'', # 0x57 +'|', # 0x58 +'', # 0x59 +'', # 0x5a +'', # 0x5b +'', # 0x5c +'', # 0x5d +'', # 0x5e +'[?]', # 0x5f +'[?]', # 0x60 +'', # 0x61 +'!', # 0x62 +'', # 0x63 +'', # 0x64 +'', # 0x65 +'', # 0x66 +'', # 0x67 +'', # 0x68 +'', # 0x69 +'', # 0x6a +'', # 0x6b +'', # 0x6c +'', # 0x6d +'', # 0x6e +'', # 0x6f +'', # 0x70 +'', # 0x71 +'', # 0x72 +'', # 0x73 +'', # 0x74 +'', # 0x75 +'', # 0x76 +'', # 0x77 +'', # 0x78 +'', # 0x79 +'', # 0x7a +'', # 0x7b +'', # 0x7c +'', # 0x7d +'', # 0x7e +'', # 0x7f +'', # 0x80 +'', # 0x81 +'', # 0x82 +'', # 0x83 +'', # 0x84 +'', # 0x85 +'', # 0x86 +'', # 0x87 +'', # 0x88 +'', # 0x89 +'', # 0x8a +'', # 0x8b +'', # 0x8c +'', # 0x8d +'', # 0x8e +'', # 0x8f +'', # 0x90 +'', # 0x91 +'', # 0x92 +'', # 0x93 +'', # 0x94 +'', # 0x95 +'', # 0x96 +'', # 0x97 +'', # 0x98 +'', # 0x99 +'', # 0x9a +'', # 0x9b +'', # 0x9c +'', # 0x9d +'', # 0x9e +'', # 0x9f +'', # 0xa0 +'', # 0xa1 +'', # 0xa2 +'', # 0xa3 +'', # 0xa4 +'', # 0xa5 +'', # 0xa6 +'', # 0xa7 +'', # 0xa8 +'', # 0xa9 +'', # 0xaa +'', # 0xab +'', # 0xac +'', # 0xad +'', # 0xae +'', # 0xaf +'[?]', # 0xb0 +'', # 0xb1 +'', # 0xb2 +'', # 0xb3 +'', # 0xb4 +'', # 0xb5 +'', # 0xb6 +'', # 0xb7 +'', # 0xb8 +'', # 0xb9 +'', # 0xba +'', # 0xbb +'', # 0xbc +'', # 0xbd +'', # 0xbe +'[?]', # 0xbf +'[?]', # 0xc0 +'[?]', # 0xc1 +'[?]', # 0xc2 +'[?]', # 0xc3 +'[?]', # 0xc4 +'[?]', # 0xc5 +'[?]', # 0xc6 +'[?]', # 0xc7 +'[?]', # 0xc8 +'[?]', # 0xc9 +'[?]', # 0xca +'[?]', # 0xcb +'[?]', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'[?]', # 0xd0 +'[?]', # 0xd1 +'[?]', # 0xd2 +'[?]', # 0xd3 +'[?]', # 0xd4 +'[?]', # 0xd5 +'[?]', # 0xd6 +'[?]', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'[?]', # 0xdc +'[?]', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'[?]', # 0xe0 +'[?]', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'[', # 0xe6 +'[?]', # 0xe7 +'<', # 0xe8 +'> ', # 0xe9 +'[?]', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x028.py b/nstock/modules/unidecode/x028.py new file mode 100644 index 0000000..dc2f3f0 --- /dev/null +++ b/nstock/modules/unidecode/x028.py @@ -0,0 +1,258 @@ +data = ( +' ', # 0x00 +'a', # 0x01 +'1', # 0x02 +'b', # 0x03 +'\'', # 0x04 +'k', # 0x05 +'2', # 0x06 +'l', # 0x07 +'@', # 0x08 +'c', # 0x09 +'i', # 0x0a +'f', # 0x0b +'/', # 0x0c +'m', # 0x0d +'s', # 0x0e +'p', # 0x0f +'"', # 0x10 +'e', # 0x11 +'3', # 0x12 +'h', # 0x13 +'9', # 0x14 +'o', # 0x15 +'6', # 0x16 +'r', # 0x17 +'^', # 0x18 +'d', # 0x19 +'j', # 0x1a +'g', # 0x1b +'>', # 0x1c +'n', # 0x1d +'t', # 0x1e +'q', # 0x1f +',', # 0x20 +'*', # 0x21 +'5', # 0x22 +'<', # 0x23 +'-', # 0x24 +'u', # 0x25 +'8', # 0x26 +'v', # 0x27 +'.', # 0x28 +'%', # 0x29 +'[', # 0x2a +'$', # 0x2b +'+', # 0x2c +'x', # 0x2d +'!', # 0x2e +'&', # 0x2f +';', # 0x30 +':', # 0x31 +'4', # 0x32 +'\\', # 0x33 +'0', # 0x34 +'z', # 0x35 +'7', # 0x36 +'(', # 0x37 +'_', # 0x38 +'?', # 0x39 +'w', # 0x3a +']', # 0x3b +'#', # 0x3c +'y', # 0x3d +')', # 0x3e +'=', # 0x3f +'[d7]', # 0x40 +'[d17]', # 0x41 +'[d27]', # 0x42 +'[d127]', # 0x43 +'[d37]', # 0x44 +'[d137]', # 0x45 +'[d237]', # 0x46 +'[d1237]', # 0x47 +'[d47]', # 0x48 +'[d147]', # 0x49 +'[d247]', # 0x4a +'[d1247]', # 0x4b +'[d347]', # 0x4c +'[d1347]', # 0x4d +'[d2347]', # 0x4e +'[d12347]', # 0x4f +'[d57]', # 0x50 +'[d157]', # 0x51 +'[d257]', # 0x52 +'[d1257]', # 0x53 +'[d357]', # 0x54 +'[d1357]', # 0x55 +'[d2357]', # 0x56 +'[d12357]', # 0x57 +'[d457]', # 0x58 +'[d1457]', # 0x59 +'[d2457]', # 0x5a +'[d12457]', # 0x5b +'[d3457]', # 0x5c +'[d13457]', # 0x5d +'[d23457]', # 0x5e +'[d123457]', # 0x5f +'[d67]', # 0x60 +'[d167]', # 0x61 +'[d267]', # 0x62 +'[d1267]', # 0x63 +'[d367]', # 0x64 +'[d1367]', # 0x65 +'[d2367]', # 0x66 +'[d12367]', # 0x67 +'[d467]', # 0x68 +'[d1467]', # 0x69 +'[d2467]', # 0x6a +'[d12467]', # 0x6b +'[d3467]', # 0x6c +'[d13467]', # 0x6d +'[d23467]', # 0x6e +'[d123467]', # 0x6f +'[d567]', # 0x70 +'[d1567]', # 0x71 +'[d2567]', # 0x72 +'[d12567]', # 0x73 +'[d3567]', # 0x74 +'[d13567]', # 0x75 +'[d23567]', # 0x76 +'[d123567]', # 0x77 +'[d4567]', # 0x78 +'[d14567]', # 0x79 +'[d24567]', # 0x7a +'[d124567]', # 0x7b +'[d34567]', # 0x7c +'[d134567]', # 0x7d +'[d234567]', # 0x7e +'[d1234567]', # 0x7f +'[d8]', # 0x80 +'[d18]', # 0x81 +'[d28]', # 0x82 +'[d128]', # 0x83 +'[d38]', # 0x84 +'[d138]', # 0x85 +'[d238]', # 0x86 +'[d1238]', # 0x87 +'[d48]', # 0x88 +'[d148]', # 0x89 +'[d248]', # 0x8a +'[d1248]', # 0x8b +'[d348]', # 0x8c +'[d1348]', # 0x8d +'[d2348]', # 0x8e +'[d12348]', # 0x8f +'[d58]', # 0x90 +'[d158]', # 0x91 +'[d258]', # 0x92 +'[d1258]', # 0x93 +'[d358]', # 0x94 +'[d1358]', # 0x95 +'[d2358]', # 0x96 +'[d12358]', # 0x97 +'[d458]', # 0x98 +'[d1458]', # 0x99 +'[d2458]', # 0x9a +'[d12458]', # 0x9b +'[d3458]', # 0x9c +'[d13458]', # 0x9d +'[d23458]', # 0x9e +'[d123458]', # 0x9f +'[d68]', # 0xa0 +'[d168]', # 0xa1 +'[d268]', # 0xa2 +'[d1268]', # 0xa3 +'[d368]', # 0xa4 +'[d1368]', # 0xa5 +'[d2368]', # 0xa6 +'[d12368]', # 0xa7 +'[d468]', # 0xa8 +'[d1468]', # 0xa9 +'[d2468]', # 0xaa +'[d12468]', # 0xab +'[d3468]', # 0xac +'[d13468]', # 0xad +'[d23468]', # 0xae +'[d123468]', # 0xaf +'[d568]', # 0xb0 +'[d1568]', # 0xb1 +'[d2568]', # 0xb2 +'[d12568]', # 0xb3 +'[d3568]', # 0xb4 +'[d13568]', # 0xb5 +'[d23568]', # 0xb6 +'[d123568]', # 0xb7 +'[d4568]', # 0xb8 +'[d14568]', # 0xb9 +'[d24568]', # 0xba +'[d124568]', # 0xbb +'[d34568]', # 0xbc +'[d134568]', # 0xbd +'[d234568]', # 0xbe +'[d1234568]', # 0xbf +'[d78]', # 0xc0 +'[d178]', # 0xc1 +'[d278]', # 0xc2 +'[d1278]', # 0xc3 +'[d378]', # 0xc4 +'[d1378]', # 0xc5 +'[d2378]', # 0xc6 +'[d12378]', # 0xc7 +'[d478]', # 0xc8 +'[d1478]', # 0xc9 +'[d2478]', # 0xca +'[d12478]', # 0xcb +'[d3478]', # 0xcc +'[d13478]', # 0xcd +'[d23478]', # 0xce +'[d123478]', # 0xcf +'[d578]', # 0xd0 +'[d1578]', # 0xd1 +'[d2578]', # 0xd2 +'[d12578]', # 0xd3 +'[d3578]', # 0xd4 +'[d13578]', # 0xd5 +'[d23578]', # 0xd6 +'[d123578]', # 0xd7 +'[d4578]', # 0xd8 +'[d14578]', # 0xd9 +'[d24578]', # 0xda +'[d124578]', # 0xdb +'[d34578]', # 0xdc +'[d134578]', # 0xdd +'[d234578]', # 0xde +'[d1234578]', # 0xdf +'[d678]', # 0xe0 +'[d1678]', # 0xe1 +'[d2678]', # 0xe2 +'[d12678]', # 0xe3 +'[d3678]', # 0xe4 +'[d13678]', # 0xe5 +'[d23678]', # 0xe6 +'[d123678]', # 0xe7 +'[d4678]', # 0xe8 +'[d14678]', # 0xe9 +'[d24678]', # 0xea +'[d124678]', # 0xeb +'[d34678]', # 0xec +'[d134678]', # 0xed +'[d234678]', # 0xee +'[d1234678]', # 0xef +'[d5678]', # 0xf0 +'[d15678]', # 0xf1 +'[d25678]', # 0xf2 +'[d125678]', # 0xf3 +'[d35678]', # 0xf4 +'[d135678]', # 0xf5 +'[d235678]', # 0xf6 +'[d1235678]', # 0xf7 +'[d45678]', # 0xf8 +'[d145678]', # 0xf9 +'[d245678]', # 0xfa +'[d1245678]', # 0xfb +'[d345678]', # 0xfc +'[d1345678]', # 0xfd +'[d2345678]', # 0xfe +'[d12345678]', # 0xff +) diff --git a/nstock/modules/unidecode/x029.py b/nstock/modules/unidecode/x029.py new file mode 100644 index 0000000..c2df254 --- /dev/null +++ b/nstock/modules/unidecode/x029.py @@ -0,0 +1,257 @@ +data = ( +'', # 0x00 +'', # 0x01 +'', # 0x02 +'', # 0x03 +'', # 0x04 +'', # 0x05 +'', # 0x06 +'', # 0x07 +'', # 0x08 +'', # 0x09 +'', # 0x0a +'', # 0x0b +'', # 0x0c +'', # 0x0d +'', # 0x0e +'', # 0x0f +'', # 0x10 +'', # 0x11 +'', # 0x12 +'', # 0x13 +'', # 0x14 +'', # 0x15 +'', # 0x16 +'', # 0x17 +'', # 0x18 +'', # 0x19 +'', # 0x1a +'', # 0x1b +'', # 0x1c +'', # 0x1d +'', # 0x1e +'', # 0x1f +'', # 0x20 +'', # 0x21 +'', # 0x22 +'', # 0x23 +'', # 0x24 +'', # 0x25 +'', # 0x26 +'', # 0x27 +'', # 0x28 +'', # 0x29 +'', # 0x2a +'', # 0x2b +'', # 0x2c +'', # 0x2d +'', # 0x2e +'', # 0x2f +'', # 0x30 +'', # 0x31 +'', # 0x32 +'', # 0x33 +'', # 0x34 +'', # 0x35 +'', # 0x36 +'', # 0x37 +'', # 0x38 +'', # 0x39 +'', # 0x3a +'', # 0x3b +'', # 0x3c +'', # 0x3d +'', # 0x3e +'', # 0x3f +'', # 0x40 +'', # 0x41 +'', # 0x42 +'', # 0x43 +'', # 0x44 +'', # 0x45 +'', # 0x46 +'', # 0x47 +'', # 0x48 +'', # 0x49 +'', # 0x4a +'', # 0x4b +'', # 0x4c +'', # 0x4d +'', # 0x4e +'', # 0x4f +'', # 0x50 +'', # 0x51 +'', # 0x52 +'', # 0x53 +'', # 0x54 +'', # 0x55 +'', # 0x56 +'', # 0x57 +'', # 0x58 +'', # 0x59 +'', # 0x5a +'', # 0x5b +'', # 0x5c +'', # 0x5d +'', # 0x5e +'', # 0x5f +'', # 0x60 +'', # 0x61 +'', # 0x62 +'', # 0x63 +'', # 0x64 +'', # 0x65 +'', # 0x66 +'', # 0x67 +'', # 0x68 +'', # 0x69 +'', # 0x6a +'', # 0x6b +'', # 0x6c +'', # 0x6d +'', # 0x6e +'', # 0x6f +'', # 0x70 +'', # 0x71 +'', # 0x72 +'', # 0x73 +'', # 0x74 +'', # 0x75 +'', # 0x76 +'', # 0x77 +'', # 0x78 +'', # 0x79 +'', # 0x7a +'', # 0x7b +'', # 0x7c +'', # 0x7d +'', # 0x7e +'', # 0x7f +'', # 0x80 +'', # 0x81 +'', # 0x82 +'{', # 0x83 +'} ', # 0x84 +'', # 0x85 +'', # 0x86 +'', # 0x87 +'', # 0x88 +'', # 0x89 +'', # 0x8a +'', # 0x8b +'', # 0x8c +'', # 0x8d +'', # 0x8e +'', # 0x8f +'', # 0x90 +'', # 0x91 +'', # 0x92 +'', # 0x93 +'', # 0x94 +'', # 0x95 +'', # 0x96 +'', # 0x97 +'', # 0x98 +'', # 0x99 +'', # 0x9a +'', # 0x9b +'', # 0x9c +'', # 0x9d +'', # 0x9e +'', # 0x9f +'', # 0xa0 +'', # 0xa1 +'', # 0xa2 +'', # 0xa3 +'', # 0xa4 +'', # 0xa5 +'', # 0xa6 +'', # 0xa7 +'', # 0xa8 +'', # 0xa9 +'', # 0xaa +'', # 0xab +'', # 0xac +'', # 0xad +'', # 0xae +'', # 0xaf +'', # 0xb0 +'', # 0xb1 +'', # 0xb2 +'', # 0xb3 +'', # 0xb4 +'', # 0xb5 +'', # 0xb6 +'', # 0xb7 +'', # 0xb8 +'', # 0xb9 +'', # 0xba +'', # 0xbb +'', # 0xbc +'', # 0xbd +'', # 0xbe +'', # 0xbf +'', # 0xc0 +'', # 0xc1 +'', # 0xc2 +'', # 0xc3 +'', # 0xc4 +'', # 0xc5 +'', # 0xc6 +'', # 0xc7 +'', # 0xc8 +'', # 0xc9 +'', # 0xca +'', # 0xcb +'', # 0xcc +'', # 0xcd +'', # 0xce +'', # 0xcf +'', # 0xd0 +'', # 0xd1 +'', # 0xd2 +'', # 0xd3 +'', # 0xd4 +'', # 0xd5 +'', # 0xd6 +'', # 0xd7 +'', # 0xd8 +'', # 0xd9 +'', # 0xda +'', # 0xdb +'', # 0xdc +'', # 0xdd +'', # 0xde +'', # 0xdf +'', # 0xe0 +'', # 0xe1 +'', # 0xe2 +'', # 0xe3 +'', # 0xe4 +'', # 0xe5 +'', # 0xe6 +'', # 0xe7 +'', # 0xe8 +'', # 0xe9 +'', # 0xea +'', # 0xeb +'', # 0xec +'', # 0xed +'', # 0xee +'', # 0xef +'', # 0xf0 +'', # 0xf1 +'', # 0xf2 +'', # 0xf3 +'', # 0xf4 +'', # 0xf5 +'', # 0xf6 +'', # 0xf7 +'', # 0xf8 +'', # 0xf9 +'', # 0xfa +'', # 0xfb +'', # 0xfc +'', # 0xfd +'', # 0xfe +) diff --git a/nstock/modules/unidecode/x02a.py b/nstock/modules/unidecode/x02a.py new file mode 100644 index 0000000..b832ef3 --- /dev/null +++ b/nstock/modules/unidecode/x02a.py @@ -0,0 +1,257 @@ +data = ( +'', # 0x00 +'', # 0x01 +'', # 0x02 +'', # 0x03 +'', # 0x04 +'', # 0x05 +'', # 0x06 +'', # 0x07 +'', # 0x08 +'', # 0x09 +'', # 0x0a +'', # 0x0b +'', # 0x0c +'', # 0x0d +'', # 0x0e +'', # 0x0f +'', # 0x10 +'', # 0x11 +'', # 0x12 +'', # 0x13 +'', # 0x14 +'', # 0x15 +'', # 0x16 +'', # 0x17 +'', # 0x18 +'', # 0x19 +'', # 0x1a +'', # 0x1b +'', # 0x1c +'', # 0x1d +'', # 0x1e +'', # 0x1f +'', # 0x20 +'', # 0x21 +'', # 0x22 +'', # 0x23 +'', # 0x24 +'', # 0x25 +'', # 0x26 +'', # 0x27 +'', # 0x28 +'', # 0x29 +'', # 0x2a +'', # 0x2b +'', # 0x2c +'', # 0x2d +'', # 0x2e +'', # 0x2f +'', # 0x30 +'', # 0x31 +'', # 0x32 +'', # 0x33 +'', # 0x34 +'', # 0x35 +'', # 0x36 +'', # 0x37 +'', # 0x38 +'', # 0x39 +'', # 0x3a +'', # 0x3b +'', # 0x3c +'', # 0x3d +'', # 0x3e +'', # 0x3f +'', # 0x40 +'', # 0x41 +'', # 0x42 +'', # 0x43 +'', # 0x44 +'', # 0x45 +'', # 0x46 +'', # 0x47 +'', # 0x48 +'', # 0x49 +'', # 0x4a +'', # 0x4b +'', # 0x4c +'', # 0x4d +'', # 0x4e +'', # 0x4f +'', # 0x50 +'', # 0x51 +'', # 0x52 +'', # 0x53 +'', # 0x54 +'', # 0x55 +'', # 0x56 +'', # 0x57 +'', # 0x58 +'', # 0x59 +'', # 0x5a +'', # 0x5b +'', # 0x5c +'', # 0x5d +'', # 0x5e +'', # 0x5f +'', # 0x60 +'', # 0x61 +'', # 0x62 +'', # 0x63 +'', # 0x64 +'', # 0x65 +'', # 0x66 +'', # 0x67 +'', # 0x68 +'', # 0x69 +'', # 0x6a +'', # 0x6b +'', # 0x6c +'', # 0x6d +'', # 0x6e +'', # 0x6f +'', # 0x70 +'', # 0x71 +'', # 0x72 +'', # 0x73 +'::=', # 0x74 +'==', # 0x75 +'===', # 0x76 +'', # 0x77 +'', # 0x78 +'', # 0x79 +'', # 0x7a +'', # 0x7b +'', # 0x7c +'', # 0x7d +'', # 0x7e +'', # 0x7f +'', # 0x80 +'', # 0x81 +'', # 0x82 +'', # 0x83 +'', # 0x84 +'', # 0x85 +'', # 0x86 +'', # 0x87 +'', # 0x88 +'', # 0x89 +'', # 0x8a +'', # 0x8b +'', # 0x8c +'', # 0x8d +'', # 0x8e +'', # 0x8f +'', # 0x90 +'', # 0x91 +'', # 0x92 +'', # 0x93 +'', # 0x94 +'', # 0x95 +'', # 0x96 +'', # 0x97 +'', # 0x98 +'', # 0x99 +'', # 0x9a +'', # 0x9b +'', # 0x9c +'', # 0x9d +'', # 0x9e +'', # 0x9f +'', # 0xa0 +'', # 0xa1 +'', # 0xa2 +'', # 0xa3 +'', # 0xa4 +'', # 0xa5 +'', # 0xa6 +'', # 0xa7 +'', # 0xa8 +'', # 0xa9 +'', # 0xaa +'', # 0xab +'', # 0xac +'', # 0xad +'', # 0xae +'', # 0xaf +'', # 0xb0 +'', # 0xb1 +'', # 0xb2 +'', # 0xb3 +'', # 0xb4 +'', # 0xb5 +'', # 0xb6 +'', # 0xb7 +'', # 0xb8 +'', # 0xb9 +'', # 0xba +'', # 0xbb +'', # 0xbc +'', # 0xbd +'', # 0xbe +'', # 0xbf +'', # 0xc0 +'', # 0xc1 +'', # 0xc2 +'', # 0xc3 +'', # 0xc4 +'', # 0xc5 +'', # 0xc6 +'', # 0xc7 +'', # 0xc8 +'', # 0xc9 +'', # 0xca +'', # 0xcb +'', # 0xcc +'', # 0xcd +'', # 0xce +'', # 0xcf +'', # 0xd0 +'', # 0xd1 +'', # 0xd2 +'', # 0xd3 +'', # 0xd4 +'', # 0xd5 +'', # 0xd6 +'', # 0xd7 +'', # 0xd8 +'', # 0xd9 +'', # 0xda +'', # 0xdb +'', # 0xdc +'', # 0xdd +'', # 0xde +'', # 0xdf +'', # 0xe0 +'', # 0xe1 +'', # 0xe2 +'', # 0xe3 +'', # 0xe4 +'', # 0xe5 +'', # 0xe6 +'', # 0xe7 +'', # 0xe8 +'', # 0xe9 +'', # 0xea +'', # 0xeb +'', # 0xec +'', # 0xed +'', # 0xee +'', # 0xef +'', # 0xf0 +'', # 0xf1 +'', # 0xf2 +'', # 0xf3 +'', # 0xf4 +'', # 0xf5 +'', # 0xf6 +'', # 0xf7 +'', # 0xf8 +'', # 0xf9 +'', # 0xfa +'', # 0xfb +'', # 0xfc +'', # 0xfd +'', # 0xfe +) diff --git a/nstock/modules/unidecode/x02c.py b/nstock/modules/unidecode/x02c.py new file mode 100644 index 0000000..0d05d06 --- /dev/null +++ b/nstock/modules/unidecode/x02c.py @@ -0,0 +1,257 @@ +data = ( +'', # 0x00 +'', # 0x01 +'', # 0x02 +'', # 0x03 +'', # 0x04 +'', # 0x05 +'', # 0x06 +'', # 0x07 +'', # 0x08 +'', # 0x09 +'', # 0x0a +'', # 0x0b +'', # 0x0c +'', # 0x0d +'', # 0x0e +'', # 0x0f +'', # 0x10 +'', # 0x11 +'', # 0x12 +'', # 0x13 +'', # 0x14 +'', # 0x15 +'', # 0x16 +'', # 0x17 +'', # 0x18 +'', # 0x19 +'', # 0x1a +'', # 0x1b +'', # 0x1c +'', # 0x1d +'', # 0x1e +'', # 0x1f +'', # 0x20 +'', # 0x21 +'', # 0x22 +'', # 0x23 +'', # 0x24 +'', # 0x25 +'', # 0x26 +'', # 0x27 +'', # 0x28 +'', # 0x29 +'', # 0x2a +'', # 0x2b +'', # 0x2c +'', # 0x2d +'', # 0x2e +'', # 0x2f +'', # 0x30 +'', # 0x31 +'', # 0x32 +'', # 0x33 +'', # 0x34 +'', # 0x35 +'', # 0x36 +'', # 0x37 +'', # 0x38 +'', # 0x39 +'', # 0x3a +'', # 0x3b +'', # 0x3c +'', # 0x3d +'', # 0x3e +'', # 0x3f +'', # 0x40 +'', # 0x41 +'', # 0x42 +'', # 0x43 +'', # 0x44 +'', # 0x45 +'', # 0x46 +'', # 0x47 +'', # 0x48 +'', # 0x49 +'', # 0x4a +'', # 0x4b +'', # 0x4c +'', # 0x4d +'', # 0x4e +'', # 0x4f +'', # 0x50 +'', # 0x51 +'', # 0x52 +'', # 0x53 +'', # 0x54 +'', # 0x55 +'', # 0x56 +'', # 0x57 +'', # 0x58 +'', # 0x59 +'', # 0x5a +'', # 0x5b +'', # 0x5c +'', # 0x5d +'', # 0x5e +'', # 0x5f +'L', # 0x60 +'l', # 0x61 +'L', # 0x62 +'P', # 0x63 +'R', # 0x64 +'a', # 0x65 +'t', # 0x66 +'H', # 0x67 +'h', # 0x68 +'K', # 0x69 +'k', # 0x6a +'Z', # 0x6b +'z', # 0x6c +'', # 0x6d +'M', # 0x6e +'A', # 0x6f +'', # 0x70 +'', # 0x71 +'', # 0x72 +'', # 0x73 +'', # 0x74 +'', # 0x75 +'', # 0x76 +'', # 0x77 +'', # 0x78 +'', # 0x79 +'', # 0x7a +'', # 0x7b +'', # 0x7c +'', # 0x7d +'', # 0x7e +'', # 0x7f +'', # 0x80 +'', # 0x81 +'', # 0x82 +'', # 0x83 +'', # 0x84 +'', # 0x85 +'', # 0x86 +'', # 0x87 +'', # 0x88 +'', # 0x89 +'', # 0x8a +'', # 0x8b +'', # 0x8c +'', # 0x8d +'', # 0x8e +'', # 0x8f +'', # 0x90 +'', # 0x91 +'', # 0x92 +'', # 0x93 +'', # 0x94 +'', # 0x95 +'', # 0x96 +'', # 0x97 +'', # 0x98 +'', # 0x99 +'', # 0x9a +'', # 0x9b +'', # 0x9c +'', # 0x9d +'', # 0x9e +'', # 0x9f +'', # 0xa0 +'', # 0xa1 +'', # 0xa2 +'', # 0xa3 +'', # 0xa4 +'', # 0xa5 +'', # 0xa6 +'', # 0xa7 +'', # 0xa8 +'', # 0xa9 +'', # 0xaa +'', # 0xab +'', # 0xac +'', # 0xad +'', # 0xae +'', # 0xaf +'', # 0xb0 +'', # 0xb1 +'', # 0xb2 +'', # 0xb3 +'', # 0xb4 +'', # 0xb5 +'', # 0xb6 +'', # 0xb7 +'', # 0xb8 +'', # 0xb9 +'', # 0xba +'', # 0xbb +'', # 0xbc +'', # 0xbd +'', # 0xbe +'', # 0xbf +'', # 0xc0 +'', # 0xc1 +'', # 0xc2 +'', # 0xc3 +'', # 0xc4 +'', # 0xc5 +'', # 0xc6 +'', # 0xc7 +'', # 0xc8 +'', # 0xc9 +'', # 0xca +'', # 0xcb +'', # 0xcc +'', # 0xcd +'', # 0xce +'', # 0xcf +'', # 0xd0 +'', # 0xd1 +'', # 0xd2 +'', # 0xd3 +'', # 0xd4 +'', # 0xd5 +'', # 0xd6 +'', # 0xd7 +'', # 0xd8 +'', # 0xd9 +'', # 0xda +'', # 0xdb +'', # 0xdc +'', # 0xdd +'', # 0xde +'', # 0xdf +'', # 0xe0 +'', # 0xe1 +'', # 0xe2 +'', # 0xe3 +'', # 0xe4 +'', # 0xe5 +'', # 0xe6 +'', # 0xe7 +'', # 0xe8 +'', # 0xe9 +'', # 0xea +'', # 0xeb +'', # 0xec +'', # 0xed +'', # 0xee +'', # 0xef +'', # 0xf0 +'', # 0xf1 +'', # 0xf2 +'', # 0xf3 +'', # 0xf4 +'', # 0xf5 +'', # 0xf6 +'', # 0xf7 +'', # 0xf8 +'', # 0xf9 +'', # 0xfa +'', # 0xfb +'', # 0xfc +'', # 0xfd +'', # 0xfe +) diff --git a/nstock/modules/unidecode/x02e.py b/nstock/modules/unidecode/x02e.py new file mode 100644 index 0000000..feaad8d --- /dev/null +++ b/nstock/modules/unidecode/x02e.py @@ -0,0 +1,257 @@ +data = ( +'[?]', # 0x00 +'[?]', # 0x01 +'[?]', # 0x02 +'[?]', # 0x03 +'[?]', # 0x04 +'[?]', # 0x05 +'[?]', # 0x06 +'[?]', # 0x07 +'[?]', # 0x08 +'[?]', # 0x09 +'[?]', # 0x0a +'[?]', # 0x0b +'[?]', # 0x0c +'[?]', # 0x0d +'[?]', # 0x0e +'[?]', # 0x0f +'[?]', # 0x10 +'[?]', # 0x11 +'[?]', # 0x12 +'[?]', # 0x13 +'[?]', # 0x14 +'[?]', # 0x15 +'[?]', # 0x16 +'[?]', # 0x17 +'[?]', # 0x18 +'[?]', # 0x19 +'[?]', # 0x1a +'[?]', # 0x1b +'[?]', # 0x1c +'[?]', # 0x1d +'[?]', # 0x1e +'[?]', # 0x1f +'[?]', # 0x20 +'[?]', # 0x21 +'[?]', # 0x22 +'[?]', # 0x23 +'[?]', # 0x24 +'[?]', # 0x25 +'[?]', # 0x26 +'[?]', # 0x27 +'[?]', # 0x28 +'[?]', # 0x29 +'[?]', # 0x2a +'[?]', # 0x2b +'[?]', # 0x2c +'[?]', # 0x2d +'[?]', # 0x2e +'[?]', # 0x2f +'[?]', # 0x30 +'[?]', # 0x31 +'[?]', # 0x32 +'[?]', # 0x33 +'[?]', # 0x34 +'[?]', # 0x35 +'[?]', # 0x36 +'[?]', # 0x37 +'[?]', # 0x38 +'[?]', # 0x39 +'[?]', # 0x3a +'[?]', # 0x3b +'[?]', # 0x3c +'[?]', # 0x3d +'[?]', # 0x3e +'[?]', # 0x3f +'[?]', # 0x40 +'[?]', # 0x41 +'[?]', # 0x42 +'[?]', # 0x43 +'[?]', # 0x44 +'[?]', # 0x45 +'[?]', # 0x46 +'[?]', # 0x47 +'[?]', # 0x48 +'[?]', # 0x49 +'[?]', # 0x4a +'[?]', # 0x4b +'[?]', # 0x4c +'[?]', # 0x4d +'[?]', # 0x4e +'[?]', # 0x4f +'[?]', # 0x50 +'[?]', # 0x51 +'[?]', # 0x52 +'[?]', # 0x53 +'[?]', # 0x54 +'[?]', # 0x55 +'[?]', # 0x56 +'[?]', # 0x57 +'[?]', # 0x58 +'[?]', # 0x59 +'[?]', # 0x5a +'[?]', # 0x5b +'[?]', # 0x5c +'[?]', # 0x5d +'[?]', # 0x5e +'[?]', # 0x5f +'[?]', # 0x60 +'[?]', # 0x61 +'[?]', # 0x62 +'[?]', # 0x63 +'[?]', # 0x64 +'[?]', # 0x65 +'[?]', # 0x66 +'[?]', # 0x67 +'[?]', # 0x68 +'[?]', # 0x69 +'[?]', # 0x6a +'[?]', # 0x6b +'[?]', # 0x6c +'[?]', # 0x6d +'[?]', # 0x6e +'[?]', # 0x6f +'[?]', # 0x70 +'[?]', # 0x71 +'[?]', # 0x72 +'[?]', # 0x73 +'[?]', # 0x74 +'[?]', # 0x75 +'[?]', # 0x76 +'[?]', # 0x77 +'[?]', # 0x78 +'[?]', # 0x79 +'[?]', # 0x7a +'[?]', # 0x7b +'[?]', # 0x7c +'[?]', # 0x7d +'[?]', # 0x7e +'[?]', # 0x7f +'[?] ', # 0x80 +'[?] ', # 0x81 +'[?] ', # 0x82 +'[?] ', # 0x83 +'[?] ', # 0x84 +'[?] ', # 0x85 +'[?] ', # 0x86 +'[?] ', # 0x87 +'[?] ', # 0x88 +'[?] ', # 0x89 +'[?] ', # 0x8a +'[?] ', # 0x8b +'[?] ', # 0x8c +'[?] ', # 0x8d +'[?] ', # 0x8e +'[?] ', # 0x8f +'[?] ', # 0x90 +'[?] ', # 0x91 +'[?] ', # 0x92 +'[?] ', # 0x93 +'[?] ', # 0x94 +'[?] ', # 0x95 +'[?] ', # 0x96 +'[?] ', # 0x97 +'[?] ', # 0x98 +'[?] ', # 0x99 +'[?]', # 0x9a +'[?] ', # 0x9b +'[?] ', # 0x9c +'[?] ', # 0x9d +'[?] ', # 0x9e +'[?] ', # 0x9f +'[?] ', # 0xa0 +'[?] ', # 0xa1 +'[?] ', # 0xa2 +'[?] ', # 0xa3 +'[?] ', # 0xa4 +'[?] ', # 0xa5 +'[?] ', # 0xa6 +'[?] ', # 0xa7 +'[?] ', # 0xa8 +'[?] ', # 0xa9 +'[?] ', # 0xaa +'[?] ', # 0xab +'[?] ', # 0xac +'[?] ', # 0xad +'[?] ', # 0xae +'[?] ', # 0xaf +'[?] ', # 0xb0 +'[?] ', # 0xb1 +'[?] ', # 0xb2 +'[?] ', # 0xb3 +'[?] ', # 0xb4 +'[?] ', # 0xb5 +'[?] ', # 0xb6 +'[?] ', # 0xb7 +'[?] ', # 0xb8 +'[?] ', # 0xb9 +'[?] ', # 0xba +'[?] ', # 0xbb +'[?] ', # 0xbc +'[?] ', # 0xbd +'[?] ', # 0xbe +'[?] ', # 0xbf +'[?] ', # 0xc0 +'[?] ', # 0xc1 +'[?] ', # 0xc2 +'[?] ', # 0xc3 +'[?] ', # 0xc4 +'[?] ', # 0xc5 +'[?] ', # 0xc6 +'[?] ', # 0xc7 +'[?] ', # 0xc8 +'[?] ', # 0xc9 +'[?] ', # 0xca +'[?] ', # 0xcb +'[?] ', # 0xcc +'[?] ', # 0xcd +'[?] ', # 0xce +'[?] ', # 0xcf +'[?] ', # 0xd0 +'[?] ', # 0xd1 +'[?] ', # 0xd2 +'[?] ', # 0xd3 +'[?] ', # 0xd4 +'[?] ', # 0xd5 +'[?] ', # 0xd6 +'[?] ', # 0xd7 +'[?] ', # 0xd8 +'[?] ', # 0xd9 +'[?] ', # 0xda +'[?] ', # 0xdb +'[?] ', # 0xdc +'[?] ', # 0xdd +'[?] ', # 0xde +'[?] ', # 0xdf +'[?] ', # 0xe0 +'[?] ', # 0xe1 +'[?] ', # 0xe2 +'[?] ', # 0xe3 +'[?] ', # 0xe4 +'[?] ', # 0xe5 +'[?] ', # 0xe6 +'[?] ', # 0xe7 +'[?] ', # 0xe8 +'[?] ', # 0xe9 +'[?] ', # 0xea +'[?] ', # 0xeb +'[?] ', # 0xec +'[?] ', # 0xed +'[?] ', # 0xee +'[?] ', # 0xef +'[?] ', # 0xf0 +'[?] ', # 0xf1 +'[?] ', # 0xf2 +'[?] ', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x02f.py b/nstock/modules/unidecode/x02f.py new file mode 100644 index 0000000..01f8b15 --- /dev/null +++ b/nstock/modules/unidecode/x02f.py @@ -0,0 +1,257 @@ +data = ( +'[?] ', # 0x00 +'[?] ', # 0x01 +'[?] ', # 0x02 +'[?] ', # 0x03 +'[?] ', # 0x04 +'[?] ', # 0x05 +'[?] ', # 0x06 +'[?] ', # 0x07 +'[?] ', # 0x08 +'[?] ', # 0x09 +'[?] ', # 0x0a +'[?] ', # 0x0b +'[?] ', # 0x0c +'[?] ', # 0x0d +'[?] ', # 0x0e +'[?] ', # 0x0f +'[?] ', # 0x10 +'[?] ', # 0x11 +'[?] ', # 0x12 +'[?] ', # 0x13 +'[?] ', # 0x14 +'[?] ', # 0x15 +'[?] ', # 0x16 +'[?] ', # 0x17 +'[?] ', # 0x18 +'[?] ', # 0x19 +'[?] ', # 0x1a +'[?] ', # 0x1b +'[?] ', # 0x1c +'[?] ', # 0x1d +'[?] ', # 0x1e +'[?] ', # 0x1f +'[?] ', # 0x20 +'[?] ', # 0x21 +'[?] ', # 0x22 +'[?] ', # 0x23 +'[?] ', # 0x24 +'[?] ', # 0x25 +'[?] ', # 0x26 +'[?] ', # 0x27 +'[?] ', # 0x28 +'[?] ', # 0x29 +'[?] ', # 0x2a +'[?] ', # 0x2b +'[?] ', # 0x2c +'[?] ', # 0x2d +'[?] ', # 0x2e +'[?] ', # 0x2f +'[?] ', # 0x30 +'[?] ', # 0x31 +'[?] ', # 0x32 +'[?] ', # 0x33 +'[?] ', # 0x34 +'[?] ', # 0x35 +'[?] ', # 0x36 +'[?] ', # 0x37 +'[?] ', # 0x38 +'[?] ', # 0x39 +'[?] ', # 0x3a +'[?] ', # 0x3b +'[?] ', # 0x3c +'[?] ', # 0x3d +'[?] ', # 0x3e +'[?] ', # 0x3f +'[?] ', # 0x40 +'[?] ', # 0x41 +'[?] ', # 0x42 +'[?] ', # 0x43 +'[?] ', # 0x44 +'[?] ', # 0x45 +'[?] ', # 0x46 +'[?] ', # 0x47 +'[?] ', # 0x48 +'[?] ', # 0x49 +'[?] ', # 0x4a +'[?] ', # 0x4b +'[?] ', # 0x4c +'[?] ', # 0x4d +'[?] ', # 0x4e +'[?] ', # 0x4f +'[?] ', # 0x50 +'[?] ', # 0x51 +'[?] ', # 0x52 +'[?] ', # 0x53 +'[?] ', # 0x54 +'[?] ', # 0x55 +'[?] ', # 0x56 +'[?] ', # 0x57 +'[?] ', # 0x58 +'[?] ', # 0x59 +'[?] ', # 0x5a +'[?] ', # 0x5b +'[?] ', # 0x5c +'[?] ', # 0x5d +'[?] ', # 0x5e +'[?] ', # 0x5f +'[?] ', # 0x60 +'[?] ', # 0x61 +'[?] ', # 0x62 +'[?] ', # 0x63 +'[?] ', # 0x64 +'[?] ', # 0x65 +'[?] ', # 0x66 +'[?] ', # 0x67 +'[?] ', # 0x68 +'[?] ', # 0x69 +'[?] ', # 0x6a +'[?] ', # 0x6b +'[?] ', # 0x6c +'[?] ', # 0x6d +'[?] ', # 0x6e +'[?] ', # 0x6f +'[?] ', # 0x70 +'[?] ', # 0x71 +'[?] ', # 0x72 +'[?] ', # 0x73 +'[?] ', # 0x74 +'[?] ', # 0x75 +'[?] ', # 0x76 +'[?] ', # 0x77 +'[?] ', # 0x78 +'[?] ', # 0x79 +'[?] ', # 0x7a +'[?] ', # 0x7b +'[?] ', # 0x7c +'[?] ', # 0x7d +'[?] ', # 0x7e +'[?] ', # 0x7f +'[?] ', # 0x80 +'[?] ', # 0x81 +'[?] ', # 0x82 +'[?] ', # 0x83 +'[?] ', # 0x84 +'[?] ', # 0x85 +'[?] ', # 0x86 +'[?] ', # 0x87 +'[?] ', # 0x88 +'[?] ', # 0x89 +'[?] ', # 0x8a +'[?] ', # 0x8b +'[?] ', # 0x8c +'[?] ', # 0x8d +'[?] ', # 0x8e +'[?] ', # 0x8f +'[?] ', # 0x90 +'[?] ', # 0x91 +'[?] ', # 0x92 +'[?] ', # 0x93 +'[?] ', # 0x94 +'[?] ', # 0x95 +'[?] ', # 0x96 +'[?] ', # 0x97 +'[?] ', # 0x98 +'[?] ', # 0x99 +'[?] ', # 0x9a +'[?] ', # 0x9b +'[?] ', # 0x9c +'[?] ', # 0x9d +'[?] ', # 0x9e +'[?] ', # 0x9f +'[?] ', # 0xa0 +'[?] ', # 0xa1 +'[?] ', # 0xa2 +'[?] ', # 0xa3 +'[?] ', # 0xa4 +'[?] ', # 0xa5 +'[?] ', # 0xa6 +'[?] ', # 0xa7 +'[?] ', # 0xa8 +'[?] ', # 0xa9 +'[?] ', # 0xaa +'[?] ', # 0xab +'[?] ', # 0xac +'[?] ', # 0xad +'[?] ', # 0xae +'[?] ', # 0xaf +'[?] ', # 0xb0 +'[?] ', # 0xb1 +'[?] ', # 0xb2 +'[?] ', # 0xb3 +'[?] ', # 0xb4 +'[?] ', # 0xb5 +'[?] ', # 0xb6 +'[?] ', # 0xb7 +'[?] ', # 0xb8 +'[?] ', # 0xb9 +'[?] ', # 0xba +'[?] ', # 0xbb +'[?] ', # 0xbc +'[?] ', # 0xbd +'[?] ', # 0xbe +'[?] ', # 0xbf +'[?] ', # 0xc0 +'[?] ', # 0xc1 +'[?] ', # 0xc2 +'[?] ', # 0xc3 +'[?] ', # 0xc4 +'[?] ', # 0xc5 +'[?] ', # 0xc6 +'[?] ', # 0xc7 +'[?] ', # 0xc8 +'[?] ', # 0xc9 +'[?] ', # 0xca +'[?] ', # 0xcb +'[?] ', # 0xcc +'[?] ', # 0xcd +'[?] ', # 0xce +'[?] ', # 0xcf +'[?] ', # 0xd0 +'[?] ', # 0xd1 +'[?] ', # 0xd2 +'[?] ', # 0xd3 +'[?] ', # 0xd4 +'[?] ', # 0xd5 +'[?]', # 0xd6 +'[?]', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'[?]', # 0xdc +'[?]', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'[?]', # 0xe0 +'[?]', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'[?]', # 0xe6 +'[?]', # 0xe7 +'[?]', # 0xe8 +'[?]', # 0xe9 +'[?]', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'[?] ', # 0xf0 +'[?] ', # 0xf1 +'[?] ', # 0xf2 +'[?] ', # 0xf3 +'[?] ', # 0xf4 +'[?] ', # 0xf5 +'[?] ', # 0xf6 +'[?] ', # 0xf7 +'[?] ', # 0xf8 +'[?] ', # 0xf9 +'[?] ', # 0xfa +'[?] ', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x030.py b/nstock/modules/unidecode/x030.py new file mode 100644 index 0000000..d65ed4c --- /dev/null +++ b/nstock/modules/unidecode/x030.py @@ -0,0 +1,257 @@ +data = ( +' ', # 0x00 +', ', # 0x01 +'. ', # 0x02 +'"', # 0x03 +'[JIS]', # 0x04 +'"', # 0x05 +'/', # 0x06 +'0', # 0x07 +'<', # 0x08 +'> ', # 0x09 +'<<', # 0x0a +'>> ', # 0x0b +'[', # 0x0c +'] ', # 0x0d +'{', # 0x0e +'} ', # 0x0f +'[(', # 0x10 +')] ', # 0x11 +'@', # 0x12 +'X ', # 0x13 +'[', # 0x14 +'] ', # 0x15 +'[[', # 0x16 +']] ', # 0x17 +'((', # 0x18 +')) ', # 0x19 +'[[', # 0x1a +']] ', # 0x1b +'~ ', # 0x1c +'``', # 0x1d +'\'\'', # 0x1e +',,', # 0x1f +'@', # 0x20 +'1', # 0x21 +'2', # 0x22 +'3', # 0x23 +'4', # 0x24 +'5', # 0x25 +'6', # 0x26 +'7', # 0x27 +'8', # 0x28 +'9', # 0x29 +'', # 0x2a +'', # 0x2b +'', # 0x2c +'', # 0x2d +'', # 0x2e +'', # 0x2f +'~', # 0x30 +'+', # 0x31 +'+', # 0x32 +'+', # 0x33 +'+', # 0x34 +'', # 0x35 +'@', # 0x36 +' // ', # 0x37 +'+10+', # 0x38 +'+20+', # 0x39 +'+30+', # 0x3a +'[?]', # 0x3b +'[?]', # 0x3c +'[?]', # 0x3d +'', # 0x3e +'', # 0x3f +'[?]', # 0x40 +'a', # 0x41 +'a', # 0x42 +'i', # 0x43 +'i', # 0x44 +'u', # 0x45 +'u', # 0x46 +'e', # 0x47 +'e', # 0x48 +'o', # 0x49 +'o', # 0x4a +'ka', # 0x4b +'ga', # 0x4c +'ki', # 0x4d +'gi', # 0x4e +'ku', # 0x4f +'gu', # 0x50 +'ke', # 0x51 +'ge', # 0x52 +'ko', # 0x53 +'go', # 0x54 +'sa', # 0x55 +'za', # 0x56 +'shi', # 0x57 +'zi', # 0x58 +'su', # 0x59 +'zu', # 0x5a +'se', # 0x5b +'ze', # 0x5c +'so', # 0x5d +'zo', # 0x5e +'ta', # 0x5f +'da', # 0x60 +'chi', # 0x61 +'di', # 0x62 +'tsu', # 0x63 +'tsu', # 0x64 +'du', # 0x65 +'te', # 0x66 +'de', # 0x67 +'to', # 0x68 +'do', # 0x69 +'na', # 0x6a +'ni', # 0x6b +'nu', # 0x6c +'ne', # 0x6d +'no', # 0x6e +'ha', # 0x6f +'ba', # 0x70 +'pa', # 0x71 +'hi', # 0x72 +'bi', # 0x73 +'pi', # 0x74 +'hu', # 0x75 +'bu', # 0x76 +'pu', # 0x77 +'he', # 0x78 +'be', # 0x79 +'pe', # 0x7a +'ho', # 0x7b +'bo', # 0x7c +'po', # 0x7d +'ma', # 0x7e +'mi', # 0x7f +'mu', # 0x80 +'me', # 0x81 +'mo', # 0x82 +'ya', # 0x83 +'ya', # 0x84 +'yu', # 0x85 +'yu', # 0x86 +'yo', # 0x87 +'yo', # 0x88 +'ra', # 0x89 +'ri', # 0x8a +'ru', # 0x8b +'re', # 0x8c +'ro', # 0x8d +'wa', # 0x8e +'wa', # 0x8f +'wi', # 0x90 +'we', # 0x91 +'wo', # 0x92 +'n', # 0x93 +'vu', # 0x94 +'[?]', # 0x95 +'[?]', # 0x96 +'[?]', # 0x97 +'[?]', # 0x98 +'', # 0x99 +'', # 0x9a +'', # 0x9b +'', # 0x9c +'"', # 0x9d +'"', # 0x9e +'[?]', # 0x9f +'[?]', # 0xa0 +'a', # 0xa1 +'a', # 0xa2 +'i', # 0xa3 +'i', # 0xa4 +'u', # 0xa5 +'u', # 0xa6 +'e', # 0xa7 +'e', # 0xa8 +'o', # 0xa9 +'o', # 0xaa +'ka', # 0xab +'ga', # 0xac +'ki', # 0xad +'gi', # 0xae +'ku', # 0xaf +'gu', # 0xb0 +'ke', # 0xb1 +'ge', # 0xb2 +'ko', # 0xb3 +'go', # 0xb4 +'sa', # 0xb5 +'za', # 0xb6 +'shi', # 0xb7 +'zi', # 0xb8 +'su', # 0xb9 +'zu', # 0xba +'se', # 0xbb +'ze', # 0xbc +'so', # 0xbd +'zo', # 0xbe +'ta', # 0xbf +'da', # 0xc0 +'chi', # 0xc1 +'di', # 0xc2 +'tsu', # 0xc3 +'tsu', # 0xc4 +'du', # 0xc5 +'te', # 0xc6 +'de', # 0xc7 +'to', # 0xc8 +'do', # 0xc9 +'na', # 0xca +'ni', # 0xcb +'nu', # 0xcc +'ne', # 0xcd +'no', # 0xce +'ha', # 0xcf +'ba', # 0xd0 +'pa', # 0xd1 +'hi', # 0xd2 +'bi', # 0xd3 +'pi', # 0xd4 +'hu', # 0xd5 +'bu', # 0xd6 +'pu', # 0xd7 +'he', # 0xd8 +'be', # 0xd9 +'pe', # 0xda +'ho', # 0xdb +'bo', # 0xdc +'po', # 0xdd +'ma', # 0xde +'mi', # 0xdf +'mu', # 0xe0 +'me', # 0xe1 +'mo', # 0xe2 +'ya', # 0xe3 +'ya', # 0xe4 +'yu', # 0xe5 +'yu', # 0xe6 +'yo', # 0xe7 +'yo', # 0xe8 +'ra', # 0xe9 +'ri', # 0xea +'ru', # 0xeb +'re', # 0xec +'ro', # 0xed +'wa', # 0xee +'wa', # 0xef +'wi', # 0xf0 +'we', # 0xf1 +'wo', # 0xf2 +'n', # 0xf3 +'vu', # 0xf4 +'ka', # 0xf5 +'ke', # 0xf6 +'va', # 0xf7 +'vi', # 0xf8 +'ve', # 0xf9 +'vo', # 0xfa +'', # 0xfb +'', # 0xfc +'"', # 0xfd +'"', # 0xfe +) diff --git a/nstock/modules/unidecode/x031.py b/nstock/modules/unidecode/x031.py new file mode 100644 index 0000000..f557608 --- /dev/null +++ b/nstock/modules/unidecode/x031.py @@ -0,0 +1,257 @@ +data = ( +'[?]', # 0x00 +'[?]', # 0x01 +'[?]', # 0x02 +'[?]', # 0x03 +'[?]', # 0x04 +'B', # 0x05 +'P', # 0x06 +'M', # 0x07 +'F', # 0x08 +'D', # 0x09 +'T', # 0x0a +'N', # 0x0b +'L', # 0x0c +'G', # 0x0d +'K', # 0x0e +'H', # 0x0f +'J', # 0x10 +'Q', # 0x11 +'X', # 0x12 +'ZH', # 0x13 +'CH', # 0x14 +'SH', # 0x15 +'R', # 0x16 +'Z', # 0x17 +'C', # 0x18 +'S', # 0x19 +'A', # 0x1a +'O', # 0x1b +'E', # 0x1c +'EH', # 0x1d +'AI', # 0x1e +'EI', # 0x1f +'AU', # 0x20 +'OU', # 0x21 +'AN', # 0x22 +'EN', # 0x23 +'ANG', # 0x24 +'ENG', # 0x25 +'ER', # 0x26 +'I', # 0x27 +'U', # 0x28 +'IU', # 0x29 +'V', # 0x2a +'NG', # 0x2b +'GN', # 0x2c +'[?]', # 0x2d +'[?]', # 0x2e +'[?]', # 0x2f +'[?]', # 0x30 +'g', # 0x31 +'gg', # 0x32 +'gs', # 0x33 +'n', # 0x34 +'nj', # 0x35 +'nh', # 0x36 +'d', # 0x37 +'dd', # 0x38 +'r', # 0x39 +'lg', # 0x3a +'lm', # 0x3b +'lb', # 0x3c +'ls', # 0x3d +'lt', # 0x3e +'lp', # 0x3f +'rh', # 0x40 +'m', # 0x41 +'b', # 0x42 +'bb', # 0x43 +'bs', # 0x44 +'s', # 0x45 +'ss', # 0x46 +'', # 0x47 +'j', # 0x48 +'jj', # 0x49 +'c', # 0x4a +'k', # 0x4b +'t', # 0x4c +'p', # 0x4d +'h', # 0x4e +'a', # 0x4f +'ae', # 0x50 +'ya', # 0x51 +'yae', # 0x52 +'eo', # 0x53 +'e', # 0x54 +'yeo', # 0x55 +'ye', # 0x56 +'o', # 0x57 +'wa', # 0x58 +'wae', # 0x59 +'oe', # 0x5a +'yo', # 0x5b +'u', # 0x5c +'weo', # 0x5d +'we', # 0x5e +'wi', # 0x5f +'yu', # 0x60 +'eu', # 0x61 +'yi', # 0x62 +'i', # 0x63 +'', # 0x64 +'nn', # 0x65 +'nd', # 0x66 +'ns', # 0x67 +'nZ', # 0x68 +'lgs', # 0x69 +'ld', # 0x6a +'lbs', # 0x6b +'lZ', # 0x6c +'lQ', # 0x6d +'mb', # 0x6e +'ms', # 0x6f +'mZ', # 0x70 +'mN', # 0x71 +'bg', # 0x72 +'', # 0x73 +'bsg', # 0x74 +'bst', # 0x75 +'bj', # 0x76 +'bt', # 0x77 +'bN', # 0x78 +'bbN', # 0x79 +'sg', # 0x7a +'sn', # 0x7b +'sd', # 0x7c +'sb', # 0x7d +'sj', # 0x7e +'Z', # 0x7f +'', # 0x80 +'N', # 0x81 +'Ns', # 0x82 +'NZ', # 0x83 +'pN', # 0x84 +'hh', # 0x85 +'Q', # 0x86 +'yo-ya', # 0x87 +'yo-yae', # 0x88 +'yo-i', # 0x89 +'yu-yeo', # 0x8a +'yu-ye', # 0x8b +'yu-i', # 0x8c +'U', # 0x8d +'U-i', # 0x8e +'[?]', # 0x8f +'', # 0x90 +'', # 0x91 +'', # 0x92 +'', # 0x93 +'', # 0x94 +'', # 0x95 +'', # 0x96 +'', # 0x97 +'', # 0x98 +'', # 0x99 +'', # 0x9a +'', # 0x9b +'', # 0x9c +'', # 0x9d +'', # 0x9e +'', # 0x9f +'BU', # 0xa0 +'ZI', # 0xa1 +'JI', # 0xa2 +'GU', # 0xa3 +'EE', # 0xa4 +'ENN', # 0xa5 +'OO', # 0xa6 +'ONN', # 0xa7 +'IR', # 0xa8 +'ANN', # 0xa9 +'INN', # 0xaa +'UNN', # 0xab +'IM', # 0xac +'NGG', # 0xad +'AINN', # 0xae +'AUNN', # 0xaf +'AM', # 0xb0 +'OM', # 0xb1 +'ONG', # 0xb2 +'INNN', # 0xb3 +'P', # 0xb4 +'T', # 0xb5 +'K', # 0xb6 +'H', # 0xb7 +'[?]', # 0xb8 +'[?]', # 0xb9 +'[?]', # 0xba +'[?]', # 0xbb +'[?]', # 0xbc +'[?]', # 0xbd +'[?]', # 0xbe +'[?]', # 0xbf +'[?]', # 0xc0 +'[?]', # 0xc1 +'[?]', # 0xc2 +'[?]', # 0xc3 +'[?]', # 0xc4 +'[?]', # 0xc5 +'[?]', # 0xc6 +'[?]', # 0xc7 +'[?]', # 0xc8 +'[?]', # 0xc9 +'[?]', # 0xca +'[?]', # 0xcb +'[?]', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'[?]', # 0xd0 +'[?]', # 0xd1 +'[?]', # 0xd2 +'[?]', # 0xd3 +'[?]', # 0xd4 +'[?]', # 0xd5 +'[?]', # 0xd6 +'[?]', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'[?]', # 0xdc +'[?]', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'[?]', # 0xe0 +'[?]', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'[?]', # 0xe6 +'[?]', # 0xe7 +'[?]', # 0xe8 +'[?]', # 0xe9 +'[?]', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x032.py b/nstock/modules/unidecode/x032.py new file mode 100644 index 0000000..30282d4 --- /dev/null +++ b/nstock/modules/unidecode/x032.py @@ -0,0 +1,257 @@ +data = ( +'(g)', # 0x00 +'(n)', # 0x01 +'(d)', # 0x02 +'(r)', # 0x03 +'(m)', # 0x04 +'(b)', # 0x05 +'(s)', # 0x06 +'()', # 0x07 +'(j)', # 0x08 +'(c)', # 0x09 +'(k)', # 0x0a +'(t)', # 0x0b +'(p)', # 0x0c +'(h)', # 0x0d +'(ga)', # 0x0e +'(na)', # 0x0f +'(da)', # 0x10 +'(ra)', # 0x11 +'(ma)', # 0x12 +'(ba)', # 0x13 +'(sa)', # 0x14 +'(a)', # 0x15 +'(ja)', # 0x16 +'(ca)', # 0x17 +'(ka)', # 0x18 +'(ta)', # 0x19 +'(pa)', # 0x1a +'(ha)', # 0x1b +'(ju)', # 0x1c +'[?]', # 0x1d +'[?]', # 0x1e +'[?]', # 0x1f +'(1) ', # 0x20 +'(2) ', # 0x21 +'(3) ', # 0x22 +'(4) ', # 0x23 +'(5) ', # 0x24 +'(6) ', # 0x25 +'(7) ', # 0x26 +'(8) ', # 0x27 +'(9) ', # 0x28 +'(10) ', # 0x29 +'(Yue) ', # 0x2a +'(Huo) ', # 0x2b +'(Shui) ', # 0x2c +'(Mu) ', # 0x2d +'(Jin) ', # 0x2e +'(Tu) ', # 0x2f +'(Ri) ', # 0x30 +'(Zhu) ', # 0x31 +'(You) ', # 0x32 +'(She) ', # 0x33 +'(Ming) ', # 0x34 +'(Te) ', # 0x35 +'(Cai) ', # 0x36 +'(Zhu) ', # 0x37 +'(Lao) ', # 0x38 +'(Dai) ', # 0x39 +'(Hu) ', # 0x3a +'(Xue) ', # 0x3b +'(Jian) ', # 0x3c +'(Qi) ', # 0x3d +'(Zi) ', # 0x3e +'(Xie) ', # 0x3f +'(Ji) ', # 0x40 +'(Xiu) ', # 0x41 +'<<', # 0x42 +'>>', # 0x43 +'[?]', # 0x44 +'[?]', # 0x45 +'[?]', # 0x46 +'[?]', # 0x47 +'[?]', # 0x48 +'[?]', # 0x49 +'[?]', # 0x4a +'[?]', # 0x4b +'[?]', # 0x4c +'[?]', # 0x4d +'[?]', # 0x4e +'[?]', # 0x4f +'[?]', # 0x50 +'21', # 0x51 +'22', # 0x52 +'23', # 0x53 +'24', # 0x54 +'25', # 0x55 +'26', # 0x56 +'27', # 0x57 +'28', # 0x58 +'29', # 0x59 +'30', # 0x5a +'31', # 0x5b +'32', # 0x5c +'33', # 0x5d +'34', # 0x5e +'35', # 0x5f +'(g)', # 0x60 +'(n)', # 0x61 +'(d)', # 0x62 +'(r)', # 0x63 +'(m)', # 0x64 +'(b)', # 0x65 +'(s)', # 0x66 +'()', # 0x67 +'(j)', # 0x68 +'(c)', # 0x69 +'(k)', # 0x6a +'(t)', # 0x6b +'(p)', # 0x6c +'(h)', # 0x6d +'(ga)', # 0x6e +'(na)', # 0x6f +'(da)', # 0x70 +'(ra)', # 0x71 +'(ma)', # 0x72 +'(ba)', # 0x73 +'(sa)', # 0x74 +'(a)', # 0x75 +'(ja)', # 0x76 +'(ca)', # 0x77 +'(ka)', # 0x78 +'(ta)', # 0x79 +'(pa)', # 0x7a +'(ha)', # 0x7b +'[?]', # 0x7c +'[?]', # 0x7d +'[?]', # 0x7e +'KIS ', # 0x7f +'(1) ', # 0x80 +'(2) ', # 0x81 +'(3) ', # 0x82 +'(4) ', # 0x83 +'(5) ', # 0x84 +'(6) ', # 0x85 +'(7) ', # 0x86 +'(8) ', # 0x87 +'(9) ', # 0x88 +'(10) ', # 0x89 +'(Yue) ', # 0x8a +'(Huo) ', # 0x8b +'(Shui) ', # 0x8c +'(Mu) ', # 0x8d +'(Jin) ', # 0x8e +'(Tu) ', # 0x8f +'(Ri) ', # 0x90 +'(Zhu) ', # 0x91 +'(You) ', # 0x92 +'(She) ', # 0x93 +'(Ming) ', # 0x94 +'(Te) ', # 0x95 +'(Cai) ', # 0x96 +'(Zhu) ', # 0x97 +'(Lao) ', # 0x98 +'(Mi) ', # 0x99 +'(Nan) ', # 0x9a +'(Nu) ', # 0x9b +'(Shi) ', # 0x9c +'(You) ', # 0x9d +'(Yin) ', # 0x9e +'(Zhu) ', # 0x9f +'(Xiang) ', # 0xa0 +'(Xiu) ', # 0xa1 +'(Xie) ', # 0xa2 +'(Zheng) ', # 0xa3 +'(Shang) ', # 0xa4 +'(Zhong) ', # 0xa5 +'(Xia) ', # 0xa6 +'(Zuo) ', # 0xa7 +'(You) ', # 0xa8 +'(Yi) ', # 0xa9 +'(Zong) ', # 0xaa +'(Xue) ', # 0xab +'(Jian) ', # 0xac +'(Qi) ', # 0xad +'(Zi) ', # 0xae +'(Xie) ', # 0xaf +'(Ye) ', # 0xb0 +'36', # 0xb1 +'37', # 0xb2 +'38', # 0xb3 +'39', # 0xb4 +'40', # 0xb5 +'41', # 0xb6 +'42', # 0xb7 +'43', # 0xb8 +'44', # 0xb9 +'45', # 0xba +'46', # 0xbb +'47', # 0xbc +'48', # 0xbd +'49', # 0xbe +'50', # 0xbf +'1M', # 0xc0 +'2M', # 0xc1 +'3M', # 0xc2 +'4M', # 0xc3 +'5M', # 0xc4 +'6M', # 0xc5 +'7M', # 0xc6 +'8M', # 0xc7 +'9M', # 0xc8 +'10M', # 0xc9 +'11M', # 0xca +'12M', # 0xcb +'[?]', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'a', # 0xd0 +'i', # 0xd1 +'u', # 0xd2 +'u', # 0xd3 +'o', # 0xd4 +'ka', # 0xd5 +'ki', # 0xd6 +'ku', # 0xd7 +'ke', # 0xd8 +'ko', # 0xd9 +'sa', # 0xda +'si', # 0xdb +'su', # 0xdc +'se', # 0xdd +'so', # 0xde +'ta', # 0xdf +'ti', # 0xe0 +'tu', # 0xe1 +'te', # 0xe2 +'to', # 0xe3 +'na', # 0xe4 +'ni', # 0xe5 +'nu', # 0xe6 +'ne', # 0xe7 +'no', # 0xe8 +'ha', # 0xe9 +'hi', # 0xea +'hu', # 0xeb +'he', # 0xec +'ho', # 0xed +'ma', # 0xee +'mi', # 0xef +'mu', # 0xf0 +'me', # 0xf1 +'mo', # 0xf2 +'ya', # 0xf3 +'yu', # 0xf4 +'yo', # 0xf5 +'ra', # 0xf6 +'ri', # 0xf7 +'ru', # 0xf8 +'re', # 0xf9 +'ro', # 0xfa +'wa', # 0xfb +'wi', # 0xfc +'we', # 0xfd +'wo', # 0xfe +) diff --git a/nstock/modules/unidecode/x033.py b/nstock/modules/unidecode/x033.py new file mode 100644 index 0000000..64eb651 --- /dev/null +++ b/nstock/modules/unidecode/x033.py @@ -0,0 +1,257 @@ +data = ( +'apartment', # 0x00 +'alpha', # 0x01 +'ampere', # 0x02 +'are', # 0x03 +'inning', # 0x04 +'inch', # 0x05 +'won', # 0x06 +'escudo', # 0x07 +'acre', # 0x08 +'ounce', # 0x09 +'ohm', # 0x0a +'kai-ri', # 0x0b +'carat', # 0x0c +'calorie', # 0x0d +'gallon', # 0x0e +'gamma', # 0x0f +'giga', # 0x10 +'guinea', # 0x11 +'curie', # 0x12 +'guilder', # 0x13 +'kilo', # 0x14 +'kilogram', # 0x15 +'kilometer', # 0x16 +'kilowatt', # 0x17 +'gram', # 0x18 +'gram ton', # 0x19 +'cruzeiro', # 0x1a +'krone', # 0x1b +'case', # 0x1c +'koruna', # 0x1d +'co-op', # 0x1e +'cycle', # 0x1f +'centime', # 0x20 +'shilling', # 0x21 +'centi', # 0x22 +'cent', # 0x23 +'dozen', # 0x24 +'desi', # 0x25 +'dollar', # 0x26 +'ton', # 0x27 +'nano', # 0x28 +'knot', # 0x29 +'heights', # 0x2a +'percent', # 0x2b +'parts', # 0x2c +'barrel', # 0x2d +'piaster', # 0x2e +'picul', # 0x2f +'pico', # 0x30 +'building', # 0x31 +'farad', # 0x32 +'feet', # 0x33 +'bushel', # 0x34 +'franc', # 0x35 +'hectare', # 0x36 +'peso', # 0x37 +'pfennig', # 0x38 +'hertz', # 0x39 +'pence', # 0x3a +'page', # 0x3b +'beta', # 0x3c +'point', # 0x3d +'volt', # 0x3e +'hon', # 0x3f +'pound', # 0x40 +'hall', # 0x41 +'horn', # 0x42 +'micro', # 0x43 +'mile', # 0x44 +'mach', # 0x45 +'mark', # 0x46 +'mansion', # 0x47 +'micron', # 0x48 +'milli', # 0x49 +'millibar', # 0x4a +'mega', # 0x4b +'megaton', # 0x4c +'meter', # 0x4d +'yard', # 0x4e +'yard', # 0x4f +'yuan', # 0x50 +'liter', # 0x51 +'lira', # 0x52 +'rupee', # 0x53 +'ruble', # 0x54 +'rem', # 0x55 +'roentgen', # 0x56 +'watt', # 0x57 +'0h', # 0x58 +'1h', # 0x59 +'2h', # 0x5a +'3h', # 0x5b +'4h', # 0x5c +'5h', # 0x5d +'6h', # 0x5e +'7h', # 0x5f +'8h', # 0x60 +'9h', # 0x61 +'10h', # 0x62 +'11h', # 0x63 +'12h', # 0x64 +'13h', # 0x65 +'14h', # 0x66 +'15h', # 0x67 +'16h', # 0x68 +'17h', # 0x69 +'18h', # 0x6a +'19h', # 0x6b +'20h', # 0x6c +'21h', # 0x6d +'22h', # 0x6e +'23h', # 0x6f +'24h', # 0x70 +'HPA', # 0x71 +'da', # 0x72 +'AU', # 0x73 +'bar', # 0x74 +'oV', # 0x75 +'pc', # 0x76 +'[?]', # 0x77 +'[?]', # 0x78 +'[?]', # 0x79 +'[?]', # 0x7a +'Heisei', # 0x7b +'Syouwa', # 0x7c +'Taisyou', # 0x7d +'Meiji', # 0x7e +'Inc.', # 0x7f +'pA', # 0x80 +'nA', # 0x81 +'microamp', # 0x82 +'mA', # 0x83 +'kA', # 0x84 +'kB', # 0x85 +'MB', # 0x86 +'GB', # 0x87 +'cal', # 0x88 +'kcal', # 0x89 +'pF', # 0x8a +'nF', # 0x8b +'microFarad', # 0x8c +'microgram', # 0x8d +'mg', # 0x8e +'kg', # 0x8f +'Hz', # 0x90 +'kHz', # 0x91 +'MHz', # 0x92 +'GHz', # 0x93 +'THz', # 0x94 +'microliter', # 0x95 +'ml', # 0x96 +'dl', # 0x97 +'kl', # 0x98 +'fm', # 0x99 +'nm', # 0x9a +'micrometer', # 0x9b +'mm', # 0x9c +'cm', # 0x9d +'km', # 0x9e +'mm^2', # 0x9f +'cm^2', # 0xa0 +'m^2', # 0xa1 +'km^2', # 0xa2 +'mm^4', # 0xa3 +'cm^3', # 0xa4 +'m^3', # 0xa5 +'km^3', # 0xa6 +'m/s', # 0xa7 +'m/s^2', # 0xa8 +'Pa', # 0xa9 +'kPa', # 0xaa +'MPa', # 0xab +'GPa', # 0xac +'rad', # 0xad +'rad/s', # 0xae +'rad/s^2', # 0xaf +'ps', # 0xb0 +'ns', # 0xb1 +'microsecond', # 0xb2 +'ms', # 0xb3 +'pV', # 0xb4 +'nV', # 0xb5 +'microvolt', # 0xb6 +'mV', # 0xb7 +'kV', # 0xb8 +'MV', # 0xb9 +'pW', # 0xba +'nW', # 0xbb +'microwatt', # 0xbc +'mW', # 0xbd +'kW', # 0xbe +'MW', # 0xbf +'kOhm', # 0xc0 +'MOhm', # 0xc1 +'a.m.', # 0xc2 +'Bq', # 0xc3 +'cc', # 0xc4 +'cd', # 0xc5 +'C/kg', # 0xc6 +'Co.', # 0xc7 +'dB', # 0xc8 +'Gy', # 0xc9 +'ha', # 0xca +'HP', # 0xcb +'in', # 0xcc +'K.K.', # 0xcd +'KM', # 0xce +'kt', # 0xcf +'lm', # 0xd0 +'ln', # 0xd1 +'log', # 0xd2 +'lx', # 0xd3 +'mb', # 0xd4 +'mil', # 0xd5 +'mol', # 0xd6 +'pH', # 0xd7 +'p.m.', # 0xd8 +'PPM', # 0xd9 +'PR', # 0xda +'sr', # 0xdb +'Sv', # 0xdc +'Wb', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'1d', # 0xe0 +'2d', # 0xe1 +'3d', # 0xe2 +'4d', # 0xe3 +'5d', # 0xe4 +'6d', # 0xe5 +'7d', # 0xe6 +'8d', # 0xe7 +'9d', # 0xe8 +'10d', # 0xe9 +'11d', # 0xea +'12d', # 0xeb +'13d', # 0xec +'14d', # 0xed +'15d', # 0xee +'16d', # 0xef +'17d', # 0xf0 +'18d', # 0xf1 +'19d', # 0xf2 +'20d', # 0xf3 +'21d', # 0xf4 +'22d', # 0xf5 +'23d', # 0xf6 +'24d', # 0xf7 +'25d', # 0xf8 +'26d', # 0xf9 +'27d', # 0xfa +'28d', # 0xfb +'29d', # 0xfc +'30d', # 0xfd +'31d', # 0xfe +) diff --git a/nstock/modules/unidecode/x04d.py b/nstock/modules/unidecode/x04d.py new file mode 100644 index 0000000..b025461 --- /dev/null +++ b/nstock/modules/unidecode/x04d.py @@ -0,0 +1,257 @@ +data = ( +'[?] ', # 0x00 +'[?] ', # 0x01 +'[?] ', # 0x02 +'[?] ', # 0x03 +'[?] ', # 0x04 +'[?] ', # 0x05 +'[?] ', # 0x06 +'[?] ', # 0x07 +'[?] ', # 0x08 +'[?] ', # 0x09 +'[?] ', # 0x0a +'[?] ', # 0x0b +'[?] ', # 0x0c +'[?] ', # 0x0d +'[?] ', # 0x0e +'[?] ', # 0x0f +'[?] ', # 0x10 +'[?] ', # 0x11 +'[?] ', # 0x12 +'[?] ', # 0x13 +'[?] ', # 0x14 +'[?] ', # 0x15 +'[?] ', # 0x16 +'[?] ', # 0x17 +'[?] ', # 0x18 +'[?] ', # 0x19 +'[?] ', # 0x1a +'[?] ', # 0x1b +'[?] ', # 0x1c +'[?] ', # 0x1d +'[?] ', # 0x1e +'[?] ', # 0x1f +'[?] ', # 0x20 +'[?] ', # 0x21 +'[?] ', # 0x22 +'[?] ', # 0x23 +'[?] ', # 0x24 +'[?] ', # 0x25 +'[?] ', # 0x26 +'[?] ', # 0x27 +'[?] ', # 0x28 +'[?] ', # 0x29 +'[?] ', # 0x2a +'[?] ', # 0x2b +'[?] ', # 0x2c +'[?] ', # 0x2d +'[?] ', # 0x2e +'[?] ', # 0x2f +'[?] ', # 0x30 +'[?] ', # 0x31 +'[?] ', # 0x32 +'[?] ', # 0x33 +'[?] ', # 0x34 +'[?] ', # 0x35 +'[?] ', # 0x36 +'[?] ', # 0x37 +'[?] ', # 0x38 +'[?] ', # 0x39 +'[?] ', # 0x3a +'[?] ', # 0x3b +'[?] ', # 0x3c +'[?] ', # 0x3d +'[?] ', # 0x3e +'[?] ', # 0x3f +'[?] ', # 0x40 +'[?] ', # 0x41 +'[?] ', # 0x42 +'[?] ', # 0x43 +'[?] ', # 0x44 +'[?] ', # 0x45 +'[?] ', # 0x46 +'[?] ', # 0x47 +'[?] ', # 0x48 +'[?] ', # 0x49 +'[?] ', # 0x4a +'[?] ', # 0x4b +'[?] ', # 0x4c +'[?] ', # 0x4d +'[?] ', # 0x4e +'[?] ', # 0x4f +'[?] ', # 0x50 +'[?] ', # 0x51 +'[?] ', # 0x52 +'[?] ', # 0x53 +'[?] ', # 0x54 +'[?] ', # 0x55 +'[?] ', # 0x56 +'[?] ', # 0x57 +'[?] ', # 0x58 +'[?] ', # 0x59 +'[?] ', # 0x5a +'[?] ', # 0x5b +'[?] ', # 0x5c +'[?] ', # 0x5d +'[?] ', # 0x5e +'[?] ', # 0x5f +'[?] ', # 0x60 +'[?] ', # 0x61 +'[?] ', # 0x62 +'[?] ', # 0x63 +'[?] ', # 0x64 +'[?] ', # 0x65 +'[?] ', # 0x66 +'[?] ', # 0x67 +'[?] ', # 0x68 +'[?] ', # 0x69 +'[?] ', # 0x6a +'[?] ', # 0x6b +'[?] ', # 0x6c +'[?] ', # 0x6d +'[?] ', # 0x6e +'[?] ', # 0x6f +'[?] ', # 0x70 +'[?] ', # 0x71 +'[?] ', # 0x72 +'[?] ', # 0x73 +'[?] ', # 0x74 +'[?] ', # 0x75 +'[?] ', # 0x76 +'[?] ', # 0x77 +'[?] ', # 0x78 +'[?] ', # 0x79 +'[?] ', # 0x7a +'[?] ', # 0x7b +'[?] ', # 0x7c +'[?] ', # 0x7d +'[?] ', # 0x7e +'[?] ', # 0x7f +'[?] ', # 0x80 +'[?] ', # 0x81 +'[?] ', # 0x82 +'[?] ', # 0x83 +'[?] ', # 0x84 +'[?] ', # 0x85 +'[?] ', # 0x86 +'[?] ', # 0x87 +'[?] ', # 0x88 +'[?] ', # 0x89 +'[?] ', # 0x8a +'[?] ', # 0x8b +'[?] ', # 0x8c +'[?] ', # 0x8d +'[?] ', # 0x8e +'[?] ', # 0x8f +'[?] ', # 0x90 +'[?] ', # 0x91 +'[?] ', # 0x92 +'[?] ', # 0x93 +'[?] ', # 0x94 +'[?] ', # 0x95 +'[?] ', # 0x96 +'[?] ', # 0x97 +'[?] ', # 0x98 +'[?] ', # 0x99 +'[?] ', # 0x9a +'[?] ', # 0x9b +'[?] ', # 0x9c +'[?] ', # 0x9d +'[?] ', # 0x9e +'[?] ', # 0x9f +'[?] ', # 0xa0 +'[?] ', # 0xa1 +'[?] ', # 0xa2 +'[?] ', # 0xa3 +'[?] ', # 0xa4 +'[?] ', # 0xa5 +'[?] ', # 0xa6 +'[?] ', # 0xa7 +'[?] ', # 0xa8 +'[?] ', # 0xa9 +'[?] ', # 0xaa +'[?] ', # 0xab +'[?] ', # 0xac +'[?] ', # 0xad +'[?] ', # 0xae +'[?] ', # 0xaf +'[?] ', # 0xb0 +'[?] ', # 0xb1 +'[?] ', # 0xb2 +'[?] ', # 0xb3 +'[?] ', # 0xb4 +'[?] ', # 0xb5 +'[?]', # 0xb6 +'[?]', # 0xb7 +'[?]', # 0xb8 +'[?]', # 0xb9 +'[?]', # 0xba +'[?]', # 0xbb +'[?]', # 0xbc +'[?]', # 0xbd +'[?]', # 0xbe +'[?]', # 0xbf +'[?]', # 0xc0 +'[?]', # 0xc1 +'[?]', # 0xc2 +'[?]', # 0xc3 +'[?]', # 0xc4 +'[?]', # 0xc5 +'[?]', # 0xc6 +'[?]', # 0xc7 +'[?]', # 0xc8 +'[?]', # 0xc9 +'[?]', # 0xca +'[?]', # 0xcb +'[?]', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'[?]', # 0xd0 +'[?]', # 0xd1 +'[?]', # 0xd2 +'[?]', # 0xd3 +'[?]', # 0xd4 +'[?]', # 0xd5 +'[?]', # 0xd6 +'[?]', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'[?]', # 0xdc +'[?]', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'[?]', # 0xe0 +'[?]', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'[?]', # 0xe6 +'[?]', # 0xe7 +'[?]', # 0xe8 +'[?]', # 0xe9 +'[?]', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x04e.py b/nstock/modules/unidecode/x04e.py new file mode 100644 index 0000000..b472b85 --- /dev/null +++ b/nstock/modules/unidecode/x04e.py @@ -0,0 +1,258 @@ +data = ( +'Yi ', # 0x00 +'Ding ', # 0x01 +'Kao ', # 0x02 +'Qi ', # 0x03 +'Shang ', # 0x04 +'Xia ', # 0x05 +'[?] ', # 0x06 +'Mo ', # 0x07 +'Zhang ', # 0x08 +'San ', # 0x09 +'Shang ', # 0x0a +'Xia ', # 0x0b +'Ji ', # 0x0c +'Bu ', # 0x0d +'Yu ', # 0x0e +'Mian ', # 0x0f +'Gai ', # 0x10 +'Chou ', # 0x11 +'Chou ', # 0x12 +'Zhuan ', # 0x13 +'Qie ', # 0x14 +'Pi ', # 0x15 +'Shi ', # 0x16 +'Shi ', # 0x17 +'Qiu ', # 0x18 +'Bing ', # 0x19 +'Ye ', # 0x1a +'Cong ', # 0x1b +'Dong ', # 0x1c +'Si ', # 0x1d +'Cheng ', # 0x1e +'Diu ', # 0x1f +'Qiu ', # 0x20 +'Liang ', # 0x21 +'Diu ', # 0x22 +'You ', # 0x23 +'Liang ', # 0x24 +'Yan ', # 0x25 +'Bing ', # 0x26 +'Sang ', # 0x27 +'Gun ', # 0x28 +'Jiu ', # 0x29 +'Ge ', # 0x2a +'Ya ', # 0x2b +'Qiang ', # 0x2c +'Zhong ', # 0x2d +'Ji ', # 0x2e +'Jie ', # 0x2f +'Feng ', # 0x30 +'Guan ', # 0x31 +'Chuan ', # 0x32 +'Chan ', # 0x33 +'Lin ', # 0x34 +'Zhuo ', # 0x35 +'Zhu ', # 0x36 +'Ha ', # 0x37 +'Wan ', # 0x38 +'Dan ', # 0x39 +'Wei ', # 0x3a +'Zhu ', # 0x3b +'Jing ', # 0x3c +'Li ', # 0x3d +'Ju ', # 0x3e +'Pie ', # 0x3f +'Fu ', # 0x40 +'Yi ', # 0x41 +'Yi ', # 0x42 +'Nai ', # 0x43 +'Shime ', # 0x44 +'Jiu ', # 0x45 +'Jiu ', # 0x46 +'Zhe ', # 0x47 +'Yao ', # 0x48 +'Yi ', # 0x49 +'[?] ', # 0x4a +'Zhi ', # 0x4b +'Wu ', # 0x4c +'Zha ', # 0x4d +'Hu ', # 0x4e +'Fa ', # 0x4f +'Le ', # 0x50 +'Zhong ', # 0x51 +'Ping ', # 0x52 +'Pang ', # 0x53 +'Qiao ', # 0x54 +'Hu ', # 0x55 +'Guai ', # 0x56 +'Cheng ', # 0x57 +'Cheng ', # 0x58 +'Yi ', # 0x59 +'Yin ', # 0x5a +'[?] ', # 0x5b +'Mie ', # 0x5c +'Jiu ', # 0x5d +'Qi ', # 0x5e +'Ye ', # 0x5f +'Xi ', # 0x60 +'Xiang ', # 0x61 +'Gai ', # 0x62 +'Diu ', # 0x63 +'Hal ', # 0x64 +'[?] ', # 0x65 +'Shu ', # 0x66 +'Twul ', # 0x67 +'Shi ', # 0x68 +'Ji ', # 0x69 +'Nang ', # 0x6a +'Jia ', # 0x6b +'Kel ', # 0x6c +'Shi ', # 0x6d +'[?] ', # 0x6e +'Ol ', # 0x6f +'Mai ', # 0x70 +'Luan ', # 0x71 +'Cal ', # 0x72 +'Ru ', # 0x73 +'Xue ', # 0x74 +'Yan ', # 0x75 +'Fu ', # 0x76 +'Sha ', # 0x77 +'Na ', # 0x78 +'Gan ', # 0x79 +'Sol ', # 0x7a +'El ', # 0x7b +'Cwul ', # 0x7c +'[?] ', # 0x7d +'Gan ', # 0x7e +'Chi ', # 0x7f +'Gui ', # 0x80 +'Gan ', # 0x81 +'Luan ', # 0x82 +'Lin ', # 0x83 +'Yi ', # 0x84 +'Jue ', # 0x85 +'Liao ', # 0x86 +'Ma ', # 0x87 +'Yu ', # 0x88 +'Zheng ', # 0x89 +'Shi ', # 0x8a +'Shi ', # 0x8b +'Er ', # 0x8c +'Chu ', # 0x8d +'Yu ', # 0x8e +'Yu ', # 0x8f +'Yu ', # 0x90 +'Yun ', # 0x91 +'Hu ', # 0x92 +'Qi ', # 0x93 +'Wu ', # 0x94 +'Jing ', # 0x95 +'Si ', # 0x96 +'Sui ', # 0x97 +'Gen ', # 0x98 +'Gen ', # 0x99 +'Ya ', # 0x9a +'Xie ', # 0x9b +'Ya ', # 0x9c +'Qi ', # 0x9d +'Ya ', # 0x9e +'Ji ', # 0x9f +'Tou ', # 0xa0 +'Wang ', # 0xa1 +'Kang ', # 0xa2 +'Ta ', # 0xa3 +'Jiao ', # 0xa4 +'Hai ', # 0xa5 +'Yi ', # 0xa6 +'Chan ', # 0xa7 +'Heng ', # 0xa8 +'Mu ', # 0xa9 +'[?] ', # 0xaa +'Xiang ', # 0xab +'Jing ', # 0xac +'Ting ', # 0xad +'Liang ', # 0xae +'Xiang ', # 0xaf +'Jing ', # 0xb0 +'Ye ', # 0xb1 +'Qin ', # 0xb2 +'Bo ', # 0xb3 +'You ', # 0xb4 +'Xie ', # 0xb5 +'Dan ', # 0xb6 +'Lian ', # 0xb7 +'Duo ', # 0xb8 +'Wei ', # 0xb9 +'Ren ', # 0xba +'Ren ', # 0xbb +'Ji ', # 0xbc +'La ', # 0xbd +'Wang ', # 0xbe +'Yi ', # 0xbf +'Shi ', # 0xc0 +'Ren ', # 0xc1 +'Le ', # 0xc2 +'Ding ', # 0xc3 +'Ze ', # 0xc4 +'Jin ', # 0xc5 +'Pu ', # 0xc6 +'Chou ', # 0xc7 +'Ba ', # 0xc8 +'Zhang ', # 0xc9 +'Jin ', # 0xca +'Jie ', # 0xcb +'Bing ', # 0xcc +'Reng ', # 0xcd +'Cong ', # 0xce +'Fo ', # 0xcf +'San ', # 0xd0 +'Lun ', # 0xd1 +'Sya ', # 0xd2 +'Cang ', # 0xd3 +'Zi ', # 0xd4 +'Shi ', # 0xd5 +'Ta ', # 0xd6 +'Zhang ', # 0xd7 +'Fu ', # 0xd8 +'Xian ', # 0xd9 +'Xian ', # 0xda +'Tuo ', # 0xdb +'Hong ', # 0xdc +'Tong ', # 0xdd +'Ren ', # 0xde +'Qian ', # 0xdf +'Gan ', # 0xe0 +'Yi ', # 0xe1 +'Di ', # 0xe2 +'Dai ', # 0xe3 +'Ling ', # 0xe4 +'Yi ', # 0xe5 +'Chao ', # 0xe6 +'Chang ', # 0xe7 +'Sa ', # 0xe8 +'[?] ', # 0xe9 +'Yi ', # 0xea +'Mu ', # 0xeb +'Men ', # 0xec +'Ren ', # 0xed +'Jia ', # 0xee +'Chao ', # 0xef +'Yang ', # 0xf0 +'Qian ', # 0xf1 +'Zhong ', # 0xf2 +'Pi ', # 0xf3 +'Wan ', # 0xf4 +'Wu ', # 0xf5 +'Jian ', # 0xf6 +'Jie ', # 0xf7 +'Yao ', # 0xf8 +'Feng ', # 0xf9 +'Cang ', # 0xfa +'Ren ', # 0xfb +'Wang ', # 0xfc +'Fen ', # 0xfd +'Di ', # 0xfe +'Fang ', # 0xff +) diff --git a/nstock/modules/unidecode/x04f.py b/nstock/modules/unidecode/x04f.py new file mode 100644 index 0000000..98c2291 --- /dev/null +++ b/nstock/modules/unidecode/x04f.py @@ -0,0 +1,258 @@ +data = ( +'Zhong ', # 0x00 +'Qi ', # 0x01 +'Pei ', # 0x02 +'Yu ', # 0x03 +'Diao ', # 0x04 +'Dun ', # 0x05 +'Wen ', # 0x06 +'Yi ', # 0x07 +'Xin ', # 0x08 +'Kang ', # 0x09 +'Yi ', # 0x0a +'Ji ', # 0x0b +'Ai ', # 0x0c +'Wu ', # 0x0d +'Ji ', # 0x0e +'Fu ', # 0x0f +'Fa ', # 0x10 +'Xiu ', # 0x11 +'Jin ', # 0x12 +'Bei ', # 0x13 +'Dan ', # 0x14 +'Fu ', # 0x15 +'Tang ', # 0x16 +'Zhong ', # 0x17 +'You ', # 0x18 +'Huo ', # 0x19 +'Hui ', # 0x1a +'Yu ', # 0x1b +'Cui ', # 0x1c +'Chuan ', # 0x1d +'San ', # 0x1e +'Wei ', # 0x1f +'Chuan ', # 0x20 +'Che ', # 0x21 +'Ya ', # 0x22 +'Xian ', # 0x23 +'Shang ', # 0x24 +'Chang ', # 0x25 +'Lun ', # 0x26 +'Cang ', # 0x27 +'Xun ', # 0x28 +'Xin ', # 0x29 +'Wei ', # 0x2a +'Zhu ', # 0x2b +'[?] ', # 0x2c +'Xuan ', # 0x2d +'Nu ', # 0x2e +'Bo ', # 0x2f +'Gu ', # 0x30 +'Ni ', # 0x31 +'Ni ', # 0x32 +'Xie ', # 0x33 +'Ban ', # 0x34 +'Xu ', # 0x35 +'Ling ', # 0x36 +'Zhou ', # 0x37 +'Shen ', # 0x38 +'Qu ', # 0x39 +'Si ', # 0x3a +'Beng ', # 0x3b +'Si ', # 0x3c +'Jia ', # 0x3d +'Pi ', # 0x3e +'Yi ', # 0x3f +'Si ', # 0x40 +'Ai ', # 0x41 +'Zheng ', # 0x42 +'Dian ', # 0x43 +'Han ', # 0x44 +'Mai ', # 0x45 +'Dan ', # 0x46 +'Zhu ', # 0x47 +'Bu ', # 0x48 +'Qu ', # 0x49 +'Bi ', # 0x4a +'Shao ', # 0x4b +'Ci ', # 0x4c +'Wei ', # 0x4d +'Di ', # 0x4e +'Zhu ', # 0x4f +'Zuo ', # 0x50 +'You ', # 0x51 +'Yang ', # 0x52 +'Ti ', # 0x53 +'Zhan ', # 0x54 +'He ', # 0x55 +'Bi ', # 0x56 +'Tuo ', # 0x57 +'She ', # 0x58 +'Yu ', # 0x59 +'Yi ', # 0x5a +'Fo ', # 0x5b +'Zuo ', # 0x5c +'Kou ', # 0x5d +'Ning ', # 0x5e +'Tong ', # 0x5f +'Ni ', # 0x60 +'Xuan ', # 0x61 +'Qu ', # 0x62 +'Yong ', # 0x63 +'Wa ', # 0x64 +'Qian ', # 0x65 +'[?] ', # 0x66 +'Ka ', # 0x67 +'[?] ', # 0x68 +'Pei ', # 0x69 +'Huai ', # 0x6a +'He ', # 0x6b +'Lao ', # 0x6c +'Xiang ', # 0x6d +'Ge ', # 0x6e +'Yang ', # 0x6f +'Bai ', # 0x70 +'Fa ', # 0x71 +'Ming ', # 0x72 +'Jia ', # 0x73 +'Er ', # 0x74 +'Bing ', # 0x75 +'Ji ', # 0x76 +'Hen ', # 0x77 +'Huo ', # 0x78 +'Gui ', # 0x79 +'Quan ', # 0x7a +'Tiao ', # 0x7b +'Jiao ', # 0x7c +'Ci ', # 0x7d +'Yi ', # 0x7e +'Shi ', # 0x7f +'Xing ', # 0x80 +'Shen ', # 0x81 +'Tuo ', # 0x82 +'Kan ', # 0x83 +'Zhi ', # 0x84 +'Gai ', # 0x85 +'Lai ', # 0x86 +'Yi ', # 0x87 +'Chi ', # 0x88 +'Kua ', # 0x89 +'Guang ', # 0x8a +'Li ', # 0x8b +'Yin ', # 0x8c +'Shi ', # 0x8d +'Mi ', # 0x8e +'Zhu ', # 0x8f +'Xu ', # 0x90 +'You ', # 0x91 +'An ', # 0x92 +'Lu ', # 0x93 +'Mou ', # 0x94 +'Er ', # 0x95 +'Lun ', # 0x96 +'Tong ', # 0x97 +'Cha ', # 0x98 +'Chi ', # 0x99 +'Xun ', # 0x9a +'Gong ', # 0x9b +'Zhou ', # 0x9c +'Yi ', # 0x9d +'Ru ', # 0x9e +'Jian ', # 0x9f +'Xia ', # 0xa0 +'Jia ', # 0xa1 +'Zai ', # 0xa2 +'Lu ', # 0xa3 +'Ko ', # 0xa4 +'Jiao ', # 0xa5 +'Zhen ', # 0xa6 +'Ce ', # 0xa7 +'Qiao ', # 0xa8 +'Kuai ', # 0xa9 +'Chai ', # 0xaa +'Ning ', # 0xab +'Nong ', # 0xac +'Jin ', # 0xad +'Wu ', # 0xae +'Hou ', # 0xaf +'Jiong ', # 0xb0 +'Cheng ', # 0xb1 +'Zhen ', # 0xb2 +'Zuo ', # 0xb3 +'Chou ', # 0xb4 +'Qin ', # 0xb5 +'Lu ', # 0xb6 +'Ju ', # 0xb7 +'Shu ', # 0xb8 +'Ting ', # 0xb9 +'Shen ', # 0xba +'Tuo ', # 0xbb +'Bo ', # 0xbc +'Nan ', # 0xbd +'Hao ', # 0xbe +'Bian ', # 0xbf +'Tui ', # 0xc0 +'Yu ', # 0xc1 +'Xi ', # 0xc2 +'Cu ', # 0xc3 +'E ', # 0xc4 +'Qiu ', # 0xc5 +'Xu ', # 0xc6 +'Kuang ', # 0xc7 +'Ku ', # 0xc8 +'Wu ', # 0xc9 +'Jun ', # 0xca +'Yi ', # 0xcb +'Fu ', # 0xcc +'Lang ', # 0xcd +'Zu ', # 0xce +'Qiao ', # 0xcf +'Li ', # 0xd0 +'Yong ', # 0xd1 +'Hun ', # 0xd2 +'Jing ', # 0xd3 +'Xian ', # 0xd4 +'San ', # 0xd5 +'Pai ', # 0xd6 +'Su ', # 0xd7 +'Fu ', # 0xd8 +'Xi ', # 0xd9 +'Li ', # 0xda +'Fu ', # 0xdb +'Ping ', # 0xdc +'Bao ', # 0xdd +'Yu ', # 0xde +'Si ', # 0xdf +'Xia ', # 0xe0 +'Xin ', # 0xe1 +'Xiu ', # 0xe2 +'Yu ', # 0xe3 +'Ti ', # 0xe4 +'Che ', # 0xe5 +'Chou ', # 0xe6 +'[?] ', # 0xe7 +'Yan ', # 0xe8 +'Lia ', # 0xe9 +'Li ', # 0xea +'Lai ', # 0xeb +'[?] ', # 0xec +'Jian ', # 0xed +'Xiu ', # 0xee +'Fu ', # 0xef +'He ', # 0xf0 +'Ju ', # 0xf1 +'Xiao ', # 0xf2 +'Pai ', # 0xf3 +'Jian ', # 0xf4 +'Biao ', # 0xf5 +'Chu ', # 0xf6 +'Fei ', # 0xf7 +'Feng ', # 0xf8 +'Ya ', # 0xf9 +'An ', # 0xfa +'Bei ', # 0xfb +'Yu ', # 0xfc +'Xin ', # 0xfd +'Bi ', # 0xfe +'Jian ', # 0xff +) diff --git a/nstock/modules/unidecode/x050.py b/nstock/modules/unidecode/x050.py new file mode 100644 index 0000000..184b87f --- /dev/null +++ b/nstock/modules/unidecode/x050.py @@ -0,0 +1,258 @@ +data = ( +'Chang ', # 0x00 +'Chi ', # 0x01 +'Bing ', # 0x02 +'Zan ', # 0x03 +'Yao ', # 0x04 +'Cui ', # 0x05 +'Lia ', # 0x06 +'Wan ', # 0x07 +'Lai ', # 0x08 +'Cang ', # 0x09 +'Zong ', # 0x0a +'Ge ', # 0x0b +'Guan ', # 0x0c +'Bei ', # 0x0d +'Tian ', # 0x0e +'Shu ', # 0x0f +'Shu ', # 0x10 +'Men ', # 0x11 +'Dao ', # 0x12 +'Tan ', # 0x13 +'Jue ', # 0x14 +'Chui ', # 0x15 +'Xing ', # 0x16 +'Peng ', # 0x17 +'Tang ', # 0x18 +'Hou ', # 0x19 +'Yi ', # 0x1a +'Qi ', # 0x1b +'Ti ', # 0x1c +'Gan ', # 0x1d +'Jing ', # 0x1e +'Jie ', # 0x1f +'Sui ', # 0x20 +'Chang ', # 0x21 +'Jie ', # 0x22 +'Fang ', # 0x23 +'Zhi ', # 0x24 +'Kong ', # 0x25 +'Juan ', # 0x26 +'Zong ', # 0x27 +'Ju ', # 0x28 +'Qian ', # 0x29 +'Ni ', # 0x2a +'Lun ', # 0x2b +'Zhuo ', # 0x2c +'Wei ', # 0x2d +'Luo ', # 0x2e +'Song ', # 0x2f +'Leng ', # 0x30 +'Hun ', # 0x31 +'Dong ', # 0x32 +'Zi ', # 0x33 +'Ben ', # 0x34 +'Wu ', # 0x35 +'Ju ', # 0x36 +'Nai ', # 0x37 +'Cai ', # 0x38 +'Jian ', # 0x39 +'Zhai ', # 0x3a +'Ye ', # 0x3b +'Zhi ', # 0x3c +'Sha ', # 0x3d +'Qing ', # 0x3e +'[?] ', # 0x3f +'Ying ', # 0x40 +'Cheng ', # 0x41 +'Jian ', # 0x42 +'Yan ', # 0x43 +'Nuan ', # 0x44 +'Zhong ', # 0x45 +'Chun ', # 0x46 +'Jia ', # 0x47 +'Jie ', # 0x48 +'Wei ', # 0x49 +'Yu ', # 0x4a +'Bing ', # 0x4b +'Ruo ', # 0x4c +'Ti ', # 0x4d +'Wei ', # 0x4e +'Pian ', # 0x4f +'Yan ', # 0x50 +'Feng ', # 0x51 +'Tang ', # 0x52 +'Wo ', # 0x53 +'E ', # 0x54 +'Xie ', # 0x55 +'Che ', # 0x56 +'Sheng ', # 0x57 +'Kan ', # 0x58 +'Di ', # 0x59 +'Zuo ', # 0x5a +'Cha ', # 0x5b +'Ting ', # 0x5c +'Bei ', # 0x5d +'Ye ', # 0x5e +'Huang ', # 0x5f +'Yao ', # 0x60 +'Zhan ', # 0x61 +'Chou ', # 0x62 +'Yan ', # 0x63 +'You ', # 0x64 +'Jian ', # 0x65 +'Xu ', # 0x66 +'Zha ', # 0x67 +'Ci ', # 0x68 +'Fu ', # 0x69 +'Bi ', # 0x6a +'Zhi ', # 0x6b +'Zong ', # 0x6c +'Mian ', # 0x6d +'Ji ', # 0x6e +'Yi ', # 0x6f +'Xie ', # 0x70 +'Xun ', # 0x71 +'Si ', # 0x72 +'Duan ', # 0x73 +'Ce ', # 0x74 +'Zhen ', # 0x75 +'Ou ', # 0x76 +'Tou ', # 0x77 +'Tou ', # 0x78 +'Bei ', # 0x79 +'Za ', # 0x7a +'Lu ', # 0x7b +'Jie ', # 0x7c +'Wei ', # 0x7d +'Fen ', # 0x7e +'Chang ', # 0x7f +'Gui ', # 0x80 +'Sou ', # 0x81 +'Zhi ', # 0x82 +'Su ', # 0x83 +'Xia ', # 0x84 +'Fu ', # 0x85 +'Yuan ', # 0x86 +'Rong ', # 0x87 +'Li ', # 0x88 +'Ru ', # 0x89 +'Yun ', # 0x8a +'Gou ', # 0x8b +'Ma ', # 0x8c +'Bang ', # 0x8d +'Dian ', # 0x8e +'Tang ', # 0x8f +'Hao ', # 0x90 +'Jie ', # 0x91 +'Xi ', # 0x92 +'Shan ', # 0x93 +'Qian ', # 0x94 +'Jue ', # 0x95 +'Cang ', # 0x96 +'Chu ', # 0x97 +'San ', # 0x98 +'Bei ', # 0x99 +'Xiao ', # 0x9a +'Yong ', # 0x9b +'Yao ', # 0x9c +'Tan ', # 0x9d +'Suo ', # 0x9e +'Yang ', # 0x9f +'Fa ', # 0xa0 +'Bing ', # 0xa1 +'Jia ', # 0xa2 +'Dai ', # 0xa3 +'Zai ', # 0xa4 +'Tang ', # 0xa5 +'[?] ', # 0xa6 +'Bin ', # 0xa7 +'Chu ', # 0xa8 +'Nuo ', # 0xa9 +'Can ', # 0xaa +'Lei ', # 0xab +'Cui ', # 0xac +'Yong ', # 0xad +'Zao ', # 0xae +'Zong ', # 0xaf +'Peng ', # 0xb0 +'Song ', # 0xb1 +'Ao ', # 0xb2 +'Chuan ', # 0xb3 +'Yu ', # 0xb4 +'Zhai ', # 0xb5 +'Cou ', # 0xb6 +'Shang ', # 0xb7 +'Qiang ', # 0xb8 +'Jing ', # 0xb9 +'Chi ', # 0xba +'Sha ', # 0xbb +'Han ', # 0xbc +'Zhang ', # 0xbd +'Qing ', # 0xbe +'Yan ', # 0xbf +'Di ', # 0xc0 +'Xi ', # 0xc1 +'Lu ', # 0xc2 +'Bei ', # 0xc3 +'Piao ', # 0xc4 +'Jin ', # 0xc5 +'Lian ', # 0xc6 +'Lu ', # 0xc7 +'Man ', # 0xc8 +'Qian ', # 0xc9 +'Xian ', # 0xca +'Tan ', # 0xcb +'Ying ', # 0xcc +'Dong ', # 0xcd +'Zhuan ', # 0xce +'Xiang ', # 0xcf +'Shan ', # 0xd0 +'Qiao ', # 0xd1 +'Jiong ', # 0xd2 +'Tui ', # 0xd3 +'Zun ', # 0xd4 +'Pu ', # 0xd5 +'Xi ', # 0xd6 +'Lao ', # 0xd7 +'Chang ', # 0xd8 +'Guang ', # 0xd9 +'Liao ', # 0xda +'Qi ', # 0xdb +'Deng ', # 0xdc +'Chan ', # 0xdd +'Wei ', # 0xde +'Ji ', # 0xdf +'Fan ', # 0xe0 +'Hui ', # 0xe1 +'Chuan ', # 0xe2 +'Jian ', # 0xe3 +'Dan ', # 0xe4 +'Jiao ', # 0xe5 +'Jiu ', # 0xe6 +'Seng ', # 0xe7 +'Fen ', # 0xe8 +'Xian ', # 0xe9 +'Jue ', # 0xea +'E ', # 0xeb +'Jiao ', # 0xec +'Jian ', # 0xed +'Tong ', # 0xee +'Lin ', # 0xef +'Bo ', # 0xf0 +'Gu ', # 0xf1 +'[?] ', # 0xf2 +'Su ', # 0xf3 +'Xian ', # 0xf4 +'Jiang ', # 0xf5 +'Min ', # 0xf6 +'Ye ', # 0xf7 +'Jin ', # 0xf8 +'Jia ', # 0xf9 +'Qiao ', # 0xfa +'Pi ', # 0xfb +'Feng ', # 0xfc +'Zhou ', # 0xfd +'Ai ', # 0xfe +'Sai ', # 0xff +) diff --git a/nstock/modules/unidecode/x051.py b/nstock/modules/unidecode/x051.py new file mode 100644 index 0000000..c192835 --- /dev/null +++ b/nstock/modules/unidecode/x051.py @@ -0,0 +1,258 @@ +data = ( +'Yi ', # 0x00 +'Jun ', # 0x01 +'Nong ', # 0x02 +'Chan ', # 0x03 +'Yi ', # 0x04 +'Dang ', # 0x05 +'Jing ', # 0x06 +'Xuan ', # 0x07 +'Kuai ', # 0x08 +'Jian ', # 0x09 +'Chu ', # 0x0a +'Dan ', # 0x0b +'Jiao ', # 0x0c +'Sha ', # 0x0d +'Zai ', # 0x0e +'[?] ', # 0x0f +'Bin ', # 0x10 +'An ', # 0x11 +'Ru ', # 0x12 +'Tai ', # 0x13 +'Chou ', # 0x14 +'Chai ', # 0x15 +'Lan ', # 0x16 +'Ni ', # 0x17 +'Jin ', # 0x18 +'Qian ', # 0x19 +'Meng ', # 0x1a +'Wu ', # 0x1b +'Ning ', # 0x1c +'Qiong ', # 0x1d +'Ni ', # 0x1e +'Chang ', # 0x1f +'Lie ', # 0x20 +'Lei ', # 0x21 +'Lu ', # 0x22 +'Kuang ', # 0x23 +'Bao ', # 0x24 +'Du ', # 0x25 +'Biao ', # 0x26 +'Zan ', # 0x27 +'Zhi ', # 0x28 +'Si ', # 0x29 +'You ', # 0x2a +'Hao ', # 0x2b +'Chen ', # 0x2c +'Chen ', # 0x2d +'Li ', # 0x2e +'Teng ', # 0x2f +'Wei ', # 0x30 +'Long ', # 0x31 +'Chu ', # 0x32 +'Chan ', # 0x33 +'Rang ', # 0x34 +'Shu ', # 0x35 +'Hui ', # 0x36 +'Li ', # 0x37 +'Luo ', # 0x38 +'Zan ', # 0x39 +'Nuo ', # 0x3a +'Tang ', # 0x3b +'Yan ', # 0x3c +'Lei ', # 0x3d +'Nang ', # 0x3e +'Er ', # 0x3f +'Wu ', # 0x40 +'Yun ', # 0x41 +'Zan ', # 0x42 +'Yuan ', # 0x43 +'Xiong ', # 0x44 +'Chong ', # 0x45 +'Zhao ', # 0x46 +'Xiong ', # 0x47 +'Xian ', # 0x48 +'Guang ', # 0x49 +'Dui ', # 0x4a +'Ke ', # 0x4b +'Dui ', # 0x4c +'Mian ', # 0x4d +'Tu ', # 0x4e +'Chang ', # 0x4f +'Er ', # 0x50 +'Dui ', # 0x51 +'Er ', # 0x52 +'Xin ', # 0x53 +'Tu ', # 0x54 +'Si ', # 0x55 +'Yan ', # 0x56 +'Yan ', # 0x57 +'Shi ', # 0x58 +'Shi ', # 0x59 +'Dang ', # 0x5a +'Qian ', # 0x5b +'Dou ', # 0x5c +'Fen ', # 0x5d +'Mao ', # 0x5e +'Shen ', # 0x5f +'Dou ', # 0x60 +'Bai ', # 0x61 +'Jing ', # 0x62 +'Li ', # 0x63 +'Huang ', # 0x64 +'Ru ', # 0x65 +'Wang ', # 0x66 +'Nei ', # 0x67 +'Quan ', # 0x68 +'Liang ', # 0x69 +'Yu ', # 0x6a +'Ba ', # 0x6b +'Gong ', # 0x6c +'Liu ', # 0x6d +'Xi ', # 0x6e +'[?] ', # 0x6f +'Lan ', # 0x70 +'Gong ', # 0x71 +'Tian ', # 0x72 +'Guan ', # 0x73 +'Xing ', # 0x74 +'Bing ', # 0x75 +'Qi ', # 0x76 +'Ju ', # 0x77 +'Dian ', # 0x78 +'Zi ', # 0x79 +'Ppwun ', # 0x7a +'Yang ', # 0x7b +'Jian ', # 0x7c +'Shou ', # 0x7d +'Ji ', # 0x7e +'Yi ', # 0x7f +'Ji ', # 0x80 +'Chan ', # 0x81 +'Jiong ', # 0x82 +'Mao ', # 0x83 +'Ran ', # 0x84 +'Nei ', # 0x85 +'Yuan ', # 0x86 +'Mao ', # 0x87 +'Gang ', # 0x88 +'Ran ', # 0x89 +'Ce ', # 0x8a +'Jiong ', # 0x8b +'Ce ', # 0x8c +'Zai ', # 0x8d +'Gua ', # 0x8e +'Jiong ', # 0x8f +'Mao ', # 0x90 +'Zhou ', # 0x91 +'Mou ', # 0x92 +'Gou ', # 0x93 +'Xu ', # 0x94 +'Mian ', # 0x95 +'Mi ', # 0x96 +'Rong ', # 0x97 +'Yin ', # 0x98 +'Xie ', # 0x99 +'Kan ', # 0x9a +'Jun ', # 0x9b +'Nong ', # 0x9c +'Yi ', # 0x9d +'Mi ', # 0x9e +'Shi ', # 0x9f +'Guan ', # 0xa0 +'Meng ', # 0xa1 +'Zhong ', # 0xa2 +'Ju ', # 0xa3 +'Yuan ', # 0xa4 +'Ming ', # 0xa5 +'Kou ', # 0xa6 +'Lam ', # 0xa7 +'Fu ', # 0xa8 +'Xie ', # 0xa9 +'Mi ', # 0xaa +'Bing ', # 0xab +'Dong ', # 0xac +'Tai ', # 0xad +'Gang ', # 0xae +'Feng ', # 0xaf +'Bing ', # 0xb0 +'Hu ', # 0xb1 +'Chong ', # 0xb2 +'Jue ', # 0xb3 +'Hu ', # 0xb4 +'Kuang ', # 0xb5 +'Ye ', # 0xb6 +'Leng ', # 0xb7 +'Pan ', # 0xb8 +'Fu ', # 0xb9 +'Min ', # 0xba +'Dong ', # 0xbb +'Xian ', # 0xbc +'Lie ', # 0xbd +'Xia ', # 0xbe +'Jian ', # 0xbf +'Jing ', # 0xc0 +'Shu ', # 0xc1 +'Mei ', # 0xc2 +'Tu ', # 0xc3 +'Qi ', # 0xc4 +'Gu ', # 0xc5 +'Zhun ', # 0xc6 +'Song ', # 0xc7 +'Jing ', # 0xc8 +'Liang ', # 0xc9 +'Qing ', # 0xca +'Diao ', # 0xcb +'Ling ', # 0xcc +'Dong ', # 0xcd +'Gan ', # 0xce +'Jian ', # 0xcf +'Yin ', # 0xd0 +'Cou ', # 0xd1 +'Yi ', # 0xd2 +'Li ', # 0xd3 +'Cang ', # 0xd4 +'Ming ', # 0xd5 +'Zhuen ', # 0xd6 +'Cui ', # 0xd7 +'Si ', # 0xd8 +'Duo ', # 0xd9 +'Jin ', # 0xda +'Lin ', # 0xdb +'Lin ', # 0xdc +'Ning ', # 0xdd +'Xi ', # 0xde +'Du ', # 0xdf +'Ji ', # 0xe0 +'Fan ', # 0xe1 +'Fan ', # 0xe2 +'Fan ', # 0xe3 +'Feng ', # 0xe4 +'Ju ', # 0xe5 +'Chu ', # 0xe6 +'Tako ', # 0xe7 +'Feng ', # 0xe8 +'Mok ', # 0xe9 +'Ci ', # 0xea +'Fu ', # 0xeb +'Feng ', # 0xec +'Ping ', # 0xed +'Feng ', # 0xee +'Kai ', # 0xef +'Huang ', # 0xf0 +'Kai ', # 0xf1 +'Gan ', # 0xf2 +'Deng ', # 0xf3 +'Ping ', # 0xf4 +'Qu ', # 0xf5 +'Xiong ', # 0xf6 +'Kuai ', # 0xf7 +'Tu ', # 0xf8 +'Ao ', # 0xf9 +'Chu ', # 0xfa +'Ji ', # 0xfb +'Dang ', # 0xfc +'Han ', # 0xfd +'Han ', # 0xfe +'Zao ', # 0xff +) diff --git a/nstock/modules/unidecode/x052.py b/nstock/modules/unidecode/x052.py new file mode 100644 index 0000000..088f221 --- /dev/null +++ b/nstock/modules/unidecode/x052.py @@ -0,0 +1,258 @@ +data = ( +'Dao ', # 0x00 +'Diao ', # 0x01 +'Dao ', # 0x02 +'Ren ', # 0x03 +'Ren ', # 0x04 +'Chuang ', # 0x05 +'Fen ', # 0x06 +'Qie ', # 0x07 +'Yi ', # 0x08 +'Ji ', # 0x09 +'Kan ', # 0x0a +'Qian ', # 0x0b +'Cun ', # 0x0c +'Chu ', # 0x0d +'Wen ', # 0x0e +'Ji ', # 0x0f +'Dan ', # 0x10 +'Xing ', # 0x11 +'Hua ', # 0x12 +'Wan ', # 0x13 +'Jue ', # 0x14 +'Li ', # 0x15 +'Yue ', # 0x16 +'Lie ', # 0x17 +'Liu ', # 0x18 +'Ze ', # 0x19 +'Gang ', # 0x1a +'Chuang ', # 0x1b +'Fu ', # 0x1c +'Chu ', # 0x1d +'Qu ', # 0x1e +'Ju ', # 0x1f +'Shan ', # 0x20 +'Min ', # 0x21 +'Ling ', # 0x22 +'Zhong ', # 0x23 +'Pan ', # 0x24 +'Bie ', # 0x25 +'Jie ', # 0x26 +'Jie ', # 0x27 +'Bao ', # 0x28 +'Li ', # 0x29 +'Shan ', # 0x2a +'Bie ', # 0x2b +'Chan ', # 0x2c +'Jing ', # 0x2d +'Gua ', # 0x2e +'Gen ', # 0x2f +'Dao ', # 0x30 +'Chuang ', # 0x31 +'Kui ', # 0x32 +'Ku ', # 0x33 +'Duo ', # 0x34 +'Er ', # 0x35 +'Zhi ', # 0x36 +'Shua ', # 0x37 +'Quan ', # 0x38 +'Cha ', # 0x39 +'Ci ', # 0x3a +'Ke ', # 0x3b +'Jie ', # 0x3c +'Gui ', # 0x3d +'Ci ', # 0x3e +'Gui ', # 0x3f +'Kai ', # 0x40 +'Duo ', # 0x41 +'Ji ', # 0x42 +'Ti ', # 0x43 +'Jing ', # 0x44 +'Lou ', # 0x45 +'Gen ', # 0x46 +'Ze ', # 0x47 +'Yuan ', # 0x48 +'Cuo ', # 0x49 +'Xue ', # 0x4a +'Ke ', # 0x4b +'La ', # 0x4c +'Qian ', # 0x4d +'Cha ', # 0x4e +'Chuang ', # 0x4f +'Gua ', # 0x50 +'Jian ', # 0x51 +'Cuo ', # 0x52 +'Li ', # 0x53 +'Ti ', # 0x54 +'Fei ', # 0x55 +'Pou ', # 0x56 +'Chan ', # 0x57 +'Qi ', # 0x58 +'Chuang ', # 0x59 +'Zi ', # 0x5a +'Gang ', # 0x5b +'Wan ', # 0x5c +'Bo ', # 0x5d +'Ji ', # 0x5e +'Duo ', # 0x5f +'Qing ', # 0x60 +'Yan ', # 0x61 +'Zhuo ', # 0x62 +'Jian ', # 0x63 +'Ji ', # 0x64 +'Bo ', # 0x65 +'Yan ', # 0x66 +'Ju ', # 0x67 +'Huo ', # 0x68 +'Sheng ', # 0x69 +'Jian ', # 0x6a +'Duo ', # 0x6b +'Duan ', # 0x6c +'Wu ', # 0x6d +'Gua ', # 0x6e +'Fu ', # 0x6f +'Sheng ', # 0x70 +'Jian ', # 0x71 +'Ge ', # 0x72 +'Zha ', # 0x73 +'Kai ', # 0x74 +'Chuang ', # 0x75 +'Juan ', # 0x76 +'Chan ', # 0x77 +'Tuan ', # 0x78 +'Lu ', # 0x79 +'Li ', # 0x7a +'Fou ', # 0x7b +'Shan ', # 0x7c +'Piao ', # 0x7d +'Kou ', # 0x7e +'Jiao ', # 0x7f +'Gua ', # 0x80 +'Qiao ', # 0x81 +'Jue ', # 0x82 +'Hua ', # 0x83 +'Zha ', # 0x84 +'Zhuo ', # 0x85 +'Lian ', # 0x86 +'Ju ', # 0x87 +'Pi ', # 0x88 +'Liu ', # 0x89 +'Gui ', # 0x8a +'Jiao ', # 0x8b +'Gui ', # 0x8c +'Jian ', # 0x8d +'Jian ', # 0x8e +'Tang ', # 0x8f +'Huo ', # 0x90 +'Ji ', # 0x91 +'Jian ', # 0x92 +'Yi ', # 0x93 +'Jian ', # 0x94 +'Zhi ', # 0x95 +'Chan ', # 0x96 +'Cuan ', # 0x97 +'Mo ', # 0x98 +'Li ', # 0x99 +'Zhu ', # 0x9a +'Li ', # 0x9b +'Ya ', # 0x9c +'Quan ', # 0x9d +'Ban ', # 0x9e +'Gong ', # 0x9f +'Jia ', # 0xa0 +'Wu ', # 0xa1 +'Mai ', # 0xa2 +'Lie ', # 0xa3 +'Jin ', # 0xa4 +'Keng ', # 0xa5 +'Xie ', # 0xa6 +'Zhi ', # 0xa7 +'Dong ', # 0xa8 +'Zhu ', # 0xa9 +'Nu ', # 0xaa +'Jie ', # 0xab +'Qu ', # 0xac +'Shao ', # 0xad +'Yi ', # 0xae +'Zhu ', # 0xaf +'Miao ', # 0xb0 +'Li ', # 0xb1 +'Jing ', # 0xb2 +'Lao ', # 0xb3 +'Lao ', # 0xb4 +'Juan ', # 0xb5 +'Kou ', # 0xb6 +'Yang ', # 0xb7 +'Wa ', # 0xb8 +'Xiao ', # 0xb9 +'Mou ', # 0xba +'Kuang ', # 0xbb +'Jie ', # 0xbc +'Lie ', # 0xbd +'He ', # 0xbe +'Shi ', # 0xbf +'Ke ', # 0xc0 +'Jing ', # 0xc1 +'Hao ', # 0xc2 +'Bo ', # 0xc3 +'Min ', # 0xc4 +'Chi ', # 0xc5 +'Lang ', # 0xc6 +'Yong ', # 0xc7 +'Yong ', # 0xc8 +'Mian ', # 0xc9 +'Ke ', # 0xca +'Xun ', # 0xcb +'Juan ', # 0xcc +'Qing ', # 0xcd +'Lu ', # 0xce +'Pou ', # 0xcf +'Meng ', # 0xd0 +'Lai ', # 0xd1 +'Le ', # 0xd2 +'Kai ', # 0xd3 +'Mian ', # 0xd4 +'Dong ', # 0xd5 +'Xu ', # 0xd6 +'Xu ', # 0xd7 +'Kan ', # 0xd8 +'Wu ', # 0xd9 +'Yi ', # 0xda +'Xun ', # 0xdb +'Weng ', # 0xdc +'Sheng ', # 0xdd +'Lao ', # 0xde +'Mu ', # 0xdf +'Lu ', # 0xe0 +'Piao ', # 0xe1 +'Shi ', # 0xe2 +'Ji ', # 0xe3 +'Qin ', # 0xe4 +'Qiang ', # 0xe5 +'Jiao ', # 0xe6 +'Quan ', # 0xe7 +'Yang ', # 0xe8 +'Yi ', # 0xe9 +'Jue ', # 0xea +'Fan ', # 0xeb +'Juan ', # 0xec +'Tong ', # 0xed +'Ju ', # 0xee +'Dan ', # 0xef +'Xie ', # 0xf0 +'Mai ', # 0xf1 +'Xun ', # 0xf2 +'Xun ', # 0xf3 +'Lu ', # 0xf4 +'Li ', # 0xf5 +'Che ', # 0xf6 +'Rang ', # 0xf7 +'Quan ', # 0xf8 +'Bao ', # 0xf9 +'Shao ', # 0xfa +'Yun ', # 0xfb +'Jiu ', # 0xfc +'Bao ', # 0xfd +'Gou ', # 0xfe +'Wu ', # 0xff +) diff --git a/nstock/modules/unidecode/x053.py b/nstock/modules/unidecode/x053.py new file mode 100644 index 0000000..fa08b6e --- /dev/null +++ b/nstock/modules/unidecode/x053.py @@ -0,0 +1,258 @@ +data = ( +'Yun ', # 0x00 +'Mwun ', # 0x01 +'Nay ', # 0x02 +'Gai ', # 0x03 +'Gai ', # 0x04 +'Bao ', # 0x05 +'Cong ', # 0x06 +'[?] ', # 0x07 +'Xiong ', # 0x08 +'Peng ', # 0x09 +'Ju ', # 0x0a +'Tao ', # 0x0b +'Ge ', # 0x0c +'Pu ', # 0x0d +'An ', # 0x0e +'Pao ', # 0x0f +'Fu ', # 0x10 +'Gong ', # 0x11 +'Da ', # 0x12 +'Jiu ', # 0x13 +'Qiong ', # 0x14 +'Bi ', # 0x15 +'Hua ', # 0x16 +'Bei ', # 0x17 +'Nao ', # 0x18 +'Chi ', # 0x19 +'Fang ', # 0x1a +'Jiu ', # 0x1b +'Yi ', # 0x1c +'Za ', # 0x1d +'Jiang ', # 0x1e +'Kang ', # 0x1f +'Jiang ', # 0x20 +'Kuang ', # 0x21 +'Hu ', # 0x22 +'Xia ', # 0x23 +'Qu ', # 0x24 +'Bian ', # 0x25 +'Gui ', # 0x26 +'Qie ', # 0x27 +'Zang ', # 0x28 +'Kuang ', # 0x29 +'Fei ', # 0x2a +'Hu ', # 0x2b +'Tou ', # 0x2c +'Gui ', # 0x2d +'Gui ', # 0x2e +'Hui ', # 0x2f +'Dan ', # 0x30 +'Gui ', # 0x31 +'Lian ', # 0x32 +'Lian ', # 0x33 +'Suan ', # 0x34 +'Du ', # 0x35 +'Jiu ', # 0x36 +'Qu ', # 0x37 +'Xi ', # 0x38 +'Pi ', # 0x39 +'Qu ', # 0x3a +'Yi ', # 0x3b +'Qia ', # 0x3c +'Yan ', # 0x3d +'Bian ', # 0x3e +'Ni ', # 0x3f +'Qu ', # 0x40 +'Shi ', # 0x41 +'Xin ', # 0x42 +'Qian ', # 0x43 +'Nian ', # 0x44 +'Sa ', # 0x45 +'Zu ', # 0x46 +'Sheng ', # 0x47 +'Wu ', # 0x48 +'Hui ', # 0x49 +'Ban ', # 0x4a +'Shi ', # 0x4b +'Xi ', # 0x4c +'Wan ', # 0x4d +'Hua ', # 0x4e +'Xie ', # 0x4f +'Wan ', # 0x50 +'Bei ', # 0x51 +'Zu ', # 0x52 +'Zhuo ', # 0x53 +'Xie ', # 0x54 +'Dan ', # 0x55 +'Mai ', # 0x56 +'Nan ', # 0x57 +'Dan ', # 0x58 +'Ji ', # 0x59 +'Bo ', # 0x5a +'Shuai ', # 0x5b +'Bu ', # 0x5c +'Kuang ', # 0x5d +'Bian ', # 0x5e +'Bu ', # 0x5f +'Zhan ', # 0x60 +'Qia ', # 0x61 +'Lu ', # 0x62 +'You ', # 0x63 +'Lu ', # 0x64 +'Xi ', # 0x65 +'Gua ', # 0x66 +'Wo ', # 0x67 +'Xie ', # 0x68 +'Jie ', # 0x69 +'Jie ', # 0x6a +'Wei ', # 0x6b +'Ang ', # 0x6c +'Qiong ', # 0x6d +'Zhi ', # 0x6e +'Mao ', # 0x6f +'Yin ', # 0x70 +'Wei ', # 0x71 +'Shao ', # 0x72 +'Ji ', # 0x73 +'Que ', # 0x74 +'Luan ', # 0x75 +'Shi ', # 0x76 +'Juan ', # 0x77 +'Xie ', # 0x78 +'Xu ', # 0x79 +'Jin ', # 0x7a +'Que ', # 0x7b +'Wu ', # 0x7c +'Ji ', # 0x7d +'E ', # 0x7e +'Qing ', # 0x7f +'Xi ', # 0x80 +'[?] ', # 0x81 +'Han ', # 0x82 +'Zhan ', # 0x83 +'E ', # 0x84 +'Ting ', # 0x85 +'Li ', # 0x86 +'Zhe ', # 0x87 +'Han ', # 0x88 +'Li ', # 0x89 +'Ya ', # 0x8a +'Ya ', # 0x8b +'Yan ', # 0x8c +'She ', # 0x8d +'Zhi ', # 0x8e +'Zha ', # 0x8f +'Pang ', # 0x90 +'[?] ', # 0x91 +'He ', # 0x92 +'Ya ', # 0x93 +'Zhi ', # 0x94 +'Ce ', # 0x95 +'Pang ', # 0x96 +'Ti ', # 0x97 +'Li ', # 0x98 +'She ', # 0x99 +'Hou ', # 0x9a +'Ting ', # 0x9b +'Zui ', # 0x9c +'Cuo ', # 0x9d +'Fei ', # 0x9e +'Yuan ', # 0x9f +'Ce ', # 0xa0 +'Yuan ', # 0xa1 +'Xiang ', # 0xa2 +'Yan ', # 0xa3 +'Li ', # 0xa4 +'Jue ', # 0xa5 +'Sha ', # 0xa6 +'Dian ', # 0xa7 +'Chu ', # 0xa8 +'Jiu ', # 0xa9 +'Qin ', # 0xaa +'Ao ', # 0xab +'Gui ', # 0xac +'Yan ', # 0xad +'Si ', # 0xae +'Li ', # 0xaf +'Chang ', # 0xb0 +'Lan ', # 0xb1 +'Li ', # 0xb2 +'Yan ', # 0xb3 +'Yan ', # 0xb4 +'Yuan ', # 0xb5 +'Si ', # 0xb6 +'Gong ', # 0xb7 +'Lin ', # 0xb8 +'Qiu ', # 0xb9 +'Qu ', # 0xba +'Qu ', # 0xbb +'Uk ', # 0xbc +'Lei ', # 0xbd +'Du ', # 0xbe +'Xian ', # 0xbf +'Zhuan ', # 0xc0 +'San ', # 0xc1 +'Can ', # 0xc2 +'Can ', # 0xc3 +'Can ', # 0xc4 +'Can ', # 0xc5 +'Ai ', # 0xc6 +'Dai ', # 0xc7 +'You ', # 0xc8 +'Cha ', # 0xc9 +'Ji ', # 0xca +'You ', # 0xcb +'Shuang ', # 0xcc +'Fan ', # 0xcd +'Shou ', # 0xce +'Guai ', # 0xcf +'Ba ', # 0xd0 +'Fa ', # 0xd1 +'Ruo ', # 0xd2 +'Shi ', # 0xd3 +'Shu ', # 0xd4 +'Zhuo ', # 0xd5 +'Qu ', # 0xd6 +'Shou ', # 0xd7 +'Bian ', # 0xd8 +'Xu ', # 0xd9 +'Jia ', # 0xda +'Pan ', # 0xdb +'Sou ', # 0xdc +'Gao ', # 0xdd +'Wei ', # 0xde +'Sou ', # 0xdf +'Die ', # 0xe0 +'Rui ', # 0xe1 +'Cong ', # 0xe2 +'Kou ', # 0xe3 +'Gu ', # 0xe4 +'Ju ', # 0xe5 +'Ling ', # 0xe6 +'Gua ', # 0xe7 +'Tao ', # 0xe8 +'Kou ', # 0xe9 +'Zhi ', # 0xea +'Jiao ', # 0xeb +'Zhao ', # 0xec +'Ba ', # 0xed +'Ding ', # 0xee +'Ke ', # 0xef +'Tai ', # 0xf0 +'Chi ', # 0xf1 +'Shi ', # 0xf2 +'You ', # 0xf3 +'Qiu ', # 0xf4 +'Po ', # 0xf5 +'Xie ', # 0xf6 +'Hao ', # 0xf7 +'Si ', # 0xf8 +'Tan ', # 0xf9 +'Chi ', # 0xfa +'Le ', # 0xfb +'Diao ', # 0xfc +'Ji ', # 0xfd +'[?] ', # 0xfe +'Hong ', # 0xff +) diff --git a/nstock/modules/unidecode/x054.py b/nstock/modules/unidecode/x054.py new file mode 100644 index 0000000..c014e0f --- /dev/null +++ b/nstock/modules/unidecode/x054.py @@ -0,0 +1,258 @@ +data = ( +'Mie ', # 0x00 +'Xu ', # 0x01 +'Mang ', # 0x02 +'Chi ', # 0x03 +'Ge ', # 0x04 +'Xuan ', # 0x05 +'Yao ', # 0x06 +'Zi ', # 0x07 +'He ', # 0x08 +'Ji ', # 0x09 +'Diao ', # 0x0a +'Cun ', # 0x0b +'Tong ', # 0x0c +'Ming ', # 0x0d +'Hou ', # 0x0e +'Li ', # 0x0f +'Tu ', # 0x10 +'Xiang ', # 0x11 +'Zha ', # 0x12 +'Xia ', # 0x13 +'Ye ', # 0x14 +'Lu ', # 0x15 +'A ', # 0x16 +'Ma ', # 0x17 +'Ou ', # 0x18 +'Xue ', # 0x19 +'Yi ', # 0x1a +'Jun ', # 0x1b +'Chou ', # 0x1c +'Lin ', # 0x1d +'Tun ', # 0x1e +'Yin ', # 0x1f +'Fei ', # 0x20 +'Bi ', # 0x21 +'Qin ', # 0x22 +'Qin ', # 0x23 +'Jie ', # 0x24 +'Bu ', # 0x25 +'Fou ', # 0x26 +'Ba ', # 0x27 +'Dun ', # 0x28 +'Fen ', # 0x29 +'E ', # 0x2a +'Han ', # 0x2b +'Ting ', # 0x2c +'Hang ', # 0x2d +'Shun ', # 0x2e +'Qi ', # 0x2f +'Hong ', # 0x30 +'Zhi ', # 0x31 +'Shen ', # 0x32 +'Wu ', # 0x33 +'Wu ', # 0x34 +'Chao ', # 0x35 +'Ne ', # 0x36 +'Xue ', # 0x37 +'Xi ', # 0x38 +'Chui ', # 0x39 +'Dou ', # 0x3a +'Wen ', # 0x3b +'Hou ', # 0x3c +'Ou ', # 0x3d +'Wu ', # 0x3e +'Gao ', # 0x3f +'Ya ', # 0x40 +'Jun ', # 0x41 +'Lu ', # 0x42 +'E ', # 0x43 +'Ge ', # 0x44 +'Mei ', # 0x45 +'Ai ', # 0x46 +'Qi ', # 0x47 +'Cheng ', # 0x48 +'Wu ', # 0x49 +'Gao ', # 0x4a +'Fu ', # 0x4b +'Jiao ', # 0x4c +'Hong ', # 0x4d +'Chi ', # 0x4e +'Sheng ', # 0x4f +'Ne ', # 0x50 +'Tun ', # 0x51 +'Fu ', # 0x52 +'Yi ', # 0x53 +'Dai ', # 0x54 +'Ou ', # 0x55 +'Li ', # 0x56 +'Bai ', # 0x57 +'Yuan ', # 0x58 +'Kuai ', # 0x59 +'[?] ', # 0x5a +'Qiang ', # 0x5b +'Wu ', # 0x5c +'E ', # 0x5d +'Shi ', # 0x5e +'Quan ', # 0x5f +'Pen ', # 0x60 +'Wen ', # 0x61 +'Ni ', # 0x62 +'M ', # 0x63 +'Ling ', # 0x64 +'Ran ', # 0x65 +'You ', # 0x66 +'Di ', # 0x67 +'Zhou ', # 0x68 +'Shi ', # 0x69 +'Zhou ', # 0x6a +'Tie ', # 0x6b +'Xi ', # 0x6c +'Yi ', # 0x6d +'Qi ', # 0x6e +'Ping ', # 0x6f +'Zi ', # 0x70 +'Gu ', # 0x71 +'Zi ', # 0x72 +'Wei ', # 0x73 +'Xu ', # 0x74 +'He ', # 0x75 +'Nao ', # 0x76 +'Xia ', # 0x77 +'Pei ', # 0x78 +'Yi ', # 0x79 +'Xiao ', # 0x7a +'Shen ', # 0x7b +'Hu ', # 0x7c +'Ming ', # 0x7d +'Da ', # 0x7e +'Qu ', # 0x7f +'Ju ', # 0x80 +'Gem ', # 0x81 +'Za ', # 0x82 +'Tuo ', # 0x83 +'Duo ', # 0x84 +'Pou ', # 0x85 +'Pao ', # 0x86 +'Bi ', # 0x87 +'Fu ', # 0x88 +'Yang ', # 0x89 +'He ', # 0x8a +'Zha ', # 0x8b +'He ', # 0x8c +'Hai ', # 0x8d +'Jiu ', # 0x8e +'Yong ', # 0x8f +'Fu ', # 0x90 +'Que ', # 0x91 +'Zhou ', # 0x92 +'Wa ', # 0x93 +'Ka ', # 0x94 +'Gu ', # 0x95 +'Ka ', # 0x96 +'Zuo ', # 0x97 +'Bu ', # 0x98 +'Long ', # 0x99 +'Dong ', # 0x9a +'Ning ', # 0x9b +'Tha ', # 0x9c +'Si ', # 0x9d +'Xian ', # 0x9e +'Huo ', # 0x9f +'Qi ', # 0xa0 +'Er ', # 0xa1 +'E ', # 0xa2 +'Guang ', # 0xa3 +'Zha ', # 0xa4 +'Xi ', # 0xa5 +'Yi ', # 0xa6 +'Lie ', # 0xa7 +'Zi ', # 0xa8 +'Mie ', # 0xa9 +'Mi ', # 0xaa +'Zhi ', # 0xab +'Yao ', # 0xac +'Ji ', # 0xad +'Zhou ', # 0xae +'Ge ', # 0xaf +'Shuai ', # 0xb0 +'Zan ', # 0xb1 +'Xiao ', # 0xb2 +'Ke ', # 0xb3 +'Hui ', # 0xb4 +'Kua ', # 0xb5 +'Huai ', # 0xb6 +'Tao ', # 0xb7 +'Xian ', # 0xb8 +'E ', # 0xb9 +'Xuan ', # 0xba +'Xiu ', # 0xbb +'Wai ', # 0xbc +'Yan ', # 0xbd +'Lao ', # 0xbe +'Yi ', # 0xbf +'Ai ', # 0xc0 +'Pin ', # 0xc1 +'Shen ', # 0xc2 +'Tong ', # 0xc3 +'Hong ', # 0xc4 +'Xiong ', # 0xc5 +'Chi ', # 0xc6 +'Wa ', # 0xc7 +'Ha ', # 0xc8 +'Zai ', # 0xc9 +'Yu ', # 0xca +'Di ', # 0xcb +'Pai ', # 0xcc +'Xiang ', # 0xcd +'Ai ', # 0xce +'Hen ', # 0xcf +'Kuang ', # 0xd0 +'Ya ', # 0xd1 +'Da ', # 0xd2 +'Xiao ', # 0xd3 +'Bi ', # 0xd4 +'Yue ', # 0xd5 +'[?] ', # 0xd6 +'Hua ', # 0xd7 +'Sasou ', # 0xd8 +'Kuai ', # 0xd9 +'Duo ', # 0xda +'[?] ', # 0xdb +'Ji ', # 0xdc +'Nong ', # 0xdd +'Mou ', # 0xde +'Yo ', # 0xdf +'Hao ', # 0xe0 +'Yuan ', # 0xe1 +'Long ', # 0xe2 +'Pou ', # 0xe3 +'Mang ', # 0xe4 +'Ge ', # 0xe5 +'E ', # 0xe6 +'Chi ', # 0xe7 +'Shao ', # 0xe8 +'Li ', # 0xe9 +'Na ', # 0xea +'Zu ', # 0xeb +'He ', # 0xec +'Ku ', # 0xed +'Xiao ', # 0xee +'Xian ', # 0xef +'Lao ', # 0xf0 +'Bo ', # 0xf1 +'Zhe ', # 0xf2 +'Zha ', # 0xf3 +'Liang ', # 0xf4 +'Ba ', # 0xf5 +'Mie ', # 0xf6 +'Le ', # 0xf7 +'Sui ', # 0xf8 +'Fou ', # 0xf9 +'Bu ', # 0xfa +'Han ', # 0xfb +'Heng ', # 0xfc +'Geng ', # 0xfd +'Shuo ', # 0xfe +'Ge ', # 0xff +) diff --git a/nstock/modules/unidecode/x055.py b/nstock/modules/unidecode/x055.py new file mode 100644 index 0000000..26aea74 --- /dev/null +++ b/nstock/modules/unidecode/x055.py @@ -0,0 +1,258 @@ +data = ( +'You ', # 0x00 +'Yan ', # 0x01 +'Gu ', # 0x02 +'Gu ', # 0x03 +'Bai ', # 0x04 +'Han ', # 0x05 +'Suo ', # 0x06 +'Chun ', # 0x07 +'Yi ', # 0x08 +'Ai ', # 0x09 +'Jia ', # 0x0a +'Tu ', # 0x0b +'Xian ', # 0x0c +'Huan ', # 0x0d +'Li ', # 0x0e +'Xi ', # 0x0f +'Tang ', # 0x10 +'Zuo ', # 0x11 +'Qiu ', # 0x12 +'Che ', # 0x13 +'Wu ', # 0x14 +'Zao ', # 0x15 +'Ya ', # 0x16 +'Dou ', # 0x17 +'Qi ', # 0x18 +'Di ', # 0x19 +'Qin ', # 0x1a +'Ma ', # 0x1b +'Mal ', # 0x1c +'Hong ', # 0x1d +'Dou ', # 0x1e +'Kes ', # 0x1f +'Lao ', # 0x20 +'Liang ', # 0x21 +'Suo ', # 0x22 +'Zao ', # 0x23 +'Huan ', # 0x24 +'Lang ', # 0x25 +'Sha ', # 0x26 +'Ji ', # 0x27 +'Zuo ', # 0x28 +'Wo ', # 0x29 +'Feng ', # 0x2a +'Yin ', # 0x2b +'Hu ', # 0x2c +'Qi ', # 0x2d +'Shou ', # 0x2e +'Wei ', # 0x2f +'Shua ', # 0x30 +'Chang ', # 0x31 +'Er ', # 0x32 +'Li ', # 0x33 +'Qiang ', # 0x34 +'An ', # 0x35 +'Jie ', # 0x36 +'Yo ', # 0x37 +'Nian ', # 0x38 +'Yu ', # 0x39 +'Tian ', # 0x3a +'Lai ', # 0x3b +'Sha ', # 0x3c +'Xi ', # 0x3d +'Tuo ', # 0x3e +'Hu ', # 0x3f +'Ai ', # 0x40 +'Zhou ', # 0x41 +'Nou ', # 0x42 +'Ken ', # 0x43 +'Zhuo ', # 0x44 +'Zhuo ', # 0x45 +'Shang ', # 0x46 +'Di ', # 0x47 +'Heng ', # 0x48 +'Lan ', # 0x49 +'A ', # 0x4a +'Xiao ', # 0x4b +'Xiang ', # 0x4c +'Tun ', # 0x4d +'Wu ', # 0x4e +'Wen ', # 0x4f +'Cui ', # 0x50 +'Sha ', # 0x51 +'Hu ', # 0x52 +'Qi ', # 0x53 +'Qi ', # 0x54 +'Tao ', # 0x55 +'Dan ', # 0x56 +'Dan ', # 0x57 +'Ye ', # 0x58 +'Zi ', # 0x59 +'Bi ', # 0x5a +'Cui ', # 0x5b +'Chuo ', # 0x5c +'He ', # 0x5d +'Ya ', # 0x5e +'Qi ', # 0x5f +'Zhe ', # 0x60 +'Pei ', # 0x61 +'Liang ', # 0x62 +'Xian ', # 0x63 +'Pi ', # 0x64 +'Sha ', # 0x65 +'La ', # 0x66 +'Ze ', # 0x67 +'Qing ', # 0x68 +'Gua ', # 0x69 +'Pa ', # 0x6a +'Zhe ', # 0x6b +'Se ', # 0x6c +'Zhuan ', # 0x6d +'Nie ', # 0x6e +'Guo ', # 0x6f +'Luo ', # 0x70 +'Yan ', # 0x71 +'Di ', # 0x72 +'Quan ', # 0x73 +'Tan ', # 0x74 +'Bo ', # 0x75 +'Ding ', # 0x76 +'Lang ', # 0x77 +'Xiao ', # 0x78 +'[?] ', # 0x79 +'Tang ', # 0x7a +'Chi ', # 0x7b +'Ti ', # 0x7c +'An ', # 0x7d +'Jiu ', # 0x7e +'Dan ', # 0x7f +'Ke ', # 0x80 +'Yong ', # 0x81 +'Wei ', # 0x82 +'Nan ', # 0x83 +'Shan ', # 0x84 +'Yu ', # 0x85 +'Zhe ', # 0x86 +'La ', # 0x87 +'Jie ', # 0x88 +'Hou ', # 0x89 +'Han ', # 0x8a +'Die ', # 0x8b +'Zhou ', # 0x8c +'Chai ', # 0x8d +'Wai ', # 0x8e +'Re ', # 0x8f +'Yu ', # 0x90 +'Yin ', # 0x91 +'Zan ', # 0x92 +'Yao ', # 0x93 +'Wo ', # 0x94 +'Mian ', # 0x95 +'Hu ', # 0x96 +'Yun ', # 0x97 +'Chuan ', # 0x98 +'Hui ', # 0x99 +'Huan ', # 0x9a +'Huan ', # 0x9b +'Xi ', # 0x9c +'He ', # 0x9d +'Ji ', # 0x9e +'Kui ', # 0x9f +'Zhong ', # 0xa0 +'Wei ', # 0xa1 +'Sha ', # 0xa2 +'Xu ', # 0xa3 +'Huang ', # 0xa4 +'Du ', # 0xa5 +'Nie ', # 0xa6 +'Xuan ', # 0xa7 +'Liang ', # 0xa8 +'Yu ', # 0xa9 +'Sang ', # 0xaa +'Chi ', # 0xab +'Qiao ', # 0xac +'Yan ', # 0xad +'Dan ', # 0xae +'Pen ', # 0xaf +'Can ', # 0xb0 +'Li ', # 0xb1 +'Yo ', # 0xb2 +'Zha ', # 0xb3 +'Wei ', # 0xb4 +'Miao ', # 0xb5 +'Ying ', # 0xb6 +'Pen ', # 0xb7 +'Phos ', # 0xb8 +'Kui ', # 0xb9 +'Xi ', # 0xba +'Yu ', # 0xbb +'Jie ', # 0xbc +'Lou ', # 0xbd +'Ku ', # 0xbe +'Sao ', # 0xbf +'Huo ', # 0xc0 +'Ti ', # 0xc1 +'Yao ', # 0xc2 +'He ', # 0xc3 +'A ', # 0xc4 +'Xiu ', # 0xc5 +'Qiang ', # 0xc6 +'Se ', # 0xc7 +'Yong ', # 0xc8 +'Su ', # 0xc9 +'Hong ', # 0xca +'Xie ', # 0xcb +'Yi ', # 0xcc +'Suo ', # 0xcd +'Ma ', # 0xce +'Cha ', # 0xcf +'Hai ', # 0xd0 +'Ke ', # 0xd1 +'Ta ', # 0xd2 +'Sang ', # 0xd3 +'Tian ', # 0xd4 +'Ru ', # 0xd5 +'Sou ', # 0xd6 +'Wa ', # 0xd7 +'Ji ', # 0xd8 +'Pang ', # 0xd9 +'Wu ', # 0xda +'Xian ', # 0xdb +'Shi ', # 0xdc +'Ge ', # 0xdd +'Zi ', # 0xde +'Jie ', # 0xdf +'Luo ', # 0xe0 +'Weng ', # 0xe1 +'Wa ', # 0xe2 +'Si ', # 0xe3 +'Chi ', # 0xe4 +'Hao ', # 0xe5 +'Suo ', # 0xe6 +'Jia ', # 0xe7 +'Hai ', # 0xe8 +'Suo ', # 0xe9 +'Qin ', # 0xea +'Nie ', # 0xeb +'He ', # 0xec +'Cis ', # 0xed +'Sai ', # 0xee +'Ng ', # 0xef +'Ge ', # 0xf0 +'Na ', # 0xf1 +'Dia ', # 0xf2 +'Ai ', # 0xf3 +'[?] ', # 0xf4 +'Tong ', # 0xf5 +'Bi ', # 0xf6 +'Ao ', # 0xf7 +'Ao ', # 0xf8 +'Lian ', # 0xf9 +'Cui ', # 0xfa +'Zhe ', # 0xfb +'Mo ', # 0xfc +'Sou ', # 0xfd +'Sou ', # 0xfe +'Tan ', # 0xff +) diff --git a/nstock/modules/unidecode/x056.py b/nstock/modules/unidecode/x056.py new file mode 100644 index 0000000..30b7fa5 --- /dev/null +++ b/nstock/modules/unidecode/x056.py @@ -0,0 +1,258 @@ +data = ( +'Di ', # 0x00 +'Qi ', # 0x01 +'Jiao ', # 0x02 +'Chong ', # 0x03 +'Jiao ', # 0x04 +'Kai ', # 0x05 +'Tan ', # 0x06 +'San ', # 0x07 +'Cao ', # 0x08 +'Jia ', # 0x09 +'Ai ', # 0x0a +'Xiao ', # 0x0b +'Piao ', # 0x0c +'Lou ', # 0x0d +'Ga ', # 0x0e +'Gu ', # 0x0f +'Xiao ', # 0x10 +'Hu ', # 0x11 +'Hui ', # 0x12 +'Guo ', # 0x13 +'Ou ', # 0x14 +'Xian ', # 0x15 +'Ze ', # 0x16 +'Chang ', # 0x17 +'Xu ', # 0x18 +'Po ', # 0x19 +'De ', # 0x1a +'Ma ', # 0x1b +'Ma ', # 0x1c +'Hu ', # 0x1d +'Lei ', # 0x1e +'Du ', # 0x1f +'Ga ', # 0x20 +'Tang ', # 0x21 +'Ye ', # 0x22 +'Beng ', # 0x23 +'Ying ', # 0x24 +'Saai ', # 0x25 +'Jiao ', # 0x26 +'Mi ', # 0x27 +'Xiao ', # 0x28 +'Hua ', # 0x29 +'Mai ', # 0x2a +'Ran ', # 0x2b +'Zuo ', # 0x2c +'Peng ', # 0x2d +'Lao ', # 0x2e +'Xiao ', # 0x2f +'Ji ', # 0x30 +'Zhu ', # 0x31 +'Chao ', # 0x32 +'Kui ', # 0x33 +'Zui ', # 0x34 +'Xiao ', # 0x35 +'Si ', # 0x36 +'Hao ', # 0x37 +'Fu ', # 0x38 +'Liao ', # 0x39 +'Qiao ', # 0x3a +'Xi ', # 0x3b +'Xiu ', # 0x3c +'Tan ', # 0x3d +'Tan ', # 0x3e +'Mo ', # 0x3f +'Xun ', # 0x40 +'E ', # 0x41 +'Zun ', # 0x42 +'Fan ', # 0x43 +'Chi ', # 0x44 +'Hui ', # 0x45 +'Zan ', # 0x46 +'Chuang ', # 0x47 +'Cu ', # 0x48 +'Dan ', # 0x49 +'Yu ', # 0x4a +'Tun ', # 0x4b +'Cheng ', # 0x4c +'Jiao ', # 0x4d +'Ye ', # 0x4e +'Xi ', # 0x4f +'Qi ', # 0x50 +'Hao ', # 0x51 +'Lian ', # 0x52 +'Xu ', # 0x53 +'Deng ', # 0x54 +'Hui ', # 0x55 +'Yin ', # 0x56 +'Pu ', # 0x57 +'Jue ', # 0x58 +'Qin ', # 0x59 +'Xun ', # 0x5a +'Nie ', # 0x5b +'Lu ', # 0x5c +'Si ', # 0x5d +'Yan ', # 0x5e +'Ying ', # 0x5f +'Da ', # 0x60 +'Dan ', # 0x61 +'Yu ', # 0x62 +'Zhou ', # 0x63 +'Jin ', # 0x64 +'Nong ', # 0x65 +'Yue ', # 0x66 +'Hui ', # 0x67 +'Qi ', # 0x68 +'E ', # 0x69 +'Zao ', # 0x6a +'Yi ', # 0x6b +'Shi ', # 0x6c +'Jiao ', # 0x6d +'Yuan ', # 0x6e +'Ai ', # 0x6f +'Yong ', # 0x70 +'Jue ', # 0x71 +'Kuai ', # 0x72 +'Yu ', # 0x73 +'Pen ', # 0x74 +'Dao ', # 0x75 +'Ge ', # 0x76 +'Xin ', # 0x77 +'Dun ', # 0x78 +'Dang ', # 0x79 +'Sin ', # 0x7a +'Sai ', # 0x7b +'Pi ', # 0x7c +'Pi ', # 0x7d +'Yin ', # 0x7e +'Zui ', # 0x7f +'Ning ', # 0x80 +'Di ', # 0x81 +'Lan ', # 0x82 +'Ta ', # 0x83 +'Huo ', # 0x84 +'Ru ', # 0x85 +'Hao ', # 0x86 +'Xia ', # 0x87 +'Ya ', # 0x88 +'Duo ', # 0x89 +'Xi ', # 0x8a +'Chou ', # 0x8b +'Ji ', # 0x8c +'Jin ', # 0x8d +'Hao ', # 0x8e +'Ti ', # 0x8f +'Chang ', # 0x90 +'[?] ', # 0x91 +'[?] ', # 0x92 +'Ca ', # 0x93 +'Ti ', # 0x94 +'Lu ', # 0x95 +'Hui ', # 0x96 +'Bo ', # 0x97 +'You ', # 0x98 +'Nie ', # 0x99 +'Yin ', # 0x9a +'Hu ', # 0x9b +'Mo ', # 0x9c +'Huang ', # 0x9d +'Zhe ', # 0x9e +'Li ', # 0x9f +'Liu ', # 0xa0 +'Haai ', # 0xa1 +'Nang ', # 0xa2 +'Xiao ', # 0xa3 +'Mo ', # 0xa4 +'Yan ', # 0xa5 +'Li ', # 0xa6 +'Lu ', # 0xa7 +'Long ', # 0xa8 +'Fu ', # 0xa9 +'Dan ', # 0xaa +'Chen ', # 0xab +'Pin ', # 0xac +'Pi ', # 0xad +'Xiang ', # 0xae +'Huo ', # 0xaf +'Mo ', # 0xb0 +'Xi ', # 0xb1 +'Duo ', # 0xb2 +'Ku ', # 0xb3 +'Yan ', # 0xb4 +'Chan ', # 0xb5 +'Ying ', # 0xb6 +'Rang ', # 0xb7 +'Dian ', # 0xb8 +'La ', # 0xb9 +'Ta ', # 0xba +'Xiao ', # 0xbb +'Jiao ', # 0xbc +'Chuo ', # 0xbd +'Huan ', # 0xbe +'Huo ', # 0xbf +'Zhuan ', # 0xc0 +'Nie ', # 0xc1 +'Xiao ', # 0xc2 +'Ca ', # 0xc3 +'Li ', # 0xc4 +'Chan ', # 0xc5 +'Chai ', # 0xc6 +'Li ', # 0xc7 +'Yi ', # 0xc8 +'Luo ', # 0xc9 +'Nang ', # 0xca +'Zan ', # 0xcb +'Su ', # 0xcc +'Xi ', # 0xcd +'So ', # 0xce +'Jian ', # 0xcf +'Za ', # 0xd0 +'Zhu ', # 0xd1 +'Lan ', # 0xd2 +'Nie ', # 0xd3 +'Nang ', # 0xd4 +'[?] ', # 0xd5 +'[?] ', # 0xd6 +'Wei ', # 0xd7 +'Hui ', # 0xd8 +'Yin ', # 0xd9 +'Qiu ', # 0xda +'Si ', # 0xdb +'Nin ', # 0xdc +'Jian ', # 0xdd +'Hui ', # 0xde +'Xin ', # 0xdf +'Yin ', # 0xe0 +'Nan ', # 0xe1 +'Tuan ', # 0xe2 +'Tuan ', # 0xe3 +'Dun ', # 0xe4 +'Kang ', # 0xe5 +'Yuan ', # 0xe6 +'Jiong ', # 0xe7 +'Pian ', # 0xe8 +'Yun ', # 0xe9 +'Cong ', # 0xea +'Hu ', # 0xeb +'Hui ', # 0xec +'Yuan ', # 0xed +'You ', # 0xee +'Guo ', # 0xef +'Kun ', # 0xf0 +'Cong ', # 0xf1 +'Wei ', # 0xf2 +'Tu ', # 0xf3 +'Wei ', # 0xf4 +'Lun ', # 0xf5 +'Guo ', # 0xf6 +'Qun ', # 0xf7 +'Ri ', # 0xf8 +'Ling ', # 0xf9 +'Gu ', # 0xfa +'Guo ', # 0xfb +'Tai ', # 0xfc +'Guo ', # 0xfd +'Tu ', # 0xfe +'You ', # 0xff +) diff --git a/nstock/modules/unidecode/x057.py b/nstock/modules/unidecode/x057.py new file mode 100644 index 0000000..9392fb8 --- /dev/null +++ b/nstock/modules/unidecode/x057.py @@ -0,0 +1,258 @@ +data = ( +'Guo ', # 0x00 +'Yin ', # 0x01 +'Hun ', # 0x02 +'Pu ', # 0x03 +'Yu ', # 0x04 +'Han ', # 0x05 +'Yuan ', # 0x06 +'Lun ', # 0x07 +'Quan ', # 0x08 +'Yu ', # 0x09 +'Qing ', # 0x0a +'Guo ', # 0x0b +'Chuan ', # 0x0c +'Wei ', # 0x0d +'Yuan ', # 0x0e +'Quan ', # 0x0f +'Ku ', # 0x10 +'Fu ', # 0x11 +'Yuan ', # 0x12 +'Yuan ', # 0x13 +'E ', # 0x14 +'Tu ', # 0x15 +'Tu ', # 0x16 +'Tu ', # 0x17 +'Tuan ', # 0x18 +'Lue ', # 0x19 +'Hui ', # 0x1a +'Yi ', # 0x1b +'Yuan ', # 0x1c +'Luan ', # 0x1d +'Luan ', # 0x1e +'Tu ', # 0x1f +'Ya ', # 0x20 +'Tu ', # 0x21 +'Ting ', # 0x22 +'Sheng ', # 0x23 +'Pu ', # 0x24 +'Lu ', # 0x25 +'Iri ', # 0x26 +'Ya ', # 0x27 +'Zai ', # 0x28 +'Wei ', # 0x29 +'Ge ', # 0x2a +'Yu ', # 0x2b +'Wu ', # 0x2c +'Gui ', # 0x2d +'Pi ', # 0x2e +'Yi ', # 0x2f +'Di ', # 0x30 +'Qian ', # 0x31 +'Qian ', # 0x32 +'Zhen ', # 0x33 +'Zhuo ', # 0x34 +'Dang ', # 0x35 +'Qia ', # 0x36 +'Akutsu ', # 0x37 +'Yama ', # 0x38 +'Kuang ', # 0x39 +'Chang ', # 0x3a +'Qi ', # 0x3b +'Nie ', # 0x3c +'Mo ', # 0x3d +'Ji ', # 0x3e +'Jia ', # 0x3f +'Zhi ', # 0x40 +'Zhi ', # 0x41 +'Ban ', # 0x42 +'Xun ', # 0x43 +'Tou ', # 0x44 +'Qin ', # 0x45 +'Fen ', # 0x46 +'Jun ', # 0x47 +'Keng ', # 0x48 +'Tun ', # 0x49 +'Fang ', # 0x4a +'Fen ', # 0x4b +'Ben ', # 0x4c +'Tan ', # 0x4d +'Kan ', # 0x4e +'Pi ', # 0x4f +'Zuo ', # 0x50 +'Keng ', # 0x51 +'Bi ', # 0x52 +'Xing ', # 0x53 +'Di ', # 0x54 +'Jing ', # 0x55 +'Ji ', # 0x56 +'Kuai ', # 0x57 +'Di ', # 0x58 +'Jing ', # 0x59 +'Jian ', # 0x5a +'Tan ', # 0x5b +'Li ', # 0x5c +'Ba ', # 0x5d +'Wu ', # 0x5e +'Fen ', # 0x5f +'Zhui ', # 0x60 +'Po ', # 0x61 +'Pan ', # 0x62 +'Tang ', # 0x63 +'Kun ', # 0x64 +'Qu ', # 0x65 +'Tan ', # 0x66 +'Zhi ', # 0x67 +'Tuo ', # 0x68 +'Gan ', # 0x69 +'Ping ', # 0x6a +'Dian ', # 0x6b +'Gua ', # 0x6c +'Ni ', # 0x6d +'Tai ', # 0x6e +'Pi ', # 0x6f +'Jiong ', # 0x70 +'Yang ', # 0x71 +'Fo ', # 0x72 +'Ao ', # 0x73 +'Liu ', # 0x74 +'Qiu ', # 0x75 +'Mu ', # 0x76 +'Ke ', # 0x77 +'Gou ', # 0x78 +'Xue ', # 0x79 +'Ba ', # 0x7a +'Chi ', # 0x7b +'Che ', # 0x7c +'Ling ', # 0x7d +'Zhu ', # 0x7e +'Fu ', # 0x7f +'Hu ', # 0x80 +'Zhi ', # 0x81 +'Chui ', # 0x82 +'La ', # 0x83 +'Long ', # 0x84 +'Long ', # 0x85 +'Lu ', # 0x86 +'Ao ', # 0x87 +'Tay ', # 0x88 +'Pao ', # 0x89 +'[?] ', # 0x8a +'Xing ', # 0x8b +'Dong ', # 0x8c +'Ji ', # 0x8d +'Ke ', # 0x8e +'Lu ', # 0x8f +'Ci ', # 0x90 +'Chi ', # 0x91 +'Lei ', # 0x92 +'Gai ', # 0x93 +'Yin ', # 0x94 +'Hou ', # 0x95 +'Dui ', # 0x96 +'Zhao ', # 0x97 +'Fu ', # 0x98 +'Guang ', # 0x99 +'Yao ', # 0x9a +'Duo ', # 0x9b +'Duo ', # 0x9c +'Gui ', # 0x9d +'Cha ', # 0x9e +'Yang ', # 0x9f +'Yin ', # 0xa0 +'Fa ', # 0xa1 +'Gou ', # 0xa2 +'Yuan ', # 0xa3 +'Die ', # 0xa4 +'Xie ', # 0xa5 +'Ken ', # 0xa6 +'Jiong ', # 0xa7 +'Shou ', # 0xa8 +'E ', # 0xa9 +'Ha ', # 0xaa +'Dian ', # 0xab +'Hong ', # 0xac +'Wu ', # 0xad +'Kua ', # 0xae +'[?] ', # 0xaf +'Tao ', # 0xb0 +'Dang ', # 0xb1 +'Kai ', # 0xb2 +'Gake ', # 0xb3 +'Nao ', # 0xb4 +'An ', # 0xb5 +'Xing ', # 0xb6 +'Xian ', # 0xb7 +'Huan ', # 0xb8 +'Bang ', # 0xb9 +'Pei ', # 0xba +'Ba ', # 0xbb +'Yi ', # 0xbc +'Yin ', # 0xbd +'Han ', # 0xbe +'Xu ', # 0xbf +'Chui ', # 0xc0 +'Cen ', # 0xc1 +'Geng ', # 0xc2 +'Ai ', # 0xc3 +'Peng ', # 0xc4 +'Fang ', # 0xc5 +'Que ', # 0xc6 +'Yong ', # 0xc7 +'Xun ', # 0xc8 +'Jia ', # 0xc9 +'Di ', # 0xca +'Mai ', # 0xcb +'Lang ', # 0xcc +'Xuan ', # 0xcd +'Cheng ', # 0xce +'Yan ', # 0xcf +'Jin ', # 0xd0 +'Zhe ', # 0xd1 +'Lei ', # 0xd2 +'Lie ', # 0xd3 +'Bu ', # 0xd4 +'Cheng ', # 0xd5 +'Gomi ', # 0xd6 +'Bu ', # 0xd7 +'Shi ', # 0xd8 +'Xun ', # 0xd9 +'Guo ', # 0xda +'Jiong ', # 0xdb +'Ye ', # 0xdc +'Nian ', # 0xdd +'Di ', # 0xde +'Yu ', # 0xdf +'Bu ', # 0xe0 +'Ya ', # 0xe1 +'Juan ', # 0xe2 +'Sui ', # 0xe3 +'Pi ', # 0xe4 +'Cheng ', # 0xe5 +'Wan ', # 0xe6 +'Ju ', # 0xe7 +'Lun ', # 0xe8 +'Zheng ', # 0xe9 +'Kong ', # 0xea +'Chong ', # 0xeb +'Dong ', # 0xec +'Dai ', # 0xed +'Tan ', # 0xee +'An ', # 0xef +'Cai ', # 0xf0 +'Shu ', # 0xf1 +'Beng ', # 0xf2 +'Kan ', # 0xf3 +'Zhi ', # 0xf4 +'Duo ', # 0xf5 +'Yi ', # 0xf6 +'Zhi ', # 0xf7 +'Yi ', # 0xf8 +'Pei ', # 0xf9 +'Ji ', # 0xfa +'Zhun ', # 0xfb +'Qi ', # 0xfc +'Sao ', # 0xfd +'Ju ', # 0xfe +'Ni ', # 0xff +) diff --git a/nstock/modules/unidecode/x058.py b/nstock/modules/unidecode/x058.py new file mode 100644 index 0000000..8805718 --- /dev/null +++ b/nstock/modules/unidecode/x058.py @@ -0,0 +1,258 @@ +data = ( +'Ku ', # 0x00 +'Ke ', # 0x01 +'Tang ', # 0x02 +'Kun ', # 0x03 +'Ni ', # 0x04 +'Jian ', # 0x05 +'Dui ', # 0x06 +'Jin ', # 0x07 +'Gang ', # 0x08 +'Yu ', # 0x09 +'E ', # 0x0a +'Peng ', # 0x0b +'Gu ', # 0x0c +'Tu ', # 0x0d +'Leng ', # 0x0e +'[?] ', # 0x0f +'Ya ', # 0x10 +'Qian ', # 0x11 +'[?] ', # 0x12 +'An ', # 0x13 +'[?] ', # 0x14 +'Duo ', # 0x15 +'Nao ', # 0x16 +'Tu ', # 0x17 +'Cheng ', # 0x18 +'Yin ', # 0x19 +'Hun ', # 0x1a +'Bi ', # 0x1b +'Lian ', # 0x1c +'Guo ', # 0x1d +'Die ', # 0x1e +'Zhuan ', # 0x1f +'Hou ', # 0x20 +'Bao ', # 0x21 +'Bao ', # 0x22 +'Yu ', # 0x23 +'Di ', # 0x24 +'Mao ', # 0x25 +'Jie ', # 0x26 +'Ruan ', # 0x27 +'E ', # 0x28 +'Geng ', # 0x29 +'Kan ', # 0x2a +'Zong ', # 0x2b +'Yu ', # 0x2c +'Huang ', # 0x2d +'E ', # 0x2e +'Yao ', # 0x2f +'Yan ', # 0x30 +'Bao ', # 0x31 +'Ji ', # 0x32 +'Mei ', # 0x33 +'Chang ', # 0x34 +'Du ', # 0x35 +'Tuo ', # 0x36 +'Yin ', # 0x37 +'Feng ', # 0x38 +'Zhong ', # 0x39 +'Jie ', # 0x3a +'Zhen ', # 0x3b +'Feng ', # 0x3c +'Gang ', # 0x3d +'Chuan ', # 0x3e +'Jian ', # 0x3f +'Pyeng ', # 0x40 +'Toride ', # 0x41 +'Xiang ', # 0x42 +'Huang ', # 0x43 +'Leng ', # 0x44 +'Duan ', # 0x45 +'[?] ', # 0x46 +'Xuan ', # 0x47 +'Ji ', # 0x48 +'Ji ', # 0x49 +'Kuai ', # 0x4a +'Ying ', # 0x4b +'Ta ', # 0x4c +'Cheng ', # 0x4d +'Yong ', # 0x4e +'Kai ', # 0x4f +'Su ', # 0x50 +'Su ', # 0x51 +'Shi ', # 0x52 +'Mi ', # 0x53 +'Ta ', # 0x54 +'Weng ', # 0x55 +'Cheng ', # 0x56 +'Tu ', # 0x57 +'Tang ', # 0x58 +'Que ', # 0x59 +'Zhong ', # 0x5a +'Li ', # 0x5b +'Peng ', # 0x5c +'Bang ', # 0x5d +'Sai ', # 0x5e +'Zang ', # 0x5f +'Dui ', # 0x60 +'Tian ', # 0x61 +'Wu ', # 0x62 +'Cheng ', # 0x63 +'Xun ', # 0x64 +'Ge ', # 0x65 +'Zhen ', # 0x66 +'Ai ', # 0x67 +'Gong ', # 0x68 +'Yan ', # 0x69 +'Kan ', # 0x6a +'Tian ', # 0x6b +'Yuan ', # 0x6c +'Wen ', # 0x6d +'Xie ', # 0x6e +'Liu ', # 0x6f +'Ama ', # 0x70 +'Lang ', # 0x71 +'Chang ', # 0x72 +'Peng ', # 0x73 +'Beng ', # 0x74 +'Chen ', # 0x75 +'Cu ', # 0x76 +'Lu ', # 0x77 +'Ou ', # 0x78 +'Qian ', # 0x79 +'Mei ', # 0x7a +'Mo ', # 0x7b +'Zhuan ', # 0x7c +'Shuang ', # 0x7d +'Shu ', # 0x7e +'Lou ', # 0x7f +'Chi ', # 0x80 +'Man ', # 0x81 +'Biao ', # 0x82 +'Jing ', # 0x83 +'Qi ', # 0x84 +'Shu ', # 0x85 +'Di ', # 0x86 +'Zhang ', # 0x87 +'Kan ', # 0x88 +'Yong ', # 0x89 +'Dian ', # 0x8a +'Chen ', # 0x8b +'Zhi ', # 0x8c +'Xi ', # 0x8d +'Guo ', # 0x8e +'Qiang ', # 0x8f +'Jin ', # 0x90 +'Di ', # 0x91 +'Shang ', # 0x92 +'Mu ', # 0x93 +'Cui ', # 0x94 +'Yan ', # 0x95 +'Ta ', # 0x96 +'Zeng ', # 0x97 +'Qi ', # 0x98 +'Qiang ', # 0x99 +'Liang ', # 0x9a +'[?] ', # 0x9b +'Zhui ', # 0x9c +'Qiao ', # 0x9d +'Zeng ', # 0x9e +'Xu ', # 0x9f +'Shan ', # 0xa0 +'Shan ', # 0xa1 +'Ba ', # 0xa2 +'Pu ', # 0xa3 +'Kuai ', # 0xa4 +'Dong ', # 0xa5 +'Fan ', # 0xa6 +'Que ', # 0xa7 +'Mo ', # 0xa8 +'Dun ', # 0xa9 +'Dun ', # 0xaa +'Dun ', # 0xab +'Di ', # 0xac +'Sheng ', # 0xad +'Duo ', # 0xae +'Duo ', # 0xaf +'Tan ', # 0xb0 +'Deng ', # 0xb1 +'Wu ', # 0xb2 +'Fen ', # 0xb3 +'Huang ', # 0xb4 +'Tan ', # 0xb5 +'Da ', # 0xb6 +'Ye ', # 0xb7 +'Sho ', # 0xb8 +'Mama ', # 0xb9 +'Yu ', # 0xba +'Qiang ', # 0xbb +'Ji ', # 0xbc +'Qiao ', # 0xbd +'Ken ', # 0xbe +'Yi ', # 0xbf +'Pi ', # 0xc0 +'Bi ', # 0xc1 +'Dian ', # 0xc2 +'Jiang ', # 0xc3 +'Ye ', # 0xc4 +'Yong ', # 0xc5 +'Bo ', # 0xc6 +'Tan ', # 0xc7 +'Lan ', # 0xc8 +'Ju ', # 0xc9 +'Huai ', # 0xca +'Dang ', # 0xcb +'Rang ', # 0xcc +'Qian ', # 0xcd +'Xun ', # 0xce +'Lan ', # 0xcf +'Xi ', # 0xd0 +'He ', # 0xd1 +'Ai ', # 0xd2 +'Ya ', # 0xd3 +'Dao ', # 0xd4 +'Hao ', # 0xd5 +'Ruan ', # 0xd6 +'Mama ', # 0xd7 +'Lei ', # 0xd8 +'Kuang ', # 0xd9 +'Lu ', # 0xda +'Yan ', # 0xdb +'Tan ', # 0xdc +'Wei ', # 0xdd +'Huai ', # 0xde +'Long ', # 0xdf +'Long ', # 0xe0 +'Rui ', # 0xe1 +'Li ', # 0xe2 +'Lin ', # 0xe3 +'Rang ', # 0xe4 +'Ten ', # 0xe5 +'Xun ', # 0xe6 +'Yan ', # 0xe7 +'Lei ', # 0xe8 +'Ba ', # 0xe9 +'[?] ', # 0xea +'Shi ', # 0xeb +'Ren ', # 0xec +'[?] ', # 0xed +'Zhuang ', # 0xee +'Zhuang ', # 0xef +'Sheng ', # 0xf0 +'Yi ', # 0xf1 +'Mai ', # 0xf2 +'Ke ', # 0xf3 +'Zhu ', # 0xf4 +'Zhuang ', # 0xf5 +'Hu ', # 0xf6 +'Hu ', # 0xf7 +'Kun ', # 0xf8 +'Yi ', # 0xf9 +'Hu ', # 0xfa +'Xu ', # 0xfb +'Kun ', # 0xfc +'Shou ', # 0xfd +'Mang ', # 0xfe +'Zun ', # 0xff +) diff --git a/nstock/modules/unidecode/x059.py b/nstock/modules/unidecode/x059.py new file mode 100644 index 0000000..4596666 --- /dev/null +++ b/nstock/modules/unidecode/x059.py @@ -0,0 +1,258 @@ +data = ( +'Shou ', # 0x00 +'Yi ', # 0x01 +'Zhi ', # 0x02 +'Gu ', # 0x03 +'Chu ', # 0x04 +'Jiang ', # 0x05 +'Feng ', # 0x06 +'Bei ', # 0x07 +'Cay ', # 0x08 +'Bian ', # 0x09 +'Sui ', # 0x0a +'Qun ', # 0x0b +'Ling ', # 0x0c +'Fu ', # 0x0d +'Zuo ', # 0x0e +'Xia ', # 0x0f +'Xiong ', # 0x10 +'[?] ', # 0x11 +'Nao ', # 0x12 +'Xia ', # 0x13 +'Kui ', # 0x14 +'Xi ', # 0x15 +'Wai ', # 0x16 +'Yuan ', # 0x17 +'Mao ', # 0x18 +'Su ', # 0x19 +'Duo ', # 0x1a +'Duo ', # 0x1b +'Ye ', # 0x1c +'Qing ', # 0x1d +'Uys ', # 0x1e +'Gou ', # 0x1f +'Gou ', # 0x20 +'Qi ', # 0x21 +'Meng ', # 0x22 +'Meng ', # 0x23 +'Yin ', # 0x24 +'Huo ', # 0x25 +'Chen ', # 0x26 +'Da ', # 0x27 +'Ze ', # 0x28 +'Tian ', # 0x29 +'Tai ', # 0x2a +'Fu ', # 0x2b +'Guai ', # 0x2c +'Yao ', # 0x2d +'Yang ', # 0x2e +'Hang ', # 0x2f +'Gao ', # 0x30 +'Shi ', # 0x31 +'Ben ', # 0x32 +'Tai ', # 0x33 +'Tou ', # 0x34 +'Yan ', # 0x35 +'Bi ', # 0x36 +'Yi ', # 0x37 +'Kua ', # 0x38 +'Jia ', # 0x39 +'Duo ', # 0x3a +'Kwu ', # 0x3b +'Kuang ', # 0x3c +'Yun ', # 0x3d +'Jia ', # 0x3e +'Pa ', # 0x3f +'En ', # 0x40 +'Lian ', # 0x41 +'Huan ', # 0x42 +'Di ', # 0x43 +'Yan ', # 0x44 +'Pao ', # 0x45 +'Quan ', # 0x46 +'Qi ', # 0x47 +'Nai ', # 0x48 +'Feng ', # 0x49 +'Xie ', # 0x4a +'Fen ', # 0x4b +'Dian ', # 0x4c +'[?] ', # 0x4d +'Kui ', # 0x4e +'Zou ', # 0x4f +'Huan ', # 0x50 +'Qi ', # 0x51 +'Kai ', # 0x52 +'Zha ', # 0x53 +'Ben ', # 0x54 +'Yi ', # 0x55 +'Jiang ', # 0x56 +'Tao ', # 0x57 +'Zang ', # 0x58 +'Ben ', # 0x59 +'Xi ', # 0x5a +'Xiang ', # 0x5b +'Fei ', # 0x5c +'Diao ', # 0x5d +'Xun ', # 0x5e +'Keng ', # 0x5f +'Dian ', # 0x60 +'Ao ', # 0x61 +'She ', # 0x62 +'Weng ', # 0x63 +'Pan ', # 0x64 +'Ao ', # 0x65 +'Wu ', # 0x66 +'Ao ', # 0x67 +'Jiang ', # 0x68 +'Lian ', # 0x69 +'Duo ', # 0x6a +'Yun ', # 0x6b +'Jiang ', # 0x6c +'Shi ', # 0x6d +'Fen ', # 0x6e +'Huo ', # 0x6f +'Bi ', # 0x70 +'Lian ', # 0x71 +'Duo ', # 0x72 +'Nu ', # 0x73 +'Nu ', # 0x74 +'Ding ', # 0x75 +'Nai ', # 0x76 +'Qian ', # 0x77 +'Jian ', # 0x78 +'Ta ', # 0x79 +'Jiu ', # 0x7a +'Nan ', # 0x7b +'Cha ', # 0x7c +'Hao ', # 0x7d +'Xian ', # 0x7e +'Fan ', # 0x7f +'Ji ', # 0x80 +'Shuo ', # 0x81 +'Ru ', # 0x82 +'Fei ', # 0x83 +'Wang ', # 0x84 +'Hong ', # 0x85 +'Zhuang ', # 0x86 +'Fu ', # 0x87 +'Ma ', # 0x88 +'Dan ', # 0x89 +'Ren ', # 0x8a +'Fu ', # 0x8b +'Jing ', # 0x8c +'Yan ', # 0x8d +'Xie ', # 0x8e +'Wen ', # 0x8f +'Zhong ', # 0x90 +'Pa ', # 0x91 +'Du ', # 0x92 +'Ji ', # 0x93 +'Keng ', # 0x94 +'Zhong ', # 0x95 +'Yao ', # 0x96 +'Jin ', # 0x97 +'Yun ', # 0x98 +'Miao ', # 0x99 +'Pei ', # 0x9a +'Shi ', # 0x9b +'Yue ', # 0x9c +'Zhuang ', # 0x9d +'Niu ', # 0x9e +'Yan ', # 0x9f +'Na ', # 0xa0 +'Xin ', # 0xa1 +'Fen ', # 0xa2 +'Bi ', # 0xa3 +'Yu ', # 0xa4 +'Tuo ', # 0xa5 +'Feng ', # 0xa6 +'Yuan ', # 0xa7 +'Fang ', # 0xa8 +'Wu ', # 0xa9 +'Yu ', # 0xaa +'Gui ', # 0xab +'Du ', # 0xac +'Ba ', # 0xad +'Ni ', # 0xae +'Zhou ', # 0xaf +'Zhuo ', # 0xb0 +'Zhao ', # 0xb1 +'Da ', # 0xb2 +'Nai ', # 0xb3 +'Yuan ', # 0xb4 +'Tou ', # 0xb5 +'Xuan ', # 0xb6 +'Zhi ', # 0xb7 +'E ', # 0xb8 +'Mei ', # 0xb9 +'Mo ', # 0xba +'Qi ', # 0xbb +'Bi ', # 0xbc +'Shen ', # 0xbd +'Qie ', # 0xbe +'E ', # 0xbf +'He ', # 0xc0 +'Xu ', # 0xc1 +'Fa ', # 0xc2 +'Zheng ', # 0xc3 +'Min ', # 0xc4 +'Ban ', # 0xc5 +'Mu ', # 0xc6 +'Fu ', # 0xc7 +'Ling ', # 0xc8 +'Zi ', # 0xc9 +'Zi ', # 0xca +'Shi ', # 0xcb +'Ran ', # 0xcc +'Shan ', # 0xcd +'Yang ', # 0xce +'Man ', # 0xcf +'Jie ', # 0xd0 +'Gu ', # 0xd1 +'Si ', # 0xd2 +'Xing ', # 0xd3 +'Wei ', # 0xd4 +'Zi ', # 0xd5 +'Ju ', # 0xd6 +'Shan ', # 0xd7 +'Pin ', # 0xd8 +'Ren ', # 0xd9 +'Yao ', # 0xda +'Tong ', # 0xdb +'Jiang ', # 0xdc +'Shu ', # 0xdd +'Ji ', # 0xde +'Gai ', # 0xdf +'Shang ', # 0xe0 +'Kuo ', # 0xe1 +'Juan ', # 0xe2 +'Jiao ', # 0xe3 +'Gou ', # 0xe4 +'Mu ', # 0xe5 +'Jian ', # 0xe6 +'Jian ', # 0xe7 +'Yi ', # 0xe8 +'Nian ', # 0xe9 +'Zhi ', # 0xea +'Ji ', # 0xeb +'Ji ', # 0xec +'Xian ', # 0xed +'Heng ', # 0xee +'Guang ', # 0xef +'Jun ', # 0xf0 +'Kua ', # 0xf1 +'Yan ', # 0xf2 +'Ming ', # 0xf3 +'Lie ', # 0xf4 +'Pei ', # 0xf5 +'Yan ', # 0xf6 +'You ', # 0xf7 +'Yan ', # 0xf8 +'Cha ', # 0xf9 +'Shen ', # 0xfa +'Yin ', # 0xfb +'Chi ', # 0xfc +'Gui ', # 0xfd +'Quan ', # 0xfe +'Zi ', # 0xff +) diff --git a/nstock/modules/unidecode/x05a.py b/nstock/modules/unidecode/x05a.py new file mode 100644 index 0000000..be56e65 --- /dev/null +++ b/nstock/modules/unidecode/x05a.py @@ -0,0 +1,258 @@ +data = ( +'Song ', # 0x00 +'Wei ', # 0x01 +'Hong ', # 0x02 +'Wa ', # 0x03 +'Lou ', # 0x04 +'Ya ', # 0x05 +'Rao ', # 0x06 +'Jiao ', # 0x07 +'Luan ', # 0x08 +'Ping ', # 0x09 +'Xian ', # 0x0a +'Shao ', # 0x0b +'Li ', # 0x0c +'Cheng ', # 0x0d +'Xiao ', # 0x0e +'Mang ', # 0x0f +'Fu ', # 0x10 +'Suo ', # 0x11 +'Wu ', # 0x12 +'Wei ', # 0x13 +'Ke ', # 0x14 +'Lai ', # 0x15 +'Chuo ', # 0x16 +'Ding ', # 0x17 +'Niang ', # 0x18 +'Xing ', # 0x19 +'Nan ', # 0x1a +'Yu ', # 0x1b +'Nuo ', # 0x1c +'Pei ', # 0x1d +'Nei ', # 0x1e +'Juan ', # 0x1f +'Shen ', # 0x20 +'Zhi ', # 0x21 +'Han ', # 0x22 +'Di ', # 0x23 +'Zhuang ', # 0x24 +'E ', # 0x25 +'Pin ', # 0x26 +'Tui ', # 0x27 +'Han ', # 0x28 +'Mian ', # 0x29 +'Wu ', # 0x2a +'Yan ', # 0x2b +'Wu ', # 0x2c +'Xi ', # 0x2d +'Yan ', # 0x2e +'Yu ', # 0x2f +'Si ', # 0x30 +'Yu ', # 0x31 +'Wa ', # 0x32 +'[?] ', # 0x33 +'Xian ', # 0x34 +'Ju ', # 0x35 +'Qu ', # 0x36 +'Shui ', # 0x37 +'Qi ', # 0x38 +'Xian ', # 0x39 +'Zhui ', # 0x3a +'Dong ', # 0x3b +'Chang ', # 0x3c +'Lu ', # 0x3d +'Ai ', # 0x3e +'E ', # 0x3f +'E ', # 0x40 +'Lou ', # 0x41 +'Mian ', # 0x42 +'Cong ', # 0x43 +'Pou ', # 0x44 +'Ju ', # 0x45 +'Po ', # 0x46 +'Cai ', # 0x47 +'Ding ', # 0x48 +'Wan ', # 0x49 +'Biao ', # 0x4a +'Xiao ', # 0x4b +'Shu ', # 0x4c +'Qi ', # 0x4d +'Hui ', # 0x4e +'Fu ', # 0x4f +'E ', # 0x50 +'Wo ', # 0x51 +'Tan ', # 0x52 +'Fei ', # 0x53 +'Wei ', # 0x54 +'Jie ', # 0x55 +'Tian ', # 0x56 +'Ni ', # 0x57 +'Quan ', # 0x58 +'Jing ', # 0x59 +'Hun ', # 0x5a +'Jing ', # 0x5b +'Qian ', # 0x5c +'Dian ', # 0x5d +'Xing ', # 0x5e +'Hu ', # 0x5f +'Wa ', # 0x60 +'Lai ', # 0x61 +'Bi ', # 0x62 +'Yin ', # 0x63 +'Chou ', # 0x64 +'Chuo ', # 0x65 +'Fu ', # 0x66 +'Jing ', # 0x67 +'Lun ', # 0x68 +'Yan ', # 0x69 +'Lan ', # 0x6a +'Kun ', # 0x6b +'Yin ', # 0x6c +'Ya ', # 0x6d +'Ju ', # 0x6e +'Li ', # 0x6f +'Dian ', # 0x70 +'Xian ', # 0x71 +'Hwa ', # 0x72 +'Hua ', # 0x73 +'Ying ', # 0x74 +'Chan ', # 0x75 +'Shen ', # 0x76 +'Ting ', # 0x77 +'Dang ', # 0x78 +'Yao ', # 0x79 +'Wu ', # 0x7a +'Nan ', # 0x7b +'Ruo ', # 0x7c +'Jia ', # 0x7d +'Tou ', # 0x7e +'Xu ', # 0x7f +'Yu ', # 0x80 +'Wei ', # 0x81 +'Ti ', # 0x82 +'Rou ', # 0x83 +'Mei ', # 0x84 +'Dan ', # 0x85 +'Ruan ', # 0x86 +'Qin ', # 0x87 +'Hui ', # 0x88 +'Wu ', # 0x89 +'Qian ', # 0x8a +'Chun ', # 0x8b +'Mao ', # 0x8c +'Fu ', # 0x8d +'Jie ', # 0x8e +'Duan ', # 0x8f +'Xi ', # 0x90 +'Zhong ', # 0x91 +'Mei ', # 0x92 +'Huang ', # 0x93 +'Mian ', # 0x94 +'An ', # 0x95 +'Ying ', # 0x96 +'Xuan ', # 0x97 +'Jie ', # 0x98 +'Wei ', # 0x99 +'Mei ', # 0x9a +'Yuan ', # 0x9b +'Zhen ', # 0x9c +'Qiu ', # 0x9d +'Ti ', # 0x9e +'Xie ', # 0x9f +'Tuo ', # 0xa0 +'Lian ', # 0xa1 +'Mao ', # 0xa2 +'Ran ', # 0xa3 +'Si ', # 0xa4 +'Pian ', # 0xa5 +'Wei ', # 0xa6 +'Wa ', # 0xa7 +'Jiu ', # 0xa8 +'Hu ', # 0xa9 +'Ao ', # 0xaa +'[?] ', # 0xab +'Bou ', # 0xac +'Xu ', # 0xad +'Tou ', # 0xae +'Gui ', # 0xaf +'Zou ', # 0xb0 +'Yao ', # 0xb1 +'Pi ', # 0xb2 +'Xi ', # 0xb3 +'Yuan ', # 0xb4 +'Ying ', # 0xb5 +'Rong ', # 0xb6 +'Ru ', # 0xb7 +'Chi ', # 0xb8 +'Liu ', # 0xb9 +'Mei ', # 0xba +'Pan ', # 0xbb +'Ao ', # 0xbc +'Ma ', # 0xbd +'Gou ', # 0xbe +'Kui ', # 0xbf +'Qin ', # 0xc0 +'Jia ', # 0xc1 +'Sao ', # 0xc2 +'Zhen ', # 0xc3 +'Yuan ', # 0xc4 +'Cha ', # 0xc5 +'Yong ', # 0xc6 +'Ming ', # 0xc7 +'Ying ', # 0xc8 +'Ji ', # 0xc9 +'Su ', # 0xca +'Niao ', # 0xcb +'Xian ', # 0xcc +'Tao ', # 0xcd +'Pang ', # 0xce +'Lang ', # 0xcf +'Nao ', # 0xd0 +'Bao ', # 0xd1 +'Ai ', # 0xd2 +'Pi ', # 0xd3 +'Pin ', # 0xd4 +'Yi ', # 0xd5 +'Piao ', # 0xd6 +'Yu ', # 0xd7 +'Lei ', # 0xd8 +'Xuan ', # 0xd9 +'Man ', # 0xda +'Yi ', # 0xdb +'Zhang ', # 0xdc +'Kang ', # 0xdd +'Yong ', # 0xde +'Ni ', # 0xdf +'Li ', # 0xe0 +'Di ', # 0xe1 +'Gui ', # 0xe2 +'Yan ', # 0xe3 +'Jin ', # 0xe4 +'Zhuan ', # 0xe5 +'Chang ', # 0xe6 +'Ce ', # 0xe7 +'Han ', # 0xe8 +'Nen ', # 0xe9 +'Lao ', # 0xea +'Mo ', # 0xeb +'Zhe ', # 0xec +'Hu ', # 0xed +'Hu ', # 0xee +'Ao ', # 0xef +'Nen ', # 0xf0 +'Qiang ', # 0xf1 +'Ma ', # 0xf2 +'Pie ', # 0xf3 +'Gu ', # 0xf4 +'Wu ', # 0xf5 +'Jiao ', # 0xf6 +'Tuo ', # 0xf7 +'Zhan ', # 0xf8 +'Mao ', # 0xf9 +'Xian ', # 0xfa +'Xian ', # 0xfb +'Mo ', # 0xfc +'Liao ', # 0xfd +'Lian ', # 0xfe +'Hua ', # 0xff +) diff --git a/nstock/modules/unidecode/x05b.py b/nstock/modules/unidecode/x05b.py new file mode 100644 index 0000000..1b167b3 --- /dev/null +++ b/nstock/modules/unidecode/x05b.py @@ -0,0 +1,258 @@ +data = ( +'Gui ', # 0x00 +'Deng ', # 0x01 +'Zhi ', # 0x02 +'Xu ', # 0x03 +'Yi ', # 0x04 +'Hua ', # 0x05 +'Xi ', # 0x06 +'Hui ', # 0x07 +'Rao ', # 0x08 +'Xi ', # 0x09 +'Yan ', # 0x0a +'Chan ', # 0x0b +'Jiao ', # 0x0c +'Mei ', # 0x0d +'Fan ', # 0x0e +'Fan ', # 0x0f +'Xian ', # 0x10 +'Yi ', # 0x11 +'Wei ', # 0x12 +'Jiao ', # 0x13 +'Fu ', # 0x14 +'Shi ', # 0x15 +'Bi ', # 0x16 +'Shan ', # 0x17 +'Sui ', # 0x18 +'Qiang ', # 0x19 +'Lian ', # 0x1a +'Huan ', # 0x1b +'Xin ', # 0x1c +'Niao ', # 0x1d +'Dong ', # 0x1e +'Yi ', # 0x1f +'Can ', # 0x20 +'Ai ', # 0x21 +'Niang ', # 0x22 +'Neng ', # 0x23 +'Ma ', # 0x24 +'Tiao ', # 0x25 +'Chou ', # 0x26 +'Jin ', # 0x27 +'Ci ', # 0x28 +'Yu ', # 0x29 +'Pin ', # 0x2a +'Yong ', # 0x2b +'Xu ', # 0x2c +'Nai ', # 0x2d +'Yan ', # 0x2e +'Tai ', # 0x2f +'Ying ', # 0x30 +'Can ', # 0x31 +'Niao ', # 0x32 +'Wo ', # 0x33 +'Ying ', # 0x34 +'Mian ', # 0x35 +'Kaka ', # 0x36 +'Ma ', # 0x37 +'Shen ', # 0x38 +'Xing ', # 0x39 +'Ni ', # 0x3a +'Du ', # 0x3b +'Liu ', # 0x3c +'Yuan ', # 0x3d +'Lan ', # 0x3e +'Yan ', # 0x3f +'Shuang ', # 0x40 +'Ling ', # 0x41 +'Jiao ', # 0x42 +'Niang ', # 0x43 +'Lan ', # 0x44 +'Xian ', # 0x45 +'Ying ', # 0x46 +'Shuang ', # 0x47 +'Shuai ', # 0x48 +'Quan ', # 0x49 +'Mi ', # 0x4a +'Li ', # 0x4b +'Luan ', # 0x4c +'Yan ', # 0x4d +'Zhu ', # 0x4e +'Lan ', # 0x4f +'Zi ', # 0x50 +'Jie ', # 0x51 +'Jue ', # 0x52 +'Jue ', # 0x53 +'Kong ', # 0x54 +'Yun ', # 0x55 +'Zi ', # 0x56 +'Zi ', # 0x57 +'Cun ', # 0x58 +'Sun ', # 0x59 +'Fu ', # 0x5a +'Bei ', # 0x5b +'Zi ', # 0x5c +'Xiao ', # 0x5d +'Xin ', # 0x5e +'Meng ', # 0x5f +'Si ', # 0x60 +'Tai ', # 0x61 +'Bao ', # 0x62 +'Ji ', # 0x63 +'Gu ', # 0x64 +'Nu ', # 0x65 +'Xue ', # 0x66 +'[?] ', # 0x67 +'Zhuan ', # 0x68 +'Hai ', # 0x69 +'Luan ', # 0x6a +'Sun ', # 0x6b +'Huai ', # 0x6c +'Mie ', # 0x6d +'Cong ', # 0x6e +'Qian ', # 0x6f +'Shu ', # 0x70 +'Chan ', # 0x71 +'Ya ', # 0x72 +'Zi ', # 0x73 +'Ni ', # 0x74 +'Fu ', # 0x75 +'Zi ', # 0x76 +'Li ', # 0x77 +'Xue ', # 0x78 +'Bo ', # 0x79 +'Ru ', # 0x7a +'Lai ', # 0x7b +'Nie ', # 0x7c +'Nie ', # 0x7d +'Ying ', # 0x7e +'Luan ', # 0x7f +'Mian ', # 0x80 +'Zhu ', # 0x81 +'Rong ', # 0x82 +'Ta ', # 0x83 +'Gui ', # 0x84 +'Zhai ', # 0x85 +'Qiong ', # 0x86 +'Yu ', # 0x87 +'Shou ', # 0x88 +'An ', # 0x89 +'Tu ', # 0x8a +'Song ', # 0x8b +'Wan ', # 0x8c +'Rou ', # 0x8d +'Yao ', # 0x8e +'Hong ', # 0x8f +'Yi ', # 0x90 +'Jing ', # 0x91 +'Zhun ', # 0x92 +'Mi ', # 0x93 +'Zhu ', # 0x94 +'Dang ', # 0x95 +'Hong ', # 0x96 +'Zong ', # 0x97 +'Guan ', # 0x98 +'Zhou ', # 0x99 +'Ding ', # 0x9a +'Wan ', # 0x9b +'Yi ', # 0x9c +'Bao ', # 0x9d +'Shi ', # 0x9e +'Shi ', # 0x9f +'Chong ', # 0xa0 +'Shen ', # 0xa1 +'Ke ', # 0xa2 +'Xuan ', # 0xa3 +'Shi ', # 0xa4 +'You ', # 0xa5 +'Huan ', # 0xa6 +'Yi ', # 0xa7 +'Tiao ', # 0xa8 +'Shi ', # 0xa9 +'Xian ', # 0xaa +'Gong ', # 0xab +'Cheng ', # 0xac +'Qun ', # 0xad +'Gong ', # 0xae +'Xiao ', # 0xaf +'Zai ', # 0xb0 +'Zha ', # 0xb1 +'Bao ', # 0xb2 +'Hai ', # 0xb3 +'Yan ', # 0xb4 +'Xiao ', # 0xb5 +'Jia ', # 0xb6 +'Shen ', # 0xb7 +'Chen ', # 0xb8 +'Rong ', # 0xb9 +'Huang ', # 0xba +'Mi ', # 0xbb +'Kou ', # 0xbc +'Kuan ', # 0xbd +'Bin ', # 0xbe +'Su ', # 0xbf +'Cai ', # 0xc0 +'Zan ', # 0xc1 +'Ji ', # 0xc2 +'Yuan ', # 0xc3 +'Ji ', # 0xc4 +'Yin ', # 0xc5 +'Mi ', # 0xc6 +'Kou ', # 0xc7 +'Qing ', # 0xc8 +'Que ', # 0xc9 +'Zhen ', # 0xca +'Jian ', # 0xcb +'Fu ', # 0xcc +'Ning ', # 0xcd +'Bing ', # 0xce +'Huan ', # 0xcf +'Mei ', # 0xd0 +'Qin ', # 0xd1 +'Han ', # 0xd2 +'Yu ', # 0xd3 +'Shi ', # 0xd4 +'Ning ', # 0xd5 +'Qin ', # 0xd6 +'Ning ', # 0xd7 +'Zhi ', # 0xd8 +'Yu ', # 0xd9 +'Bao ', # 0xda +'Kuan ', # 0xdb +'Ning ', # 0xdc +'Qin ', # 0xdd +'Mo ', # 0xde +'Cha ', # 0xdf +'Ju ', # 0xe0 +'Gua ', # 0xe1 +'Qin ', # 0xe2 +'Hu ', # 0xe3 +'Wu ', # 0xe4 +'Liao ', # 0xe5 +'Shi ', # 0xe6 +'Zhu ', # 0xe7 +'Zhai ', # 0xe8 +'Shen ', # 0xe9 +'Wei ', # 0xea +'Xie ', # 0xeb +'Kuan ', # 0xec +'Hui ', # 0xed +'Liao ', # 0xee +'Jun ', # 0xef +'Huan ', # 0xf0 +'Yi ', # 0xf1 +'Yi ', # 0xf2 +'Bao ', # 0xf3 +'Qin ', # 0xf4 +'Chong ', # 0xf5 +'Bao ', # 0xf6 +'Feng ', # 0xf7 +'Cun ', # 0xf8 +'Dui ', # 0xf9 +'Si ', # 0xfa +'Xun ', # 0xfb +'Dao ', # 0xfc +'Lu ', # 0xfd +'Dui ', # 0xfe +'Shou ', # 0xff +) diff --git a/nstock/modules/unidecode/x05c.py b/nstock/modules/unidecode/x05c.py new file mode 100644 index 0000000..62957e8 --- /dev/null +++ b/nstock/modules/unidecode/x05c.py @@ -0,0 +1,258 @@ +data = ( +'Po ', # 0x00 +'Feng ', # 0x01 +'Zhuan ', # 0x02 +'Fu ', # 0x03 +'She ', # 0x04 +'Ke ', # 0x05 +'Jiang ', # 0x06 +'Jiang ', # 0x07 +'Zhuan ', # 0x08 +'Wei ', # 0x09 +'Zun ', # 0x0a +'Xun ', # 0x0b +'Shu ', # 0x0c +'Dui ', # 0x0d +'Dao ', # 0x0e +'Xiao ', # 0x0f +'Ji ', # 0x10 +'Shao ', # 0x11 +'Er ', # 0x12 +'Er ', # 0x13 +'Er ', # 0x14 +'Ga ', # 0x15 +'Jian ', # 0x16 +'Shu ', # 0x17 +'Chen ', # 0x18 +'Shang ', # 0x19 +'Shang ', # 0x1a +'Mo ', # 0x1b +'Ga ', # 0x1c +'Chang ', # 0x1d +'Liao ', # 0x1e +'Xian ', # 0x1f +'Xian ', # 0x20 +'[?] ', # 0x21 +'Wang ', # 0x22 +'Wang ', # 0x23 +'You ', # 0x24 +'Liao ', # 0x25 +'Liao ', # 0x26 +'Yao ', # 0x27 +'Mang ', # 0x28 +'Wang ', # 0x29 +'Wang ', # 0x2a +'Wang ', # 0x2b +'Ga ', # 0x2c +'Yao ', # 0x2d +'Duo ', # 0x2e +'Kui ', # 0x2f +'Zhong ', # 0x30 +'Jiu ', # 0x31 +'Gan ', # 0x32 +'Gu ', # 0x33 +'Gan ', # 0x34 +'Tui ', # 0x35 +'Gan ', # 0x36 +'Gan ', # 0x37 +'Shi ', # 0x38 +'Yin ', # 0x39 +'Chi ', # 0x3a +'Kao ', # 0x3b +'Ni ', # 0x3c +'Jin ', # 0x3d +'Wei ', # 0x3e +'Niao ', # 0x3f +'Ju ', # 0x40 +'Pi ', # 0x41 +'Ceng ', # 0x42 +'Xi ', # 0x43 +'Bi ', # 0x44 +'Ju ', # 0x45 +'Jie ', # 0x46 +'Tian ', # 0x47 +'Qu ', # 0x48 +'Ti ', # 0x49 +'Jie ', # 0x4a +'Wu ', # 0x4b +'Diao ', # 0x4c +'Shi ', # 0x4d +'Shi ', # 0x4e +'Ping ', # 0x4f +'Ji ', # 0x50 +'Xie ', # 0x51 +'Chen ', # 0x52 +'Xi ', # 0x53 +'Ni ', # 0x54 +'Zhan ', # 0x55 +'Xi ', # 0x56 +'[?] ', # 0x57 +'Man ', # 0x58 +'E ', # 0x59 +'Lou ', # 0x5a +'Ping ', # 0x5b +'Ti ', # 0x5c +'Fei ', # 0x5d +'Shu ', # 0x5e +'Xie ', # 0x5f +'Tu ', # 0x60 +'Lu ', # 0x61 +'Lu ', # 0x62 +'Xi ', # 0x63 +'Ceng ', # 0x64 +'Lu ', # 0x65 +'Ju ', # 0x66 +'Xie ', # 0x67 +'Ju ', # 0x68 +'Jue ', # 0x69 +'Liao ', # 0x6a +'Jue ', # 0x6b +'Shu ', # 0x6c +'Xi ', # 0x6d +'Che ', # 0x6e +'Tun ', # 0x6f +'Ni ', # 0x70 +'Shan ', # 0x71 +'[?] ', # 0x72 +'Xian ', # 0x73 +'Li ', # 0x74 +'Xue ', # 0x75 +'Nata ', # 0x76 +'[?] ', # 0x77 +'Long ', # 0x78 +'Yi ', # 0x79 +'Qi ', # 0x7a +'Ren ', # 0x7b +'Wu ', # 0x7c +'Han ', # 0x7d +'Shen ', # 0x7e +'Yu ', # 0x7f +'Chu ', # 0x80 +'Sui ', # 0x81 +'Qi ', # 0x82 +'[?] ', # 0x83 +'Yue ', # 0x84 +'Ban ', # 0x85 +'Yao ', # 0x86 +'Ang ', # 0x87 +'Ya ', # 0x88 +'Wu ', # 0x89 +'Jie ', # 0x8a +'E ', # 0x8b +'Ji ', # 0x8c +'Qian ', # 0x8d +'Fen ', # 0x8e +'Yuan ', # 0x8f +'Qi ', # 0x90 +'Cen ', # 0x91 +'Qian ', # 0x92 +'Qi ', # 0x93 +'Cha ', # 0x94 +'Jie ', # 0x95 +'Qu ', # 0x96 +'Gang ', # 0x97 +'Xian ', # 0x98 +'Ao ', # 0x99 +'Lan ', # 0x9a +'Dao ', # 0x9b +'Ba ', # 0x9c +'Zuo ', # 0x9d +'Zuo ', # 0x9e +'Yang ', # 0x9f +'Ju ', # 0xa0 +'Gang ', # 0xa1 +'Ke ', # 0xa2 +'Gou ', # 0xa3 +'Xue ', # 0xa4 +'Bei ', # 0xa5 +'Li ', # 0xa6 +'Tiao ', # 0xa7 +'Ju ', # 0xa8 +'Yan ', # 0xa9 +'Fu ', # 0xaa +'Xiu ', # 0xab +'Jia ', # 0xac +'Ling ', # 0xad +'Tuo ', # 0xae +'Pei ', # 0xaf +'You ', # 0xb0 +'Dai ', # 0xb1 +'Kuang ', # 0xb2 +'Yue ', # 0xb3 +'Qu ', # 0xb4 +'Hu ', # 0xb5 +'Po ', # 0xb6 +'Min ', # 0xb7 +'An ', # 0xb8 +'Tiao ', # 0xb9 +'Ling ', # 0xba +'Chi ', # 0xbb +'Yuri ', # 0xbc +'Dong ', # 0xbd +'Cem ', # 0xbe +'Kui ', # 0xbf +'Xiu ', # 0xc0 +'Mao ', # 0xc1 +'Tong ', # 0xc2 +'Xue ', # 0xc3 +'Yi ', # 0xc4 +'Kura ', # 0xc5 +'He ', # 0xc6 +'Ke ', # 0xc7 +'Luo ', # 0xc8 +'E ', # 0xc9 +'Fu ', # 0xca +'Xun ', # 0xcb +'Die ', # 0xcc +'Lu ', # 0xcd +'An ', # 0xce +'Er ', # 0xcf +'Gai ', # 0xd0 +'Quan ', # 0xd1 +'Tong ', # 0xd2 +'Yi ', # 0xd3 +'Mu ', # 0xd4 +'Shi ', # 0xd5 +'An ', # 0xd6 +'Wei ', # 0xd7 +'Hu ', # 0xd8 +'Zhi ', # 0xd9 +'Mi ', # 0xda +'Li ', # 0xdb +'Ji ', # 0xdc +'Tong ', # 0xdd +'Wei ', # 0xde +'You ', # 0xdf +'Sang ', # 0xe0 +'Xia ', # 0xe1 +'Li ', # 0xe2 +'Yao ', # 0xe3 +'Jiao ', # 0xe4 +'Zheng ', # 0xe5 +'Luan ', # 0xe6 +'Jiao ', # 0xe7 +'E ', # 0xe8 +'E ', # 0xe9 +'Yu ', # 0xea +'Ye ', # 0xeb +'Bu ', # 0xec +'Qiao ', # 0xed +'Qun ', # 0xee +'Feng ', # 0xef +'Feng ', # 0xf0 +'Nao ', # 0xf1 +'Li ', # 0xf2 +'You ', # 0xf3 +'Xian ', # 0xf4 +'Hong ', # 0xf5 +'Dao ', # 0xf6 +'Shen ', # 0xf7 +'Cheng ', # 0xf8 +'Tu ', # 0xf9 +'Geng ', # 0xfa +'Jun ', # 0xfb +'Hao ', # 0xfc +'Xia ', # 0xfd +'Yin ', # 0xfe +'Yu ', # 0xff +) diff --git a/nstock/modules/unidecode/x05d.py b/nstock/modules/unidecode/x05d.py new file mode 100644 index 0000000..c85032a --- /dev/null +++ b/nstock/modules/unidecode/x05d.py @@ -0,0 +1,258 @@ +data = ( +'Lang ', # 0x00 +'Kan ', # 0x01 +'Lao ', # 0x02 +'Lai ', # 0x03 +'Xian ', # 0x04 +'Que ', # 0x05 +'Kong ', # 0x06 +'Chong ', # 0x07 +'Chong ', # 0x08 +'Ta ', # 0x09 +'Lin ', # 0x0a +'Hua ', # 0x0b +'Ju ', # 0x0c +'Lai ', # 0x0d +'Qi ', # 0x0e +'Min ', # 0x0f +'Kun ', # 0x10 +'Kun ', # 0x11 +'Zu ', # 0x12 +'Gu ', # 0x13 +'Cui ', # 0x14 +'Ya ', # 0x15 +'Ya ', # 0x16 +'Gang ', # 0x17 +'Lun ', # 0x18 +'Lun ', # 0x19 +'Leng ', # 0x1a +'Jue ', # 0x1b +'Duo ', # 0x1c +'Zheng ', # 0x1d +'Guo ', # 0x1e +'Yin ', # 0x1f +'Dong ', # 0x20 +'Han ', # 0x21 +'Zheng ', # 0x22 +'Wei ', # 0x23 +'Yao ', # 0x24 +'Pi ', # 0x25 +'Yan ', # 0x26 +'Song ', # 0x27 +'Jie ', # 0x28 +'Beng ', # 0x29 +'Zu ', # 0x2a +'Jue ', # 0x2b +'Dong ', # 0x2c +'Zhan ', # 0x2d +'Gu ', # 0x2e +'Yin ', # 0x2f +'[?] ', # 0x30 +'Ze ', # 0x31 +'Huang ', # 0x32 +'Yu ', # 0x33 +'Wei ', # 0x34 +'Yang ', # 0x35 +'Feng ', # 0x36 +'Qiu ', # 0x37 +'Dun ', # 0x38 +'Ti ', # 0x39 +'Yi ', # 0x3a +'Zhi ', # 0x3b +'Shi ', # 0x3c +'Zai ', # 0x3d +'Yao ', # 0x3e +'E ', # 0x3f +'Zhu ', # 0x40 +'Kan ', # 0x41 +'Lu ', # 0x42 +'Yan ', # 0x43 +'Mei ', # 0x44 +'Gan ', # 0x45 +'Ji ', # 0x46 +'Ji ', # 0x47 +'Huan ', # 0x48 +'Ting ', # 0x49 +'Sheng ', # 0x4a +'Mei ', # 0x4b +'Qian ', # 0x4c +'Wu ', # 0x4d +'Yu ', # 0x4e +'Zong ', # 0x4f +'Lan ', # 0x50 +'Jue ', # 0x51 +'Yan ', # 0x52 +'Yan ', # 0x53 +'Wei ', # 0x54 +'Zong ', # 0x55 +'Cha ', # 0x56 +'Sui ', # 0x57 +'Rong ', # 0x58 +'Yamashina ', # 0x59 +'Qin ', # 0x5a +'Yu ', # 0x5b +'Kewashii ', # 0x5c +'Lou ', # 0x5d +'Tu ', # 0x5e +'Dui ', # 0x5f +'Xi ', # 0x60 +'Weng ', # 0x61 +'Cang ', # 0x62 +'Dang ', # 0x63 +'Hong ', # 0x64 +'Jie ', # 0x65 +'Ai ', # 0x66 +'Liu ', # 0x67 +'Wu ', # 0x68 +'Song ', # 0x69 +'Qiao ', # 0x6a +'Zi ', # 0x6b +'Wei ', # 0x6c +'Beng ', # 0x6d +'Dian ', # 0x6e +'Cuo ', # 0x6f +'Qian ', # 0x70 +'Yong ', # 0x71 +'Nie ', # 0x72 +'Cuo ', # 0x73 +'Ji ', # 0x74 +'[?] ', # 0x75 +'Tao ', # 0x76 +'Song ', # 0x77 +'Zong ', # 0x78 +'Jiang ', # 0x79 +'Liao ', # 0x7a +'Kang ', # 0x7b +'Chan ', # 0x7c +'Die ', # 0x7d +'Cen ', # 0x7e +'Ding ', # 0x7f +'Tu ', # 0x80 +'Lou ', # 0x81 +'Zhang ', # 0x82 +'Zhan ', # 0x83 +'Zhan ', # 0x84 +'Ao ', # 0x85 +'Cao ', # 0x86 +'Qu ', # 0x87 +'Qiang ', # 0x88 +'Zui ', # 0x89 +'Zui ', # 0x8a +'Dao ', # 0x8b +'Dao ', # 0x8c +'Xi ', # 0x8d +'Yu ', # 0x8e +'Bo ', # 0x8f +'Long ', # 0x90 +'Xiang ', # 0x91 +'Ceng ', # 0x92 +'Bo ', # 0x93 +'Qin ', # 0x94 +'Jiao ', # 0x95 +'Yan ', # 0x96 +'Lao ', # 0x97 +'Zhan ', # 0x98 +'Lin ', # 0x99 +'Liao ', # 0x9a +'Liao ', # 0x9b +'Jin ', # 0x9c +'Deng ', # 0x9d +'Duo ', # 0x9e +'Zun ', # 0x9f +'Jiao ', # 0xa0 +'Gui ', # 0xa1 +'Yao ', # 0xa2 +'Qiao ', # 0xa3 +'Yao ', # 0xa4 +'Jue ', # 0xa5 +'Zhan ', # 0xa6 +'Yi ', # 0xa7 +'Xue ', # 0xa8 +'Nao ', # 0xa9 +'Ye ', # 0xaa +'Ye ', # 0xab +'Yi ', # 0xac +'E ', # 0xad +'Xian ', # 0xae +'Ji ', # 0xaf +'Xie ', # 0xb0 +'Ke ', # 0xb1 +'Xi ', # 0xb2 +'Di ', # 0xb3 +'Ao ', # 0xb4 +'Zui ', # 0xb5 +'[?] ', # 0xb6 +'Ni ', # 0xb7 +'Rong ', # 0xb8 +'Dao ', # 0xb9 +'Ling ', # 0xba +'Za ', # 0xbb +'Yu ', # 0xbc +'Yue ', # 0xbd +'Yin ', # 0xbe +'[?] ', # 0xbf +'Jie ', # 0xc0 +'Li ', # 0xc1 +'Sui ', # 0xc2 +'Long ', # 0xc3 +'Long ', # 0xc4 +'Dian ', # 0xc5 +'Ying ', # 0xc6 +'Xi ', # 0xc7 +'Ju ', # 0xc8 +'Chan ', # 0xc9 +'Ying ', # 0xca +'Kui ', # 0xcb +'Yan ', # 0xcc +'Wei ', # 0xcd +'Nao ', # 0xce +'Quan ', # 0xcf +'Chao ', # 0xd0 +'Cuan ', # 0xd1 +'Luan ', # 0xd2 +'Dian ', # 0xd3 +'Dian ', # 0xd4 +'[?] ', # 0xd5 +'Yan ', # 0xd6 +'Yan ', # 0xd7 +'Yan ', # 0xd8 +'Nao ', # 0xd9 +'Yan ', # 0xda +'Chuan ', # 0xdb +'Gui ', # 0xdc +'Chuan ', # 0xdd +'Zhou ', # 0xde +'Huang ', # 0xdf +'Jing ', # 0xe0 +'Xun ', # 0xe1 +'Chao ', # 0xe2 +'Chao ', # 0xe3 +'Lie ', # 0xe4 +'Gong ', # 0xe5 +'Zuo ', # 0xe6 +'Qiao ', # 0xe7 +'Ju ', # 0xe8 +'Gong ', # 0xe9 +'Kek ', # 0xea +'Wu ', # 0xeb +'Pwu ', # 0xec +'Pwu ', # 0xed +'Chai ', # 0xee +'Qiu ', # 0xef +'Qiu ', # 0xf0 +'Ji ', # 0xf1 +'Yi ', # 0xf2 +'Si ', # 0xf3 +'Ba ', # 0xf4 +'Zhi ', # 0xf5 +'Zhao ', # 0xf6 +'Xiang ', # 0xf7 +'Yi ', # 0xf8 +'Jin ', # 0xf9 +'Xun ', # 0xfa +'Juan ', # 0xfb +'Phas ', # 0xfc +'Xun ', # 0xfd +'Jin ', # 0xfe +'Fu ', # 0xff +) diff --git a/nstock/modules/unidecode/x05e.py b/nstock/modules/unidecode/x05e.py new file mode 100644 index 0000000..af87928 --- /dev/null +++ b/nstock/modules/unidecode/x05e.py @@ -0,0 +1,258 @@ +data = ( +'Za ', # 0x00 +'Bi ', # 0x01 +'Shi ', # 0x02 +'Bu ', # 0x03 +'Ding ', # 0x04 +'Shuai ', # 0x05 +'Fan ', # 0x06 +'Nie ', # 0x07 +'Shi ', # 0x08 +'Fen ', # 0x09 +'Pa ', # 0x0a +'Zhi ', # 0x0b +'Xi ', # 0x0c +'Hu ', # 0x0d +'Dan ', # 0x0e +'Wei ', # 0x0f +'Zhang ', # 0x10 +'Tang ', # 0x11 +'Dai ', # 0x12 +'Ma ', # 0x13 +'Pei ', # 0x14 +'Pa ', # 0x15 +'Tie ', # 0x16 +'Fu ', # 0x17 +'Lian ', # 0x18 +'Zhi ', # 0x19 +'Zhou ', # 0x1a +'Bo ', # 0x1b +'Zhi ', # 0x1c +'Di ', # 0x1d +'Mo ', # 0x1e +'Yi ', # 0x1f +'Yi ', # 0x20 +'Ping ', # 0x21 +'Qia ', # 0x22 +'Juan ', # 0x23 +'Ru ', # 0x24 +'Shuai ', # 0x25 +'Dai ', # 0x26 +'Zheng ', # 0x27 +'Shui ', # 0x28 +'Qiao ', # 0x29 +'Zhen ', # 0x2a +'Shi ', # 0x2b +'Qun ', # 0x2c +'Xi ', # 0x2d +'Bang ', # 0x2e +'Dai ', # 0x2f +'Gui ', # 0x30 +'Chou ', # 0x31 +'Ping ', # 0x32 +'Zhang ', # 0x33 +'Sha ', # 0x34 +'Wan ', # 0x35 +'Dai ', # 0x36 +'Wei ', # 0x37 +'Chang ', # 0x38 +'Sha ', # 0x39 +'Qi ', # 0x3a +'Ze ', # 0x3b +'Guo ', # 0x3c +'Mao ', # 0x3d +'Du ', # 0x3e +'Hou ', # 0x3f +'Zheng ', # 0x40 +'Xu ', # 0x41 +'Mi ', # 0x42 +'Wei ', # 0x43 +'Wo ', # 0x44 +'Fu ', # 0x45 +'Yi ', # 0x46 +'Bang ', # 0x47 +'Ping ', # 0x48 +'Tazuna ', # 0x49 +'Gong ', # 0x4a +'Pan ', # 0x4b +'Huang ', # 0x4c +'Dao ', # 0x4d +'Mi ', # 0x4e +'Jia ', # 0x4f +'Teng ', # 0x50 +'Hui ', # 0x51 +'Zhong ', # 0x52 +'Shan ', # 0x53 +'Man ', # 0x54 +'Mu ', # 0x55 +'Biao ', # 0x56 +'Guo ', # 0x57 +'Ze ', # 0x58 +'Mu ', # 0x59 +'Bang ', # 0x5a +'Zhang ', # 0x5b +'Jiong ', # 0x5c +'Chan ', # 0x5d +'Fu ', # 0x5e +'Zhi ', # 0x5f +'Hu ', # 0x60 +'Fan ', # 0x61 +'Chuang ', # 0x62 +'Bi ', # 0x63 +'Hei ', # 0x64 +'[?] ', # 0x65 +'Mi ', # 0x66 +'Qiao ', # 0x67 +'Chan ', # 0x68 +'Fen ', # 0x69 +'Meng ', # 0x6a +'Bang ', # 0x6b +'Chou ', # 0x6c +'Mie ', # 0x6d +'Chu ', # 0x6e +'Jie ', # 0x6f +'Xian ', # 0x70 +'Lan ', # 0x71 +'Gan ', # 0x72 +'Ping ', # 0x73 +'Nian ', # 0x74 +'Qian ', # 0x75 +'Bing ', # 0x76 +'Bing ', # 0x77 +'Xing ', # 0x78 +'Gan ', # 0x79 +'Yao ', # 0x7a +'Huan ', # 0x7b +'You ', # 0x7c +'You ', # 0x7d +'Ji ', # 0x7e +'Yan ', # 0x7f +'Pi ', # 0x80 +'Ting ', # 0x81 +'Ze ', # 0x82 +'Guang ', # 0x83 +'Zhuang ', # 0x84 +'Mo ', # 0x85 +'Qing ', # 0x86 +'Bi ', # 0x87 +'Qin ', # 0x88 +'Dun ', # 0x89 +'Chuang ', # 0x8a +'Gui ', # 0x8b +'Ya ', # 0x8c +'Bai ', # 0x8d +'Jie ', # 0x8e +'Xu ', # 0x8f +'Lu ', # 0x90 +'Wu ', # 0x91 +'[?] ', # 0x92 +'Ku ', # 0x93 +'Ying ', # 0x94 +'Di ', # 0x95 +'Pao ', # 0x96 +'Dian ', # 0x97 +'Ya ', # 0x98 +'Miao ', # 0x99 +'Geng ', # 0x9a +'Ci ', # 0x9b +'Fu ', # 0x9c +'Tong ', # 0x9d +'Pang ', # 0x9e +'Fei ', # 0x9f +'Xiang ', # 0xa0 +'Yi ', # 0xa1 +'Zhi ', # 0xa2 +'Tiao ', # 0xa3 +'Zhi ', # 0xa4 +'Xiu ', # 0xa5 +'Du ', # 0xa6 +'Zuo ', # 0xa7 +'Xiao ', # 0xa8 +'Tu ', # 0xa9 +'Gui ', # 0xaa +'Ku ', # 0xab +'Pang ', # 0xac +'Ting ', # 0xad +'You ', # 0xae +'Bu ', # 0xaf +'Ding ', # 0xb0 +'Cheng ', # 0xb1 +'Lai ', # 0xb2 +'Bei ', # 0xb3 +'Ji ', # 0xb4 +'An ', # 0xb5 +'Shu ', # 0xb6 +'Kang ', # 0xb7 +'Yong ', # 0xb8 +'Tuo ', # 0xb9 +'Song ', # 0xba +'Shu ', # 0xbb +'Qing ', # 0xbc +'Yu ', # 0xbd +'Yu ', # 0xbe +'Miao ', # 0xbf +'Sou ', # 0xc0 +'Ce ', # 0xc1 +'Xiang ', # 0xc2 +'Fei ', # 0xc3 +'Jiu ', # 0xc4 +'He ', # 0xc5 +'Hui ', # 0xc6 +'Liu ', # 0xc7 +'Sha ', # 0xc8 +'Lian ', # 0xc9 +'Lang ', # 0xca +'Sou ', # 0xcb +'Jian ', # 0xcc +'Pou ', # 0xcd +'Qing ', # 0xce +'Jiu ', # 0xcf +'Jiu ', # 0xd0 +'Qin ', # 0xd1 +'Ao ', # 0xd2 +'Kuo ', # 0xd3 +'Lou ', # 0xd4 +'Yin ', # 0xd5 +'Liao ', # 0xd6 +'Dai ', # 0xd7 +'Lu ', # 0xd8 +'Yi ', # 0xd9 +'Chu ', # 0xda +'Chan ', # 0xdb +'Tu ', # 0xdc +'Si ', # 0xdd +'Xin ', # 0xde +'Miao ', # 0xdf +'Chang ', # 0xe0 +'Wu ', # 0xe1 +'Fei ', # 0xe2 +'Guang ', # 0xe3 +'Koc ', # 0xe4 +'Kuai ', # 0xe5 +'Bi ', # 0xe6 +'Qiang ', # 0xe7 +'Xie ', # 0xe8 +'Lin ', # 0xe9 +'Lin ', # 0xea +'Liao ', # 0xeb +'Lu ', # 0xec +'[?] ', # 0xed +'Ying ', # 0xee +'Xian ', # 0xef +'Ting ', # 0xf0 +'Yong ', # 0xf1 +'Li ', # 0xf2 +'Ting ', # 0xf3 +'Yin ', # 0xf4 +'Xun ', # 0xf5 +'Yan ', # 0xf6 +'Ting ', # 0xf7 +'Di ', # 0xf8 +'Po ', # 0xf9 +'Jian ', # 0xfa +'Hui ', # 0xfb +'Nai ', # 0xfc +'Hui ', # 0xfd +'Gong ', # 0xfe +'Nian ', # 0xff +) diff --git a/nstock/modules/unidecode/x05f.py b/nstock/modules/unidecode/x05f.py new file mode 100644 index 0000000..032eab8 --- /dev/null +++ b/nstock/modules/unidecode/x05f.py @@ -0,0 +1,258 @@ +data = ( +'Kai ', # 0x00 +'Bian ', # 0x01 +'Yi ', # 0x02 +'Qi ', # 0x03 +'Nong ', # 0x04 +'Fen ', # 0x05 +'Ju ', # 0x06 +'Yan ', # 0x07 +'Yi ', # 0x08 +'Zang ', # 0x09 +'Bi ', # 0x0a +'Yi ', # 0x0b +'Yi ', # 0x0c +'Er ', # 0x0d +'San ', # 0x0e +'Shi ', # 0x0f +'Er ', # 0x10 +'Shi ', # 0x11 +'Shi ', # 0x12 +'Gong ', # 0x13 +'Diao ', # 0x14 +'Yin ', # 0x15 +'Hu ', # 0x16 +'Fu ', # 0x17 +'Hong ', # 0x18 +'Wu ', # 0x19 +'Tui ', # 0x1a +'Chi ', # 0x1b +'Jiang ', # 0x1c +'Ba ', # 0x1d +'Shen ', # 0x1e +'Di ', # 0x1f +'Zhang ', # 0x20 +'Jue ', # 0x21 +'Tao ', # 0x22 +'Fu ', # 0x23 +'Di ', # 0x24 +'Mi ', # 0x25 +'Xian ', # 0x26 +'Hu ', # 0x27 +'Chao ', # 0x28 +'Nu ', # 0x29 +'Jing ', # 0x2a +'Zhen ', # 0x2b +'Yi ', # 0x2c +'Mi ', # 0x2d +'Quan ', # 0x2e +'Wan ', # 0x2f +'Shao ', # 0x30 +'Ruo ', # 0x31 +'Xuan ', # 0x32 +'Jing ', # 0x33 +'Dun ', # 0x34 +'Zhang ', # 0x35 +'Jiang ', # 0x36 +'Qiang ', # 0x37 +'Peng ', # 0x38 +'Dan ', # 0x39 +'Qiang ', # 0x3a +'Bi ', # 0x3b +'Bi ', # 0x3c +'She ', # 0x3d +'Dan ', # 0x3e +'Jian ', # 0x3f +'Gou ', # 0x40 +'Sei ', # 0x41 +'Fa ', # 0x42 +'Bi ', # 0x43 +'Kou ', # 0x44 +'Nagi ', # 0x45 +'Bie ', # 0x46 +'Xiao ', # 0x47 +'Dan ', # 0x48 +'Kuo ', # 0x49 +'Qiang ', # 0x4a +'Hong ', # 0x4b +'Mi ', # 0x4c +'Kuo ', # 0x4d +'Wan ', # 0x4e +'Jue ', # 0x4f +'Ji ', # 0x50 +'Ji ', # 0x51 +'Gui ', # 0x52 +'Dang ', # 0x53 +'Lu ', # 0x54 +'Lu ', # 0x55 +'Tuan ', # 0x56 +'Hui ', # 0x57 +'Zhi ', # 0x58 +'Hui ', # 0x59 +'Hui ', # 0x5a +'Yi ', # 0x5b +'Yi ', # 0x5c +'Yi ', # 0x5d +'Yi ', # 0x5e +'Huo ', # 0x5f +'Huo ', # 0x60 +'Shan ', # 0x61 +'Xing ', # 0x62 +'Wen ', # 0x63 +'Tong ', # 0x64 +'Yan ', # 0x65 +'Yan ', # 0x66 +'Yu ', # 0x67 +'Chi ', # 0x68 +'Cai ', # 0x69 +'Biao ', # 0x6a +'Diao ', # 0x6b +'Bin ', # 0x6c +'Peng ', # 0x6d +'Yong ', # 0x6e +'Piao ', # 0x6f +'Zhang ', # 0x70 +'Ying ', # 0x71 +'Chi ', # 0x72 +'Chi ', # 0x73 +'Zhuo ', # 0x74 +'Tuo ', # 0x75 +'Ji ', # 0x76 +'Pang ', # 0x77 +'Zhong ', # 0x78 +'Yi ', # 0x79 +'Wang ', # 0x7a +'Che ', # 0x7b +'Bi ', # 0x7c +'Chi ', # 0x7d +'Ling ', # 0x7e +'Fu ', # 0x7f +'Wang ', # 0x80 +'Zheng ', # 0x81 +'Cu ', # 0x82 +'Wang ', # 0x83 +'Jing ', # 0x84 +'Dai ', # 0x85 +'Xi ', # 0x86 +'Xun ', # 0x87 +'Hen ', # 0x88 +'Yang ', # 0x89 +'Huai ', # 0x8a +'Lu ', # 0x8b +'Hou ', # 0x8c +'Wa ', # 0x8d +'Cheng ', # 0x8e +'Zhi ', # 0x8f +'Xu ', # 0x90 +'Jing ', # 0x91 +'Tu ', # 0x92 +'Cong ', # 0x93 +'[?] ', # 0x94 +'Lai ', # 0x95 +'Cong ', # 0x96 +'De ', # 0x97 +'Pai ', # 0x98 +'Xi ', # 0x99 +'[?] ', # 0x9a +'Qi ', # 0x9b +'Chang ', # 0x9c +'Zhi ', # 0x9d +'Cong ', # 0x9e +'Zhou ', # 0x9f +'Lai ', # 0xa0 +'Yu ', # 0xa1 +'Xie ', # 0xa2 +'Jie ', # 0xa3 +'Jian ', # 0xa4 +'Chi ', # 0xa5 +'Jia ', # 0xa6 +'Bian ', # 0xa7 +'Huang ', # 0xa8 +'Fu ', # 0xa9 +'Xun ', # 0xaa +'Wei ', # 0xab +'Pang ', # 0xac +'Yao ', # 0xad +'Wei ', # 0xae +'Xi ', # 0xaf +'Zheng ', # 0xb0 +'Piao ', # 0xb1 +'Chi ', # 0xb2 +'De ', # 0xb3 +'Zheng ', # 0xb4 +'Zheng ', # 0xb5 +'Bie ', # 0xb6 +'De ', # 0xb7 +'Chong ', # 0xb8 +'Che ', # 0xb9 +'Jiao ', # 0xba +'Wei ', # 0xbb +'Jiao ', # 0xbc +'Hui ', # 0xbd +'Mei ', # 0xbe +'Long ', # 0xbf +'Xiang ', # 0xc0 +'Bao ', # 0xc1 +'Qu ', # 0xc2 +'Xin ', # 0xc3 +'Shu ', # 0xc4 +'Bi ', # 0xc5 +'Yi ', # 0xc6 +'Le ', # 0xc7 +'Ren ', # 0xc8 +'Dao ', # 0xc9 +'Ding ', # 0xca +'Gai ', # 0xcb +'Ji ', # 0xcc +'Ren ', # 0xcd +'Ren ', # 0xce +'Chan ', # 0xcf +'Tan ', # 0xd0 +'Te ', # 0xd1 +'Te ', # 0xd2 +'Gan ', # 0xd3 +'Qi ', # 0xd4 +'Shi ', # 0xd5 +'Cun ', # 0xd6 +'Zhi ', # 0xd7 +'Wang ', # 0xd8 +'Mang ', # 0xd9 +'Xi ', # 0xda +'Fan ', # 0xdb +'Ying ', # 0xdc +'Tian ', # 0xdd +'Min ', # 0xde +'Min ', # 0xdf +'Zhong ', # 0xe0 +'Chong ', # 0xe1 +'Wu ', # 0xe2 +'Ji ', # 0xe3 +'Wu ', # 0xe4 +'Xi ', # 0xe5 +'Ye ', # 0xe6 +'You ', # 0xe7 +'Wan ', # 0xe8 +'Cong ', # 0xe9 +'Zhong ', # 0xea +'Kuai ', # 0xeb +'Yu ', # 0xec +'Bian ', # 0xed +'Zhi ', # 0xee +'Qi ', # 0xef +'Cui ', # 0xf0 +'Chen ', # 0xf1 +'Tai ', # 0xf2 +'Tun ', # 0xf3 +'Qian ', # 0xf4 +'Nian ', # 0xf5 +'Hun ', # 0xf6 +'Xiong ', # 0xf7 +'Niu ', # 0xf8 +'Wang ', # 0xf9 +'Xian ', # 0xfa +'Xin ', # 0xfb +'Kang ', # 0xfc +'Hu ', # 0xfd +'Kai ', # 0xfe +'Fen ', # 0xff +) diff --git a/nstock/modules/unidecode/x060.py b/nstock/modules/unidecode/x060.py new file mode 100644 index 0000000..ad3728f --- /dev/null +++ b/nstock/modules/unidecode/x060.py @@ -0,0 +1,258 @@ +data = ( +'Huai ', # 0x00 +'Tai ', # 0x01 +'Song ', # 0x02 +'Wu ', # 0x03 +'Ou ', # 0x04 +'Chang ', # 0x05 +'Chuang ', # 0x06 +'Ju ', # 0x07 +'Yi ', # 0x08 +'Bao ', # 0x09 +'Chao ', # 0x0a +'Min ', # 0x0b +'Pei ', # 0x0c +'Zuo ', # 0x0d +'Zen ', # 0x0e +'Yang ', # 0x0f +'Kou ', # 0x10 +'Ban ', # 0x11 +'Nu ', # 0x12 +'Nao ', # 0x13 +'Zheng ', # 0x14 +'Pa ', # 0x15 +'Bu ', # 0x16 +'Tie ', # 0x17 +'Gu ', # 0x18 +'Hu ', # 0x19 +'Ju ', # 0x1a +'Da ', # 0x1b +'Lian ', # 0x1c +'Si ', # 0x1d +'Chou ', # 0x1e +'Di ', # 0x1f +'Dai ', # 0x20 +'Yi ', # 0x21 +'Tu ', # 0x22 +'You ', # 0x23 +'Fu ', # 0x24 +'Ji ', # 0x25 +'Peng ', # 0x26 +'Xing ', # 0x27 +'Yuan ', # 0x28 +'Ni ', # 0x29 +'Guai ', # 0x2a +'Fu ', # 0x2b +'Xi ', # 0x2c +'Bi ', # 0x2d +'You ', # 0x2e +'Qie ', # 0x2f +'Xuan ', # 0x30 +'Cong ', # 0x31 +'Bing ', # 0x32 +'Huang ', # 0x33 +'Xu ', # 0x34 +'Chu ', # 0x35 +'Pi ', # 0x36 +'Xi ', # 0x37 +'Xi ', # 0x38 +'Tan ', # 0x39 +'Koraeru ', # 0x3a +'Zong ', # 0x3b +'Dui ', # 0x3c +'[?] ', # 0x3d +'Ki ', # 0x3e +'Yi ', # 0x3f +'Chi ', # 0x40 +'Ren ', # 0x41 +'Xun ', # 0x42 +'Shi ', # 0x43 +'Xi ', # 0x44 +'Lao ', # 0x45 +'Heng ', # 0x46 +'Kuang ', # 0x47 +'Mu ', # 0x48 +'Zhi ', # 0x49 +'Xie ', # 0x4a +'Lian ', # 0x4b +'Tiao ', # 0x4c +'Huang ', # 0x4d +'Die ', # 0x4e +'Hao ', # 0x4f +'Kong ', # 0x50 +'Gui ', # 0x51 +'Heng ', # 0x52 +'Xi ', # 0x53 +'Xiao ', # 0x54 +'Shu ', # 0x55 +'S ', # 0x56 +'Kua ', # 0x57 +'Qiu ', # 0x58 +'Yang ', # 0x59 +'Hui ', # 0x5a +'Hui ', # 0x5b +'Chi ', # 0x5c +'Jia ', # 0x5d +'Yi ', # 0x5e +'Xiong ', # 0x5f +'Guai ', # 0x60 +'Lin ', # 0x61 +'Hui ', # 0x62 +'Zi ', # 0x63 +'Xu ', # 0x64 +'Chi ', # 0x65 +'Xiang ', # 0x66 +'Nu ', # 0x67 +'Hen ', # 0x68 +'En ', # 0x69 +'Ke ', # 0x6a +'Tong ', # 0x6b +'Tian ', # 0x6c +'Gong ', # 0x6d +'Quan ', # 0x6e +'Xi ', # 0x6f +'Qia ', # 0x70 +'Yue ', # 0x71 +'Peng ', # 0x72 +'Ken ', # 0x73 +'De ', # 0x74 +'Hui ', # 0x75 +'E ', # 0x76 +'Kyuu ', # 0x77 +'Tong ', # 0x78 +'Yan ', # 0x79 +'Kai ', # 0x7a +'Ce ', # 0x7b +'Nao ', # 0x7c +'Yun ', # 0x7d +'Mang ', # 0x7e +'Yong ', # 0x7f +'Yong ', # 0x80 +'Yuan ', # 0x81 +'Pi ', # 0x82 +'Kun ', # 0x83 +'Qiao ', # 0x84 +'Yue ', # 0x85 +'Yu ', # 0x86 +'Yu ', # 0x87 +'Jie ', # 0x88 +'Xi ', # 0x89 +'Zhe ', # 0x8a +'Lin ', # 0x8b +'Ti ', # 0x8c +'Han ', # 0x8d +'Hao ', # 0x8e +'Qie ', # 0x8f +'Ti ', # 0x90 +'Bu ', # 0x91 +'Yi ', # 0x92 +'Qian ', # 0x93 +'Hui ', # 0x94 +'Xi ', # 0x95 +'Bei ', # 0x96 +'Man ', # 0x97 +'Yi ', # 0x98 +'Heng ', # 0x99 +'Song ', # 0x9a +'Quan ', # 0x9b +'Cheng ', # 0x9c +'Hui ', # 0x9d +'Wu ', # 0x9e +'Wu ', # 0x9f +'You ', # 0xa0 +'Li ', # 0xa1 +'Liang ', # 0xa2 +'Huan ', # 0xa3 +'Cong ', # 0xa4 +'Yi ', # 0xa5 +'Yue ', # 0xa6 +'Li ', # 0xa7 +'Nin ', # 0xa8 +'Nao ', # 0xa9 +'E ', # 0xaa +'Que ', # 0xab +'Xuan ', # 0xac +'Qian ', # 0xad +'Wu ', # 0xae +'Min ', # 0xaf +'Cong ', # 0xb0 +'Fei ', # 0xb1 +'Bei ', # 0xb2 +'Duo ', # 0xb3 +'Cui ', # 0xb4 +'Chang ', # 0xb5 +'Men ', # 0xb6 +'Li ', # 0xb7 +'Ji ', # 0xb8 +'Guan ', # 0xb9 +'Guan ', # 0xba +'Xing ', # 0xbb +'Dao ', # 0xbc +'Qi ', # 0xbd +'Kong ', # 0xbe +'Tian ', # 0xbf +'Lun ', # 0xc0 +'Xi ', # 0xc1 +'Kan ', # 0xc2 +'Kun ', # 0xc3 +'Ni ', # 0xc4 +'Qing ', # 0xc5 +'Chou ', # 0xc6 +'Dun ', # 0xc7 +'Guo ', # 0xc8 +'Chan ', # 0xc9 +'Liang ', # 0xca +'Wan ', # 0xcb +'Yuan ', # 0xcc +'Jin ', # 0xcd +'Ji ', # 0xce +'Lin ', # 0xcf +'Yu ', # 0xd0 +'Huo ', # 0xd1 +'He ', # 0xd2 +'Quan ', # 0xd3 +'Tan ', # 0xd4 +'Ti ', # 0xd5 +'Ti ', # 0xd6 +'Nie ', # 0xd7 +'Wang ', # 0xd8 +'Chuo ', # 0xd9 +'Bu ', # 0xda +'Hun ', # 0xdb +'Xi ', # 0xdc +'Tang ', # 0xdd +'Xin ', # 0xde +'Wei ', # 0xdf +'Hui ', # 0xe0 +'E ', # 0xe1 +'Rui ', # 0xe2 +'Zong ', # 0xe3 +'Jian ', # 0xe4 +'Yong ', # 0xe5 +'Dian ', # 0xe6 +'Ju ', # 0xe7 +'Can ', # 0xe8 +'Cheng ', # 0xe9 +'De ', # 0xea +'Bei ', # 0xeb +'Qie ', # 0xec +'Can ', # 0xed +'Dan ', # 0xee +'Guan ', # 0xef +'Duo ', # 0xf0 +'Nao ', # 0xf1 +'Yun ', # 0xf2 +'Xiang ', # 0xf3 +'Zhui ', # 0xf4 +'Die ', # 0xf5 +'Huang ', # 0xf6 +'Chun ', # 0xf7 +'Qiong ', # 0xf8 +'Re ', # 0xf9 +'Xing ', # 0xfa +'Ce ', # 0xfb +'Bian ', # 0xfc +'Hun ', # 0xfd +'Zong ', # 0xfe +'Ti ', # 0xff +) diff --git a/nstock/modules/unidecode/x061.py b/nstock/modules/unidecode/x061.py new file mode 100644 index 0000000..6e8ab80 --- /dev/null +++ b/nstock/modules/unidecode/x061.py @@ -0,0 +1,258 @@ +data = ( +'Qiao ', # 0x00 +'Chou ', # 0x01 +'Bei ', # 0x02 +'Xuan ', # 0x03 +'Wei ', # 0x04 +'Ge ', # 0x05 +'Qian ', # 0x06 +'Wei ', # 0x07 +'Yu ', # 0x08 +'Yu ', # 0x09 +'Bi ', # 0x0a +'Xuan ', # 0x0b +'Huan ', # 0x0c +'Min ', # 0x0d +'Bi ', # 0x0e +'Yi ', # 0x0f +'Mian ', # 0x10 +'Yong ', # 0x11 +'Kai ', # 0x12 +'Dang ', # 0x13 +'Yin ', # 0x14 +'E ', # 0x15 +'Chen ', # 0x16 +'Mou ', # 0x17 +'Ke ', # 0x18 +'Ke ', # 0x19 +'Yu ', # 0x1a +'Ai ', # 0x1b +'Qie ', # 0x1c +'Yan ', # 0x1d +'Nuo ', # 0x1e +'Gan ', # 0x1f +'Yun ', # 0x20 +'Zong ', # 0x21 +'Sai ', # 0x22 +'Leng ', # 0x23 +'Fen ', # 0x24 +'[?] ', # 0x25 +'Kui ', # 0x26 +'Kui ', # 0x27 +'Que ', # 0x28 +'Gong ', # 0x29 +'Yun ', # 0x2a +'Su ', # 0x2b +'Su ', # 0x2c +'Qi ', # 0x2d +'Yao ', # 0x2e +'Song ', # 0x2f +'Huang ', # 0x30 +'Ji ', # 0x31 +'Gu ', # 0x32 +'Ju ', # 0x33 +'Chuang ', # 0x34 +'Ni ', # 0x35 +'Xie ', # 0x36 +'Kai ', # 0x37 +'Zheng ', # 0x38 +'Yong ', # 0x39 +'Cao ', # 0x3a +'Sun ', # 0x3b +'Shen ', # 0x3c +'Bo ', # 0x3d +'Kai ', # 0x3e +'Yuan ', # 0x3f +'Xie ', # 0x40 +'Hun ', # 0x41 +'Yong ', # 0x42 +'Yang ', # 0x43 +'Li ', # 0x44 +'Sao ', # 0x45 +'Tao ', # 0x46 +'Yin ', # 0x47 +'Ci ', # 0x48 +'Xu ', # 0x49 +'Qian ', # 0x4a +'Tai ', # 0x4b +'Huang ', # 0x4c +'Yun ', # 0x4d +'Shen ', # 0x4e +'Ming ', # 0x4f +'[?] ', # 0x50 +'She ', # 0x51 +'Cong ', # 0x52 +'Piao ', # 0x53 +'Mo ', # 0x54 +'Mu ', # 0x55 +'Guo ', # 0x56 +'Chi ', # 0x57 +'Can ', # 0x58 +'Can ', # 0x59 +'Can ', # 0x5a +'Cui ', # 0x5b +'Min ', # 0x5c +'Te ', # 0x5d +'Zhang ', # 0x5e +'Tong ', # 0x5f +'Ao ', # 0x60 +'Shuang ', # 0x61 +'Man ', # 0x62 +'Guan ', # 0x63 +'Que ', # 0x64 +'Zao ', # 0x65 +'Jiu ', # 0x66 +'Hui ', # 0x67 +'Kai ', # 0x68 +'Lian ', # 0x69 +'Ou ', # 0x6a +'Song ', # 0x6b +'Jin ', # 0x6c +'Yin ', # 0x6d +'Lu ', # 0x6e +'Shang ', # 0x6f +'Wei ', # 0x70 +'Tuan ', # 0x71 +'Man ', # 0x72 +'Qian ', # 0x73 +'She ', # 0x74 +'Yong ', # 0x75 +'Qing ', # 0x76 +'Kang ', # 0x77 +'Di ', # 0x78 +'Zhi ', # 0x79 +'Lou ', # 0x7a +'Juan ', # 0x7b +'Qi ', # 0x7c +'Qi ', # 0x7d +'Yu ', # 0x7e +'Ping ', # 0x7f +'Liao ', # 0x80 +'Cong ', # 0x81 +'You ', # 0x82 +'Chong ', # 0x83 +'Zhi ', # 0x84 +'Tong ', # 0x85 +'Cheng ', # 0x86 +'Qi ', # 0x87 +'Qu ', # 0x88 +'Peng ', # 0x89 +'Bei ', # 0x8a +'Bie ', # 0x8b +'Chun ', # 0x8c +'Jiao ', # 0x8d +'Zeng ', # 0x8e +'Chi ', # 0x8f +'Lian ', # 0x90 +'Ping ', # 0x91 +'Kui ', # 0x92 +'Hui ', # 0x93 +'Qiao ', # 0x94 +'Cheng ', # 0x95 +'Yin ', # 0x96 +'Yin ', # 0x97 +'Xi ', # 0x98 +'Xi ', # 0x99 +'Dan ', # 0x9a +'Tan ', # 0x9b +'Duo ', # 0x9c +'Dui ', # 0x9d +'Dui ', # 0x9e +'Su ', # 0x9f +'Jue ', # 0xa0 +'Ce ', # 0xa1 +'Xiao ', # 0xa2 +'Fan ', # 0xa3 +'Fen ', # 0xa4 +'Lao ', # 0xa5 +'Lao ', # 0xa6 +'Chong ', # 0xa7 +'Han ', # 0xa8 +'Qi ', # 0xa9 +'Xian ', # 0xaa +'Min ', # 0xab +'Jing ', # 0xac +'Liao ', # 0xad +'Wu ', # 0xae +'Can ', # 0xaf +'Jue ', # 0xb0 +'Cu ', # 0xb1 +'Xian ', # 0xb2 +'Tan ', # 0xb3 +'Sheng ', # 0xb4 +'Pi ', # 0xb5 +'Yi ', # 0xb6 +'Chu ', # 0xb7 +'Xian ', # 0xb8 +'Nao ', # 0xb9 +'Dan ', # 0xba +'Tan ', # 0xbb +'Jing ', # 0xbc +'Song ', # 0xbd +'Han ', # 0xbe +'Jiao ', # 0xbf +'Wai ', # 0xc0 +'Huan ', # 0xc1 +'Dong ', # 0xc2 +'Qin ', # 0xc3 +'Qin ', # 0xc4 +'Qu ', # 0xc5 +'Cao ', # 0xc6 +'Ken ', # 0xc7 +'Xie ', # 0xc8 +'Ying ', # 0xc9 +'Ao ', # 0xca +'Mao ', # 0xcb +'Yi ', # 0xcc +'Lin ', # 0xcd +'Se ', # 0xce +'Jun ', # 0xcf +'Huai ', # 0xd0 +'Men ', # 0xd1 +'Lan ', # 0xd2 +'Ai ', # 0xd3 +'Lin ', # 0xd4 +'Yan ', # 0xd5 +'Gua ', # 0xd6 +'Xia ', # 0xd7 +'Chi ', # 0xd8 +'Yu ', # 0xd9 +'Yin ', # 0xda +'Dai ', # 0xdb +'Meng ', # 0xdc +'Ai ', # 0xdd +'Meng ', # 0xde +'Dui ', # 0xdf +'Qi ', # 0xe0 +'Mo ', # 0xe1 +'Lan ', # 0xe2 +'Men ', # 0xe3 +'Chou ', # 0xe4 +'Zhi ', # 0xe5 +'Nuo ', # 0xe6 +'Nuo ', # 0xe7 +'Yan ', # 0xe8 +'Yang ', # 0xe9 +'Bo ', # 0xea +'Zhi ', # 0xeb +'Kuang ', # 0xec +'Kuang ', # 0xed +'You ', # 0xee +'Fu ', # 0xef +'Liu ', # 0xf0 +'Mie ', # 0xf1 +'Cheng ', # 0xf2 +'[?] ', # 0xf3 +'Chan ', # 0xf4 +'Meng ', # 0xf5 +'Lan ', # 0xf6 +'Huai ', # 0xf7 +'Xuan ', # 0xf8 +'Rang ', # 0xf9 +'Chan ', # 0xfa +'Ji ', # 0xfb +'Ju ', # 0xfc +'Huan ', # 0xfd +'She ', # 0xfe +'Yi ', # 0xff +) diff --git a/nstock/modules/unidecode/x062.py b/nstock/modules/unidecode/x062.py new file mode 100644 index 0000000..9797920 --- /dev/null +++ b/nstock/modules/unidecode/x062.py @@ -0,0 +1,258 @@ +data = ( +'Lian ', # 0x00 +'Nan ', # 0x01 +'Mi ', # 0x02 +'Tang ', # 0x03 +'Jue ', # 0x04 +'Gang ', # 0x05 +'Gang ', # 0x06 +'Gang ', # 0x07 +'Ge ', # 0x08 +'Yue ', # 0x09 +'Wu ', # 0x0a +'Jian ', # 0x0b +'Xu ', # 0x0c +'Shu ', # 0x0d +'Rong ', # 0x0e +'Xi ', # 0x0f +'Cheng ', # 0x10 +'Wo ', # 0x11 +'Jie ', # 0x12 +'Ge ', # 0x13 +'Jian ', # 0x14 +'Qiang ', # 0x15 +'Huo ', # 0x16 +'Qiang ', # 0x17 +'Zhan ', # 0x18 +'Dong ', # 0x19 +'Qi ', # 0x1a +'Jia ', # 0x1b +'Die ', # 0x1c +'Zei ', # 0x1d +'Jia ', # 0x1e +'Ji ', # 0x1f +'Shi ', # 0x20 +'Kan ', # 0x21 +'Ji ', # 0x22 +'Kui ', # 0x23 +'Gai ', # 0x24 +'Deng ', # 0x25 +'Zhan ', # 0x26 +'Chuang ', # 0x27 +'Ge ', # 0x28 +'Jian ', # 0x29 +'Jie ', # 0x2a +'Yu ', # 0x2b +'Jian ', # 0x2c +'Yan ', # 0x2d +'Lu ', # 0x2e +'Xi ', # 0x2f +'Zhan ', # 0x30 +'Xi ', # 0x31 +'Xi ', # 0x32 +'Chuo ', # 0x33 +'Dai ', # 0x34 +'Qu ', # 0x35 +'Hu ', # 0x36 +'Hu ', # 0x37 +'Hu ', # 0x38 +'E ', # 0x39 +'Shi ', # 0x3a +'Li ', # 0x3b +'Mao ', # 0x3c +'Hu ', # 0x3d +'Li ', # 0x3e +'Fang ', # 0x3f +'Suo ', # 0x40 +'Bian ', # 0x41 +'Dian ', # 0x42 +'Jiong ', # 0x43 +'Shang ', # 0x44 +'Yi ', # 0x45 +'Yi ', # 0x46 +'Shan ', # 0x47 +'Hu ', # 0x48 +'Fei ', # 0x49 +'Yan ', # 0x4a +'Shou ', # 0x4b +'T ', # 0x4c +'Cai ', # 0x4d +'Zha ', # 0x4e +'Qiu ', # 0x4f +'Le ', # 0x50 +'Bu ', # 0x51 +'Ba ', # 0x52 +'Da ', # 0x53 +'Reng ', # 0x54 +'Fu ', # 0x55 +'Hameru ', # 0x56 +'Zai ', # 0x57 +'Tuo ', # 0x58 +'Zhang ', # 0x59 +'Diao ', # 0x5a +'Kang ', # 0x5b +'Yu ', # 0x5c +'Ku ', # 0x5d +'Han ', # 0x5e +'Shen ', # 0x5f +'Cha ', # 0x60 +'Yi ', # 0x61 +'Gu ', # 0x62 +'Kou ', # 0x63 +'Wu ', # 0x64 +'Tuo ', # 0x65 +'Qian ', # 0x66 +'Zhi ', # 0x67 +'Ren ', # 0x68 +'Kuo ', # 0x69 +'Men ', # 0x6a +'Sao ', # 0x6b +'Yang ', # 0x6c +'Niu ', # 0x6d +'Ban ', # 0x6e +'Che ', # 0x6f +'Rao ', # 0x70 +'Xi ', # 0x71 +'Qian ', # 0x72 +'Ban ', # 0x73 +'Jia ', # 0x74 +'Yu ', # 0x75 +'Fu ', # 0x76 +'Ao ', # 0x77 +'Xi ', # 0x78 +'Pi ', # 0x79 +'Zhi ', # 0x7a +'Zi ', # 0x7b +'E ', # 0x7c +'Dun ', # 0x7d +'Zhao ', # 0x7e +'Cheng ', # 0x7f +'Ji ', # 0x80 +'Yan ', # 0x81 +'Kuang ', # 0x82 +'Bian ', # 0x83 +'Chao ', # 0x84 +'Ju ', # 0x85 +'Wen ', # 0x86 +'Hu ', # 0x87 +'Yue ', # 0x88 +'Jue ', # 0x89 +'Ba ', # 0x8a +'Qin ', # 0x8b +'Zhen ', # 0x8c +'Zheng ', # 0x8d +'Yun ', # 0x8e +'Wan ', # 0x8f +'Nu ', # 0x90 +'Yi ', # 0x91 +'Shu ', # 0x92 +'Zhua ', # 0x93 +'Pou ', # 0x94 +'Tou ', # 0x95 +'Dou ', # 0x96 +'Kang ', # 0x97 +'Zhe ', # 0x98 +'Pou ', # 0x99 +'Fu ', # 0x9a +'Pao ', # 0x9b +'Ba ', # 0x9c +'Ao ', # 0x9d +'Ze ', # 0x9e +'Tuan ', # 0x9f +'Kou ', # 0xa0 +'Lun ', # 0xa1 +'Qiang ', # 0xa2 +'[?] ', # 0xa3 +'Hu ', # 0xa4 +'Bao ', # 0xa5 +'Bing ', # 0xa6 +'Zhi ', # 0xa7 +'Peng ', # 0xa8 +'Tan ', # 0xa9 +'Pu ', # 0xaa +'Pi ', # 0xab +'Tai ', # 0xac +'Yao ', # 0xad +'Zhen ', # 0xae +'Zha ', # 0xaf +'Yang ', # 0xb0 +'Bao ', # 0xb1 +'He ', # 0xb2 +'Ni ', # 0xb3 +'Yi ', # 0xb4 +'Di ', # 0xb5 +'Chi ', # 0xb6 +'Pi ', # 0xb7 +'Za ', # 0xb8 +'Mo ', # 0xb9 +'Mo ', # 0xba +'Shen ', # 0xbb +'Ya ', # 0xbc +'Chou ', # 0xbd +'Qu ', # 0xbe +'Min ', # 0xbf +'Chu ', # 0xc0 +'Jia ', # 0xc1 +'Fu ', # 0xc2 +'Zhan ', # 0xc3 +'Zhu ', # 0xc4 +'Dan ', # 0xc5 +'Chai ', # 0xc6 +'Mu ', # 0xc7 +'Nian ', # 0xc8 +'La ', # 0xc9 +'Fu ', # 0xca +'Pao ', # 0xcb +'Ban ', # 0xcc +'Pai ', # 0xcd +'Ling ', # 0xce +'Na ', # 0xcf +'Guai ', # 0xd0 +'Qian ', # 0xd1 +'Ju ', # 0xd2 +'Tuo ', # 0xd3 +'Ba ', # 0xd4 +'Tuo ', # 0xd5 +'Tuo ', # 0xd6 +'Ao ', # 0xd7 +'Ju ', # 0xd8 +'Zhuo ', # 0xd9 +'Pan ', # 0xda +'Zhao ', # 0xdb +'Bai ', # 0xdc +'Bai ', # 0xdd +'Di ', # 0xde +'Ni ', # 0xdf +'Ju ', # 0xe0 +'Kuo ', # 0xe1 +'Long ', # 0xe2 +'Jian ', # 0xe3 +'[?] ', # 0xe4 +'Yong ', # 0xe5 +'Lan ', # 0xe6 +'Ning ', # 0xe7 +'Bo ', # 0xe8 +'Ze ', # 0xe9 +'Qian ', # 0xea +'Hen ', # 0xeb +'Gua ', # 0xec +'Shi ', # 0xed +'Jie ', # 0xee +'Zheng ', # 0xef +'Nin ', # 0xf0 +'Gong ', # 0xf1 +'Gong ', # 0xf2 +'Quan ', # 0xf3 +'Shuan ', # 0xf4 +'Cun ', # 0xf5 +'Zan ', # 0xf6 +'Kao ', # 0xf7 +'Chi ', # 0xf8 +'Xie ', # 0xf9 +'Ce ', # 0xfa +'Hui ', # 0xfb +'Pin ', # 0xfc +'Zhuai ', # 0xfd +'Shi ', # 0xfe +'Na ', # 0xff +) diff --git a/nstock/modules/unidecode/x063.py b/nstock/modules/unidecode/x063.py new file mode 100644 index 0000000..896cea2 --- /dev/null +++ b/nstock/modules/unidecode/x063.py @@ -0,0 +1,258 @@ +data = ( +'Bo ', # 0x00 +'Chi ', # 0x01 +'Gua ', # 0x02 +'Zhi ', # 0x03 +'Kuo ', # 0x04 +'Duo ', # 0x05 +'Duo ', # 0x06 +'Zhi ', # 0x07 +'Qie ', # 0x08 +'An ', # 0x09 +'Nong ', # 0x0a +'Zhen ', # 0x0b +'Ge ', # 0x0c +'Jiao ', # 0x0d +'Ku ', # 0x0e +'Dong ', # 0x0f +'Ru ', # 0x10 +'Tiao ', # 0x11 +'Lie ', # 0x12 +'Zha ', # 0x13 +'Lu ', # 0x14 +'Die ', # 0x15 +'Wa ', # 0x16 +'Jue ', # 0x17 +'Mushiru ', # 0x18 +'Ju ', # 0x19 +'Zhi ', # 0x1a +'Luan ', # 0x1b +'Ya ', # 0x1c +'Zhua ', # 0x1d +'Ta ', # 0x1e +'Xie ', # 0x1f +'Nao ', # 0x20 +'Dang ', # 0x21 +'Jiao ', # 0x22 +'Zheng ', # 0x23 +'Ji ', # 0x24 +'Hui ', # 0x25 +'Xun ', # 0x26 +'Ku ', # 0x27 +'Ai ', # 0x28 +'Tuo ', # 0x29 +'Nuo ', # 0x2a +'Cuo ', # 0x2b +'Bo ', # 0x2c +'Geng ', # 0x2d +'Ti ', # 0x2e +'Zhen ', # 0x2f +'Cheng ', # 0x30 +'Suo ', # 0x31 +'Suo ', # 0x32 +'Keng ', # 0x33 +'Mei ', # 0x34 +'Long ', # 0x35 +'Ju ', # 0x36 +'Peng ', # 0x37 +'Jian ', # 0x38 +'Yi ', # 0x39 +'Ting ', # 0x3a +'Shan ', # 0x3b +'Nuo ', # 0x3c +'Wan ', # 0x3d +'Xie ', # 0x3e +'Cha ', # 0x3f +'Feng ', # 0x40 +'Jiao ', # 0x41 +'Wu ', # 0x42 +'Jun ', # 0x43 +'Jiu ', # 0x44 +'Tong ', # 0x45 +'Kun ', # 0x46 +'Huo ', # 0x47 +'Tu ', # 0x48 +'Zhuo ', # 0x49 +'Pou ', # 0x4a +'Le ', # 0x4b +'Ba ', # 0x4c +'Han ', # 0x4d +'Shao ', # 0x4e +'Nie ', # 0x4f +'Juan ', # 0x50 +'Ze ', # 0x51 +'Song ', # 0x52 +'Ye ', # 0x53 +'Jue ', # 0x54 +'Bu ', # 0x55 +'Huan ', # 0x56 +'Bu ', # 0x57 +'Zun ', # 0x58 +'Yi ', # 0x59 +'Zhai ', # 0x5a +'Lu ', # 0x5b +'Sou ', # 0x5c +'Tuo ', # 0x5d +'Lao ', # 0x5e +'Sun ', # 0x5f +'Bang ', # 0x60 +'Jian ', # 0x61 +'Huan ', # 0x62 +'Dao ', # 0x63 +'[?] ', # 0x64 +'Wan ', # 0x65 +'Qin ', # 0x66 +'Peng ', # 0x67 +'She ', # 0x68 +'Lie ', # 0x69 +'Min ', # 0x6a +'Men ', # 0x6b +'Fu ', # 0x6c +'Bai ', # 0x6d +'Ju ', # 0x6e +'Dao ', # 0x6f +'Wo ', # 0x70 +'Ai ', # 0x71 +'Juan ', # 0x72 +'Yue ', # 0x73 +'Zong ', # 0x74 +'Chen ', # 0x75 +'Chui ', # 0x76 +'Jie ', # 0x77 +'Tu ', # 0x78 +'Ben ', # 0x79 +'Na ', # 0x7a +'Nian ', # 0x7b +'Nuo ', # 0x7c +'Zu ', # 0x7d +'Wo ', # 0x7e +'Xi ', # 0x7f +'Xian ', # 0x80 +'Cheng ', # 0x81 +'Dian ', # 0x82 +'Sao ', # 0x83 +'Lun ', # 0x84 +'Qing ', # 0x85 +'Gang ', # 0x86 +'Duo ', # 0x87 +'Shou ', # 0x88 +'Diao ', # 0x89 +'Pou ', # 0x8a +'Di ', # 0x8b +'Zhang ', # 0x8c +'Gun ', # 0x8d +'Ji ', # 0x8e +'Tao ', # 0x8f +'Qia ', # 0x90 +'Qi ', # 0x91 +'Pai ', # 0x92 +'Shu ', # 0x93 +'Qian ', # 0x94 +'Ling ', # 0x95 +'Yi ', # 0x96 +'Ya ', # 0x97 +'Jue ', # 0x98 +'Zheng ', # 0x99 +'Liang ', # 0x9a +'Gua ', # 0x9b +'Yi ', # 0x9c +'Huo ', # 0x9d +'Shan ', # 0x9e +'Zheng ', # 0x9f +'Lue ', # 0xa0 +'Cai ', # 0xa1 +'Tan ', # 0xa2 +'Che ', # 0xa3 +'Bing ', # 0xa4 +'Jie ', # 0xa5 +'Ti ', # 0xa6 +'Kong ', # 0xa7 +'Tui ', # 0xa8 +'Yan ', # 0xa9 +'Cuo ', # 0xaa +'Zou ', # 0xab +'Ju ', # 0xac +'Tian ', # 0xad +'Qian ', # 0xae +'Ken ', # 0xaf +'Bai ', # 0xb0 +'Shou ', # 0xb1 +'Jie ', # 0xb2 +'Lu ', # 0xb3 +'Guo ', # 0xb4 +'Haba ', # 0xb5 +'[?] ', # 0xb6 +'Zhi ', # 0xb7 +'Dan ', # 0xb8 +'Mang ', # 0xb9 +'Xian ', # 0xba +'Sao ', # 0xbb +'Guan ', # 0xbc +'Peng ', # 0xbd +'Yuan ', # 0xbe +'Nuo ', # 0xbf +'Jian ', # 0xc0 +'Zhen ', # 0xc1 +'Jiu ', # 0xc2 +'Jian ', # 0xc3 +'Yu ', # 0xc4 +'Yan ', # 0xc5 +'Kui ', # 0xc6 +'Nan ', # 0xc7 +'Hong ', # 0xc8 +'Rou ', # 0xc9 +'Pi ', # 0xca +'Wei ', # 0xcb +'Sai ', # 0xcc +'Zou ', # 0xcd +'Xuan ', # 0xce +'Miao ', # 0xcf +'Ti ', # 0xd0 +'Nie ', # 0xd1 +'Cha ', # 0xd2 +'Shi ', # 0xd3 +'Zong ', # 0xd4 +'Zhen ', # 0xd5 +'Yi ', # 0xd6 +'Shun ', # 0xd7 +'Heng ', # 0xd8 +'Bian ', # 0xd9 +'Yang ', # 0xda +'Huan ', # 0xdb +'Yan ', # 0xdc +'Zuan ', # 0xdd +'An ', # 0xde +'Xu ', # 0xdf +'Ya ', # 0xe0 +'Wo ', # 0xe1 +'Ke ', # 0xe2 +'Chuai ', # 0xe3 +'Ji ', # 0xe4 +'Ti ', # 0xe5 +'La ', # 0xe6 +'La ', # 0xe7 +'Cheng ', # 0xe8 +'Kai ', # 0xe9 +'Jiu ', # 0xea +'Jiu ', # 0xeb +'Tu ', # 0xec +'Jie ', # 0xed +'Hui ', # 0xee +'Geng ', # 0xef +'Chong ', # 0xf0 +'Shuo ', # 0xf1 +'She ', # 0xf2 +'Xie ', # 0xf3 +'Yuan ', # 0xf4 +'Qian ', # 0xf5 +'Ye ', # 0xf6 +'Cha ', # 0xf7 +'Zha ', # 0xf8 +'Bei ', # 0xf9 +'Yao ', # 0xfa +'[?] ', # 0xfb +'[?] ', # 0xfc +'Lan ', # 0xfd +'Wen ', # 0xfe +'Qin ', # 0xff +) diff --git a/nstock/modules/unidecode/x064.py b/nstock/modules/unidecode/x064.py new file mode 100644 index 0000000..dc1514b --- /dev/null +++ b/nstock/modules/unidecode/x064.py @@ -0,0 +1,258 @@ +data = ( +'Chan ', # 0x00 +'Ge ', # 0x01 +'Lou ', # 0x02 +'Zong ', # 0x03 +'Geng ', # 0x04 +'Jiao ', # 0x05 +'Gou ', # 0x06 +'Qin ', # 0x07 +'Yong ', # 0x08 +'Que ', # 0x09 +'Chou ', # 0x0a +'Chi ', # 0x0b +'Zhan ', # 0x0c +'Sun ', # 0x0d +'Sun ', # 0x0e +'Bo ', # 0x0f +'Chu ', # 0x10 +'Rong ', # 0x11 +'Beng ', # 0x12 +'Cuo ', # 0x13 +'Sao ', # 0x14 +'Ke ', # 0x15 +'Yao ', # 0x16 +'Dao ', # 0x17 +'Zhi ', # 0x18 +'Nu ', # 0x19 +'Xie ', # 0x1a +'Jian ', # 0x1b +'Sou ', # 0x1c +'Qiu ', # 0x1d +'Gao ', # 0x1e +'Xian ', # 0x1f +'Shuo ', # 0x20 +'Sang ', # 0x21 +'Jin ', # 0x22 +'Mie ', # 0x23 +'E ', # 0x24 +'Chui ', # 0x25 +'Nuo ', # 0x26 +'Shan ', # 0x27 +'Ta ', # 0x28 +'Jie ', # 0x29 +'Tang ', # 0x2a +'Pan ', # 0x2b +'Ban ', # 0x2c +'Da ', # 0x2d +'Li ', # 0x2e +'Tao ', # 0x2f +'Hu ', # 0x30 +'Zhi ', # 0x31 +'Wa ', # 0x32 +'Xia ', # 0x33 +'Qian ', # 0x34 +'Wen ', # 0x35 +'Qiang ', # 0x36 +'Tian ', # 0x37 +'Zhen ', # 0x38 +'E ', # 0x39 +'Xi ', # 0x3a +'Nuo ', # 0x3b +'Quan ', # 0x3c +'Cha ', # 0x3d +'Zha ', # 0x3e +'Ge ', # 0x3f +'Wu ', # 0x40 +'En ', # 0x41 +'She ', # 0x42 +'Kang ', # 0x43 +'She ', # 0x44 +'Shu ', # 0x45 +'Bai ', # 0x46 +'Yao ', # 0x47 +'Bin ', # 0x48 +'Sou ', # 0x49 +'Tan ', # 0x4a +'Sa ', # 0x4b +'Chan ', # 0x4c +'Suo ', # 0x4d +'Liao ', # 0x4e +'Chong ', # 0x4f +'Chuang ', # 0x50 +'Guo ', # 0x51 +'Bing ', # 0x52 +'Feng ', # 0x53 +'Shuai ', # 0x54 +'Di ', # 0x55 +'Qi ', # 0x56 +'Sou ', # 0x57 +'Zhai ', # 0x58 +'Lian ', # 0x59 +'Tang ', # 0x5a +'Chi ', # 0x5b +'Guan ', # 0x5c +'Lu ', # 0x5d +'Luo ', # 0x5e +'Lou ', # 0x5f +'Zong ', # 0x60 +'Gai ', # 0x61 +'Hu ', # 0x62 +'Zha ', # 0x63 +'Chuang ', # 0x64 +'Tang ', # 0x65 +'Hua ', # 0x66 +'Cui ', # 0x67 +'Nai ', # 0x68 +'Mo ', # 0x69 +'Jiang ', # 0x6a +'Gui ', # 0x6b +'Ying ', # 0x6c +'Zhi ', # 0x6d +'Ao ', # 0x6e +'Zhi ', # 0x6f +'Nie ', # 0x70 +'Man ', # 0x71 +'Shan ', # 0x72 +'Kou ', # 0x73 +'Shu ', # 0x74 +'Suo ', # 0x75 +'Tuan ', # 0x76 +'Jiao ', # 0x77 +'Mo ', # 0x78 +'Mo ', # 0x79 +'Zhe ', # 0x7a +'Xian ', # 0x7b +'Keng ', # 0x7c +'Piao ', # 0x7d +'Jiang ', # 0x7e +'Yin ', # 0x7f +'Gou ', # 0x80 +'Qian ', # 0x81 +'Lue ', # 0x82 +'Ji ', # 0x83 +'Ying ', # 0x84 +'Jue ', # 0x85 +'Pie ', # 0x86 +'Pie ', # 0x87 +'Lao ', # 0x88 +'Dun ', # 0x89 +'Xian ', # 0x8a +'Ruan ', # 0x8b +'Kui ', # 0x8c +'Zan ', # 0x8d +'Yi ', # 0x8e +'Xun ', # 0x8f +'Cheng ', # 0x90 +'Cheng ', # 0x91 +'Sa ', # 0x92 +'Nao ', # 0x93 +'Heng ', # 0x94 +'Si ', # 0x95 +'Qian ', # 0x96 +'Huang ', # 0x97 +'Da ', # 0x98 +'Zun ', # 0x99 +'Nian ', # 0x9a +'Lin ', # 0x9b +'Zheng ', # 0x9c +'Hui ', # 0x9d +'Zhuang ', # 0x9e +'Jiao ', # 0x9f +'Ji ', # 0xa0 +'Cao ', # 0xa1 +'Dan ', # 0xa2 +'Dan ', # 0xa3 +'Che ', # 0xa4 +'Bo ', # 0xa5 +'Che ', # 0xa6 +'Jue ', # 0xa7 +'Xiao ', # 0xa8 +'Liao ', # 0xa9 +'Ben ', # 0xaa +'Fu ', # 0xab +'Qiao ', # 0xac +'Bo ', # 0xad +'Cuo ', # 0xae +'Zhuo ', # 0xaf +'Zhuan ', # 0xb0 +'Tuo ', # 0xb1 +'Pu ', # 0xb2 +'Qin ', # 0xb3 +'Dun ', # 0xb4 +'Nian ', # 0xb5 +'[?] ', # 0xb6 +'Xie ', # 0xb7 +'Lu ', # 0xb8 +'Jiao ', # 0xb9 +'Cuan ', # 0xba +'Ta ', # 0xbb +'Han ', # 0xbc +'Qiao ', # 0xbd +'Zhua ', # 0xbe +'Jian ', # 0xbf +'Gan ', # 0xc0 +'Yong ', # 0xc1 +'Lei ', # 0xc2 +'Kuo ', # 0xc3 +'Lu ', # 0xc4 +'Shan ', # 0xc5 +'Zhuo ', # 0xc6 +'Ze ', # 0xc7 +'Pu ', # 0xc8 +'Chuo ', # 0xc9 +'Ji ', # 0xca +'Dang ', # 0xcb +'Suo ', # 0xcc +'Cao ', # 0xcd +'Qing ', # 0xce +'Jing ', # 0xcf +'Huan ', # 0xd0 +'Jie ', # 0xd1 +'Qin ', # 0xd2 +'Kuai ', # 0xd3 +'Dan ', # 0xd4 +'Xi ', # 0xd5 +'Ge ', # 0xd6 +'Pi ', # 0xd7 +'Bo ', # 0xd8 +'Ao ', # 0xd9 +'Ju ', # 0xda +'Ye ', # 0xdb +'[?] ', # 0xdc +'Mang ', # 0xdd +'Sou ', # 0xde +'Mi ', # 0xdf +'Ji ', # 0xe0 +'Tai ', # 0xe1 +'Zhuo ', # 0xe2 +'Dao ', # 0xe3 +'Xing ', # 0xe4 +'Lan ', # 0xe5 +'Ca ', # 0xe6 +'Ju ', # 0xe7 +'Ye ', # 0xe8 +'Ru ', # 0xe9 +'Ye ', # 0xea +'Ye ', # 0xeb +'Ni ', # 0xec +'Hu ', # 0xed +'Ji ', # 0xee +'Bin ', # 0xef +'Ning ', # 0xf0 +'Ge ', # 0xf1 +'Zhi ', # 0xf2 +'Jie ', # 0xf3 +'Kuo ', # 0xf4 +'Mo ', # 0xf5 +'Jian ', # 0xf6 +'Xie ', # 0xf7 +'Lie ', # 0xf8 +'Tan ', # 0xf9 +'Bai ', # 0xfa +'Sou ', # 0xfb +'Lu ', # 0xfc +'Lue ', # 0xfd +'Rao ', # 0xfe +'Zhi ', # 0xff +) diff --git a/nstock/modules/unidecode/x065.py b/nstock/modules/unidecode/x065.py new file mode 100644 index 0000000..ede5176 --- /dev/null +++ b/nstock/modules/unidecode/x065.py @@ -0,0 +1,258 @@ +data = ( +'Pan ', # 0x00 +'Yang ', # 0x01 +'Lei ', # 0x02 +'Sa ', # 0x03 +'Shu ', # 0x04 +'Zan ', # 0x05 +'Nian ', # 0x06 +'Xian ', # 0x07 +'Jun ', # 0x08 +'Huo ', # 0x09 +'Li ', # 0x0a +'La ', # 0x0b +'Han ', # 0x0c +'Ying ', # 0x0d +'Lu ', # 0x0e +'Long ', # 0x0f +'Qian ', # 0x10 +'Qian ', # 0x11 +'Zan ', # 0x12 +'Qian ', # 0x13 +'Lan ', # 0x14 +'San ', # 0x15 +'Ying ', # 0x16 +'Mei ', # 0x17 +'Rang ', # 0x18 +'Chan ', # 0x19 +'[?] ', # 0x1a +'Cuan ', # 0x1b +'Xi ', # 0x1c +'She ', # 0x1d +'Luo ', # 0x1e +'Jun ', # 0x1f +'Mi ', # 0x20 +'Li ', # 0x21 +'Zan ', # 0x22 +'Luan ', # 0x23 +'Tan ', # 0x24 +'Zuan ', # 0x25 +'Li ', # 0x26 +'Dian ', # 0x27 +'Wa ', # 0x28 +'Dang ', # 0x29 +'Jiao ', # 0x2a +'Jue ', # 0x2b +'Lan ', # 0x2c +'Li ', # 0x2d +'Nang ', # 0x2e +'Zhi ', # 0x2f +'Gui ', # 0x30 +'Gui ', # 0x31 +'Qi ', # 0x32 +'Xin ', # 0x33 +'Pu ', # 0x34 +'Sui ', # 0x35 +'Shou ', # 0x36 +'Kao ', # 0x37 +'You ', # 0x38 +'Gai ', # 0x39 +'Yi ', # 0x3a +'Gong ', # 0x3b +'Gan ', # 0x3c +'Ban ', # 0x3d +'Fang ', # 0x3e +'Zheng ', # 0x3f +'Bo ', # 0x40 +'Dian ', # 0x41 +'Kou ', # 0x42 +'Min ', # 0x43 +'Wu ', # 0x44 +'Gu ', # 0x45 +'He ', # 0x46 +'Ce ', # 0x47 +'Xiao ', # 0x48 +'Mi ', # 0x49 +'Chu ', # 0x4a +'Ge ', # 0x4b +'Di ', # 0x4c +'Xu ', # 0x4d +'Jiao ', # 0x4e +'Min ', # 0x4f +'Chen ', # 0x50 +'Jiu ', # 0x51 +'Zhen ', # 0x52 +'Duo ', # 0x53 +'Yu ', # 0x54 +'Chi ', # 0x55 +'Ao ', # 0x56 +'Bai ', # 0x57 +'Xu ', # 0x58 +'Jiao ', # 0x59 +'Duo ', # 0x5a +'Lian ', # 0x5b +'Nie ', # 0x5c +'Bi ', # 0x5d +'Chang ', # 0x5e +'Dian ', # 0x5f +'Duo ', # 0x60 +'Yi ', # 0x61 +'Gan ', # 0x62 +'San ', # 0x63 +'Ke ', # 0x64 +'Yan ', # 0x65 +'Dun ', # 0x66 +'Qi ', # 0x67 +'Dou ', # 0x68 +'Xiao ', # 0x69 +'Duo ', # 0x6a +'Jiao ', # 0x6b +'Jing ', # 0x6c +'Yang ', # 0x6d +'Xia ', # 0x6e +'Min ', # 0x6f +'Shu ', # 0x70 +'Ai ', # 0x71 +'Qiao ', # 0x72 +'Ai ', # 0x73 +'Zheng ', # 0x74 +'Di ', # 0x75 +'Zhen ', # 0x76 +'Fu ', # 0x77 +'Shu ', # 0x78 +'Liao ', # 0x79 +'Qu ', # 0x7a +'Xiong ', # 0x7b +'Xi ', # 0x7c +'Jiao ', # 0x7d +'Sen ', # 0x7e +'Jiao ', # 0x7f +'Zhuo ', # 0x80 +'Yi ', # 0x81 +'Lian ', # 0x82 +'Bi ', # 0x83 +'Li ', # 0x84 +'Xiao ', # 0x85 +'Xiao ', # 0x86 +'Wen ', # 0x87 +'Xue ', # 0x88 +'Qi ', # 0x89 +'Qi ', # 0x8a +'Zhai ', # 0x8b +'Bin ', # 0x8c +'Jue ', # 0x8d +'Zhai ', # 0x8e +'[?] ', # 0x8f +'Fei ', # 0x90 +'Ban ', # 0x91 +'Ban ', # 0x92 +'Lan ', # 0x93 +'Yu ', # 0x94 +'Lan ', # 0x95 +'Wei ', # 0x96 +'Dou ', # 0x97 +'Sheng ', # 0x98 +'Liao ', # 0x99 +'Jia ', # 0x9a +'Hu ', # 0x9b +'Xie ', # 0x9c +'Jia ', # 0x9d +'Yu ', # 0x9e +'Zhen ', # 0x9f +'Jiao ', # 0xa0 +'Wo ', # 0xa1 +'Tou ', # 0xa2 +'Chu ', # 0xa3 +'Jin ', # 0xa4 +'Chi ', # 0xa5 +'Yin ', # 0xa6 +'Fu ', # 0xa7 +'Qiang ', # 0xa8 +'Zhan ', # 0xa9 +'Qu ', # 0xaa +'Zhuo ', # 0xab +'Zhan ', # 0xac +'Duan ', # 0xad +'Zhuo ', # 0xae +'Si ', # 0xaf +'Xin ', # 0xb0 +'Zhuo ', # 0xb1 +'Zhuo ', # 0xb2 +'Qin ', # 0xb3 +'Lin ', # 0xb4 +'Zhuo ', # 0xb5 +'Chu ', # 0xb6 +'Duan ', # 0xb7 +'Zhu ', # 0xb8 +'Fang ', # 0xb9 +'Xie ', # 0xba +'Hang ', # 0xbb +'Yu ', # 0xbc +'Shi ', # 0xbd +'Pei ', # 0xbe +'You ', # 0xbf +'Mye ', # 0xc0 +'Pang ', # 0xc1 +'Qi ', # 0xc2 +'Zhan ', # 0xc3 +'Mao ', # 0xc4 +'Lu ', # 0xc5 +'Pei ', # 0xc6 +'Pi ', # 0xc7 +'Liu ', # 0xc8 +'Fu ', # 0xc9 +'Fang ', # 0xca +'Xuan ', # 0xcb +'Jing ', # 0xcc +'Jing ', # 0xcd +'Ni ', # 0xce +'Zu ', # 0xcf +'Zhao ', # 0xd0 +'Yi ', # 0xd1 +'Liu ', # 0xd2 +'Shao ', # 0xd3 +'Jian ', # 0xd4 +'Es ', # 0xd5 +'Yi ', # 0xd6 +'Qi ', # 0xd7 +'Zhi ', # 0xd8 +'Fan ', # 0xd9 +'Piao ', # 0xda +'Fan ', # 0xdb +'Zhan ', # 0xdc +'Guai ', # 0xdd +'Sui ', # 0xde +'Yu ', # 0xdf +'Wu ', # 0xe0 +'Ji ', # 0xe1 +'Ji ', # 0xe2 +'Ji ', # 0xe3 +'Huo ', # 0xe4 +'Ri ', # 0xe5 +'Dan ', # 0xe6 +'Jiu ', # 0xe7 +'Zhi ', # 0xe8 +'Zao ', # 0xe9 +'Xie ', # 0xea +'Tiao ', # 0xeb +'Xun ', # 0xec +'Xu ', # 0xed +'Xu ', # 0xee +'Xu ', # 0xef +'Gan ', # 0xf0 +'Han ', # 0xf1 +'Tai ', # 0xf2 +'Di ', # 0xf3 +'Xu ', # 0xf4 +'Chan ', # 0xf5 +'Shi ', # 0xf6 +'Kuang ', # 0xf7 +'Yang ', # 0xf8 +'Shi ', # 0xf9 +'Wang ', # 0xfa +'Min ', # 0xfb +'Min ', # 0xfc +'Tun ', # 0xfd +'Chun ', # 0xfe +'Wu ', # 0xff +) diff --git a/nstock/modules/unidecode/x066.py b/nstock/modules/unidecode/x066.py new file mode 100644 index 0000000..01898d5 --- /dev/null +++ b/nstock/modules/unidecode/x066.py @@ -0,0 +1,258 @@ +data = ( +'Yun ', # 0x00 +'Bei ', # 0x01 +'Ang ', # 0x02 +'Ze ', # 0x03 +'Ban ', # 0x04 +'Jie ', # 0x05 +'Kun ', # 0x06 +'Sheng ', # 0x07 +'Hu ', # 0x08 +'Fang ', # 0x09 +'Hao ', # 0x0a +'Gui ', # 0x0b +'Chang ', # 0x0c +'Xuan ', # 0x0d +'Ming ', # 0x0e +'Hun ', # 0x0f +'Fen ', # 0x10 +'Qin ', # 0x11 +'Hu ', # 0x12 +'Yi ', # 0x13 +'Xi ', # 0x14 +'Xin ', # 0x15 +'Yan ', # 0x16 +'Ze ', # 0x17 +'Fang ', # 0x18 +'Tan ', # 0x19 +'Shen ', # 0x1a +'Ju ', # 0x1b +'Yang ', # 0x1c +'Zan ', # 0x1d +'Bing ', # 0x1e +'Xing ', # 0x1f +'Ying ', # 0x20 +'Xuan ', # 0x21 +'Pei ', # 0x22 +'Zhen ', # 0x23 +'Ling ', # 0x24 +'Chun ', # 0x25 +'Hao ', # 0x26 +'Mei ', # 0x27 +'Zuo ', # 0x28 +'Mo ', # 0x29 +'Bian ', # 0x2a +'Xu ', # 0x2b +'Hun ', # 0x2c +'Zhao ', # 0x2d +'Zong ', # 0x2e +'Shi ', # 0x2f +'Shi ', # 0x30 +'Yu ', # 0x31 +'Fei ', # 0x32 +'Die ', # 0x33 +'Mao ', # 0x34 +'Ni ', # 0x35 +'Chang ', # 0x36 +'Wen ', # 0x37 +'Dong ', # 0x38 +'Ai ', # 0x39 +'Bing ', # 0x3a +'Ang ', # 0x3b +'Zhou ', # 0x3c +'Long ', # 0x3d +'Xian ', # 0x3e +'Kuang ', # 0x3f +'Tiao ', # 0x40 +'Chao ', # 0x41 +'Shi ', # 0x42 +'Huang ', # 0x43 +'Huang ', # 0x44 +'Xuan ', # 0x45 +'Kui ', # 0x46 +'Xu ', # 0x47 +'Jiao ', # 0x48 +'Jin ', # 0x49 +'Zhi ', # 0x4a +'Jin ', # 0x4b +'Shang ', # 0x4c +'Tong ', # 0x4d +'Hong ', # 0x4e +'Yan ', # 0x4f +'Gai ', # 0x50 +'Xiang ', # 0x51 +'Shai ', # 0x52 +'Xiao ', # 0x53 +'Ye ', # 0x54 +'Yun ', # 0x55 +'Hui ', # 0x56 +'Han ', # 0x57 +'Han ', # 0x58 +'Jun ', # 0x59 +'Wan ', # 0x5a +'Xian ', # 0x5b +'Kun ', # 0x5c +'Zhou ', # 0x5d +'Xi ', # 0x5e +'Cheng ', # 0x5f +'Sheng ', # 0x60 +'Bu ', # 0x61 +'Zhe ', # 0x62 +'Zhe ', # 0x63 +'Wu ', # 0x64 +'Han ', # 0x65 +'Hui ', # 0x66 +'Hao ', # 0x67 +'Chen ', # 0x68 +'Wan ', # 0x69 +'Tian ', # 0x6a +'Zhuo ', # 0x6b +'Zui ', # 0x6c +'Zhou ', # 0x6d +'Pu ', # 0x6e +'Jing ', # 0x6f +'Xi ', # 0x70 +'Shan ', # 0x71 +'Yi ', # 0x72 +'Xi ', # 0x73 +'Qing ', # 0x74 +'Qi ', # 0x75 +'Jing ', # 0x76 +'Gui ', # 0x77 +'Zhen ', # 0x78 +'Yi ', # 0x79 +'Zhi ', # 0x7a +'An ', # 0x7b +'Wan ', # 0x7c +'Lin ', # 0x7d +'Liang ', # 0x7e +'Chang ', # 0x7f +'Wang ', # 0x80 +'Xiao ', # 0x81 +'Zan ', # 0x82 +'Hi ', # 0x83 +'Xuan ', # 0x84 +'Xuan ', # 0x85 +'Yi ', # 0x86 +'Xia ', # 0x87 +'Yun ', # 0x88 +'Hui ', # 0x89 +'Fu ', # 0x8a +'Min ', # 0x8b +'Kui ', # 0x8c +'He ', # 0x8d +'Ying ', # 0x8e +'Du ', # 0x8f +'Wei ', # 0x90 +'Shu ', # 0x91 +'Qing ', # 0x92 +'Mao ', # 0x93 +'Nan ', # 0x94 +'Jian ', # 0x95 +'Nuan ', # 0x96 +'An ', # 0x97 +'Yang ', # 0x98 +'Chun ', # 0x99 +'Yao ', # 0x9a +'Suo ', # 0x9b +'Jin ', # 0x9c +'Ming ', # 0x9d +'Jiao ', # 0x9e +'Kai ', # 0x9f +'Gao ', # 0xa0 +'Weng ', # 0xa1 +'Chang ', # 0xa2 +'Qi ', # 0xa3 +'Hao ', # 0xa4 +'Yan ', # 0xa5 +'Li ', # 0xa6 +'Ai ', # 0xa7 +'Ji ', # 0xa8 +'Gui ', # 0xa9 +'Men ', # 0xaa +'Zan ', # 0xab +'Xie ', # 0xac +'Hao ', # 0xad +'Mu ', # 0xae +'Mo ', # 0xaf +'Cong ', # 0xb0 +'Ni ', # 0xb1 +'Zhang ', # 0xb2 +'Hui ', # 0xb3 +'Bao ', # 0xb4 +'Han ', # 0xb5 +'Xuan ', # 0xb6 +'Chuan ', # 0xb7 +'Liao ', # 0xb8 +'Xian ', # 0xb9 +'Dan ', # 0xba +'Jing ', # 0xbb +'Pie ', # 0xbc +'Lin ', # 0xbd +'Tun ', # 0xbe +'Xi ', # 0xbf +'Yi ', # 0xc0 +'Ji ', # 0xc1 +'Huang ', # 0xc2 +'Tai ', # 0xc3 +'Ye ', # 0xc4 +'Ye ', # 0xc5 +'Li ', # 0xc6 +'Tan ', # 0xc7 +'Tong ', # 0xc8 +'Xiao ', # 0xc9 +'Fei ', # 0xca +'Qin ', # 0xcb +'Zhao ', # 0xcc +'Hao ', # 0xcd +'Yi ', # 0xce +'Xiang ', # 0xcf +'Xing ', # 0xd0 +'Sen ', # 0xd1 +'Jiao ', # 0xd2 +'Bao ', # 0xd3 +'Jing ', # 0xd4 +'Yian ', # 0xd5 +'Ai ', # 0xd6 +'Ye ', # 0xd7 +'Ru ', # 0xd8 +'Shu ', # 0xd9 +'Meng ', # 0xda +'Xun ', # 0xdb +'Yao ', # 0xdc +'Pu ', # 0xdd +'Li ', # 0xde +'Chen ', # 0xdf +'Kuang ', # 0xe0 +'Die ', # 0xe1 +'[?] ', # 0xe2 +'Yan ', # 0xe3 +'Huo ', # 0xe4 +'Lu ', # 0xe5 +'Xi ', # 0xe6 +'Rong ', # 0xe7 +'Long ', # 0xe8 +'Nang ', # 0xe9 +'Luo ', # 0xea +'Luan ', # 0xeb +'Shai ', # 0xec +'Tang ', # 0xed +'Yan ', # 0xee +'Chu ', # 0xef +'Yue ', # 0xf0 +'Yue ', # 0xf1 +'Qu ', # 0xf2 +'Yi ', # 0xf3 +'Geng ', # 0xf4 +'Ye ', # 0xf5 +'Hu ', # 0xf6 +'He ', # 0xf7 +'Shu ', # 0xf8 +'Cao ', # 0xf9 +'Cao ', # 0xfa +'Noboru ', # 0xfb +'Man ', # 0xfc +'Ceng ', # 0xfd +'Ceng ', # 0xfe +'Ti ', # 0xff +) diff --git a/nstock/modules/unidecode/x067.py b/nstock/modules/unidecode/x067.py new file mode 100644 index 0000000..2e863ae --- /dev/null +++ b/nstock/modules/unidecode/x067.py @@ -0,0 +1,258 @@ +data = ( +'Zui ', # 0x00 +'Can ', # 0x01 +'Xu ', # 0x02 +'Hui ', # 0x03 +'Yin ', # 0x04 +'Qie ', # 0x05 +'Fen ', # 0x06 +'Pi ', # 0x07 +'Yue ', # 0x08 +'You ', # 0x09 +'Ruan ', # 0x0a +'Peng ', # 0x0b +'Ban ', # 0x0c +'Fu ', # 0x0d +'Ling ', # 0x0e +'Fei ', # 0x0f +'Qu ', # 0x10 +'[?] ', # 0x11 +'Nu ', # 0x12 +'Tiao ', # 0x13 +'Shuo ', # 0x14 +'Zhen ', # 0x15 +'Lang ', # 0x16 +'Lang ', # 0x17 +'Juan ', # 0x18 +'Ming ', # 0x19 +'Huang ', # 0x1a +'Wang ', # 0x1b +'Tun ', # 0x1c +'Zhao ', # 0x1d +'Ji ', # 0x1e +'Qi ', # 0x1f +'Ying ', # 0x20 +'Zong ', # 0x21 +'Wang ', # 0x22 +'Tong ', # 0x23 +'Lang ', # 0x24 +'[?] ', # 0x25 +'Meng ', # 0x26 +'Long ', # 0x27 +'Mu ', # 0x28 +'Deng ', # 0x29 +'Wei ', # 0x2a +'Mo ', # 0x2b +'Ben ', # 0x2c +'Zha ', # 0x2d +'Zhu ', # 0x2e +'Zhu ', # 0x2f +'[?] ', # 0x30 +'Zhu ', # 0x31 +'Ren ', # 0x32 +'Ba ', # 0x33 +'Po ', # 0x34 +'Duo ', # 0x35 +'Duo ', # 0x36 +'Dao ', # 0x37 +'Li ', # 0x38 +'Qiu ', # 0x39 +'Ji ', # 0x3a +'Jiu ', # 0x3b +'Bi ', # 0x3c +'Xiu ', # 0x3d +'Ting ', # 0x3e +'Ci ', # 0x3f +'Sha ', # 0x40 +'Eburi ', # 0x41 +'Za ', # 0x42 +'Quan ', # 0x43 +'Qian ', # 0x44 +'Yu ', # 0x45 +'Gan ', # 0x46 +'Wu ', # 0x47 +'Cha ', # 0x48 +'Shan ', # 0x49 +'Xun ', # 0x4a +'Fan ', # 0x4b +'Wu ', # 0x4c +'Zi ', # 0x4d +'Li ', # 0x4e +'Xing ', # 0x4f +'Cai ', # 0x50 +'Cun ', # 0x51 +'Ren ', # 0x52 +'Shao ', # 0x53 +'Tuo ', # 0x54 +'Di ', # 0x55 +'Zhang ', # 0x56 +'Mang ', # 0x57 +'Chi ', # 0x58 +'Yi ', # 0x59 +'Gu ', # 0x5a +'Gong ', # 0x5b +'Du ', # 0x5c +'Yi ', # 0x5d +'Qi ', # 0x5e +'Shu ', # 0x5f +'Gang ', # 0x60 +'Tiao ', # 0x61 +'Moku ', # 0x62 +'Soma ', # 0x63 +'Tochi ', # 0x64 +'Lai ', # 0x65 +'Sugi ', # 0x66 +'Mang ', # 0x67 +'Yang ', # 0x68 +'Ma ', # 0x69 +'Miao ', # 0x6a +'Si ', # 0x6b +'Yuan ', # 0x6c +'Hang ', # 0x6d +'Fei ', # 0x6e +'Bei ', # 0x6f +'Jie ', # 0x70 +'Dong ', # 0x71 +'Gao ', # 0x72 +'Yao ', # 0x73 +'Xian ', # 0x74 +'Chu ', # 0x75 +'Qun ', # 0x76 +'Pa ', # 0x77 +'Shu ', # 0x78 +'Hua ', # 0x79 +'Xin ', # 0x7a +'Chou ', # 0x7b +'Zhu ', # 0x7c +'Chou ', # 0x7d +'Song ', # 0x7e +'Ban ', # 0x7f +'Song ', # 0x80 +'Ji ', # 0x81 +'Yue ', # 0x82 +'Jin ', # 0x83 +'Gou ', # 0x84 +'Ji ', # 0x85 +'Mao ', # 0x86 +'Pi ', # 0x87 +'Bi ', # 0x88 +'Wang ', # 0x89 +'Ang ', # 0x8a +'Fang ', # 0x8b +'Fen ', # 0x8c +'Yi ', # 0x8d +'Fu ', # 0x8e +'Nan ', # 0x8f +'Xi ', # 0x90 +'Hu ', # 0x91 +'Ya ', # 0x92 +'Dou ', # 0x93 +'Xun ', # 0x94 +'Zhen ', # 0x95 +'Yao ', # 0x96 +'Lin ', # 0x97 +'Rui ', # 0x98 +'E ', # 0x99 +'Mei ', # 0x9a +'Zhao ', # 0x9b +'Guo ', # 0x9c +'Zhi ', # 0x9d +'Cong ', # 0x9e +'Yun ', # 0x9f +'Waku ', # 0xa0 +'Dou ', # 0xa1 +'Shu ', # 0xa2 +'Zao ', # 0xa3 +'[?] ', # 0xa4 +'Li ', # 0xa5 +'Haze ', # 0xa6 +'Jian ', # 0xa7 +'Cheng ', # 0xa8 +'Matsu ', # 0xa9 +'Qiang ', # 0xaa +'Feng ', # 0xab +'Nan ', # 0xac +'Xiao ', # 0xad +'Xian ', # 0xae +'Ku ', # 0xaf +'Ping ', # 0xb0 +'Yi ', # 0xb1 +'Xi ', # 0xb2 +'Zhi ', # 0xb3 +'Guai ', # 0xb4 +'Xiao ', # 0xb5 +'Jia ', # 0xb6 +'Jia ', # 0xb7 +'Gou ', # 0xb8 +'Fu ', # 0xb9 +'Mo ', # 0xba +'Yi ', # 0xbb +'Ye ', # 0xbc +'Ye ', # 0xbd +'Shi ', # 0xbe +'Nie ', # 0xbf +'Bi ', # 0xc0 +'Duo ', # 0xc1 +'Yi ', # 0xc2 +'Ling ', # 0xc3 +'Bing ', # 0xc4 +'Ni ', # 0xc5 +'La ', # 0xc6 +'He ', # 0xc7 +'Pan ', # 0xc8 +'Fan ', # 0xc9 +'Zhong ', # 0xca +'Dai ', # 0xcb +'Ci ', # 0xcc +'Yang ', # 0xcd +'Fu ', # 0xce +'Bo ', # 0xcf +'Mou ', # 0xd0 +'Gan ', # 0xd1 +'Qi ', # 0xd2 +'Ran ', # 0xd3 +'Rou ', # 0xd4 +'Mao ', # 0xd5 +'Zhao ', # 0xd6 +'Song ', # 0xd7 +'Zhe ', # 0xd8 +'Xia ', # 0xd9 +'You ', # 0xda +'Shen ', # 0xdb +'Ju ', # 0xdc +'Tuo ', # 0xdd +'Zuo ', # 0xde +'Nan ', # 0xdf +'Ning ', # 0xe0 +'Yong ', # 0xe1 +'Di ', # 0xe2 +'Zhi ', # 0xe3 +'Zha ', # 0xe4 +'Cha ', # 0xe5 +'Dan ', # 0xe6 +'Gu ', # 0xe7 +'Pu ', # 0xe8 +'Jiu ', # 0xe9 +'Ao ', # 0xea +'Fu ', # 0xeb +'Jian ', # 0xec +'Bo ', # 0xed +'Duo ', # 0xee +'Ke ', # 0xef +'Nai ', # 0xf0 +'Zhu ', # 0xf1 +'Bi ', # 0xf2 +'Liu ', # 0xf3 +'Chai ', # 0xf4 +'Zha ', # 0xf5 +'Si ', # 0xf6 +'Zhu ', # 0xf7 +'Pei ', # 0xf8 +'Shi ', # 0xf9 +'Guai ', # 0xfa +'Cha ', # 0xfb +'Yao ', # 0xfc +'Jue ', # 0xfd +'Jiu ', # 0xfe +'Shi ', # 0xff +) diff --git a/nstock/modules/unidecode/x068.py b/nstock/modules/unidecode/x068.py new file mode 100644 index 0000000..c562311 --- /dev/null +++ b/nstock/modules/unidecode/x068.py @@ -0,0 +1,258 @@ +data = ( +'Zhi ', # 0x00 +'Liu ', # 0x01 +'Mei ', # 0x02 +'Hoy ', # 0x03 +'Rong ', # 0x04 +'Zha ', # 0x05 +'[?] ', # 0x06 +'Biao ', # 0x07 +'Zhan ', # 0x08 +'Jie ', # 0x09 +'Long ', # 0x0a +'Dong ', # 0x0b +'Lu ', # 0x0c +'Sayng ', # 0x0d +'Li ', # 0x0e +'Lan ', # 0x0f +'Yong ', # 0x10 +'Shu ', # 0x11 +'Xun ', # 0x12 +'Shuan ', # 0x13 +'Qi ', # 0x14 +'Zhen ', # 0x15 +'Qi ', # 0x16 +'Li ', # 0x17 +'Yi ', # 0x18 +'Xiang ', # 0x19 +'Zhen ', # 0x1a +'Li ', # 0x1b +'Su ', # 0x1c +'Gua ', # 0x1d +'Kan ', # 0x1e +'Bing ', # 0x1f +'Ren ', # 0x20 +'Xiao ', # 0x21 +'Bo ', # 0x22 +'Ren ', # 0x23 +'Bing ', # 0x24 +'Zi ', # 0x25 +'Chou ', # 0x26 +'Yi ', # 0x27 +'Jie ', # 0x28 +'Xu ', # 0x29 +'Zhu ', # 0x2a +'Jian ', # 0x2b +'Zui ', # 0x2c +'Er ', # 0x2d +'Er ', # 0x2e +'You ', # 0x2f +'Fa ', # 0x30 +'Gong ', # 0x31 +'Kao ', # 0x32 +'Lao ', # 0x33 +'Zhan ', # 0x34 +'Li ', # 0x35 +'Yin ', # 0x36 +'Yang ', # 0x37 +'He ', # 0x38 +'Gen ', # 0x39 +'Zhi ', # 0x3a +'Chi ', # 0x3b +'Ge ', # 0x3c +'Zai ', # 0x3d +'Luan ', # 0x3e +'Fu ', # 0x3f +'Jie ', # 0x40 +'Hang ', # 0x41 +'Gui ', # 0x42 +'Tao ', # 0x43 +'Guang ', # 0x44 +'Wei ', # 0x45 +'Kuang ', # 0x46 +'Ru ', # 0x47 +'An ', # 0x48 +'An ', # 0x49 +'Juan ', # 0x4a +'Yi ', # 0x4b +'Zhuo ', # 0x4c +'Ku ', # 0x4d +'Zhi ', # 0x4e +'Qiong ', # 0x4f +'Tong ', # 0x50 +'Sang ', # 0x51 +'Sang ', # 0x52 +'Huan ', # 0x53 +'Jie ', # 0x54 +'Jiu ', # 0x55 +'Xue ', # 0x56 +'Duo ', # 0x57 +'Zhui ', # 0x58 +'Yu ', # 0x59 +'Zan ', # 0x5a +'Kasei ', # 0x5b +'Ying ', # 0x5c +'Masu ', # 0x5d +'[?] ', # 0x5e +'Zhan ', # 0x5f +'Ya ', # 0x60 +'Nao ', # 0x61 +'Zhen ', # 0x62 +'Dang ', # 0x63 +'Qi ', # 0x64 +'Qiao ', # 0x65 +'Hua ', # 0x66 +'Kuai ', # 0x67 +'Jiang ', # 0x68 +'Zhuang ', # 0x69 +'Xun ', # 0x6a +'Suo ', # 0x6b +'Sha ', # 0x6c +'Zhen ', # 0x6d +'Bei ', # 0x6e +'Ting ', # 0x6f +'Gua ', # 0x70 +'Jing ', # 0x71 +'Bo ', # 0x72 +'Ben ', # 0x73 +'Fu ', # 0x74 +'Rui ', # 0x75 +'Tong ', # 0x76 +'Jue ', # 0x77 +'Xi ', # 0x78 +'Lang ', # 0x79 +'Liu ', # 0x7a +'Feng ', # 0x7b +'Qi ', # 0x7c +'Wen ', # 0x7d +'Jun ', # 0x7e +'Gan ', # 0x7f +'Cu ', # 0x80 +'Liang ', # 0x81 +'Qiu ', # 0x82 +'Ting ', # 0x83 +'You ', # 0x84 +'Mei ', # 0x85 +'Bang ', # 0x86 +'Long ', # 0x87 +'Peng ', # 0x88 +'Zhuang ', # 0x89 +'Di ', # 0x8a +'Xuan ', # 0x8b +'Tu ', # 0x8c +'Zao ', # 0x8d +'Ao ', # 0x8e +'Gu ', # 0x8f +'Bi ', # 0x90 +'Di ', # 0x91 +'Han ', # 0x92 +'Zi ', # 0x93 +'Zhi ', # 0x94 +'Ren ', # 0x95 +'Bei ', # 0x96 +'Geng ', # 0x97 +'Jian ', # 0x98 +'Huan ', # 0x99 +'Wan ', # 0x9a +'Nuo ', # 0x9b +'Jia ', # 0x9c +'Tiao ', # 0x9d +'Ji ', # 0x9e +'Xiao ', # 0x9f +'Lu ', # 0xa0 +'Huan ', # 0xa1 +'Shao ', # 0xa2 +'Cen ', # 0xa3 +'Fen ', # 0xa4 +'Song ', # 0xa5 +'Meng ', # 0xa6 +'Wu ', # 0xa7 +'Li ', # 0xa8 +'Li ', # 0xa9 +'Dou ', # 0xaa +'Cen ', # 0xab +'Ying ', # 0xac +'Suo ', # 0xad +'Ju ', # 0xae +'Ti ', # 0xaf +'Jie ', # 0xb0 +'Kun ', # 0xb1 +'Zhuo ', # 0xb2 +'Shu ', # 0xb3 +'Chan ', # 0xb4 +'Fan ', # 0xb5 +'Wei ', # 0xb6 +'Jing ', # 0xb7 +'Li ', # 0xb8 +'Bing ', # 0xb9 +'Fumoto ', # 0xba +'Shikimi ', # 0xbb +'Tao ', # 0xbc +'Zhi ', # 0xbd +'Lai ', # 0xbe +'Lian ', # 0xbf +'Jian ', # 0xc0 +'Zhuo ', # 0xc1 +'Ling ', # 0xc2 +'Li ', # 0xc3 +'Qi ', # 0xc4 +'Bing ', # 0xc5 +'Zhun ', # 0xc6 +'Cong ', # 0xc7 +'Qian ', # 0xc8 +'Mian ', # 0xc9 +'Qi ', # 0xca +'Qi ', # 0xcb +'Cai ', # 0xcc +'Gun ', # 0xcd +'Chan ', # 0xce +'Te ', # 0xcf +'Fei ', # 0xd0 +'Pai ', # 0xd1 +'Bang ', # 0xd2 +'Pou ', # 0xd3 +'Hun ', # 0xd4 +'Zong ', # 0xd5 +'Cheng ', # 0xd6 +'Zao ', # 0xd7 +'Ji ', # 0xd8 +'Li ', # 0xd9 +'Peng ', # 0xda +'Yu ', # 0xdb +'Yu ', # 0xdc +'Gu ', # 0xdd +'Hun ', # 0xde +'Dong ', # 0xdf +'Tang ', # 0xe0 +'Gang ', # 0xe1 +'Wang ', # 0xe2 +'Di ', # 0xe3 +'Xi ', # 0xe4 +'Fan ', # 0xe5 +'Cheng ', # 0xe6 +'Zhan ', # 0xe7 +'Qi ', # 0xe8 +'Yuan ', # 0xe9 +'Yan ', # 0xea +'Yu ', # 0xeb +'Quan ', # 0xec +'Yi ', # 0xed +'Sen ', # 0xee +'Ren ', # 0xef +'Chui ', # 0xf0 +'Leng ', # 0xf1 +'Qi ', # 0xf2 +'Zhuo ', # 0xf3 +'Fu ', # 0xf4 +'Ke ', # 0xf5 +'Lai ', # 0xf6 +'Zou ', # 0xf7 +'Zou ', # 0xf8 +'Zhuo ', # 0xf9 +'Guan ', # 0xfa +'Fen ', # 0xfb +'Fen ', # 0xfc +'Chen ', # 0xfd +'Qiong ', # 0xfe +'Nie ', # 0xff +) diff --git a/nstock/modules/unidecode/x069.py b/nstock/modules/unidecode/x069.py new file mode 100644 index 0000000..7fa8c7d --- /dev/null +++ b/nstock/modules/unidecode/x069.py @@ -0,0 +1,258 @@ +data = ( +'Wan ', # 0x00 +'Guo ', # 0x01 +'Lu ', # 0x02 +'Hao ', # 0x03 +'Jie ', # 0x04 +'Yi ', # 0x05 +'Chou ', # 0x06 +'Ju ', # 0x07 +'Ju ', # 0x08 +'Cheng ', # 0x09 +'Zuo ', # 0x0a +'Liang ', # 0x0b +'Qiang ', # 0x0c +'Zhi ', # 0x0d +'Zhui ', # 0x0e +'Ya ', # 0x0f +'Ju ', # 0x10 +'Bei ', # 0x11 +'Jiao ', # 0x12 +'Zhuo ', # 0x13 +'Zi ', # 0x14 +'Bin ', # 0x15 +'Peng ', # 0x16 +'Ding ', # 0x17 +'Chu ', # 0x18 +'Chang ', # 0x19 +'Kunugi ', # 0x1a +'Momiji ', # 0x1b +'Jian ', # 0x1c +'Gui ', # 0x1d +'Xi ', # 0x1e +'Du ', # 0x1f +'Qian ', # 0x20 +'Kunugi ', # 0x21 +'Soko ', # 0x22 +'Shide ', # 0x23 +'Luo ', # 0x24 +'Zhi ', # 0x25 +'Ken ', # 0x26 +'Myeng ', # 0x27 +'Tafu ', # 0x28 +'[?] ', # 0x29 +'Peng ', # 0x2a +'Zhan ', # 0x2b +'[?] ', # 0x2c +'Tuo ', # 0x2d +'Sen ', # 0x2e +'Duo ', # 0x2f +'Ye ', # 0x30 +'Fou ', # 0x31 +'Wei ', # 0x32 +'Wei ', # 0x33 +'Duan ', # 0x34 +'Jia ', # 0x35 +'Zong ', # 0x36 +'Jian ', # 0x37 +'Yi ', # 0x38 +'Shen ', # 0x39 +'Xi ', # 0x3a +'Yan ', # 0x3b +'Yan ', # 0x3c +'Chuan ', # 0x3d +'Zhan ', # 0x3e +'Chun ', # 0x3f +'Yu ', # 0x40 +'He ', # 0x41 +'Zha ', # 0x42 +'Wo ', # 0x43 +'Pian ', # 0x44 +'Bi ', # 0x45 +'Yao ', # 0x46 +'Huo ', # 0x47 +'Xu ', # 0x48 +'Ruo ', # 0x49 +'Yang ', # 0x4a +'La ', # 0x4b +'Yan ', # 0x4c +'Ben ', # 0x4d +'Hun ', # 0x4e +'Kui ', # 0x4f +'Jie ', # 0x50 +'Kui ', # 0x51 +'Si ', # 0x52 +'Feng ', # 0x53 +'Xie ', # 0x54 +'Tuo ', # 0x55 +'Zhi ', # 0x56 +'Jian ', # 0x57 +'Mu ', # 0x58 +'Mao ', # 0x59 +'Chu ', # 0x5a +'Hu ', # 0x5b +'Hu ', # 0x5c +'Lian ', # 0x5d +'Leng ', # 0x5e +'Ting ', # 0x5f +'Nan ', # 0x60 +'Yu ', # 0x61 +'You ', # 0x62 +'Mei ', # 0x63 +'Song ', # 0x64 +'Xuan ', # 0x65 +'Xuan ', # 0x66 +'Ying ', # 0x67 +'Zhen ', # 0x68 +'Pian ', # 0x69 +'Ye ', # 0x6a +'Ji ', # 0x6b +'Jie ', # 0x6c +'Ye ', # 0x6d +'Chu ', # 0x6e +'Shun ', # 0x6f +'Yu ', # 0x70 +'Cou ', # 0x71 +'Wei ', # 0x72 +'Mei ', # 0x73 +'Di ', # 0x74 +'Ji ', # 0x75 +'Jie ', # 0x76 +'Kai ', # 0x77 +'Qiu ', # 0x78 +'Ying ', # 0x79 +'Rou ', # 0x7a +'Heng ', # 0x7b +'Lou ', # 0x7c +'Le ', # 0x7d +'Hazou ', # 0x7e +'Katsura ', # 0x7f +'Pin ', # 0x80 +'Muro ', # 0x81 +'Gai ', # 0x82 +'Tan ', # 0x83 +'Lan ', # 0x84 +'Yun ', # 0x85 +'Yu ', # 0x86 +'Chen ', # 0x87 +'Lu ', # 0x88 +'Ju ', # 0x89 +'Sakaki ', # 0x8a +'[?] ', # 0x8b +'Pi ', # 0x8c +'Xie ', # 0x8d +'Jia ', # 0x8e +'Yi ', # 0x8f +'Zhan ', # 0x90 +'Fu ', # 0x91 +'Nai ', # 0x92 +'Mi ', # 0x93 +'Lang ', # 0x94 +'Rong ', # 0x95 +'Gu ', # 0x96 +'Jian ', # 0x97 +'Ju ', # 0x98 +'Ta ', # 0x99 +'Yao ', # 0x9a +'Zhen ', # 0x9b +'Bang ', # 0x9c +'Sha ', # 0x9d +'Yuan ', # 0x9e +'Zi ', # 0x9f +'Ming ', # 0xa0 +'Su ', # 0xa1 +'Jia ', # 0xa2 +'Yao ', # 0xa3 +'Jie ', # 0xa4 +'Huang ', # 0xa5 +'Gan ', # 0xa6 +'Fei ', # 0xa7 +'Zha ', # 0xa8 +'Qian ', # 0xa9 +'Ma ', # 0xaa +'Sun ', # 0xab +'Yuan ', # 0xac +'Xie ', # 0xad +'Rong ', # 0xae +'Shi ', # 0xaf +'Zhi ', # 0xb0 +'Cui ', # 0xb1 +'Yun ', # 0xb2 +'Ting ', # 0xb3 +'Liu ', # 0xb4 +'Rong ', # 0xb5 +'Tang ', # 0xb6 +'Que ', # 0xb7 +'Zhai ', # 0xb8 +'Si ', # 0xb9 +'Sheng ', # 0xba +'Ta ', # 0xbb +'Ke ', # 0xbc +'Xi ', # 0xbd +'Gu ', # 0xbe +'Qi ', # 0xbf +'Kao ', # 0xc0 +'Gao ', # 0xc1 +'Sun ', # 0xc2 +'Pan ', # 0xc3 +'Tao ', # 0xc4 +'Ge ', # 0xc5 +'Xun ', # 0xc6 +'Dian ', # 0xc7 +'Nou ', # 0xc8 +'Ji ', # 0xc9 +'Shuo ', # 0xca +'Gou ', # 0xcb +'Chui ', # 0xcc +'Qiang ', # 0xcd +'Cha ', # 0xce +'Qian ', # 0xcf +'Huai ', # 0xd0 +'Mei ', # 0xd1 +'Xu ', # 0xd2 +'Gang ', # 0xd3 +'Gao ', # 0xd4 +'Zhuo ', # 0xd5 +'Tuo ', # 0xd6 +'Hashi ', # 0xd7 +'Yang ', # 0xd8 +'Dian ', # 0xd9 +'Jia ', # 0xda +'Jian ', # 0xdb +'Zui ', # 0xdc +'Kashi ', # 0xdd +'Ori ', # 0xde +'Bin ', # 0xdf +'Zhu ', # 0xe0 +'[?] ', # 0xe1 +'Xi ', # 0xe2 +'Qi ', # 0xe3 +'Lian ', # 0xe4 +'Hui ', # 0xe5 +'Yong ', # 0xe6 +'Qian ', # 0xe7 +'Guo ', # 0xe8 +'Gai ', # 0xe9 +'Gai ', # 0xea +'Tuan ', # 0xeb +'Hua ', # 0xec +'Cu ', # 0xed +'Sen ', # 0xee +'Cui ', # 0xef +'Beng ', # 0xf0 +'You ', # 0xf1 +'Hu ', # 0xf2 +'Jiang ', # 0xf3 +'Hu ', # 0xf4 +'Huan ', # 0xf5 +'Kui ', # 0xf6 +'Yi ', # 0xf7 +'Nie ', # 0xf8 +'Gao ', # 0xf9 +'Kang ', # 0xfa +'Gui ', # 0xfb +'Gui ', # 0xfc +'Cao ', # 0xfd +'Man ', # 0xfe +'Jin ', # 0xff +) diff --git a/nstock/modules/unidecode/x06a.py b/nstock/modules/unidecode/x06a.py new file mode 100644 index 0000000..12fcabd --- /dev/null +++ b/nstock/modules/unidecode/x06a.py @@ -0,0 +1,258 @@ +data = ( +'Di ', # 0x00 +'Zhuang ', # 0x01 +'Le ', # 0x02 +'Lang ', # 0x03 +'Chen ', # 0x04 +'Cong ', # 0x05 +'Li ', # 0x06 +'Xiu ', # 0x07 +'Qing ', # 0x08 +'Shuang ', # 0x09 +'Fan ', # 0x0a +'Tong ', # 0x0b +'Guan ', # 0x0c +'Ji ', # 0x0d +'Suo ', # 0x0e +'Lei ', # 0x0f +'Lu ', # 0x10 +'Liang ', # 0x11 +'Mi ', # 0x12 +'Lou ', # 0x13 +'Chao ', # 0x14 +'Su ', # 0x15 +'Ke ', # 0x16 +'Shu ', # 0x17 +'Tang ', # 0x18 +'Biao ', # 0x19 +'Lu ', # 0x1a +'Jiu ', # 0x1b +'Shu ', # 0x1c +'Zha ', # 0x1d +'Shu ', # 0x1e +'Zhang ', # 0x1f +'Men ', # 0x20 +'Mo ', # 0x21 +'Niao ', # 0x22 +'Yang ', # 0x23 +'Tiao ', # 0x24 +'Peng ', # 0x25 +'Zhu ', # 0x26 +'Sha ', # 0x27 +'Xi ', # 0x28 +'Quan ', # 0x29 +'Heng ', # 0x2a +'Jian ', # 0x2b +'Cong ', # 0x2c +'[?] ', # 0x2d +'Hokuso ', # 0x2e +'Qiang ', # 0x2f +'Tara ', # 0x30 +'Ying ', # 0x31 +'Er ', # 0x32 +'Xin ', # 0x33 +'Zhi ', # 0x34 +'Qiao ', # 0x35 +'Zui ', # 0x36 +'Cong ', # 0x37 +'Pu ', # 0x38 +'Shu ', # 0x39 +'Hua ', # 0x3a +'Kui ', # 0x3b +'Zhen ', # 0x3c +'Zun ', # 0x3d +'Yue ', # 0x3e +'Zhan ', # 0x3f +'Xi ', # 0x40 +'Xun ', # 0x41 +'Dian ', # 0x42 +'Fa ', # 0x43 +'Gan ', # 0x44 +'Mo ', # 0x45 +'Wu ', # 0x46 +'Qiao ', # 0x47 +'Nao ', # 0x48 +'Lin ', # 0x49 +'Liu ', # 0x4a +'Qiao ', # 0x4b +'Xian ', # 0x4c +'Run ', # 0x4d +'Fan ', # 0x4e +'Zhan ', # 0x4f +'Tuo ', # 0x50 +'Lao ', # 0x51 +'Yun ', # 0x52 +'Shun ', # 0x53 +'Tui ', # 0x54 +'Cheng ', # 0x55 +'Tang ', # 0x56 +'Meng ', # 0x57 +'Ju ', # 0x58 +'Cheng ', # 0x59 +'Su ', # 0x5a +'Jue ', # 0x5b +'Jue ', # 0x5c +'Tan ', # 0x5d +'Hui ', # 0x5e +'Ji ', # 0x5f +'Nuo ', # 0x60 +'Xiang ', # 0x61 +'Tuo ', # 0x62 +'Ning ', # 0x63 +'Rui ', # 0x64 +'Zhu ', # 0x65 +'Chuang ', # 0x66 +'Zeng ', # 0x67 +'Fen ', # 0x68 +'Qiong ', # 0x69 +'Ran ', # 0x6a +'Heng ', # 0x6b +'Cen ', # 0x6c +'Gu ', # 0x6d +'Liu ', # 0x6e +'Lao ', # 0x6f +'Gao ', # 0x70 +'Chu ', # 0x71 +'Zusa ', # 0x72 +'Nude ', # 0x73 +'Ca ', # 0x74 +'San ', # 0x75 +'Ji ', # 0x76 +'Dou ', # 0x77 +'Shou ', # 0x78 +'Lu ', # 0x79 +'[?] ', # 0x7a +'[?] ', # 0x7b +'Yuan ', # 0x7c +'Ta ', # 0x7d +'Shu ', # 0x7e +'Jiang ', # 0x7f +'Tan ', # 0x80 +'Lin ', # 0x81 +'Nong ', # 0x82 +'Yin ', # 0x83 +'Xi ', # 0x84 +'Sui ', # 0x85 +'Shan ', # 0x86 +'Zui ', # 0x87 +'Xuan ', # 0x88 +'Cheng ', # 0x89 +'Gan ', # 0x8a +'Ju ', # 0x8b +'Zui ', # 0x8c +'Yi ', # 0x8d +'Qin ', # 0x8e +'Pu ', # 0x8f +'Yan ', # 0x90 +'Lei ', # 0x91 +'Feng ', # 0x92 +'Hui ', # 0x93 +'Dang ', # 0x94 +'Ji ', # 0x95 +'Sui ', # 0x96 +'Bo ', # 0x97 +'Bi ', # 0x98 +'Ding ', # 0x99 +'Chu ', # 0x9a +'Zhua ', # 0x9b +'Kuai ', # 0x9c +'Ji ', # 0x9d +'Jie ', # 0x9e +'Jia ', # 0x9f +'Qing ', # 0xa0 +'Zhe ', # 0xa1 +'Jian ', # 0xa2 +'Qiang ', # 0xa3 +'Dao ', # 0xa4 +'Yi ', # 0xa5 +'Biao ', # 0xa6 +'Song ', # 0xa7 +'She ', # 0xa8 +'Lin ', # 0xa9 +'Kunugi ', # 0xaa +'Cha ', # 0xab +'Meng ', # 0xac +'Yin ', # 0xad +'Tao ', # 0xae +'Tai ', # 0xaf +'Mian ', # 0xb0 +'Qi ', # 0xb1 +'Toan ', # 0xb2 +'Bin ', # 0xb3 +'Huo ', # 0xb4 +'Ji ', # 0xb5 +'Qian ', # 0xb6 +'Mi ', # 0xb7 +'Ning ', # 0xb8 +'Yi ', # 0xb9 +'Gao ', # 0xba +'Jian ', # 0xbb +'Yin ', # 0xbc +'Er ', # 0xbd +'Qing ', # 0xbe +'Yan ', # 0xbf +'Qi ', # 0xc0 +'Mi ', # 0xc1 +'Zhao ', # 0xc2 +'Gui ', # 0xc3 +'Chun ', # 0xc4 +'Ji ', # 0xc5 +'Kui ', # 0xc6 +'Po ', # 0xc7 +'Deng ', # 0xc8 +'Chu ', # 0xc9 +'[?] ', # 0xca +'Mian ', # 0xcb +'You ', # 0xcc +'Zhi ', # 0xcd +'Guang ', # 0xce +'Qian ', # 0xcf +'Lei ', # 0xd0 +'Lei ', # 0xd1 +'Sa ', # 0xd2 +'Lu ', # 0xd3 +'Li ', # 0xd4 +'Cuan ', # 0xd5 +'Lu ', # 0xd6 +'Mie ', # 0xd7 +'Hui ', # 0xd8 +'Ou ', # 0xd9 +'Lu ', # 0xda +'Jie ', # 0xdb +'Gao ', # 0xdc +'Du ', # 0xdd +'Yuan ', # 0xde +'Li ', # 0xdf +'Fei ', # 0xe0 +'Zhuo ', # 0xe1 +'Sou ', # 0xe2 +'Lian ', # 0xe3 +'Tamo ', # 0xe4 +'Chu ', # 0xe5 +'[?] ', # 0xe6 +'Zhu ', # 0xe7 +'Lu ', # 0xe8 +'Yan ', # 0xe9 +'Li ', # 0xea +'Zhu ', # 0xeb +'Chen ', # 0xec +'Jie ', # 0xed +'E ', # 0xee +'Su ', # 0xef +'Huai ', # 0xf0 +'Nie ', # 0xf1 +'Yu ', # 0xf2 +'Long ', # 0xf3 +'Lai ', # 0xf4 +'[?] ', # 0xf5 +'Xian ', # 0xf6 +'Kwi ', # 0xf7 +'Ju ', # 0xf8 +'Xiao ', # 0xf9 +'Ling ', # 0xfa +'Ying ', # 0xfb +'Jian ', # 0xfc +'Yin ', # 0xfd +'You ', # 0xfe +'Ying ', # 0xff +) diff --git a/nstock/modules/unidecode/x06b.py b/nstock/modules/unidecode/x06b.py new file mode 100644 index 0000000..56aa7c6 --- /dev/null +++ b/nstock/modules/unidecode/x06b.py @@ -0,0 +1,258 @@ +data = ( +'Xiang ', # 0x00 +'Nong ', # 0x01 +'Bo ', # 0x02 +'Chan ', # 0x03 +'Lan ', # 0x04 +'Ju ', # 0x05 +'Shuang ', # 0x06 +'She ', # 0x07 +'Wei ', # 0x08 +'Cong ', # 0x09 +'Quan ', # 0x0a +'Qu ', # 0x0b +'Cang ', # 0x0c +'[?] ', # 0x0d +'Yu ', # 0x0e +'Luo ', # 0x0f +'Li ', # 0x10 +'Zan ', # 0x11 +'Luan ', # 0x12 +'Dang ', # 0x13 +'Jue ', # 0x14 +'Em ', # 0x15 +'Lan ', # 0x16 +'Lan ', # 0x17 +'Zhu ', # 0x18 +'Lei ', # 0x19 +'Li ', # 0x1a +'Ba ', # 0x1b +'Nang ', # 0x1c +'Yu ', # 0x1d +'Ling ', # 0x1e +'Tsuki ', # 0x1f +'Qian ', # 0x20 +'Ci ', # 0x21 +'Huan ', # 0x22 +'Xin ', # 0x23 +'Yu ', # 0x24 +'Yu ', # 0x25 +'Qian ', # 0x26 +'Ou ', # 0x27 +'Xu ', # 0x28 +'Chao ', # 0x29 +'Chu ', # 0x2a +'Chi ', # 0x2b +'Kai ', # 0x2c +'Yi ', # 0x2d +'Jue ', # 0x2e +'Xi ', # 0x2f +'Xu ', # 0x30 +'Xia ', # 0x31 +'Yu ', # 0x32 +'Kuai ', # 0x33 +'Lang ', # 0x34 +'Kuan ', # 0x35 +'Shuo ', # 0x36 +'Xi ', # 0x37 +'Ai ', # 0x38 +'Yi ', # 0x39 +'Qi ', # 0x3a +'Hu ', # 0x3b +'Chi ', # 0x3c +'Qin ', # 0x3d +'Kuan ', # 0x3e +'Kan ', # 0x3f +'Kuan ', # 0x40 +'Kan ', # 0x41 +'Chuan ', # 0x42 +'Sha ', # 0x43 +'Gua ', # 0x44 +'Yin ', # 0x45 +'Xin ', # 0x46 +'Xie ', # 0x47 +'Yu ', # 0x48 +'Qian ', # 0x49 +'Xiao ', # 0x4a +'Yi ', # 0x4b +'Ge ', # 0x4c +'Wu ', # 0x4d +'Tan ', # 0x4e +'Jin ', # 0x4f +'Ou ', # 0x50 +'Hu ', # 0x51 +'Ti ', # 0x52 +'Huan ', # 0x53 +'Xu ', # 0x54 +'Pen ', # 0x55 +'Xi ', # 0x56 +'Xiao ', # 0x57 +'Xu ', # 0x58 +'Xi ', # 0x59 +'Sen ', # 0x5a +'Lian ', # 0x5b +'Chu ', # 0x5c +'Yi ', # 0x5d +'Kan ', # 0x5e +'Yu ', # 0x5f +'Chuo ', # 0x60 +'Huan ', # 0x61 +'Zhi ', # 0x62 +'Zheng ', # 0x63 +'Ci ', # 0x64 +'Bu ', # 0x65 +'Wu ', # 0x66 +'Qi ', # 0x67 +'Bu ', # 0x68 +'Bu ', # 0x69 +'Wai ', # 0x6a +'Ju ', # 0x6b +'Qian ', # 0x6c +'Chi ', # 0x6d +'Se ', # 0x6e +'Chi ', # 0x6f +'Se ', # 0x70 +'Zhong ', # 0x71 +'Sui ', # 0x72 +'Sui ', # 0x73 +'Li ', # 0x74 +'Cuo ', # 0x75 +'Yu ', # 0x76 +'Li ', # 0x77 +'Gui ', # 0x78 +'Dai ', # 0x79 +'Dai ', # 0x7a +'Si ', # 0x7b +'Jian ', # 0x7c +'Zhe ', # 0x7d +'Mo ', # 0x7e +'Mo ', # 0x7f +'Yao ', # 0x80 +'Mo ', # 0x81 +'Cu ', # 0x82 +'Yang ', # 0x83 +'Tian ', # 0x84 +'Sheng ', # 0x85 +'Dai ', # 0x86 +'Shang ', # 0x87 +'Xu ', # 0x88 +'Xun ', # 0x89 +'Shu ', # 0x8a +'Can ', # 0x8b +'Jue ', # 0x8c +'Piao ', # 0x8d +'Qia ', # 0x8e +'Qiu ', # 0x8f +'Su ', # 0x90 +'Qing ', # 0x91 +'Yun ', # 0x92 +'Lian ', # 0x93 +'Yi ', # 0x94 +'Fou ', # 0x95 +'Zhi ', # 0x96 +'Ye ', # 0x97 +'Can ', # 0x98 +'Hun ', # 0x99 +'Dan ', # 0x9a +'Ji ', # 0x9b +'Ye ', # 0x9c +'Zhen ', # 0x9d +'Yun ', # 0x9e +'Wen ', # 0x9f +'Chou ', # 0xa0 +'Bin ', # 0xa1 +'Ti ', # 0xa2 +'Jin ', # 0xa3 +'Shang ', # 0xa4 +'Yin ', # 0xa5 +'Diao ', # 0xa6 +'Cu ', # 0xa7 +'Hui ', # 0xa8 +'Cuan ', # 0xa9 +'Yi ', # 0xaa +'Dan ', # 0xab +'Du ', # 0xac +'Jiang ', # 0xad +'Lian ', # 0xae +'Bin ', # 0xaf +'Du ', # 0xb0 +'Tsukusu ', # 0xb1 +'Jian ', # 0xb2 +'Shu ', # 0xb3 +'Ou ', # 0xb4 +'Duan ', # 0xb5 +'Zhu ', # 0xb6 +'Yin ', # 0xb7 +'Qing ', # 0xb8 +'Yi ', # 0xb9 +'Sha ', # 0xba +'Que ', # 0xbb +'Ke ', # 0xbc +'Yao ', # 0xbd +'Jun ', # 0xbe +'Dian ', # 0xbf +'Hui ', # 0xc0 +'Hui ', # 0xc1 +'Gu ', # 0xc2 +'Que ', # 0xc3 +'Ji ', # 0xc4 +'Yi ', # 0xc5 +'Ou ', # 0xc6 +'Hui ', # 0xc7 +'Duan ', # 0xc8 +'Yi ', # 0xc9 +'Xiao ', # 0xca +'Wu ', # 0xcb +'Guan ', # 0xcc +'Mu ', # 0xcd +'Mei ', # 0xce +'Mei ', # 0xcf +'Ai ', # 0xd0 +'Zuo ', # 0xd1 +'Du ', # 0xd2 +'Yu ', # 0xd3 +'Bi ', # 0xd4 +'Bi ', # 0xd5 +'Bi ', # 0xd6 +'Pi ', # 0xd7 +'Pi ', # 0xd8 +'Bi ', # 0xd9 +'Chan ', # 0xda +'Mao ', # 0xdb +'[?] ', # 0xdc +'[?] ', # 0xdd +'Pu ', # 0xde +'Mushiru ', # 0xdf +'Jia ', # 0xe0 +'Zhan ', # 0xe1 +'Sai ', # 0xe2 +'Mu ', # 0xe3 +'Tuo ', # 0xe4 +'Xun ', # 0xe5 +'Er ', # 0xe6 +'Rong ', # 0xe7 +'Xian ', # 0xe8 +'Ju ', # 0xe9 +'Mu ', # 0xea +'Hao ', # 0xeb +'Qiu ', # 0xec +'Dou ', # 0xed +'Mushiru ', # 0xee +'Tan ', # 0xef +'Pei ', # 0xf0 +'Ju ', # 0xf1 +'Duo ', # 0xf2 +'Cui ', # 0xf3 +'Bi ', # 0xf4 +'San ', # 0xf5 +'[?] ', # 0xf6 +'Mao ', # 0xf7 +'Sui ', # 0xf8 +'Yu ', # 0xf9 +'Yu ', # 0xfa +'Tuo ', # 0xfb +'He ', # 0xfc +'Jian ', # 0xfd +'Ta ', # 0xfe +'San ', # 0xff +) diff --git a/nstock/modules/unidecode/x06c.py b/nstock/modules/unidecode/x06c.py new file mode 100644 index 0000000..a1534e7 --- /dev/null +++ b/nstock/modules/unidecode/x06c.py @@ -0,0 +1,258 @@ +data = ( +'Lu ', # 0x00 +'Mu ', # 0x01 +'Li ', # 0x02 +'Tong ', # 0x03 +'Rong ', # 0x04 +'Chang ', # 0x05 +'Pu ', # 0x06 +'Luo ', # 0x07 +'Zhan ', # 0x08 +'Sao ', # 0x09 +'Zhan ', # 0x0a +'Meng ', # 0x0b +'Luo ', # 0x0c +'Qu ', # 0x0d +'Die ', # 0x0e +'Shi ', # 0x0f +'Di ', # 0x10 +'Min ', # 0x11 +'Jue ', # 0x12 +'Mang ', # 0x13 +'Qi ', # 0x14 +'Pie ', # 0x15 +'Nai ', # 0x16 +'Qi ', # 0x17 +'Dao ', # 0x18 +'Xian ', # 0x19 +'Chuan ', # 0x1a +'Fen ', # 0x1b +'Ri ', # 0x1c +'Nei ', # 0x1d +'[?] ', # 0x1e +'Fu ', # 0x1f +'Shen ', # 0x20 +'Dong ', # 0x21 +'Qing ', # 0x22 +'Qi ', # 0x23 +'Yin ', # 0x24 +'Xi ', # 0x25 +'Hai ', # 0x26 +'Yang ', # 0x27 +'An ', # 0x28 +'Ya ', # 0x29 +'Ke ', # 0x2a +'Qing ', # 0x2b +'Ya ', # 0x2c +'Dong ', # 0x2d +'Dan ', # 0x2e +'Lu ', # 0x2f +'Qing ', # 0x30 +'Yang ', # 0x31 +'Yun ', # 0x32 +'Yun ', # 0x33 +'Shui ', # 0x34 +'San ', # 0x35 +'Zheng ', # 0x36 +'Bing ', # 0x37 +'Yong ', # 0x38 +'Dang ', # 0x39 +'Shitamizu ', # 0x3a +'Le ', # 0x3b +'Ni ', # 0x3c +'Tun ', # 0x3d +'Fan ', # 0x3e +'Gui ', # 0x3f +'Ting ', # 0x40 +'Zhi ', # 0x41 +'Qiu ', # 0x42 +'Bin ', # 0x43 +'Ze ', # 0x44 +'Mian ', # 0x45 +'Cuan ', # 0x46 +'Hui ', # 0x47 +'Diao ', # 0x48 +'Yi ', # 0x49 +'Cha ', # 0x4a +'Zhuo ', # 0x4b +'Chuan ', # 0x4c +'Wan ', # 0x4d +'Fan ', # 0x4e +'Dai ', # 0x4f +'Xi ', # 0x50 +'Tuo ', # 0x51 +'Mang ', # 0x52 +'Qiu ', # 0x53 +'Qi ', # 0x54 +'Shan ', # 0x55 +'Pai ', # 0x56 +'Han ', # 0x57 +'Qian ', # 0x58 +'Wu ', # 0x59 +'Wu ', # 0x5a +'Xun ', # 0x5b +'Si ', # 0x5c +'Ru ', # 0x5d +'Gong ', # 0x5e +'Jiang ', # 0x5f +'Chi ', # 0x60 +'Wu ', # 0x61 +'Tsuchi ', # 0x62 +'[?] ', # 0x63 +'Tang ', # 0x64 +'Zhi ', # 0x65 +'Chi ', # 0x66 +'Qian ', # 0x67 +'Mi ', # 0x68 +'Yu ', # 0x69 +'Wang ', # 0x6a +'Qing ', # 0x6b +'Jing ', # 0x6c +'Rui ', # 0x6d +'Jun ', # 0x6e +'Hong ', # 0x6f +'Tai ', # 0x70 +'Quan ', # 0x71 +'Ji ', # 0x72 +'Bian ', # 0x73 +'Bian ', # 0x74 +'Gan ', # 0x75 +'Wen ', # 0x76 +'Zhong ', # 0x77 +'Fang ', # 0x78 +'Xiong ', # 0x79 +'Jue ', # 0x7a +'Hang ', # 0x7b +'Niou ', # 0x7c +'Qi ', # 0x7d +'Fen ', # 0x7e +'Xu ', # 0x7f +'Xu ', # 0x80 +'Qin ', # 0x81 +'Yi ', # 0x82 +'Wo ', # 0x83 +'Yun ', # 0x84 +'Yuan ', # 0x85 +'Hang ', # 0x86 +'Yan ', # 0x87 +'Chen ', # 0x88 +'Chen ', # 0x89 +'Dan ', # 0x8a +'You ', # 0x8b +'Dun ', # 0x8c +'Hu ', # 0x8d +'Huo ', # 0x8e +'Qie ', # 0x8f +'Mu ', # 0x90 +'Rou ', # 0x91 +'Mei ', # 0x92 +'Ta ', # 0x93 +'Mian ', # 0x94 +'Wu ', # 0x95 +'Chong ', # 0x96 +'Tian ', # 0x97 +'Bi ', # 0x98 +'Sha ', # 0x99 +'Zhi ', # 0x9a +'Pei ', # 0x9b +'Pan ', # 0x9c +'Zhui ', # 0x9d +'Za ', # 0x9e +'Gou ', # 0x9f +'Liu ', # 0xa0 +'Mei ', # 0xa1 +'Ze ', # 0xa2 +'Feng ', # 0xa3 +'Ou ', # 0xa4 +'Li ', # 0xa5 +'Lun ', # 0xa6 +'Cang ', # 0xa7 +'Feng ', # 0xa8 +'Wei ', # 0xa9 +'Hu ', # 0xaa +'Mo ', # 0xab +'Mei ', # 0xac +'Shu ', # 0xad +'Ju ', # 0xae +'Zan ', # 0xaf +'Tuo ', # 0xb0 +'Tuo ', # 0xb1 +'Tuo ', # 0xb2 +'He ', # 0xb3 +'Li ', # 0xb4 +'Mi ', # 0xb5 +'Yi ', # 0xb6 +'Fa ', # 0xb7 +'Fei ', # 0xb8 +'You ', # 0xb9 +'Tian ', # 0xba +'Zhi ', # 0xbb +'Zhao ', # 0xbc +'Gu ', # 0xbd +'Zhan ', # 0xbe +'Yan ', # 0xbf +'Si ', # 0xc0 +'Kuang ', # 0xc1 +'Jiong ', # 0xc2 +'Ju ', # 0xc3 +'Xie ', # 0xc4 +'Qiu ', # 0xc5 +'Yi ', # 0xc6 +'Jia ', # 0xc7 +'Zhong ', # 0xc8 +'Quan ', # 0xc9 +'Bo ', # 0xca +'Hui ', # 0xcb +'Mi ', # 0xcc +'Ben ', # 0xcd +'Zhuo ', # 0xce +'Chu ', # 0xcf +'Le ', # 0xd0 +'You ', # 0xd1 +'Gu ', # 0xd2 +'Hong ', # 0xd3 +'Gan ', # 0xd4 +'Fa ', # 0xd5 +'Mao ', # 0xd6 +'Si ', # 0xd7 +'Hu ', # 0xd8 +'Ping ', # 0xd9 +'Ci ', # 0xda +'Fan ', # 0xdb +'Chi ', # 0xdc +'Su ', # 0xdd +'Ning ', # 0xde +'Cheng ', # 0xdf +'Ling ', # 0xe0 +'Pao ', # 0xe1 +'Bo ', # 0xe2 +'Qi ', # 0xe3 +'Si ', # 0xe4 +'Ni ', # 0xe5 +'Ju ', # 0xe6 +'Yue ', # 0xe7 +'Zhu ', # 0xe8 +'Sheng ', # 0xe9 +'Lei ', # 0xea +'Xuan ', # 0xeb +'Xue ', # 0xec +'Fu ', # 0xed +'Pan ', # 0xee +'Min ', # 0xef +'Tai ', # 0xf0 +'Yang ', # 0xf1 +'Ji ', # 0xf2 +'Yong ', # 0xf3 +'Guan ', # 0xf4 +'Beng ', # 0xf5 +'Xue ', # 0xf6 +'Long ', # 0xf7 +'Lu ', # 0xf8 +'[?] ', # 0xf9 +'Bo ', # 0xfa +'Xie ', # 0xfb +'Po ', # 0xfc +'Ze ', # 0xfd +'Jing ', # 0xfe +'Yin ', # 0xff +) diff --git a/nstock/modules/unidecode/x06d.py b/nstock/modules/unidecode/x06d.py new file mode 100644 index 0000000..a911346 --- /dev/null +++ b/nstock/modules/unidecode/x06d.py @@ -0,0 +1,258 @@ +data = ( +'Zhou ', # 0x00 +'Ji ', # 0x01 +'Yi ', # 0x02 +'Hui ', # 0x03 +'Hui ', # 0x04 +'Zui ', # 0x05 +'Cheng ', # 0x06 +'Yin ', # 0x07 +'Wei ', # 0x08 +'Hou ', # 0x09 +'Jian ', # 0x0a +'Yang ', # 0x0b +'Lie ', # 0x0c +'Si ', # 0x0d +'Ji ', # 0x0e +'Er ', # 0x0f +'Xing ', # 0x10 +'Fu ', # 0x11 +'Sa ', # 0x12 +'Suo ', # 0x13 +'Zhi ', # 0x14 +'Yin ', # 0x15 +'Wu ', # 0x16 +'Xi ', # 0x17 +'Kao ', # 0x18 +'Zhu ', # 0x19 +'Jiang ', # 0x1a +'Luo ', # 0x1b +'[?] ', # 0x1c +'An ', # 0x1d +'Dong ', # 0x1e +'Yi ', # 0x1f +'Mou ', # 0x20 +'Lei ', # 0x21 +'Yi ', # 0x22 +'Mi ', # 0x23 +'Quan ', # 0x24 +'Jin ', # 0x25 +'Mo ', # 0x26 +'Wei ', # 0x27 +'Xiao ', # 0x28 +'Xie ', # 0x29 +'Hong ', # 0x2a +'Xu ', # 0x2b +'Shuo ', # 0x2c +'Kuang ', # 0x2d +'Tao ', # 0x2e +'Qie ', # 0x2f +'Ju ', # 0x30 +'Er ', # 0x31 +'Zhou ', # 0x32 +'Ru ', # 0x33 +'Ping ', # 0x34 +'Xun ', # 0x35 +'Xiong ', # 0x36 +'Zhi ', # 0x37 +'Guang ', # 0x38 +'Huan ', # 0x39 +'Ming ', # 0x3a +'Huo ', # 0x3b +'Wa ', # 0x3c +'Qia ', # 0x3d +'Pai ', # 0x3e +'Wu ', # 0x3f +'Qu ', # 0x40 +'Liu ', # 0x41 +'Yi ', # 0x42 +'Jia ', # 0x43 +'Jing ', # 0x44 +'Qian ', # 0x45 +'Jiang ', # 0x46 +'Jiao ', # 0x47 +'Cheng ', # 0x48 +'Shi ', # 0x49 +'Zhuo ', # 0x4a +'Ce ', # 0x4b +'Pal ', # 0x4c +'Kuai ', # 0x4d +'Ji ', # 0x4e +'Liu ', # 0x4f +'Chan ', # 0x50 +'Hun ', # 0x51 +'Hu ', # 0x52 +'Nong ', # 0x53 +'Xun ', # 0x54 +'Jin ', # 0x55 +'Lie ', # 0x56 +'Qiu ', # 0x57 +'Wei ', # 0x58 +'Zhe ', # 0x59 +'Jun ', # 0x5a +'Han ', # 0x5b +'Bang ', # 0x5c +'Mang ', # 0x5d +'Zhuo ', # 0x5e +'You ', # 0x5f +'Xi ', # 0x60 +'Bo ', # 0x61 +'Dou ', # 0x62 +'Wan ', # 0x63 +'Hong ', # 0x64 +'Yi ', # 0x65 +'Pu ', # 0x66 +'Ying ', # 0x67 +'Lan ', # 0x68 +'Hao ', # 0x69 +'Lang ', # 0x6a +'Han ', # 0x6b +'Li ', # 0x6c +'Geng ', # 0x6d +'Fu ', # 0x6e +'Wu ', # 0x6f +'Lian ', # 0x70 +'Chun ', # 0x71 +'Feng ', # 0x72 +'Yi ', # 0x73 +'Yu ', # 0x74 +'Tong ', # 0x75 +'Lao ', # 0x76 +'Hai ', # 0x77 +'Jin ', # 0x78 +'Jia ', # 0x79 +'Chong ', # 0x7a +'Weng ', # 0x7b +'Mei ', # 0x7c +'Sui ', # 0x7d +'Cheng ', # 0x7e +'Pei ', # 0x7f +'Xian ', # 0x80 +'Shen ', # 0x81 +'Tu ', # 0x82 +'Kun ', # 0x83 +'Pin ', # 0x84 +'Nie ', # 0x85 +'Han ', # 0x86 +'Jing ', # 0x87 +'Xiao ', # 0x88 +'She ', # 0x89 +'Nian ', # 0x8a +'Tu ', # 0x8b +'Yong ', # 0x8c +'Xiao ', # 0x8d +'Xian ', # 0x8e +'Ting ', # 0x8f +'E ', # 0x90 +'Su ', # 0x91 +'Tun ', # 0x92 +'Juan ', # 0x93 +'Cen ', # 0x94 +'Ti ', # 0x95 +'Li ', # 0x96 +'Shui ', # 0x97 +'Si ', # 0x98 +'Lei ', # 0x99 +'Shui ', # 0x9a +'Tao ', # 0x9b +'Du ', # 0x9c +'Lao ', # 0x9d +'Lai ', # 0x9e +'Lian ', # 0x9f +'Wei ', # 0xa0 +'Wo ', # 0xa1 +'Yun ', # 0xa2 +'Huan ', # 0xa3 +'Di ', # 0xa4 +'[?] ', # 0xa5 +'Run ', # 0xa6 +'Jian ', # 0xa7 +'Zhang ', # 0xa8 +'Se ', # 0xa9 +'Fu ', # 0xaa +'Guan ', # 0xab +'Xing ', # 0xac +'Shou ', # 0xad +'Shuan ', # 0xae +'Ya ', # 0xaf +'Chuo ', # 0xb0 +'Zhang ', # 0xb1 +'Ye ', # 0xb2 +'Kong ', # 0xb3 +'Wo ', # 0xb4 +'Han ', # 0xb5 +'Tuo ', # 0xb6 +'Dong ', # 0xb7 +'He ', # 0xb8 +'Wo ', # 0xb9 +'Ju ', # 0xba +'Gan ', # 0xbb +'Liang ', # 0xbc +'Hun ', # 0xbd +'Ta ', # 0xbe +'Zhuo ', # 0xbf +'Dian ', # 0xc0 +'Qie ', # 0xc1 +'De ', # 0xc2 +'Juan ', # 0xc3 +'Zi ', # 0xc4 +'Xi ', # 0xc5 +'Yao ', # 0xc6 +'Qi ', # 0xc7 +'Gu ', # 0xc8 +'Guo ', # 0xc9 +'Han ', # 0xca +'Lin ', # 0xcb +'Tang ', # 0xcc +'Zhou ', # 0xcd +'Peng ', # 0xce +'Hao ', # 0xcf +'Chang ', # 0xd0 +'Shu ', # 0xd1 +'Qi ', # 0xd2 +'Fang ', # 0xd3 +'Chi ', # 0xd4 +'Lu ', # 0xd5 +'Nao ', # 0xd6 +'Ju ', # 0xd7 +'Tao ', # 0xd8 +'Cong ', # 0xd9 +'Lei ', # 0xda +'Zhi ', # 0xdb +'Peng ', # 0xdc +'Fei ', # 0xdd +'Song ', # 0xde +'Tian ', # 0xdf +'Pi ', # 0xe0 +'Dan ', # 0xe1 +'Yu ', # 0xe2 +'Ni ', # 0xe3 +'Yu ', # 0xe4 +'Lu ', # 0xe5 +'Gan ', # 0xe6 +'Mi ', # 0xe7 +'Jing ', # 0xe8 +'Ling ', # 0xe9 +'Lun ', # 0xea +'Yin ', # 0xeb +'Cui ', # 0xec +'Qu ', # 0xed +'Huai ', # 0xee +'Yu ', # 0xef +'Nian ', # 0xf0 +'Shen ', # 0xf1 +'Piao ', # 0xf2 +'Chun ', # 0xf3 +'Wa ', # 0xf4 +'Yuan ', # 0xf5 +'Lai ', # 0xf6 +'Hun ', # 0xf7 +'Qing ', # 0xf8 +'Yan ', # 0xf9 +'Qian ', # 0xfa +'Tian ', # 0xfb +'Miao ', # 0xfc +'Zhi ', # 0xfd +'Yin ', # 0xfe +'Mi ', # 0xff +) diff --git a/nstock/modules/unidecode/x06e.py b/nstock/modules/unidecode/x06e.py new file mode 100644 index 0000000..d4698fd --- /dev/null +++ b/nstock/modules/unidecode/x06e.py @@ -0,0 +1,258 @@ +data = ( +'Ben ', # 0x00 +'Yuan ', # 0x01 +'Wen ', # 0x02 +'Re ', # 0x03 +'Fei ', # 0x04 +'Qing ', # 0x05 +'Yuan ', # 0x06 +'Ke ', # 0x07 +'Ji ', # 0x08 +'She ', # 0x09 +'Yuan ', # 0x0a +'Shibui ', # 0x0b +'Lu ', # 0x0c +'Zi ', # 0x0d +'Du ', # 0x0e +'[?] ', # 0x0f +'Jian ', # 0x10 +'Min ', # 0x11 +'Pi ', # 0x12 +'Tani ', # 0x13 +'Yu ', # 0x14 +'Yuan ', # 0x15 +'Shen ', # 0x16 +'Shen ', # 0x17 +'Rou ', # 0x18 +'Huan ', # 0x19 +'Zhu ', # 0x1a +'Jian ', # 0x1b +'Nuan ', # 0x1c +'Yu ', # 0x1d +'Qiu ', # 0x1e +'Ting ', # 0x1f +'Qu ', # 0x20 +'Du ', # 0x21 +'Feng ', # 0x22 +'Zha ', # 0x23 +'Bo ', # 0x24 +'Wo ', # 0x25 +'Wo ', # 0x26 +'Di ', # 0x27 +'Wei ', # 0x28 +'Wen ', # 0x29 +'Ru ', # 0x2a +'Xie ', # 0x2b +'Ce ', # 0x2c +'Wei ', # 0x2d +'Ge ', # 0x2e +'Gang ', # 0x2f +'Yan ', # 0x30 +'Hong ', # 0x31 +'Xuan ', # 0x32 +'Mi ', # 0x33 +'Ke ', # 0x34 +'Mao ', # 0x35 +'Ying ', # 0x36 +'Yan ', # 0x37 +'You ', # 0x38 +'Hong ', # 0x39 +'Miao ', # 0x3a +'Xing ', # 0x3b +'Mei ', # 0x3c +'Zai ', # 0x3d +'Hun ', # 0x3e +'Nai ', # 0x3f +'Kui ', # 0x40 +'Shi ', # 0x41 +'E ', # 0x42 +'Pai ', # 0x43 +'Mei ', # 0x44 +'Lian ', # 0x45 +'Qi ', # 0x46 +'Qi ', # 0x47 +'Mei ', # 0x48 +'Tian ', # 0x49 +'Cou ', # 0x4a +'Wei ', # 0x4b +'Can ', # 0x4c +'Tuan ', # 0x4d +'Mian ', # 0x4e +'Hui ', # 0x4f +'Mo ', # 0x50 +'Xu ', # 0x51 +'Ji ', # 0x52 +'Pen ', # 0x53 +'Jian ', # 0x54 +'Jian ', # 0x55 +'Hu ', # 0x56 +'Feng ', # 0x57 +'Xiang ', # 0x58 +'Yi ', # 0x59 +'Yin ', # 0x5a +'Zhan ', # 0x5b +'Shi ', # 0x5c +'Jie ', # 0x5d +'Cheng ', # 0x5e +'Huang ', # 0x5f +'Tan ', # 0x60 +'Yu ', # 0x61 +'Bi ', # 0x62 +'Min ', # 0x63 +'Shi ', # 0x64 +'Tu ', # 0x65 +'Sheng ', # 0x66 +'Yong ', # 0x67 +'Qu ', # 0x68 +'Zhong ', # 0x69 +'Suei ', # 0x6a +'Jiu ', # 0x6b +'Jiao ', # 0x6c +'Qiou ', # 0x6d +'Yin ', # 0x6e +'Tang ', # 0x6f +'Long ', # 0x70 +'Huo ', # 0x71 +'Yuan ', # 0x72 +'Nan ', # 0x73 +'Ban ', # 0x74 +'You ', # 0x75 +'Quan ', # 0x76 +'Chui ', # 0x77 +'Liang ', # 0x78 +'Chan ', # 0x79 +'Yan ', # 0x7a +'Chun ', # 0x7b +'Nie ', # 0x7c +'Zi ', # 0x7d +'Wan ', # 0x7e +'Shi ', # 0x7f +'Man ', # 0x80 +'Ying ', # 0x81 +'Ratsu ', # 0x82 +'Kui ', # 0x83 +'[?] ', # 0x84 +'Jian ', # 0x85 +'Xu ', # 0x86 +'Lu ', # 0x87 +'Gui ', # 0x88 +'Gai ', # 0x89 +'[?] ', # 0x8a +'[?] ', # 0x8b +'Po ', # 0x8c +'Jin ', # 0x8d +'Gui ', # 0x8e +'Tang ', # 0x8f +'Yuan ', # 0x90 +'Suo ', # 0x91 +'Yuan ', # 0x92 +'Lian ', # 0x93 +'Yao ', # 0x94 +'Meng ', # 0x95 +'Zhun ', # 0x96 +'Sheng ', # 0x97 +'Ke ', # 0x98 +'Tai ', # 0x99 +'Da ', # 0x9a +'Wa ', # 0x9b +'Liu ', # 0x9c +'Gou ', # 0x9d +'Sao ', # 0x9e +'Ming ', # 0x9f +'Zha ', # 0xa0 +'Shi ', # 0xa1 +'Yi ', # 0xa2 +'Lun ', # 0xa3 +'Ma ', # 0xa4 +'Pu ', # 0xa5 +'Wei ', # 0xa6 +'Li ', # 0xa7 +'Cai ', # 0xa8 +'Wu ', # 0xa9 +'Xi ', # 0xaa +'Wen ', # 0xab +'Qiang ', # 0xac +'Ze ', # 0xad +'Shi ', # 0xae +'Su ', # 0xaf +'Yi ', # 0xb0 +'Zhen ', # 0xb1 +'Sou ', # 0xb2 +'Yun ', # 0xb3 +'Xiu ', # 0xb4 +'Yin ', # 0xb5 +'Rong ', # 0xb6 +'Hun ', # 0xb7 +'Su ', # 0xb8 +'Su ', # 0xb9 +'Ni ', # 0xba +'Ta ', # 0xbb +'Shi ', # 0xbc +'Ru ', # 0xbd +'Wei ', # 0xbe +'Pan ', # 0xbf +'Chu ', # 0xc0 +'Chu ', # 0xc1 +'Pang ', # 0xc2 +'Weng ', # 0xc3 +'Cang ', # 0xc4 +'Mie ', # 0xc5 +'He ', # 0xc6 +'Dian ', # 0xc7 +'Hao ', # 0xc8 +'Huang ', # 0xc9 +'Xi ', # 0xca +'Zi ', # 0xcb +'Di ', # 0xcc +'Zhi ', # 0xcd +'Ying ', # 0xce +'Fu ', # 0xcf +'Jie ', # 0xd0 +'Hua ', # 0xd1 +'Ge ', # 0xd2 +'Zi ', # 0xd3 +'Tao ', # 0xd4 +'Teng ', # 0xd5 +'Sui ', # 0xd6 +'Bi ', # 0xd7 +'Jiao ', # 0xd8 +'Hui ', # 0xd9 +'Gun ', # 0xda +'Yin ', # 0xdb +'Gao ', # 0xdc +'Long ', # 0xdd +'Zhi ', # 0xde +'Yan ', # 0xdf +'She ', # 0xe0 +'Man ', # 0xe1 +'Ying ', # 0xe2 +'Chun ', # 0xe3 +'Lu ', # 0xe4 +'Lan ', # 0xe5 +'Luan ', # 0xe6 +'[?] ', # 0xe7 +'Bin ', # 0xe8 +'Tan ', # 0xe9 +'Yu ', # 0xea +'Sou ', # 0xeb +'Hu ', # 0xec +'Bi ', # 0xed +'Biao ', # 0xee +'Zhi ', # 0xef +'Jiang ', # 0xf0 +'Kou ', # 0xf1 +'Shen ', # 0xf2 +'Shang ', # 0xf3 +'Di ', # 0xf4 +'Mi ', # 0xf5 +'Ao ', # 0xf6 +'Lu ', # 0xf7 +'Hu ', # 0xf8 +'Hu ', # 0xf9 +'You ', # 0xfa +'Chan ', # 0xfb +'Fan ', # 0xfc +'Yong ', # 0xfd +'Gun ', # 0xfe +'Man ', # 0xff +) diff --git a/nstock/modules/unidecode/x06f.py b/nstock/modules/unidecode/x06f.py new file mode 100644 index 0000000..36bf2a2 --- /dev/null +++ b/nstock/modules/unidecode/x06f.py @@ -0,0 +1,258 @@ +data = ( +'Qing ', # 0x00 +'Yu ', # 0x01 +'Piao ', # 0x02 +'Ji ', # 0x03 +'Ya ', # 0x04 +'Jiao ', # 0x05 +'Qi ', # 0x06 +'Xi ', # 0x07 +'Ji ', # 0x08 +'Lu ', # 0x09 +'Lu ', # 0x0a +'Long ', # 0x0b +'Jin ', # 0x0c +'Guo ', # 0x0d +'Cong ', # 0x0e +'Lou ', # 0x0f +'Zhi ', # 0x10 +'Gai ', # 0x11 +'Qiang ', # 0x12 +'Li ', # 0x13 +'Yan ', # 0x14 +'Cao ', # 0x15 +'Jiao ', # 0x16 +'Cong ', # 0x17 +'Qun ', # 0x18 +'Tuan ', # 0x19 +'Ou ', # 0x1a +'Teng ', # 0x1b +'Ye ', # 0x1c +'Xi ', # 0x1d +'Mi ', # 0x1e +'Tang ', # 0x1f +'Mo ', # 0x20 +'Shang ', # 0x21 +'Han ', # 0x22 +'Lian ', # 0x23 +'Lan ', # 0x24 +'Wa ', # 0x25 +'Li ', # 0x26 +'Qian ', # 0x27 +'Feng ', # 0x28 +'Xuan ', # 0x29 +'Yi ', # 0x2a +'Man ', # 0x2b +'Zi ', # 0x2c +'Mang ', # 0x2d +'Kang ', # 0x2e +'Lei ', # 0x2f +'Peng ', # 0x30 +'Shu ', # 0x31 +'Zhang ', # 0x32 +'Zhang ', # 0x33 +'Chong ', # 0x34 +'Xu ', # 0x35 +'Huan ', # 0x36 +'Kuo ', # 0x37 +'Jian ', # 0x38 +'Yan ', # 0x39 +'Chuang ', # 0x3a +'Liao ', # 0x3b +'Cui ', # 0x3c +'Ti ', # 0x3d +'Yang ', # 0x3e +'Jiang ', # 0x3f +'Cong ', # 0x40 +'Ying ', # 0x41 +'Hong ', # 0x42 +'Xun ', # 0x43 +'Shu ', # 0x44 +'Guan ', # 0x45 +'Ying ', # 0x46 +'Xiao ', # 0x47 +'[?] ', # 0x48 +'[?] ', # 0x49 +'Xu ', # 0x4a +'Lian ', # 0x4b +'Zhi ', # 0x4c +'Wei ', # 0x4d +'Pi ', # 0x4e +'Jue ', # 0x4f +'Jiao ', # 0x50 +'Po ', # 0x51 +'Dang ', # 0x52 +'Hui ', # 0x53 +'Jie ', # 0x54 +'Wu ', # 0x55 +'Pa ', # 0x56 +'Ji ', # 0x57 +'Pan ', # 0x58 +'Gui ', # 0x59 +'Xiao ', # 0x5a +'Qian ', # 0x5b +'Qian ', # 0x5c +'Xi ', # 0x5d +'Lu ', # 0x5e +'Xi ', # 0x5f +'Xuan ', # 0x60 +'Dun ', # 0x61 +'Huang ', # 0x62 +'Min ', # 0x63 +'Run ', # 0x64 +'Su ', # 0x65 +'Liao ', # 0x66 +'Zhen ', # 0x67 +'Zhong ', # 0x68 +'Yi ', # 0x69 +'Di ', # 0x6a +'Wan ', # 0x6b +'Dan ', # 0x6c +'Tan ', # 0x6d +'Chao ', # 0x6e +'Xun ', # 0x6f +'Kui ', # 0x70 +'Yie ', # 0x71 +'Shao ', # 0x72 +'Tu ', # 0x73 +'Zhu ', # 0x74 +'San ', # 0x75 +'Hei ', # 0x76 +'Bi ', # 0x77 +'Shan ', # 0x78 +'Chan ', # 0x79 +'Chan ', # 0x7a +'Shu ', # 0x7b +'Tong ', # 0x7c +'Pu ', # 0x7d +'Lin ', # 0x7e +'Wei ', # 0x7f +'Se ', # 0x80 +'Se ', # 0x81 +'Cheng ', # 0x82 +'Jiong ', # 0x83 +'Cheng ', # 0x84 +'Hua ', # 0x85 +'Jiao ', # 0x86 +'Lao ', # 0x87 +'Che ', # 0x88 +'Gan ', # 0x89 +'Cun ', # 0x8a +'Heng ', # 0x8b +'Si ', # 0x8c +'Shu ', # 0x8d +'Peng ', # 0x8e +'Han ', # 0x8f +'Yun ', # 0x90 +'Liu ', # 0x91 +'Hong ', # 0x92 +'Fu ', # 0x93 +'Hao ', # 0x94 +'He ', # 0x95 +'Xian ', # 0x96 +'Jian ', # 0x97 +'Shan ', # 0x98 +'Xi ', # 0x99 +'Oki ', # 0x9a +'[?] ', # 0x9b +'Lan ', # 0x9c +'[?] ', # 0x9d +'Yu ', # 0x9e +'Lin ', # 0x9f +'Min ', # 0xa0 +'Zao ', # 0xa1 +'Dang ', # 0xa2 +'Wan ', # 0xa3 +'Ze ', # 0xa4 +'Xie ', # 0xa5 +'Yu ', # 0xa6 +'Li ', # 0xa7 +'Shi ', # 0xa8 +'Xue ', # 0xa9 +'Ling ', # 0xaa +'Man ', # 0xab +'Zi ', # 0xac +'Yong ', # 0xad +'Kuai ', # 0xae +'Can ', # 0xaf +'Lian ', # 0xb0 +'Dian ', # 0xb1 +'Ye ', # 0xb2 +'Ao ', # 0xb3 +'Huan ', # 0xb4 +'Zhen ', # 0xb5 +'Chan ', # 0xb6 +'Man ', # 0xb7 +'Dan ', # 0xb8 +'Dan ', # 0xb9 +'Yi ', # 0xba +'Sui ', # 0xbb +'Pi ', # 0xbc +'Ju ', # 0xbd +'Ta ', # 0xbe +'Qin ', # 0xbf +'Ji ', # 0xc0 +'Zhuo ', # 0xc1 +'Lian ', # 0xc2 +'Nong ', # 0xc3 +'Guo ', # 0xc4 +'Jin ', # 0xc5 +'Fen ', # 0xc6 +'Se ', # 0xc7 +'Ji ', # 0xc8 +'Sui ', # 0xc9 +'Hui ', # 0xca +'Chu ', # 0xcb +'Ta ', # 0xcc +'Song ', # 0xcd +'Ding ', # 0xce +'[?] ', # 0xcf +'Zhu ', # 0xd0 +'Lai ', # 0xd1 +'Bin ', # 0xd2 +'Lian ', # 0xd3 +'Mi ', # 0xd4 +'Shi ', # 0xd5 +'Shu ', # 0xd6 +'Mi ', # 0xd7 +'Ning ', # 0xd8 +'Ying ', # 0xd9 +'Ying ', # 0xda +'Meng ', # 0xdb +'Jin ', # 0xdc +'Qi ', # 0xdd +'Pi ', # 0xde +'Ji ', # 0xdf +'Hao ', # 0xe0 +'Ru ', # 0xe1 +'Zui ', # 0xe2 +'Wo ', # 0xe3 +'Tao ', # 0xe4 +'Yin ', # 0xe5 +'Yin ', # 0xe6 +'Dui ', # 0xe7 +'Ci ', # 0xe8 +'Huo ', # 0xe9 +'Jing ', # 0xea +'Lan ', # 0xeb +'Jun ', # 0xec +'Ai ', # 0xed +'Pu ', # 0xee +'Zhuo ', # 0xef +'Wei ', # 0xf0 +'Bin ', # 0xf1 +'Gu ', # 0xf2 +'Qian ', # 0xf3 +'Xing ', # 0xf4 +'Hama ', # 0xf5 +'Kuo ', # 0xf6 +'Fei ', # 0xf7 +'[?] ', # 0xf8 +'Boku ', # 0xf9 +'Jian ', # 0xfa +'Wei ', # 0xfb +'Luo ', # 0xfc +'Zan ', # 0xfd +'Lu ', # 0xfe +'Li ', # 0xff +) diff --git a/nstock/modules/unidecode/x070.py b/nstock/modules/unidecode/x070.py new file mode 100644 index 0000000..b12567f --- /dev/null +++ b/nstock/modules/unidecode/x070.py @@ -0,0 +1,258 @@ +data = ( +'You ', # 0x00 +'Yang ', # 0x01 +'Lu ', # 0x02 +'Si ', # 0x03 +'Jie ', # 0x04 +'Ying ', # 0x05 +'Du ', # 0x06 +'Wang ', # 0x07 +'Hui ', # 0x08 +'Xie ', # 0x09 +'Pan ', # 0x0a +'Shen ', # 0x0b +'Biao ', # 0x0c +'Chan ', # 0x0d +'Mo ', # 0x0e +'Liu ', # 0x0f +'Jian ', # 0x10 +'Pu ', # 0x11 +'Se ', # 0x12 +'Cheng ', # 0x13 +'Gu ', # 0x14 +'Bin ', # 0x15 +'Huo ', # 0x16 +'Xian ', # 0x17 +'Lu ', # 0x18 +'Qin ', # 0x19 +'Han ', # 0x1a +'Ying ', # 0x1b +'Yong ', # 0x1c +'Li ', # 0x1d +'Jing ', # 0x1e +'Xiao ', # 0x1f +'Ying ', # 0x20 +'Sui ', # 0x21 +'Wei ', # 0x22 +'Xie ', # 0x23 +'Huai ', # 0x24 +'Hao ', # 0x25 +'Zhu ', # 0x26 +'Long ', # 0x27 +'Lai ', # 0x28 +'Dui ', # 0x29 +'Fan ', # 0x2a +'Hu ', # 0x2b +'Lai ', # 0x2c +'[?] ', # 0x2d +'[?] ', # 0x2e +'Ying ', # 0x2f +'Mi ', # 0x30 +'Ji ', # 0x31 +'Lian ', # 0x32 +'Jian ', # 0x33 +'Ying ', # 0x34 +'Fen ', # 0x35 +'Lin ', # 0x36 +'Yi ', # 0x37 +'Jian ', # 0x38 +'Yue ', # 0x39 +'Chan ', # 0x3a +'Dai ', # 0x3b +'Rang ', # 0x3c +'Jian ', # 0x3d +'Lan ', # 0x3e +'Fan ', # 0x3f +'Shuang ', # 0x40 +'Yuan ', # 0x41 +'Zhuo ', # 0x42 +'Feng ', # 0x43 +'She ', # 0x44 +'Lei ', # 0x45 +'Lan ', # 0x46 +'Cong ', # 0x47 +'Qu ', # 0x48 +'Yong ', # 0x49 +'Qian ', # 0x4a +'Fa ', # 0x4b +'Guan ', # 0x4c +'Que ', # 0x4d +'Yan ', # 0x4e +'Hao ', # 0x4f +'Hyeng ', # 0x50 +'Sa ', # 0x51 +'Zan ', # 0x52 +'Luan ', # 0x53 +'Yan ', # 0x54 +'Li ', # 0x55 +'Mi ', # 0x56 +'Shan ', # 0x57 +'Tan ', # 0x58 +'Dang ', # 0x59 +'Jiao ', # 0x5a +'Chan ', # 0x5b +'[?] ', # 0x5c +'Hao ', # 0x5d +'Ba ', # 0x5e +'Zhu ', # 0x5f +'Lan ', # 0x60 +'Lan ', # 0x61 +'Nang ', # 0x62 +'Wan ', # 0x63 +'Luan ', # 0x64 +'Xun ', # 0x65 +'Xian ', # 0x66 +'Yan ', # 0x67 +'Gan ', # 0x68 +'Yan ', # 0x69 +'Yu ', # 0x6a +'Huo ', # 0x6b +'Si ', # 0x6c +'Mie ', # 0x6d +'Guang ', # 0x6e +'Deng ', # 0x6f +'Hui ', # 0x70 +'Xiao ', # 0x71 +'Xiao ', # 0x72 +'Hu ', # 0x73 +'Hong ', # 0x74 +'Ling ', # 0x75 +'Zao ', # 0x76 +'Zhuan ', # 0x77 +'Jiu ', # 0x78 +'Zha ', # 0x79 +'Xie ', # 0x7a +'Chi ', # 0x7b +'Zhuo ', # 0x7c +'Zai ', # 0x7d +'Zai ', # 0x7e +'Can ', # 0x7f +'Yang ', # 0x80 +'Qi ', # 0x81 +'Zhong ', # 0x82 +'Fen ', # 0x83 +'Niu ', # 0x84 +'Jiong ', # 0x85 +'Wen ', # 0x86 +'Po ', # 0x87 +'Yi ', # 0x88 +'Lu ', # 0x89 +'Chui ', # 0x8a +'Pi ', # 0x8b +'Kai ', # 0x8c +'Pan ', # 0x8d +'Yan ', # 0x8e +'Kai ', # 0x8f +'Pang ', # 0x90 +'Mu ', # 0x91 +'Chao ', # 0x92 +'Liao ', # 0x93 +'Gui ', # 0x94 +'Kang ', # 0x95 +'Tun ', # 0x96 +'Guang ', # 0x97 +'Xin ', # 0x98 +'Zhi ', # 0x99 +'Guang ', # 0x9a +'Guang ', # 0x9b +'Wei ', # 0x9c +'Qiang ', # 0x9d +'[?] ', # 0x9e +'Da ', # 0x9f +'Xia ', # 0xa0 +'Zheng ', # 0xa1 +'Zhu ', # 0xa2 +'Ke ', # 0xa3 +'Zhao ', # 0xa4 +'Fu ', # 0xa5 +'Ba ', # 0xa6 +'Duo ', # 0xa7 +'Duo ', # 0xa8 +'Ling ', # 0xa9 +'Zhuo ', # 0xaa +'Xuan ', # 0xab +'Ju ', # 0xac +'Tan ', # 0xad +'Pao ', # 0xae +'Jiong ', # 0xaf +'Pao ', # 0xb0 +'Tai ', # 0xb1 +'Tai ', # 0xb2 +'Bing ', # 0xb3 +'Yang ', # 0xb4 +'Tong ', # 0xb5 +'Han ', # 0xb6 +'Zhu ', # 0xb7 +'Zha ', # 0xb8 +'Dian ', # 0xb9 +'Wei ', # 0xba +'Shi ', # 0xbb +'Lian ', # 0xbc +'Chi ', # 0xbd +'Huang ', # 0xbe +'[?] ', # 0xbf +'Hu ', # 0xc0 +'Shuo ', # 0xc1 +'Lan ', # 0xc2 +'Jing ', # 0xc3 +'Jiao ', # 0xc4 +'Xu ', # 0xc5 +'Xing ', # 0xc6 +'Quan ', # 0xc7 +'Lie ', # 0xc8 +'Huan ', # 0xc9 +'Yang ', # 0xca +'Xiao ', # 0xcb +'Xiu ', # 0xcc +'Xian ', # 0xcd +'Yin ', # 0xce +'Wu ', # 0xcf +'Zhou ', # 0xd0 +'Yao ', # 0xd1 +'Shi ', # 0xd2 +'Wei ', # 0xd3 +'Tong ', # 0xd4 +'Xue ', # 0xd5 +'Zai ', # 0xd6 +'Kai ', # 0xd7 +'Hong ', # 0xd8 +'Luo ', # 0xd9 +'Xia ', # 0xda +'Zhu ', # 0xdb +'Xuan ', # 0xdc +'Zheng ', # 0xdd +'Po ', # 0xde +'Yan ', # 0xdf +'Hui ', # 0xe0 +'Guang ', # 0xe1 +'Zhe ', # 0xe2 +'Hui ', # 0xe3 +'Kao ', # 0xe4 +'[?] ', # 0xe5 +'Fan ', # 0xe6 +'Shao ', # 0xe7 +'Ye ', # 0xe8 +'Hui ', # 0xe9 +'[?] ', # 0xea +'Tang ', # 0xeb +'Jin ', # 0xec +'Re ', # 0xed +'[?] ', # 0xee +'Xi ', # 0xef +'Fu ', # 0xf0 +'Jiong ', # 0xf1 +'Che ', # 0xf2 +'Pu ', # 0xf3 +'Jing ', # 0xf4 +'Zhuo ', # 0xf5 +'Ting ', # 0xf6 +'Wan ', # 0xf7 +'Hai ', # 0xf8 +'Peng ', # 0xf9 +'Lang ', # 0xfa +'Shan ', # 0xfb +'Hu ', # 0xfc +'Feng ', # 0xfd +'Chi ', # 0xfe +'Rong ', # 0xff +) diff --git a/nstock/modules/unidecode/x071.py b/nstock/modules/unidecode/x071.py new file mode 100644 index 0000000..bad8f7e --- /dev/null +++ b/nstock/modules/unidecode/x071.py @@ -0,0 +1,258 @@ +data = ( +'Hu ', # 0x00 +'Xi ', # 0x01 +'Shu ', # 0x02 +'He ', # 0x03 +'Xun ', # 0x04 +'Ku ', # 0x05 +'Jue ', # 0x06 +'Xiao ', # 0x07 +'Xi ', # 0x08 +'Yan ', # 0x09 +'Han ', # 0x0a +'Zhuang ', # 0x0b +'Jun ', # 0x0c +'Di ', # 0x0d +'Xie ', # 0x0e +'Ji ', # 0x0f +'Wu ', # 0x10 +'[?] ', # 0x11 +'[?] ', # 0x12 +'Han ', # 0x13 +'Yan ', # 0x14 +'Huan ', # 0x15 +'Men ', # 0x16 +'Ju ', # 0x17 +'Chou ', # 0x18 +'Bei ', # 0x19 +'Fen ', # 0x1a +'Lin ', # 0x1b +'Kun ', # 0x1c +'Hun ', # 0x1d +'Tun ', # 0x1e +'Xi ', # 0x1f +'Cui ', # 0x20 +'Wu ', # 0x21 +'Hong ', # 0x22 +'Ju ', # 0x23 +'Fu ', # 0x24 +'Wo ', # 0x25 +'Jiao ', # 0x26 +'Cong ', # 0x27 +'Feng ', # 0x28 +'Ping ', # 0x29 +'Qiong ', # 0x2a +'Ruo ', # 0x2b +'Xi ', # 0x2c +'Qiong ', # 0x2d +'Xin ', # 0x2e +'Zhuo ', # 0x2f +'Yan ', # 0x30 +'Yan ', # 0x31 +'Yi ', # 0x32 +'Jue ', # 0x33 +'Yu ', # 0x34 +'Gang ', # 0x35 +'Ran ', # 0x36 +'Pi ', # 0x37 +'Gu ', # 0x38 +'[?] ', # 0x39 +'Sheng ', # 0x3a +'Chang ', # 0x3b +'Shao ', # 0x3c +'[?] ', # 0x3d +'[?] ', # 0x3e +'[?] ', # 0x3f +'[?] ', # 0x40 +'Chen ', # 0x41 +'He ', # 0x42 +'Kui ', # 0x43 +'Zhong ', # 0x44 +'Duan ', # 0x45 +'Xia ', # 0x46 +'Hui ', # 0x47 +'Feng ', # 0x48 +'Lian ', # 0x49 +'Xuan ', # 0x4a +'Xing ', # 0x4b +'Huang ', # 0x4c +'Jiao ', # 0x4d +'Jian ', # 0x4e +'Bi ', # 0x4f +'Ying ', # 0x50 +'Zhu ', # 0x51 +'Wei ', # 0x52 +'Tuan ', # 0x53 +'Tian ', # 0x54 +'Xi ', # 0x55 +'Nuan ', # 0x56 +'Nuan ', # 0x57 +'Chan ', # 0x58 +'Yan ', # 0x59 +'Jiong ', # 0x5a +'Jiong ', # 0x5b +'Yu ', # 0x5c +'Mei ', # 0x5d +'Sha ', # 0x5e +'Wei ', # 0x5f +'Ye ', # 0x60 +'Xin ', # 0x61 +'Qiong ', # 0x62 +'Rou ', # 0x63 +'Mei ', # 0x64 +'Huan ', # 0x65 +'Xu ', # 0x66 +'Zhao ', # 0x67 +'Wei ', # 0x68 +'Fan ', # 0x69 +'Qiu ', # 0x6a +'Sui ', # 0x6b +'Yang ', # 0x6c +'Lie ', # 0x6d +'Zhu ', # 0x6e +'Jie ', # 0x6f +'Gao ', # 0x70 +'Gua ', # 0x71 +'Bao ', # 0x72 +'Hu ', # 0x73 +'Yun ', # 0x74 +'Xia ', # 0x75 +'[?] ', # 0x76 +'[?] ', # 0x77 +'Bian ', # 0x78 +'Gou ', # 0x79 +'Tui ', # 0x7a +'Tang ', # 0x7b +'Chao ', # 0x7c +'Shan ', # 0x7d +'N ', # 0x7e +'Bo ', # 0x7f +'Huang ', # 0x80 +'Xie ', # 0x81 +'Xi ', # 0x82 +'Wu ', # 0x83 +'Xi ', # 0x84 +'Yun ', # 0x85 +'He ', # 0x86 +'He ', # 0x87 +'Xi ', # 0x88 +'Yun ', # 0x89 +'Xiong ', # 0x8a +'Nai ', # 0x8b +'Shan ', # 0x8c +'Qiong ', # 0x8d +'Yao ', # 0x8e +'Xun ', # 0x8f +'Mi ', # 0x90 +'Lian ', # 0x91 +'Ying ', # 0x92 +'Wen ', # 0x93 +'Rong ', # 0x94 +'Oozutsu ', # 0x95 +'[?] ', # 0x96 +'Qiang ', # 0x97 +'Liu ', # 0x98 +'Xi ', # 0x99 +'Bi ', # 0x9a +'Biao ', # 0x9b +'Zong ', # 0x9c +'Lu ', # 0x9d +'Jian ', # 0x9e +'Shou ', # 0x9f +'Yi ', # 0xa0 +'Lou ', # 0xa1 +'Feng ', # 0xa2 +'Sui ', # 0xa3 +'Yi ', # 0xa4 +'Tong ', # 0xa5 +'Jue ', # 0xa6 +'Zong ', # 0xa7 +'Yun ', # 0xa8 +'Hu ', # 0xa9 +'Yi ', # 0xaa +'Zhi ', # 0xab +'Ao ', # 0xac +'Wei ', # 0xad +'Liao ', # 0xae +'Han ', # 0xaf +'Ou ', # 0xb0 +'Re ', # 0xb1 +'Jiong ', # 0xb2 +'Man ', # 0xb3 +'[?] ', # 0xb4 +'Shang ', # 0xb5 +'Cuan ', # 0xb6 +'Zeng ', # 0xb7 +'Jian ', # 0xb8 +'Xi ', # 0xb9 +'Xi ', # 0xba +'Xi ', # 0xbb +'Yi ', # 0xbc +'Xiao ', # 0xbd +'Chi ', # 0xbe +'Huang ', # 0xbf +'Chan ', # 0xc0 +'Ye ', # 0xc1 +'Qian ', # 0xc2 +'Ran ', # 0xc3 +'Yan ', # 0xc4 +'Xian ', # 0xc5 +'Qiao ', # 0xc6 +'Zun ', # 0xc7 +'Deng ', # 0xc8 +'Dun ', # 0xc9 +'Shen ', # 0xca +'Jiao ', # 0xcb +'Fen ', # 0xcc +'Si ', # 0xcd +'Liao ', # 0xce +'Yu ', # 0xcf +'Lin ', # 0xd0 +'Tong ', # 0xd1 +'Shao ', # 0xd2 +'Fen ', # 0xd3 +'Fan ', # 0xd4 +'Yan ', # 0xd5 +'Xun ', # 0xd6 +'Lan ', # 0xd7 +'Mei ', # 0xd8 +'Tang ', # 0xd9 +'Yi ', # 0xda +'Jing ', # 0xdb +'Men ', # 0xdc +'[?] ', # 0xdd +'[?] ', # 0xde +'Ying ', # 0xdf +'Yu ', # 0xe0 +'Yi ', # 0xe1 +'Xue ', # 0xe2 +'Lan ', # 0xe3 +'Tai ', # 0xe4 +'Zao ', # 0xe5 +'Can ', # 0xe6 +'Sui ', # 0xe7 +'Xi ', # 0xe8 +'Que ', # 0xe9 +'Cong ', # 0xea +'Lian ', # 0xeb +'Hui ', # 0xec +'Zhu ', # 0xed +'Xie ', # 0xee +'Ling ', # 0xef +'Wei ', # 0xf0 +'Yi ', # 0xf1 +'Xie ', # 0xf2 +'Zhao ', # 0xf3 +'Hui ', # 0xf4 +'Tatsu ', # 0xf5 +'Nung ', # 0xf6 +'Lan ', # 0xf7 +'Ru ', # 0xf8 +'Xian ', # 0xf9 +'Kao ', # 0xfa +'Xun ', # 0xfb +'Jin ', # 0xfc +'Chou ', # 0xfd +'Chou ', # 0xfe +'Yao ', # 0xff +) diff --git a/nstock/modules/unidecode/x072.py b/nstock/modules/unidecode/x072.py new file mode 100644 index 0000000..c91c93c --- /dev/null +++ b/nstock/modules/unidecode/x072.py @@ -0,0 +1,258 @@ +data = ( +'He ', # 0x00 +'Lan ', # 0x01 +'Biao ', # 0x02 +'Rong ', # 0x03 +'Li ', # 0x04 +'Mo ', # 0x05 +'Bao ', # 0x06 +'Ruo ', # 0x07 +'Lu ', # 0x08 +'La ', # 0x09 +'Ao ', # 0x0a +'Xun ', # 0x0b +'Kuang ', # 0x0c +'Shuo ', # 0x0d +'[?] ', # 0x0e +'Li ', # 0x0f +'Lu ', # 0x10 +'Jue ', # 0x11 +'Liao ', # 0x12 +'Yan ', # 0x13 +'Xi ', # 0x14 +'Xie ', # 0x15 +'Long ', # 0x16 +'Ye ', # 0x17 +'[?] ', # 0x18 +'Rang ', # 0x19 +'Yue ', # 0x1a +'Lan ', # 0x1b +'Cong ', # 0x1c +'Jue ', # 0x1d +'Tong ', # 0x1e +'Guan ', # 0x1f +'[?] ', # 0x20 +'Che ', # 0x21 +'Mi ', # 0x22 +'Tang ', # 0x23 +'Lan ', # 0x24 +'Zhu ', # 0x25 +'[?] ', # 0x26 +'Ling ', # 0x27 +'Cuan ', # 0x28 +'Yu ', # 0x29 +'Zhua ', # 0x2a +'Tsumekanmuri ', # 0x2b +'Pa ', # 0x2c +'Zheng ', # 0x2d +'Pao ', # 0x2e +'Cheng ', # 0x2f +'Yuan ', # 0x30 +'Ai ', # 0x31 +'Wei ', # 0x32 +'[?] ', # 0x33 +'Jue ', # 0x34 +'Jue ', # 0x35 +'Fu ', # 0x36 +'Ye ', # 0x37 +'Ba ', # 0x38 +'Die ', # 0x39 +'Ye ', # 0x3a +'Yao ', # 0x3b +'Zu ', # 0x3c +'Shuang ', # 0x3d +'Er ', # 0x3e +'Qiang ', # 0x3f +'Chuang ', # 0x40 +'Ge ', # 0x41 +'Zang ', # 0x42 +'Die ', # 0x43 +'Qiang ', # 0x44 +'Yong ', # 0x45 +'Qiang ', # 0x46 +'Pian ', # 0x47 +'Ban ', # 0x48 +'Pan ', # 0x49 +'Shao ', # 0x4a +'Jian ', # 0x4b +'Pai ', # 0x4c +'Du ', # 0x4d +'Chuang ', # 0x4e +'Tou ', # 0x4f +'Zha ', # 0x50 +'Bian ', # 0x51 +'Die ', # 0x52 +'Bang ', # 0x53 +'Bo ', # 0x54 +'Chuang ', # 0x55 +'You ', # 0x56 +'[?] ', # 0x57 +'Du ', # 0x58 +'Ya ', # 0x59 +'Cheng ', # 0x5a +'Niu ', # 0x5b +'Ushihen ', # 0x5c +'Pin ', # 0x5d +'Jiu ', # 0x5e +'Mou ', # 0x5f +'Tuo ', # 0x60 +'Mu ', # 0x61 +'Lao ', # 0x62 +'Ren ', # 0x63 +'Mang ', # 0x64 +'Fang ', # 0x65 +'Mao ', # 0x66 +'Mu ', # 0x67 +'Gang ', # 0x68 +'Wu ', # 0x69 +'Yan ', # 0x6a +'Ge ', # 0x6b +'Bei ', # 0x6c +'Si ', # 0x6d +'Jian ', # 0x6e +'Gu ', # 0x6f +'You ', # 0x70 +'Ge ', # 0x71 +'Sheng ', # 0x72 +'Mu ', # 0x73 +'Di ', # 0x74 +'Qian ', # 0x75 +'Quan ', # 0x76 +'Quan ', # 0x77 +'Zi ', # 0x78 +'Te ', # 0x79 +'Xi ', # 0x7a +'Mang ', # 0x7b +'Keng ', # 0x7c +'Qian ', # 0x7d +'Wu ', # 0x7e +'Gu ', # 0x7f +'Xi ', # 0x80 +'Li ', # 0x81 +'Li ', # 0x82 +'Pou ', # 0x83 +'Ji ', # 0x84 +'Gang ', # 0x85 +'Zhi ', # 0x86 +'Ben ', # 0x87 +'Quan ', # 0x88 +'Run ', # 0x89 +'Du ', # 0x8a +'Ju ', # 0x8b +'Jia ', # 0x8c +'Jian ', # 0x8d +'Feng ', # 0x8e +'Pian ', # 0x8f +'Ke ', # 0x90 +'Ju ', # 0x91 +'Kao ', # 0x92 +'Chu ', # 0x93 +'Xi ', # 0x94 +'Bei ', # 0x95 +'Luo ', # 0x96 +'Jie ', # 0x97 +'Ma ', # 0x98 +'San ', # 0x99 +'Wei ', # 0x9a +'Li ', # 0x9b +'Dun ', # 0x9c +'Tong ', # 0x9d +'[?] ', # 0x9e +'Jiang ', # 0x9f +'Ikenie ', # 0xa0 +'Li ', # 0xa1 +'Du ', # 0xa2 +'Lie ', # 0xa3 +'Pi ', # 0xa4 +'Piao ', # 0xa5 +'Bao ', # 0xa6 +'Xi ', # 0xa7 +'Chou ', # 0xa8 +'Wei ', # 0xa9 +'Kui ', # 0xaa +'Chou ', # 0xab +'Quan ', # 0xac +'Fan ', # 0xad +'Ba ', # 0xae +'Fan ', # 0xaf +'Qiu ', # 0xb0 +'Ji ', # 0xb1 +'Cai ', # 0xb2 +'Chuo ', # 0xb3 +'An ', # 0xb4 +'Jie ', # 0xb5 +'Zhuang ', # 0xb6 +'Guang ', # 0xb7 +'Ma ', # 0xb8 +'You ', # 0xb9 +'Kang ', # 0xba +'Bo ', # 0xbb +'Hou ', # 0xbc +'Ya ', # 0xbd +'Yin ', # 0xbe +'Huan ', # 0xbf +'Zhuang ', # 0xc0 +'Yun ', # 0xc1 +'Kuang ', # 0xc2 +'Niu ', # 0xc3 +'Di ', # 0xc4 +'Qing ', # 0xc5 +'Zhong ', # 0xc6 +'Mu ', # 0xc7 +'Bei ', # 0xc8 +'Pi ', # 0xc9 +'Ju ', # 0xca +'Ni ', # 0xcb +'Sheng ', # 0xcc +'Pao ', # 0xcd +'Xia ', # 0xce +'Tuo ', # 0xcf +'Hu ', # 0xd0 +'Ling ', # 0xd1 +'Fei ', # 0xd2 +'Pi ', # 0xd3 +'Ni ', # 0xd4 +'Ao ', # 0xd5 +'You ', # 0xd6 +'Gou ', # 0xd7 +'Yue ', # 0xd8 +'Ju ', # 0xd9 +'Dan ', # 0xda +'Po ', # 0xdb +'Gu ', # 0xdc +'Xian ', # 0xdd +'Ning ', # 0xde +'Huan ', # 0xdf +'Hen ', # 0xe0 +'Jiao ', # 0xe1 +'He ', # 0xe2 +'Zhao ', # 0xe3 +'Ji ', # 0xe4 +'Xun ', # 0xe5 +'Shan ', # 0xe6 +'Ta ', # 0xe7 +'Rong ', # 0xe8 +'Shou ', # 0xe9 +'Tong ', # 0xea +'Lao ', # 0xeb +'Du ', # 0xec +'Xia ', # 0xed +'Shi ', # 0xee +'Hua ', # 0xef +'Zheng ', # 0xf0 +'Yu ', # 0xf1 +'Sun ', # 0xf2 +'Yu ', # 0xf3 +'Bi ', # 0xf4 +'Mang ', # 0xf5 +'Xi ', # 0xf6 +'Juan ', # 0xf7 +'Li ', # 0xf8 +'Xia ', # 0xf9 +'Yin ', # 0xfa +'Suan ', # 0xfb +'Lang ', # 0xfc +'Bei ', # 0xfd +'Zhi ', # 0xfe +'Yan ', # 0xff +) diff --git a/nstock/modules/unidecode/x073.py b/nstock/modules/unidecode/x073.py new file mode 100644 index 0000000..4cf0176 --- /dev/null +++ b/nstock/modules/unidecode/x073.py @@ -0,0 +1,258 @@ +data = ( +'Sha ', # 0x00 +'Li ', # 0x01 +'Han ', # 0x02 +'Xian ', # 0x03 +'Jing ', # 0x04 +'Pai ', # 0x05 +'Fei ', # 0x06 +'Yao ', # 0x07 +'Ba ', # 0x08 +'Qi ', # 0x09 +'Ni ', # 0x0a +'Biao ', # 0x0b +'Yin ', # 0x0c +'Lai ', # 0x0d +'Xi ', # 0x0e +'Jian ', # 0x0f +'Qiang ', # 0x10 +'Kun ', # 0x11 +'Yan ', # 0x12 +'Guo ', # 0x13 +'Zong ', # 0x14 +'Mi ', # 0x15 +'Chang ', # 0x16 +'Yi ', # 0x17 +'Zhi ', # 0x18 +'Zheng ', # 0x19 +'Ya ', # 0x1a +'Meng ', # 0x1b +'Cai ', # 0x1c +'Cu ', # 0x1d +'She ', # 0x1e +'Kari ', # 0x1f +'Cen ', # 0x20 +'Luo ', # 0x21 +'Hu ', # 0x22 +'Zong ', # 0x23 +'Ji ', # 0x24 +'Wei ', # 0x25 +'Feng ', # 0x26 +'Wo ', # 0x27 +'Yuan ', # 0x28 +'Xing ', # 0x29 +'Zhu ', # 0x2a +'Mao ', # 0x2b +'Wei ', # 0x2c +'Yuan ', # 0x2d +'Xian ', # 0x2e +'Tuan ', # 0x2f +'Ya ', # 0x30 +'Nao ', # 0x31 +'Xie ', # 0x32 +'Jia ', # 0x33 +'Hou ', # 0x34 +'Bian ', # 0x35 +'You ', # 0x36 +'You ', # 0x37 +'Mei ', # 0x38 +'Zha ', # 0x39 +'Yao ', # 0x3a +'Sun ', # 0x3b +'Bo ', # 0x3c +'Ming ', # 0x3d +'Hua ', # 0x3e +'Yuan ', # 0x3f +'Sou ', # 0x40 +'Ma ', # 0x41 +'Yuan ', # 0x42 +'Dai ', # 0x43 +'Yu ', # 0x44 +'Shi ', # 0x45 +'Hao ', # 0x46 +'[?] ', # 0x47 +'Yi ', # 0x48 +'Zhen ', # 0x49 +'Chuang ', # 0x4a +'Hao ', # 0x4b +'Man ', # 0x4c +'Jing ', # 0x4d +'Jiang ', # 0x4e +'Mu ', # 0x4f +'Zhang ', # 0x50 +'Chan ', # 0x51 +'Ao ', # 0x52 +'Ao ', # 0x53 +'Hao ', # 0x54 +'Cui ', # 0x55 +'Fen ', # 0x56 +'Jue ', # 0x57 +'Bi ', # 0x58 +'Bi ', # 0x59 +'Huang ', # 0x5a +'Pu ', # 0x5b +'Lin ', # 0x5c +'Yu ', # 0x5d +'Tong ', # 0x5e +'Yao ', # 0x5f +'Liao ', # 0x60 +'Shuo ', # 0x61 +'Xiao ', # 0x62 +'Swu ', # 0x63 +'Ton ', # 0x64 +'Xi ', # 0x65 +'Ge ', # 0x66 +'Juan ', # 0x67 +'Du ', # 0x68 +'Hui ', # 0x69 +'Kuai ', # 0x6a +'Xian ', # 0x6b +'Xie ', # 0x6c +'Ta ', # 0x6d +'Xian ', # 0x6e +'Xun ', # 0x6f +'Ning ', # 0x70 +'Pin ', # 0x71 +'Huo ', # 0x72 +'Nou ', # 0x73 +'Meng ', # 0x74 +'Lie ', # 0x75 +'Nao ', # 0x76 +'Guang ', # 0x77 +'Shou ', # 0x78 +'Lu ', # 0x79 +'Ta ', # 0x7a +'Xian ', # 0x7b +'Mi ', # 0x7c +'Rang ', # 0x7d +'Huan ', # 0x7e +'Nao ', # 0x7f +'Luo ', # 0x80 +'Xian ', # 0x81 +'Qi ', # 0x82 +'Jue ', # 0x83 +'Xuan ', # 0x84 +'Miao ', # 0x85 +'Zi ', # 0x86 +'Lu ', # 0x87 +'Lu ', # 0x88 +'Yu ', # 0x89 +'Su ', # 0x8a +'Wang ', # 0x8b +'Qiu ', # 0x8c +'Ga ', # 0x8d +'Ding ', # 0x8e +'Le ', # 0x8f +'Ba ', # 0x90 +'Ji ', # 0x91 +'Hong ', # 0x92 +'Di ', # 0x93 +'Quan ', # 0x94 +'Gan ', # 0x95 +'Jiu ', # 0x96 +'Yu ', # 0x97 +'Ji ', # 0x98 +'Yu ', # 0x99 +'Yang ', # 0x9a +'Ma ', # 0x9b +'Gong ', # 0x9c +'Wu ', # 0x9d +'Fu ', # 0x9e +'Wen ', # 0x9f +'Jie ', # 0xa0 +'Ya ', # 0xa1 +'Fen ', # 0xa2 +'Bian ', # 0xa3 +'Beng ', # 0xa4 +'Yue ', # 0xa5 +'Jue ', # 0xa6 +'Yun ', # 0xa7 +'Jue ', # 0xa8 +'Wan ', # 0xa9 +'Jian ', # 0xaa +'Mei ', # 0xab +'Dan ', # 0xac +'Pi ', # 0xad +'Wei ', # 0xae +'Huan ', # 0xaf +'Xian ', # 0xb0 +'Qiang ', # 0xb1 +'Ling ', # 0xb2 +'Dai ', # 0xb3 +'Yi ', # 0xb4 +'An ', # 0xb5 +'Ping ', # 0xb6 +'Dian ', # 0xb7 +'Fu ', # 0xb8 +'Xuan ', # 0xb9 +'Xi ', # 0xba +'Bo ', # 0xbb +'Ci ', # 0xbc +'Gou ', # 0xbd +'Jia ', # 0xbe +'Shao ', # 0xbf +'Po ', # 0xc0 +'Ci ', # 0xc1 +'Ke ', # 0xc2 +'Ran ', # 0xc3 +'Sheng ', # 0xc4 +'Shen ', # 0xc5 +'Yi ', # 0xc6 +'Zu ', # 0xc7 +'Jia ', # 0xc8 +'Min ', # 0xc9 +'Shan ', # 0xca +'Liu ', # 0xcb +'Bi ', # 0xcc +'Zhen ', # 0xcd +'Zhen ', # 0xce +'Jue ', # 0xcf +'Fa ', # 0xd0 +'Long ', # 0xd1 +'Jin ', # 0xd2 +'Jiao ', # 0xd3 +'Jian ', # 0xd4 +'Li ', # 0xd5 +'Guang ', # 0xd6 +'Xian ', # 0xd7 +'Zhou ', # 0xd8 +'Gong ', # 0xd9 +'Yan ', # 0xda +'Xiu ', # 0xdb +'Yang ', # 0xdc +'Xu ', # 0xdd +'Luo ', # 0xde +'Su ', # 0xdf +'Zhu ', # 0xe0 +'Qin ', # 0xe1 +'Ken ', # 0xe2 +'Xun ', # 0xe3 +'Bao ', # 0xe4 +'Er ', # 0xe5 +'Xiang ', # 0xe6 +'Yao ', # 0xe7 +'Xia ', # 0xe8 +'Heng ', # 0xe9 +'Gui ', # 0xea +'Chong ', # 0xeb +'Xu ', # 0xec +'Ban ', # 0xed +'Pei ', # 0xee +'[?] ', # 0xef +'Dang ', # 0xf0 +'Ei ', # 0xf1 +'Hun ', # 0xf2 +'Wen ', # 0xf3 +'E ', # 0xf4 +'Cheng ', # 0xf5 +'Ti ', # 0xf6 +'Wu ', # 0xf7 +'Wu ', # 0xf8 +'Cheng ', # 0xf9 +'Jun ', # 0xfa +'Mei ', # 0xfb +'Bei ', # 0xfc +'Ting ', # 0xfd +'Xian ', # 0xfe +'Chuo ', # 0xff +) diff --git a/nstock/modules/unidecode/x074.py b/nstock/modules/unidecode/x074.py new file mode 100644 index 0000000..312fc64 --- /dev/null +++ b/nstock/modules/unidecode/x074.py @@ -0,0 +1,258 @@ +data = ( +'Han ', # 0x00 +'Xuan ', # 0x01 +'Yan ', # 0x02 +'Qiu ', # 0x03 +'Quan ', # 0x04 +'Lang ', # 0x05 +'Li ', # 0x06 +'Xiu ', # 0x07 +'Fu ', # 0x08 +'Liu ', # 0x09 +'Ye ', # 0x0a +'Xi ', # 0x0b +'Ling ', # 0x0c +'Li ', # 0x0d +'Jin ', # 0x0e +'Lian ', # 0x0f +'Suo ', # 0x10 +'Chiisai ', # 0x11 +'[?] ', # 0x12 +'Wan ', # 0x13 +'Dian ', # 0x14 +'Pin ', # 0x15 +'Zhan ', # 0x16 +'Cui ', # 0x17 +'Min ', # 0x18 +'Yu ', # 0x19 +'Ju ', # 0x1a +'Chen ', # 0x1b +'Lai ', # 0x1c +'Wen ', # 0x1d +'Sheng ', # 0x1e +'Wei ', # 0x1f +'Dian ', # 0x20 +'Chu ', # 0x21 +'Zhuo ', # 0x22 +'Pei ', # 0x23 +'Cheng ', # 0x24 +'Hu ', # 0x25 +'Qi ', # 0x26 +'E ', # 0x27 +'Kun ', # 0x28 +'Chang ', # 0x29 +'Qi ', # 0x2a +'Beng ', # 0x2b +'Wan ', # 0x2c +'Lu ', # 0x2d +'Cong ', # 0x2e +'Guan ', # 0x2f +'Yan ', # 0x30 +'Diao ', # 0x31 +'Bei ', # 0x32 +'Lin ', # 0x33 +'Qin ', # 0x34 +'Pi ', # 0x35 +'Pa ', # 0x36 +'Que ', # 0x37 +'Zhuo ', # 0x38 +'Qin ', # 0x39 +'Fa ', # 0x3a +'[?] ', # 0x3b +'Qiong ', # 0x3c +'Du ', # 0x3d +'Jie ', # 0x3e +'Hun ', # 0x3f +'Yu ', # 0x40 +'Mao ', # 0x41 +'Mei ', # 0x42 +'Chun ', # 0x43 +'Xuan ', # 0x44 +'Ti ', # 0x45 +'Xing ', # 0x46 +'Dai ', # 0x47 +'Rou ', # 0x48 +'Min ', # 0x49 +'Zhen ', # 0x4a +'Wei ', # 0x4b +'Ruan ', # 0x4c +'Huan ', # 0x4d +'Jie ', # 0x4e +'Chuan ', # 0x4f +'Jian ', # 0x50 +'Zhuan ', # 0x51 +'Yang ', # 0x52 +'Lian ', # 0x53 +'Quan ', # 0x54 +'Xia ', # 0x55 +'Duan ', # 0x56 +'Yuan ', # 0x57 +'Ye ', # 0x58 +'Nao ', # 0x59 +'Hu ', # 0x5a +'Ying ', # 0x5b +'Yu ', # 0x5c +'Huang ', # 0x5d +'Rui ', # 0x5e +'Se ', # 0x5f +'Liu ', # 0x60 +'Shi ', # 0x61 +'Rong ', # 0x62 +'Suo ', # 0x63 +'Yao ', # 0x64 +'Wen ', # 0x65 +'Wu ', # 0x66 +'Jin ', # 0x67 +'Jin ', # 0x68 +'Ying ', # 0x69 +'Ma ', # 0x6a +'Tao ', # 0x6b +'Liu ', # 0x6c +'Tang ', # 0x6d +'Li ', # 0x6e +'Lang ', # 0x6f +'Gui ', # 0x70 +'Zhen ', # 0x71 +'Qiang ', # 0x72 +'Cuo ', # 0x73 +'Jue ', # 0x74 +'Zhao ', # 0x75 +'Yao ', # 0x76 +'Ai ', # 0x77 +'Bin ', # 0x78 +'Tu ', # 0x79 +'Chang ', # 0x7a +'Kun ', # 0x7b +'Zhuan ', # 0x7c +'Cong ', # 0x7d +'Jin ', # 0x7e +'Yi ', # 0x7f +'Cui ', # 0x80 +'Cong ', # 0x81 +'Qi ', # 0x82 +'Li ', # 0x83 +'Ying ', # 0x84 +'Suo ', # 0x85 +'Qiu ', # 0x86 +'Xuan ', # 0x87 +'Ao ', # 0x88 +'Lian ', # 0x89 +'Man ', # 0x8a +'Zhang ', # 0x8b +'Yin ', # 0x8c +'[?] ', # 0x8d +'Ying ', # 0x8e +'Zhi ', # 0x8f +'Lu ', # 0x90 +'Wu ', # 0x91 +'Deng ', # 0x92 +'Xiou ', # 0x93 +'Zeng ', # 0x94 +'Xun ', # 0x95 +'Qu ', # 0x96 +'Dang ', # 0x97 +'Lin ', # 0x98 +'Liao ', # 0x99 +'Qiong ', # 0x9a +'Su ', # 0x9b +'Huang ', # 0x9c +'Gui ', # 0x9d +'Pu ', # 0x9e +'Jing ', # 0x9f +'Fan ', # 0xa0 +'Jin ', # 0xa1 +'Liu ', # 0xa2 +'Ji ', # 0xa3 +'[?] ', # 0xa4 +'Jing ', # 0xa5 +'Ai ', # 0xa6 +'Bi ', # 0xa7 +'Can ', # 0xa8 +'Qu ', # 0xa9 +'Zao ', # 0xaa +'Dang ', # 0xab +'Jiao ', # 0xac +'Gun ', # 0xad +'Tan ', # 0xae +'Hui ', # 0xaf +'Huan ', # 0xb0 +'Se ', # 0xb1 +'Sui ', # 0xb2 +'Tian ', # 0xb3 +'[?] ', # 0xb4 +'Yu ', # 0xb5 +'Jin ', # 0xb6 +'Lu ', # 0xb7 +'Bin ', # 0xb8 +'Shou ', # 0xb9 +'Wen ', # 0xba +'Zui ', # 0xbb +'Lan ', # 0xbc +'Xi ', # 0xbd +'Ji ', # 0xbe +'Xuan ', # 0xbf +'Ruan ', # 0xc0 +'Huo ', # 0xc1 +'Gai ', # 0xc2 +'Lei ', # 0xc3 +'Du ', # 0xc4 +'Li ', # 0xc5 +'Zhi ', # 0xc6 +'Rou ', # 0xc7 +'Li ', # 0xc8 +'Zan ', # 0xc9 +'Qiong ', # 0xca +'Zhe ', # 0xcb +'Gui ', # 0xcc +'Sui ', # 0xcd +'La ', # 0xce +'Long ', # 0xcf +'Lu ', # 0xd0 +'Li ', # 0xd1 +'Zan ', # 0xd2 +'Lan ', # 0xd3 +'Ying ', # 0xd4 +'Mi ', # 0xd5 +'Xiang ', # 0xd6 +'Xi ', # 0xd7 +'Guan ', # 0xd8 +'Dao ', # 0xd9 +'Zan ', # 0xda +'Huan ', # 0xdb +'Gua ', # 0xdc +'Bo ', # 0xdd +'Die ', # 0xde +'Bao ', # 0xdf +'Hu ', # 0xe0 +'Zhi ', # 0xe1 +'Piao ', # 0xe2 +'Ban ', # 0xe3 +'Rang ', # 0xe4 +'Li ', # 0xe5 +'Wa ', # 0xe6 +'Dekaguramu ', # 0xe7 +'Jiang ', # 0xe8 +'Qian ', # 0xe9 +'Fan ', # 0xea +'Pen ', # 0xeb +'Fang ', # 0xec +'Dan ', # 0xed +'Weng ', # 0xee +'Ou ', # 0xef +'Deshiguramu ', # 0xf0 +'Miriguramu ', # 0xf1 +'Thon ', # 0xf2 +'Hu ', # 0xf3 +'Ling ', # 0xf4 +'Yi ', # 0xf5 +'Ping ', # 0xf6 +'Ci ', # 0xf7 +'Hekutogura ', # 0xf8 +'Juan ', # 0xf9 +'Chang ', # 0xfa +'Chi ', # 0xfb +'Sarake ', # 0xfc +'Dang ', # 0xfd +'Meng ', # 0xfe +'Pou ', # 0xff +) diff --git a/nstock/modules/unidecode/x075.py b/nstock/modules/unidecode/x075.py new file mode 100644 index 0000000..a356ac4 --- /dev/null +++ b/nstock/modules/unidecode/x075.py @@ -0,0 +1,258 @@ +data = ( +'Zhui ', # 0x00 +'Ping ', # 0x01 +'Bian ', # 0x02 +'Zhou ', # 0x03 +'Zhen ', # 0x04 +'Senchigura ', # 0x05 +'Ci ', # 0x06 +'Ying ', # 0x07 +'Qi ', # 0x08 +'Xian ', # 0x09 +'Lou ', # 0x0a +'Di ', # 0x0b +'Ou ', # 0x0c +'Meng ', # 0x0d +'Zhuan ', # 0x0e +'Peng ', # 0x0f +'Lin ', # 0x10 +'Zeng ', # 0x11 +'Wu ', # 0x12 +'Pi ', # 0x13 +'Dan ', # 0x14 +'Weng ', # 0x15 +'Ying ', # 0x16 +'Yan ', # 0x17 +'Gan ', # 0x18 +'Dai ', # 0x19 +'Shen ', # 0x1a +'Tian ', # 0x1b +'Tian ', # 0x1c +'Han ', # 0x1d +'Chang ', # 0x1e +'Sheng ', # 0x1f +'Qing ', # 0x20 +'Sheng ', # 0x21 +'Chan ', # 0x22 +'Chan ', # 0x23 +'Rui ', # 0x24 +'Sheng ', # 0x25 +'Su ', # 0x26 +'Sen ', # 0x27 +'Yong ', # 0x28 +'Shuai ', # 0x29 +'Lu ', # 0x2a +'Fu ', # 0x2b +'Yong ', # 0x2c +'Beng ', # 0x2d +'Feng ', # 0x2e +'Ning ', # 0x2f +'Tian ', # 0x30 +'You ', # 0x31 +'Jia ', # 0x32 +'Shen ', # 0x33 +'Zha ', # 0x34 +'Dian ', # 0x35 +'Fu ', # 0x36 +'Nan ', # 0x37 +'Dian ', # 0x38 +'Ping ', # 0x39 +'Ting ', # 0x3a +'Hua ', # 0x3b +'Ting ', # 0x3c +'Quan ', # 0x3d +'Zi ', # 0x3e +'Meng ', # 0x3f +'Bi ', # 0x40 +'Qi ', # 0x41 +'Liu ', # 0x42 +'Xun ', # 0x43 +'Liu ', # 0x44 +'Chang ', # 0x45 +'Mu ', # 0x46 +'Yun ', # 0x47 +'Fan ', # 0x48 +'Fu ', # 0x49 +'Geng ', # 0x4a +'Tian ', # 0x4b +'Jie ', # 0x4c +'Jie ', # 0x4d +'Quan ', # 0x4e +'Wei ', # 0x4f +'Fu ', # 0x50 +'Tian ', # 0x51 +'Mu ', # 0x52 +'Tap ', # 0x53 +'Pan ', # 0x54 +'Jiang ', # 0x55 +'Wa ', # 0x56 +'Da ', # 0x57 +'Nan ', # 0x58 +'Liu ', # 0x59 +'Ben ', # 0x5a +'Zhen ', # 0x5b +'Chu ', # 0x5c +'Mu ', # 0x5d +'Mu ', # 0x5e +'Ce ', # 0x5f +'Cen ', # 0x60 +'Gai ', # 0x61 +'Bi ', # 0x62 +'Da ', # 0x63 +'Zhi ', # 0x64 +'Lue ', # 0x65 +'Qi ', # 0x66 +'Lue ', # 0x67 +'Pan ', # 0x68 +'Kesa ', # 0x69 +'Fan ', # 0x6a +'Hua ', # 0x6b +'Yu ', # 0x6c +'Yu ', # 0x6d +'Mu ', # 0x6e +'Jun ', # 0x6f +'Yi ', # 0x70 +'Liu ', # 0x71 +'Yu ', # 0x72 +'Die ', # 0x73 +'Chou ', # 0x74 +'Hua ', # 0x75 +'Dang ', # 0x76 +'Chuo ', # 0x77 +'Ji ', # 0x78 +'Wan ', # 0x79 +'Jiang ', # 0x7a +'Sheng ', # 0x7b +'Chang ', # 0x7c +'Tuan ', # 0x7d +'Lei ', # 0x7e +'Ji ', # 0x7f +'Cha ', # 0x80 +'Liu ', # 0x81 +'Tatamu ', # 0x82 +'Tuan ', # 0x83 +'Lin ', # 0x84 +'Jiang ', # 0x85 +'Jiang ', # 0x86 +'Chou ', # 0x87 +'Bo ', # 0x88 +'Die ', # 0x89 +'Die ', # 0x8a +'Pi ', # 0x8b +'Nie ', # 0x8c +'Dan ', # 0x8d +'Shu ', # 0x8e +'Shu ', # 0x8f +'Zhi ', # 0x90 +'Yi ', # 0x91 +'Chuang ', # 0x92 +'Nai ', # 0x93 +'Ding ', # 0x94 +'Bi ', # 0x95 +'Jie ', # 0x96 +'Liao ', # 0x97 +'Gong ', # 0x98 +'Ge ', # 0x99 +'Jiu ', # 0x9a +'Zhou ', # 0x9b +'Xia ', # 0x9c +'Shan ', # 0x9d +'Xu ', # 0x9e +'Nue ', # 0x9f +'Li ', # 0xa0 +'Yang ', # 0xa1 +'Chen ', # 0xa2 +'You ', # 0xa3 +'Ba ', # 0xa4 +'Jie ', # 0xa5 +'Jue ', # 0xa6 +'Zhi ', # 0xa7 +'Xia ', # 0xa8 +'Cui ', # 0xa9 +'Bi ', # 0xaa +'Yi ', # 0xab +'Li ', # 0xac +'Zong ', # 0xad +'Chuang ', # 0xae +'Feng ', # 0xaf +'Zhu ', # 0xb0 +'Pao ', # 0xb1 +'Pi ', # 0xb2 +'Gan ', # 0xb3 +'Ke ', # 0xb4 +'Ci ', # 0xb5 +'Xie ', # 0xb6 +'Qi ', # 0xb7 +'Dan ', # 0xb8 +'Zhen ', # 0xb9 +'Fa ', # 0xba +'Zhi ', # 0xbb +'Teng ', # 0xbc +'Ju ', # 0xbd +'Ji ', # 0xbe +'Fei ', # 0xbf +'Qu ', # 0xc0 +'Dian ', # 0xc1 +'Jia ', # 0xc2 +'Xian ', # 0xc3 +'Cha ', # 0xc4 +'Bing ', # 0xc5 +'Ni ', # 0xc6 +'Zheng ', # 0xc7 +'Yong ', # 0xc8 +'Jing ', # 0xc9 +'Quan ', # 0xca +'Chong ', # 0xcb +'Tong ', # 0xcc +'Yi ', # 0xcd +'Kai ', # 0xce +'Wei ', # 0xcf +'Hui ', # 0xd0 +'Duo ', # 0xd1 +'Yang ', # 0xd2 +'Chi ', # 0xd3 +'Zhi ', # 0xd4 +'Hen ', # 0xd5 +'Ya ', # 0xd6 +'Mei ', # 0xd7 +'Dou ', # 0xd8 +'Jing ', # 0xd9 +'Xiao ', # 0xda +'Tong ', # 0xdb +'Tu ', # 0xdc +'Mang ', # 0xdd +'Pi ', # 0xde +'Xiao ', # 0xdf +'Suan ', # 0xe0 +'Pu ', # 0xe1 +'Li ', # 0xe2 +'Zhi ', # 0xe3 +'Cuo ', # 0xe4 +'Duo ', # 0xe5 +'Wu ', # 0xe6 +'Sha ', # 0xe7 +'Lao ', # 0xe8 +'Shou ', # 0xe9 +'Huan ', # 0xea +'Xian ', # 0xeb +'Yi ', # 0xec +'Peng ', # 0xed +'Zhang ', # 0xee +'Guan ', # 0xef +'Tan ', # 0xf0 +'Fei ', # 0xf1 +'Ma ', # 0xf2 +'Lin ', # 0xf3 +'Chi ', # 0xf4 +'Ji ', # 0xf5 +'Dian ', # 0xf6 +'An ', # 0xf7 +'Chi ', # 0xf8 +'Bi ', # 0xf9 +'Bei ', # 0xfa +'Min ', # 0xfb +'Gu ', # 0xfc +'Dui ', # 0xfd +'E ', # 0xfe +'Wei ', # 0xff +) diff --git a/nstock/modules/unidecode/x076.py b/nstock/modules/unidecode/x076.py new file mode 100644 index 0000000..fc8b167 --- /dev/null +++ b/nstock/modules/unidecode/x076.py @@ -0,0 +1,258 @@ +data = ( +'Yu ', # 0x00 +'Cui ', # 0x01 +'Ya ', # 0x02 +'Zhu ', # 0x03 +'Cu ', # 0x04 +'Dan ', # 0x05 +'Shen ', # 0x06 +'Zhung ', # 0x07 +'Ji ', # 0x08 +'Yu ', # 0x09 +'Hou ', # 0x0a +'Feng ', # 0x0b +'La ', # 0x0c +'Yang ', # 0x0d +'Shen ', # 0x0e +'Tu ', # 0x0f +'Yu ', # 0x10 +'Gua ', # 0x11 +'Wen ', # 0x12 +'Huan ', # 0x13 +'Ku ', # 0x14 +'Jia ', # 0x15 +'Yin ', # 0x16 +'Yi ', # 0x17 +'Lu ', # 0x18 +'Sao ', # 0x19 +'Jue ', # 0x1a +'Chi ', # 0x1b +'Xi ', # 0x1c +'Guan ', # 0x1d +'Yi ', # 0x1e +'Wen ', # 0x1f +'Ji ', # 0x20 +'Chuang ', # 0x21 +'Ban ', # 0x22 +'Lei ', # 0x23 +'Liu ', # 0x24 +'Chai ', # 0x25 +'Shou ', # 0x26 +'Nue ', # 0x27 +'Dian ', # 0x28 +'Da ', # 0x29 +'Pie ', # 0x2a +'Tan ', # 0x2b +'Zhang ', # 0x2c +'Biao ', # 0x2d +'Shen ', # 0x2e +'Cu ', # 0x2f +'Luo ', # 0x30 +'Yi ', # 0x31 +'Zong ', # 0x32 +'Chou ', # 0x33 +'Zhang ', # 0x34 +'Zhai ', # 0x35 +'Sou ', # 0x36 +'Suo ', # 0x37 +'Que ', # 0x38 +'Diao ', # 0x39 +'Lou ', # 0x3a +'Lu ', # 0x3b +'Mo ', # 0x3c +'Jin ', # 0x3d +'Yin ', # 0x3e +'Ying ', # 0x3f +'Huang ', # 0x40 +'Fu ', # 0x41 +'Liao ', # 0x42 +'Long ', # 0x43 +'Qiao ', # 0x44 +'Liu ', # 0x45 +'Lao ', # 0x46 +'Xian ', # 0x47 +'Fei ', # 0x48 +'Dan ', # 0x49 +'Yin ', # 0x4a +'He ', # 0x4b +'Yan ', # 0x4c +'Ban ', # 0x4d +'Xian ', # 0x4e +'Guan ', # 0x4f +'Guai ', # 0x50 +'Nong ', # 0x51 +'Yu ', # 0x52 +'Wei ', # 0x53 +'Yi ', # 0x54 +'Yong ', # 0x55 +'Pi ', # 0x56 +'Lei ', # 0x57 +'Li ', # 0x58 +'Shu ', # 0x59 +'Dan ', # 0x5a +'Lin ', # 0x5b +'Dian ', # 0x5c +'Lin ', # 0x5d +'Lai ', # 0x5e +'Pie ', # 0x5f +'Ji ', # 0x60 +'Chi ', # 0x61 +'Yang ', # 0x62 +'Xian ', # 0x63 +'Jie ', # 0x64 +'Zheng ', # 0x65 +'[?] ', # 0x66 +'Li ', # 0x67 +'Huo ', # 0x68 +'Lai ', # 0x69 +'Shaku ', # 0x6a +'Dian ', # 0x6b +'Xian ', # 0x6c +'Ying ', # 0x6d +'Yin ', # 0x6e +'Qu ', # 0x6f +'Yong ', # 0x70 +'Tan ', # 0x71 +'Dian ', # 0x72 +'Luo ', # 0x73 +'Luan ', # 0x74 +'Luan ', # 0x75 +'Bo ', # 0x76 +'[?] ', # 0x77 +'Gui ', # 0x78 +'Po ', # 0x79 +'Fa ', # 0x7a +'Deng ', # 0x7b +'Fa ', # 0x7c +'Bai ', # 0x7d +'Bai ', # 0x7e +'Qie ', # 0x7f +'Bi ', # 0x80 +'Zao ', # 0x81 +'Zao ', # 0x82 +'Mao ', # 0x83 +'De ', # 0x84 +'Pa ', # 0x85 +'Jie ', # 0x86 +'Huang ', # 0x87 +'Gui ', # 0x88 +'Ci ', # 0x89 +'Ling ', # 0x8a +'Gao ', # 0x8b +'Mo ', # 0x8c +'Ji ', # 0x8d +'Jiao ', # 0x8e +'Peng ', # 0x8f +'Gao ', # 0x90 +'Ai ', # 0x91 +'E ', # 0x92 +'Hao ', # 0x93 +'Han ', # 0x94 +'Bi ', # 0x95 +'Wan ', # 0x96 +'Chou ', # 0x97 +'Qian ', # 0x98 +'Xi ', # 0x99 +'Ai ', # 0x9a +'Jiong ', # 0x9b +'Hao ', # 0x9c +'Huang ', # 0x9d +'Hao ', # 0x9e +'Ze ', # 0x9f +'Cui ', # 0xa0 +'Hao ', # 0xa1 +'Xiao ', # 0xa2 +'Ye ', # 0xa3 +'Po ', # 0xa4 +'Hao ', # 0xa5 +'Jiao ', # 0xa6 +'Ai ', # 0xa7 +'Xing ', # 0xa8 +'Huang ', # 0xa9 +'Li ', # 0xaa +'Piao ', # 0xab +'He ', # 0xac +'Jiao ', # 0xad +'Pi ', # 0xae +'Gan ', # 0xaf +'Pao ', # 0xb0 +'Zhou ', # 0xb1 +'Jun ', # 0xb2 +'Qiu ', # 0xb3 +'Cun ', # 0xb4 +'Que ', # 0xb5 +'Zha ', # 0xb6 +'Gu ', # 0xb7 +'Jun ', # 0xb8 +'Jun ', # 0xb9 +'Zhou ', # 0xba +'Zha ', # 0xbb +'Gu ', # 0xbc +'Zhan ', # 0xbd +'Du ', # 0xbe +'Min ', # 0xbf +'Qi ', # 0xc0 +'Ying ', # 0xc1 +'Yu ', # 0xc2 +'Bei ', # 0xc3 +'Zhao ', # 0xc4 +'Zhong ', # 0xc5 +'Pen ', # 0xc6 +'He ', # 0xc7 +'Ying ', # 0xc8 +'He ', # 0xc9 +'Yi ', # 0xca +'Bo ', # 0xcb +'Wan ', # 0xcc +'He ', # 0xcd +'Ang ', # 0xce +'Zhan ', # 0xcf +'Yan ', # 0xd0 +'Jian ', # 0xd1 +'He ', # 0xd2 +'Yu ', # 0xd3 +'Kui ', # 0xd4 +'Fan ', # 0xd5 +'Gai ', # 0xd6 +'Dao ', # 0xd7 +'Pan ', # 0xd8 +'Fu ', # 0xd9 +'Qiu ', # 0xda +'Sheng ', # 0xdb +'Dao ', # 0xdc +'Lu ', # 0xdd +'Zhan ', # 0xde +'Meng ', # 0xdf +'Li ', # 0xe0 +'Jin ', # 0xe1 +'Xu ', # 0xe2 +'Jian ', # 0xe3 +'Pan ', # 0xe4 +'Guan ', # 0xe5 +'An ', # 0xe6 +'Lu ', # 0xe7 +'Shu ', # 0xe8 +'Zhou ', # 0xe9 +'Dang ', # 0xea +'An ', # 0xeb +'Gu ', # 0xec +'Li ', # 0xed +'Mu ', # 0xee +'Cheng ', # 0xef +'Gan ', # 0xf0 +'Xu ', # 0xf1 +'Mang ', # 0xf2 +'Mang ', # 0xf3 +'Zhi ', # 0xf4 +'Qi ', # 0xf5 +'Ruan ', # 0xf6 +'Tian ', # 0xf7 +'Xiang ', # 0xf8 +'Dun ', # 0xf9 +'Xin ', # 0xfa +'Xi ', # 0xfb +'Pan ', # 0xfc +'Feng ', # 0xfd +'Dun ', # 0xfe +'Min ', # 0xff +) diff --git a/nstock/modules/unidecode/x077.py b/nstock/modules/unidecode/x077.py new file mode 100644 index 0000000..3ed6a36 --- /dev/null +++ b/nstock/modules/unidecode/x077.py @@ -0,0 +1,258 @@ +data = ( +'Ming ', # 0x00 +'Sheng ', # 0x01 +'Shi ', # 0x02 +'Yun ', # 0x03 +'Mian ', # 0x04 +'Pan ', # 0x05 +'Fang ', # 0x06 +'Miao ', # 0x07 +'Dan ', # 0x08 +'Mei ', # 0x09 +'Mao ', # 0x0a +'Kan ', # 0x0b +'Xian ', # 0x0c +'Ou ', # 0x0d +'Shi ', # 0x0e +'Yang ', # 0x0f +'Zheng ', # 0x10 +'Yao ', # 0x11 +'Shen ', # 0x12 +'Huo ', # 0x13 +'Da ', # 0x14 +'Zhen ', # 0x15 +'Kuang ', # 0x16 +'Ju ', # 0x17 +'Shen ', # 0x18 +'Chi ', # 0x19 +'Sheng ', # 0x1a +'Mei ', # 0x1b +'Mo ', # 0x1c +'Zhu ', # 0x1d +'Zhen ', # 0x1e +'Zhen ', # 0x1f +'Mian ', # 0x20 +'Di ', # 0x21 +'Yuan ', # 0x22 +'Die ', # 0x23 +'Yi ', # 0x24 +'Zi ', # 0x25 +'Zi ', # 0x26 +'Chao ', # 0x27 +'Zha ', # 0x28 +'Xuan ', # 0x29 +'Bing ', # 0x2a +'Mi ', # 0x2b +'Long ', # 0x2c +'Sui ', # 0x2d +'Dong ', # 0x2e +'Mi ', # 0x2f +'Die ', # 0x30 +'Yi ', # 0x31 +'Er ', # 0x32 +'Ming ', # 0x33 +'Xuan ', # 0x34 +'Chi ', # 0x35 +'Kuang ', # 0x36 +'Juan ', # 0x37 +'Mou ', # 0x38 +'Zhen ', # 0x39 +'Tiao ', # 0x3a +'Yang ', # 0x3b +'Yan ', # 0x3c +'Mo ', # 0x3d +'Zhong ', # 0x3e +'Mai ', # 0x3f +'Zhao ', # 0x40 +'Zheng ', # 0x41 +'Mei ', # 0x42 +'Jun ', # 0x43 +'Shao ', # 0x44 +'Han ', # 0x45 +'Huan ', # 0x46 +'Di ', # 0x47 +'Cheng ', # 0x48 +'Cuo ', # 0x49 +'Juan ', # 0x4a +'E ', # 0x4b +'Wan ', # 0x4c +'Xian ', # 0x4d +'Xi ', # 0x4e +'Kun ', # 0x4f +'Lai ', # 0x50 +'Jian ', # 0x51 +'Shan ', # 0x52 +'Tian ', # 0x53 +'Hun ', # 0x54 +'Wan ', # 0x55 +'Ling ', # 0x56 +'Shi ', # 0x57 +'Qiong ', # 0x58 +'Lie ', # 0x59 +'Yai ', # 0x5a +'Jing ', # 0x5b +'Zheng ', # 0x5c +'Li ', # 0x5d +'Lai ', # 0x5e +'Sui ', # 0x5f +'Juan ', # 0x60 +'Shui ', # 0x61 +'Sui ', # 0x62 +'Du ', # 0x63 +'Bi ', # 0x64 +'Bi ', # 0x65 +'Mu ', # 0x66 +'Hun ', # 0x67 +'Ni ', # 0x68 +'Lu ', # 0x69 +'Yi ', # 0x6a +'Jie ', # 0x6b +'Cai ', # 0x6c +'Zhou ', # 0x6d +'Yu ', # 0x6e +'Hun ', # 0x6f +'Ma ', # 0x70 +'Xia ', # 0x71 +'Xing ', # 0x72 +'Xi ', # 0x73 +'Gun ', # 0x74 +'Cai ', # 0x75 +'Chun ', # 0x76 +'Jian ', # 0x77 +'Mei ', # 0x78 +'Du ', # 0x79 +'Hou ', # 0x7a +'Xuan ', # 0x7b +'Ti ', # 0x7c +'Kui ', # 0x7d +'Gao ', # 0x7e +'Rui ', # 0x7f +'Mou ', # 0x80 +'Xu ', # 0x81 +'Fa ', # 0x82 +'Wen ', # 0x83 +'Miao ', # 0x84 +'Chou ', # 0x85 +'Kui ', # 0x86 +'Mi ', # 0x87 +'Weng ', # 0x88 +'Kou ', # 0x89 +'Dang ', # 0x8a +'Chen ', # 0x8b +'Ke ', # 0x8c +'Sou ', # 0x8d +'Xia ', # 0x8e +'Qiong ', # 0x8f +'Mao ', # 0x90 +'Ming ', # 0x91 +'Man ', # 0x92 +'Shui ', # 0x93 +'Ze ', # 0x94 +'Zhang ', # 0x95 +'Yi ', # 0x96 +'Diao ', # 0x97 +'Ou ', # 0x98 +'Mo ', # 0x99 +'Shun ', # 0x9a +'Cong ', # 0x9b +'Lou ', # 0x9c +'Chi ', # 0x9d +'Man ', # 0x9e +'Piao ', # 0x9f +'Cheng ', # 0xa0 +'Ji ', # 0xa1 +'Meng ', # 0xa2 +'[?] ', # 0xa3 +'Run ', # 0xa4 +'Pie ', # 0xa5 +'Xi ', # 0xa6 +'Qiao ', # 0xa7 +'Pu ', # 0xa8 +'Zhu ', # 0xa9 +'Deng ', # 0xaa +'Shen ', # 0xab +'Shun ', # 0xac +'Liao ', # 0xad +'Che ', # 0xae +'Xian ', # 0xaf +'Kan ', # 0xb0 +'Ye ', # 0xb1 +'Xu ', # 0xb2 +'Tong ', # 0xb3 +'Mou ', # 0xb4 +'Lin ', # 0xb5 +'Kui ', # 0xb6 +'Xian ', # 0xb7 +'Ye ', # 0xb8 +'Ai ', # 0xb9 +'Hui ', # 0xba +'Zhan ', # 0xbb +'Jian ', # 0xbc +'Gu ', # 0xbd +'Zhao ', # 0xbe +'Qu ', # 0xbf +'Wei ', # 0xc0 +'Chou ', # 0xc1 +'Sao ', # 0xc2 +'Ning ', # 0xc3 +'Xun ', # 0xc4 +'Yao ', # 0xc5 +'Huo ', # 0xc6 +'Meng ', # 0xc7 +'Mian ', # 0xc8 +'Bin ', # 0xc9 +'Mian ', # 0xca +'Li ', # 0xcb +'Kuang ', # 0xcc +'Jue ', # 0xcd +'Xuan ', # 0xce +'Mian ', # 0xcf +'Huo ', # 0xd0 +'Lu ', # 0xd1 +'Meng ', # 0xd2 +'Long ', # 0xd3 +'Guan ', # 0xd4 +'Man ', # 0xd5 +'Xi ', # 0xd6 +'Chu ', # 0xd7 +'Tang ', # 0xd8 +'Kan ', # 0xd9 +'Zhu ', # 0xda +'Mao ', # 0xdb +'Jin ', # 0xdc +'Lin ', # 0xdd +'Yu ', # 0xde +'Shuo ', # 0xdf +'Ce ', # 0xe0 +'Jue ', # 0xe1 +'Shi ', # 0xe2 +'Yi ', # 0xe3 +'Shen ', # 0xe4 +'Zhi ', # 0xe5 +'Hou ', # 0xe6 +'Shen ', # 0xe7 +'Ying ', # 0xe8 +'Ju ', # 0xe9 +'Zhou ', # 0xea +'Jiao ', # 0xeb +'Cuo ', # 0xec +'Duan ', # 0xed +'Ai ', # 0xee +'Jiao ', # 0xef +'Zeng ', # 0xf0 +'Huo ', # 0xf1 +'Bai ', # 0xf2 +'Shi ', # 0xf3 +'Ding ', # 0xf4 +'Qi ', # 0xf5 +'Ji ', # 0xf6 +'Zi ', # 0xf7 +'Gan ', # 0xf8 +'Wu ', # 0xf9 +'Tuo ', # 0xfa +'Ku ', # 0xfb +'Qiang ', # 0xfc +'Xi ', # 0xfd +'Fan ', # 0xfe +'Kuang ', # 0xff +) diff --git a/nstock/modules/unidecode/x078.py b/nstock/modules/unidecode/x078.py new file mode 100644 index 0000000..23d677d --- /dev/null +++ b/nstock/modules/unidecode/x078.py @@ -0,0 +1,258 @@ +data = ( +'Dang ', # 0x00 +'Ma ', # 0x01 +'Sha ', # 0x02 +'Dan ', # 0x03 +'Jue ', # 0x04 +'Li ', # 0x05 +'Fu ', # 0x06 +'Min ', # 0x07 +'Nuo ', # 0x08 +'Huo ', # 0x09 +'Kang ', # 0x0a +'Zhi ', # 0x0b +'Qi ', # 0x0c +'Kan ', # 0x0d +'Jie ', # 0x0e +'Fen ', # 0x0f +'E ', # 0x10 +'Ya ', # 0x11 +'Pi ', # 0x12 +'Zhe ', # 0x13 +'Yan ', # 0x14 +'Sui ', # 0x15 +'Zhuan ', # 0x16 +'Che ', # 0x17 +'Dun ', # 0x18 +'Pan ', # 0x19 +'Yan ', # 0x1a +'[?] ', # 0x1b +'Feng ', # 0x1c +'Fa ', # 0x1d +'Mo ', # 0x1e +'Zha ', # 0x1f +'Qu ', # 0x20 +'Yu ', # 0x21 +'Luo ', # 0x22 +'Tuo ', # 0x23 +'Tuo ', # 0x24 +'Di ', # 0x25 +'Zhai ', # 0x26 +'Zhen ', # 0x27 +'Ai ', # 0x28 +'Fei ', # 0x29 +'Mu ', # 0x2a +'Zhu ', # 0x2b +'Li ', # 0x2c +'Bian ', # 0x2d +'Nu ', # 0x2e +'Ping ', # 0x2f +'Peng ', # 0x30 +'Ling ', # 0x31 +'Pao ', # 0x32 +'Le ', # 0x33 +'Po ', # 0x34 +'Bo ', # 0x35 +'Po ', # 0x36 +'Shen ', # 0x37 +'Za ', # 0x38 +'Nuo ', # 0x39 +'Li ', # 0x3a +'Long ', # 0x3b +'Tong ', # 0x3c +'[?] ', # 0x3d +'Li ', # 0x3e +'Aragane ', # 0x3f +'Chu ', # 0x40 +'Keng ', # 0x41 +'Quan ', # 0x42 +'Zhu ', # 0x43 +'Kuang ', # 0x44 +'Huo ', # 0x45 +'E ', # 0x46 +'Nao ', # 0x47 +'Jia ', # 0x48 +'Lu ', # 0x49 +'Wei ', # 0x4a +'Ai ', # 0x4b +'Luo ', # 0x4c +'Ken ', # 0x4d +'Xing ', # 0x4e +'Yan ', # 0x4f +'Tong ', # 0x50 +'Peng ', # 0x51 +'Xi ', # 0x52 +'[?] ', # 0x53 +'Hong ', # 0x54 +'Shuo ', # 0x55 +'Xia ', # 0x56 +'Qiao ', # 0x57 +'[?] ', # 0x58 +'Wei ', # 0x59 +'Qiao ', # 0x5a +'[?] ', # 0x5b +'Keng ', # 0x5c +'Xiao ', # 0x5d +'Que ', # 0x5e +'Chan ', # 0x5f +'Lang ', # 0x60 +'Hong ', # 0x61 +'Yu ', # 0x62 +'Xiao ', # 0x63 +'Xia ', # 0x64 +'Mang ', # 0x65 +'Long ', # 0x66 +'Iong ', # 0x67 +'Che ', # 0x68 +'Che ', # 0x69 +'E ', # 0x6a +'Liu ', # 0x6b +'Ying ', # 0x6c +'Mang ', # 0x6d +'Que ', # 0x6e +'Yan ', # 0x6f +'Sha ', # 0x70 +'Kun ', # 0x71 +'Yu ', # 0x72 +'[?] ', # 0x73 +'Kaki ', # 0x74 +'Lu ', # 0x75 +'Chen ', # 0x76 +'Jian ', # 0x77 +'Nue ', # 0x78 +'Song ', # 0x79 +'Zhuo ', # 0x7a +'Keng ', # 0x7b +'Peng ', # 0x7c +'Yan ', # 0x7d +'Zhui ', # 0x7e +'Kong ', # 0x7f +'Ceng ', # 0x80 +'Qi ', # 0x81 +'Zong ', # 0x82 +'Qing ', # 0x83 +'Lin ', # 0x84 +'Jun ', # 0x85 +'Bo ', # 0x86 +'Ding ', # 0x87 +'Min ', # 0x88 +'Diao ', # 0x89 +'Jian ', # 0x8a +'He ', # 0x8b +'Lu ', # 0x8c +'Ai ', # 0x8d +'Sui ', # 0x8e +'Que ', # 0x8f +'Ling ', # 0x90 +'Bei ', # 0x91 +'Yin ', # 0x92 +'Dui ', # 0x93 +'Wu ', # 0x94 +'Qi ', # 0x95 +'Lun ', # 0x96 +'Wan ', # 0x97 +'Dian ', # 0x98 +'Gang ', # 0x99 +'Pei ', # 0x9a +'Qi ', # 0x9b +'Chen ', # 0x9c +'Ruan ', # 0x9d +'Yan ', # 0x9e +'Die ', # 0x9f +'Ding ', # 0xa0 +'Du ', # 0xa1 +'Tuo ', # 0xa2 +'Jie ', # 0xa3 +'Ying ', # 0xa4 +'Bian ', # 0xa5 +'Ke ', # 0xa6 +'Bi ', # 0xa7 +'Wei ', # 0xa8 +'Shuo ', # 0xa9 +'Zhen ', # 0xaa +'Duan ', # 0xab +'Xia ', # 0xac +'Dang ', # 0xad +'Ti ', # 0xae +'Nao ', # 0xaf +'Peng ', # 0xb0 +'Jian ', # 0xb1 +'Di ', # 0xb2 +'Tan ', # 0xb3 +'Cha ', # 0xb4 +'Seki ', # 0xb5 +'Qi ', # 0xb6 +'[?] ', # 0xb7 +'Feng ', # 0xb8 +'Xuan ', # 0xb9 +'Que ', # 0xba +'Que ', # 0xbb +'Ma ', # 0xbc +'Gong ', # 0xbd +'Nian ', # 0xbe +'Su ', # 0xbf +'E ', # 0xc0 +'Ci ', # 0xc1 +'Liu ', # 0xc2 +'Si ', # 0xc3 +'Tang ', # 0xc4 +'Bang ', # 0xc5 +'Hua ', # 0xc6 +'Pi ', # 0xc7 +'Wei ', # 0xc8 +'Sang ', # 0xc9 +'Lei ', # 0xca +'Cuo ', # 0xcb +'Zhen ', # 0xcc +'Xia ', # 0xcd +'Qi ', # 0xce +'Lian ', # 0xcf +'Pan ', # 0xd0 +'Wei ', # 0xd1 +'Yun ', # 0xd2 +'Dui ', # 0xd3 +'Zhe ', # 0xd4 +'Ke ', # 0xd5 +'La ', # 0xd6 +'[?] ', # 0xd7 +'Qing ', # 0xd8 +'Gun ', # 0xd9 +'Zhuan ', # 0xda +'Chan ', # 0xdb +'Qi ', # 0xdc +'Ao ', # 0xdd +'Peng ', # 0xde +'Lu ', # 0xdf +'Lu ', # 0xe0 +'Kan ', # 0xe1 +'Qiang ', # 0xe2 +'Chen ', # 0xe3 +'Yin ', # 0xe4 +'Lei ', # 0xe5 +'Biao ', # 0xe6 +'Qi ', # 0xe7 +'Mo ', # 0xe8 +'Qi ', # 0xe9 +'Cui ', # 0xea +'Zong ', # 0xeb +'Qing ', # 0xec +'Chuo ', # 0xed +'[?] ', # 0xee +'Ji ', # 0xef +'Shan ', # 0xf0 +'Lao ', # 0xf1 +'Qu ', # 0xf2 +'Zeng ', # 0xf3 +'Deng ', # 0xf4 +'Jian ', # 0xf5 +'Xi ', # 0xf6 +'Lin ', # 0xf7 +'Ding ', # 0xf8 +'Dian ', # 0xf9 +'Huang ', # 0xfa +'Pan ', # 0xfb +'Za ', # 0xfc +'Qiao ', # 0xfd +'Di ', # 0xfe +'Li ', # 0xff +) diff --git a/nstock/modules/unidecode/x079.py b/nstock/modules/unidecode/x079.py new file mode 100644 index 0000000..ed1c514 --- /dev/null +++ b/nstock/modules/unidecode/x079.py @@ -0,0 +1,258 @@ +data = ( +'Tani ', # 0x00 +'Jiao ', # 0x01 +'[?] ', # 0x02 +'Zhang ', # 0x03 +'Qiao ', # 0x04 +'Dun ', # 0x05 +'Xian ', # 0x06 +'Yu ', # 0x07 +'Zhui ', # 0x08 +'He ', # 0x09 +'Huo ', # 0x0a +'Zhai ', # 0x0b +'Lei ', # 0x0c +'Ke ', # 0x0d +'Chu ', # 0x0e +'Ji ', # 0x0f +'Que ', # 0x10 +'Dang ', # 0x11 +'Yi ', # 0x12 +'Jiang ', # 0x13 +'Pi ', # 0x14 +'Pi ', # 0x15 +'Yu ', # 0x16 +'Pin ', # 0x17 +'Qi ', # 0x18 +'Ai ', # 0x19 +'Kai ', # 0x1a +'Jian ', # 0x1b +'Yu ', # 0x1c +'Ruan ', # 0x1d +'Meng ', # 0x1e +'Pao ', # 0x1f +'Ci ', # 0x20 +'[?] ', # 0x21 +'[?] ', # 0x22 +'Mie ', # 0x23 +'Ca ', # 0x24 +'Xian ', # 0x25 +'Kuang ', # 0x26 +'Lei ', # 0x27 +'Lei ', # 0x28 +'Zhi ', # 0x29 +'Li ', # 0x2a +'Li ', # 0x2b +'Fan ', # 0x2c +'Que ', # 0x2d +'Pao ', # 0x2e +'Ying ', # 0x2f +'Li ', # 0x30 +'Long ', # 0x31 +'Long ', # 0x32 +'Mo ', # 0x33 +'Bo ', # 0x34 +'Shuang ', # 0x35 +'Guan ', # 0x36 +'Lan ', # 0x37 +'Zan ', # 0x38 +'Yan ', # 0x39 +'Shi ', # 0x3a +'Shi ', # 0x3b +'Li ', # 0x3c +'Reng ', # 0x3d +'She ', # 0x3e +'Yue ', # 0x3f +'Si ', # 0x40 +'Qi ', # 0x41 +'Ta ', # 0x42 +'Ma ', # 0x43 +'Xie ', # 0x44 +'Xian ', # 0x45 +'Xian ', # 0x46 +'Zhi ', # 0x47 +'Qi ', # 0x48 +'Zhi ', # 0x49 +'Beng ', # 0x4a +'Dui ', # 0x4b +'Zhong ', # 0x4c +'[?] ', # 0x4d +'Yi ', # 0x4e +'Shi ', # 0x4f +'You ', # 0x50 +'Zhi ', # 0x51 +'Tiao ', # 0x52 +'Fu ', # 0x53 +'Fu ', # 0x54 +'Mi ', # 0x55 +'Zu ', # 0x56 +'Zhi ', # 0x57 +'Suan ', # 0x58 +'Mei ', # 0x59 +'Zuo ', # 0x5a +'Qu ', # 0x5b +'Hu ', # 0x5c +'Zhu ', # 0x5d +'Shen ', # 0x5e +'Sui ', # 0x5f +'Ci ', # 0x60 +'Chai ', # 0x61 +'Mi ', # 0x62 +'Lu ', # 0x63 +'Yu ', # 0x64 +'Xiang ', # 0x65 +'Wu ', # 0x66 +'Tiao ', # 0x67 +'Piao ', # 0x68 +'Zhu ', # 0x69 +'Gui ', # 0x6a +'Xia ', # 0x6b +'Zhi ', # 0x6c +'Ji ', # 0x6d +'Gao ', # 0x6e +'Zhen ', # 0x6f +'Gao ', # 0x70 +'Shui ', # 0x71 +'Jin ', # 0x72 +'Chen ', # 0x73 +'Gai ', # 0x74 +'Kun ', # 0x75 +'Di ', # 0x76 +'Dao ', # 0x77 +'Huo ', # 0x78 +'Tao ', # 0x79 +'Qi ', # 0x7a +'Gu ', # 0x7b +'Guan ', # 0x7c +'Zui ', # 0x7d +'Ling ', # 0x7e +'Lu ', # 0x7f +'Bing ', # 0x80 +'Jin ', # 0x81 +'Dao ', # 0x82 +'Zhi ', # 0x83 +'Lu ', # 0x84 +'Shan ', # 0x85 +'Bei ', # 0x86 +'Zhe ', # 0x87 +'Hui ', # 0x88 +'You ', # 0x89 +'Xi ', # 0x8a +'Yin ', # 0x8b +'Zi ', # 0x8c +'Huo ', # 0x8d +'Zhen ', # 0x8e +'Fu ', # 0x8f +'Yuan ', # 0x90 +'Wu ', # 0x91 +'Xian ', # 0x92 +'Yang ', # 0x93 +'Ti ', # 0x94 +'Yi ', # 0x95 +'Mei ', # 0x96 +'Si ', # 0x97 +'Di ', # 0x98 +'[?] ', # 0x99 +'Zhuo ', # 0x9a +'Zhen ', # 0x9b +'Yong ', # 0x9c +'Ji ', # 0x9d +'Gao ', # 0x9e +'Tang ', # 0x9f +'Si ', # 0xa0 +'Ma ', # 0xa1 +'Ta ', # 0xa2 +'[?] ', # 0xa3 +'Xuan ', # 0xa4 +'Qi ', # 0xa5 +'Yu ', # 0xa6 +'Xi ', # 0xa7 +'Ji ', # 0xa8 +'Si ', # 0xa9 +'Chan ', # 0xaa +'Tan ', # 0xab +'Kuai ', # 0xac +'Sui ', # 0xad +'Li ', # 0xae +'Nong ', # 0xaf +'Ni ', # 0xb0 +'Dao ', # 0xb1 +'Li ', # 0xb2 +'Rang ', # 0xb3 +'Yue ', # 0xb4 +'Ti ', # 0xb5 +'Zan ', # 0xb6 +'Lei ', # 0xb7 +'Rou ', # 0xb8 +'Yu ', # 0xb9 +'Yu ', # 0xba +'Chi ', # 0xbb +'Xie ', # 0xbc +'Qin ', # 0xbd +'He ', # 0xbe +'Tu ', # 0xbf +'Xiu ', # 0xc0 +'Si ', # 0xc1 +'Ren ', # 0xc2 +'Tu ', # 0xc3 +'Zi ', # 0xc4 +'Cha ', # 0xc5 +'Gan ', # 0xc6 +'Yi ', # 0xc7 +'Xian ', # 0xc8 +'Bing ', # 0xc9 +'Nian ', # 0xca +'Qiu ', # 0xcb +'Qiu ', # 0xcc +'Chong ', # 0xcd +'Fen ', # 0xce +'Hao ', # 0xcf +'Yun ', # 0xd0 +'Ke ', # 0xd1 +'Miao ', # 0xd2 +'Zhi ', # 0xd3 +'Geng ', # 0xd4 +'Bi ', # 0xd5 +'Zhi ', # 0xd6 +'Yu ', # 0xd7 +'Mi ', # 0xd8 +'Ku ', # 0xd9 +'Ban ', # 0xda +'Pi ', # 0xdb +'Ni ', # 0xdc +'Li ', # 0xdd +'You ', # 0xde +'Zu ', # 0xdf +'Pi ', # 0xe0 +'Ba ', # 0xe1 +'Ling ', # 0xe2 +'Mo ', # 0xe3 +'Cheng ', # 0xe4 +'Nian ', # 0xe5 +'Qin ', # 0xe6 +'Yang ', # 0xe7 +'Zuo ', # 0xe8 +'Zhi ', # 0xe9 +'Zhi ', # 0xea +'Shu ', # 0xeb +'Ju ', # 0xec +'Zi ', # 0xed +'Huo ', # 0xee +'Ji ', # 0xef +'Cheng ', # 0xf0 +'Tong ', # 0xf1 +'Zhi ', # 0xf2 +'Huo ', # 0xf3 +'He ', # 0xf4 +'Yin ', # 0xf5 +'Zi ', # 0xf6 +'Zhi ', # 0xf7 +'Jie ', # 0xf8 +'Ren ', # 0xf9 +'Du ', # 0xfa +'Yi ', # 0xfb +'Zhu ', # 0xfc +'Hui ', # 0xfd +'Nong ', # 0xfe +'Fu ', # 0xff +) diff --git a/nstock/modules/unidecode/x07a.py b/nstock/modules/unidecode/x07a.py new file mode 100644 index 0000000..b6d512c --- /dev/null +++ b/nstock/modules/unidecode/x07a.py @@ -0,0 +1,258 @@ +data = ( +'Xi ', # 0x00 +'Kao ', # 0x01 +'Lang ', # 0x02 +'Fu ', # 0x03 +'Ze ', # 0x04 +'Shui ', # 0x05 +'Lu ', # 0x06 +'Kun ', # 0x07 +'Gan ', # 0x08 +'Geng ', # 0x09 +'Ti ', # 0x0a +'Cheng ', # 0x0b +'Tu ', # 0x0c +'Shao ', # 0x0d +'Shui ', # 0x0e +'Ya ', # 0x0f +'Lun ', # 0x10 +'Lu ', # 0x11 +'Gu ', # 0x12 +'Zuo ', # 0x13 +'Ren ', # 0x14 +'Zhun ', # 0x15 +'Bang ', # 0x16 +'Bai ', # 0x17 +'Ji ', # 0x18 +'Zhi ', # 0x19 +'Zhi ', # 0x1a +'Kun ', # 0x1b +'Leng ', # 0x1c +'Peng ', # 0x1d +'Ke ', # 0x1e +'Bing ', # 0x1f +'Chou ', # 0x20 +'Zu ', # 0x21 +'Yu ', # 0x22 +'Su ', # 0x23 +'Lue ', # 0x24 +'[?] ', # 0x25 +'Yi ', # 0x26 +'Xi ', # 0x27 +'Bian ', # 0x28 +'Ji ', # 0x29 +'Fu ', # 0x2a +'Bi ', # 0x2b +'Nuo ', # 0x2c +'Jie ', # 0x2d +'Zhong ', # 0x2e +'Zong ', # 0x2f +'Xu ', # 0x30 +'Cheng ', # 0x31 +'Dao ', # 0x32 +'Wen ', # 0x33 +'Lian ', # 0x34 +'Zi ', # 0x35 +'Yu ', # 0x36 +'Ji ', # 0x37 +'Xu ', # 0x38 +'Zhen ', # 0x39 +'Zhi ', # 0x3a +'Dao ', # 0x3b +'Jia ', # 0x3c +'Ji ', # 0x3d +'Gao ', # 0x3e +'Gao ', # 0x3f +'Gu ', # 0x40 +'Rong ', # 0x41 +'Sui ', # 0x42 +'You ', # 0x43 +'Ji ', # 0x44 +'Kang ', # 0x45 +'Mu ', # 0x46 +'Shan ', # 0x47 +'Men ', # 0x48 +'Zhi ', # 0x49 +'Ji ', # 0x4a +'Lu ', # 0x4b +'Su ', # 0x4c +'Ji ', # 0x4d +'Ying ', # 0x4e +'Wen ', # 0x4f +'Qiu ', # 0x50 +'Se ', # 0x51 +'[?] ', # 0x52 +'Yi ', # 0x53 +'Huang ', # 0x54 +'Qie ', # 0x55 +'Ji ', # 0x56 +'Sui ', # 0x57 +'Xiao ', # 0x58 +'Pu ', # 0x59 +'Jiao ', # 0x5a +'Zhuo ', # 0x5b +'Tong ', # 0x5c +'Sai ', # 0x5d +'Lu ', # 0x5e +'Sui ', # 0x5f +'Nong ', # 0x60 +'Se ', # 0x61 +'Hui ', # 0x62 +'Rang ', # 0x63 +'Nuo ', # 0x64 +'Yu ', # 0x65 +'Bin ', # 0x66 +'Ji ', # 0x67 +'Tui ', # 0x68 +'Wen ', # 0x69 +'Cheng ', # 0x6a +'Huo ', # 0x6b +'Gong ', # 0x6c +'Lu ', # 0x6d +'Biao ', # 0x6e +'[?] ', # 0x6f +'Rang ', # 0x70 +'Zhuo ', # 0x71 +'Li ', # 0x72 +'Zan ', # 0x73 +'Xue ', # 0x74 +'Wa ', # 0x75 +'Jiu ', # 0x76 +'Qiong ', # 0x77 +'Xi ', # 0x78 +'Qiong ', # 0x79 +'Kong ', # 0x7a +'Yu ', # 0x7b +'Sen ', # 0x7c +'Jing ', # 0x7d +'Yao ', # 0x7e +'Chuan ', # 0x7f +'Zhun ', # 0x80 +'Tu ', # 0x81 +'Lao ', # 0x82 +'Qie ', # 0x83 +'Zhai ', # 0x84 +'Yao ', # 0x85 +'Bian ', # 0x86 +'Bao ', # 0x87 +'Yao ', # 0x88 +'Bing ', # 0x89 +'Wa ', # 0x8a +'Zhu ', # 0x8b +'Jiao ', # 0x8c +'Qiao ', # 0x8d +'Diao ', # 0x8e +'Wu ', # 0x8f +'Gui ', # 0x90 +'Yao ', # 0x91 +'Zhi ', # 0x92 +'Chuang ', # 0x93 +'Yao ', # 0x94 +'Tiao ', # 0x95 +'Jiao ', # 0x96 +'Chuang ', # 0x97 +'Jiong ', # 0x98 +'Xiao ', # 0x99 +'Cheng ', # 0x9a +'Kou ', # 0x9b +'Cuan ', # 0x9c +'Wo ', # 0x9d +'Dan ', # 0x9e +'Ku ', # 0x9f +'Ke ', # 0xa0 +'Zhui ', # 0xa1 +'Xu ', # 0xa2 +'Su ', # 0xa3 +'Guan ', # 0xa4 +'Kui ', # 0xa5 +'Dou ', # 0xa6 +'[?] ', # 0xa7 +'Yin ', # 0xa8 +'Wo ', # 0xa9 +'Wa ', # 0xaa +'Ya ', # 0xab +'Yu ', # 0xac +'Ju ', # 0xad +'Qiong ', # 0xae +'Yao ', # 0xaf +'Yao ', # 0xb0 +'Tiao ', # 0xb1 +'Chao ', # 0xb2 +'Yu ', # 0xb3 +'Tian ', # 0xb4 +'Diao ', # 0xb5 +'Ju ', # 0xb6 +'Liao ', # 0xb7 +'Xi ', # 0xb8 +'Wu ', # 0xb9 +'Kui ', # 0xba +'Chuang ', # 0xbb +'Zhao ', # 0xbc +'[?] ', # 0xbd +'Kuan ', # 0xbe +'Long ', # 0xbf +'Cheng ', # 0xc0 +'Cui ', # 0xc1 +'Piao ', # 0xc2 +'Zao ', # 0xc3 +'Cuan ', # 0xc4 +'Qiao ', # 0xc5 +'Qiong ', # 0xc6 +'Dou ', # 0xc7 +'Zao ', # 0xc8 +'Long ', # 0xc9 +'Qie ', # 0xca +'Li ', # 0xcb +'Chu ', # 0xcc +'Shi ', # 0xcd +'Fou ', # 0xce +'Qian ', # 0xcf +'Chu ', # 0xd0 +'Hong ', # 0xd1 +'Qi ', # 0xd2 +'Qian ', # 0xd3 +'Gong ', # 0xd4 +'Shi ', # 0xd5 +'Shu ', # 0xd6 +'Miao ', # 0xd7 +'Ju ', # 0xd8 +'Zhan ', # 0xd9 +'Zhu ', # 0xda +'Ling ', # 0xdb +'Long ', # 0xdc +'Bing ', # 0xdd +'Jing ', # 0xde +'Jing ', # 0xdf +'Zhang ', # 0xe0 +'Yi ', # 0xe1 +'Si ', # 0xe2 +'Jun ', # 0xe3 +'Hong ', # 0xe4 +'Tong ', # 0xe5 +'Song ', # 0xe6 +'Jing ', # 0xe7 +'Diao ', # 0xe8 +'Yi ', # 0xe9 +'Shu ', # 0xea +'Jing ', # 0xeb +'Qu ', # 0xec +'Jie ', # 0xed +'Ping ', # 0xee +'Duan ', # 0xef +'Shao ', # 0xf0 +'Zhuan ', # 0xf1 +'Ceng ', # 0xf2 +'Deng ', # 0xf3 +'Cui ', # 0xf4 +'Huai ', # 0xf5 +'Jing ', # 0xf6 +'Kan ', # 0xf7 +'Jing ', # 0xf8 +'Zhu ', # 0xf9 +'Zhu ', # 0xfa +'Le ', # 0xfb +'Peng ', # 0xfc +'Yu ', # 0xfd +'Chi ', # 0xfe +'Gan ', # 0xff +) diff --git a/nstock/modules/unidecode/x07b.py b/nstock/modules/unidecode/x07b.py new file mode 100644 index 0000000..c904395 --- /dev/null +++ b/nstock/modules/unidecode/x07b.py @@ -0,0 +1,258 @@ +data = ( +'Mang ', # 0x00 +'Zhu ', # 0x01 +'Utsubo ', # 0x02 +'Du ', # 0x03 +'Ji ', # 0x04 +'Xiao ', # 0x05 +'Ba ', # 0x06 +'Suan ', # 0x07 +'Ji ', # 0x08 +'Zhen ', # 0x09 +'Zhao ', # 0x0a +'Sun ', # 0x0b +'Ya ', # 0x0c +'Zhui ', # 0x0d +'Yuan ', # 0x0e +'Hu ', # 0x0f +'Gang ', # 0x10 +'Xiao ', # 0x11 +'Cen ', # 0x12 +'Pi ', # 0x13 +'Bi ', # 0x14 +'Jian ', # 0x15 +'Yi ', # 0x16 +'Dong ', # 0x17 +'Shan ', # 0x18 +'Sheng ', # 0x19 +'Xia ', # 0x1a +'Di ', # 0x1b +'Zhu ', # 0x1c +'Na ', # 0x1d +'Chi ', # 0x1e +'Gu ', # 0x1f +'Li ', # 0x20 +'Qie ', # 0x21 +'Min ', # 0x22 +'Bao ', # 0x23 +'Tiao ', # 0x24 +'Si ', # 0x25 +'Fu ', # 0x26 +'Ce ', # 0x27 +'Ben ', # 0x28 +'Pei ', # 0x29 +'Da ', # 0x2a +'Zi ', # 0x2b +'Di ', # 0x2c +'Ling ', # 0x2d +'Ze ', # 0x2e +'Nu ', # 0x2f +'Fu ', # 0x30 +'Gou ', # 0x31 +'Fan ', # 0x32 +'Jia ', # 0x33 +'Ge ', # 0x34 +'Fan ', # 0x35 +'Shi ', # 0x36 +'Mao ', # 0x37 +'Po ', # 0x38 +'Sey ', # 0x39 +'Jian ', # 0x3a +'Qiong ', # 0x3b +'Long ', # 0x3c +'Souke ', # 0x3d +'Bian ', # 0x3e +'Luo ', # 0x3f +'Gui ', # 0x40 +'Qu ', # 0x41 +'Chi ', # 0x42 +'Yin ', # 0x43 +'Yao ', # 0x44 +'Xian ', # 0x45 +'Bi ', # 0x46 +'Qiong ', # 0x47 +'Gua ', # 0x48 +'Deng ', # 0x49 +'Jiao ', # 0x4a +'Jin ', # 0x4b +'Quan ', # 0x4c +'Sun ', # 0x4d +'Ru ', # 0x4e +'Fa ', # 0x4f +'Kuang ', # 0x50 +'Zhu ', # 0x51 +'Tong ', # 0x52 +'Ji ', # 0x53 +'Da ', # 0x54 +'Xing ', # 0x55 +'Ce ', # 0x56 +'Zhong ', # 0x57 +'Kou ', # 0x58 +'Lai ', # 0x59 +'Bi ', # 0x5a +'Shai ', # 0x5b +'Dang ', # 0x5c +'Zheng ', # 0x5d +'Ce ', # 0x5e +'Fu ', # 0x5f +'Yun ', # 0x60 +'Tu ', # 0x61 +'Pa ', # 0x62 +'Li ', # 0x63 +'Lang ', # 0x64 +'Ju ', # 0x65 +'Guan ', # 0x66 +'Jian ', # 0x67 +'Han ', # 0x68 +'Tong ', # 0x69 +'Xia ', # 0x6a +'Zhi ', # 0x6b +'Cheng ', # 0x6c +'Suan ', # 0x6d +'Shi ', # 0x6e +'Zhu ', # 0x6f +'Zuo ', # 0x70 +'Xiao ', # 0x71 +'Shao ', # 0x72 +'Ting ', # 0x73 +'Ce ', # 0x74 +'Yan ', # 0x75 +'Gao ', # 0x76 +'Kuai ', # 0x77 +'Gan ', # 0x78 +'Chou ', # 0x79 +'Kago ', # 0x7a +'Gang ', # 0x7b +'Yun ', # 0x7c +'O ', # 0x7d +'Qian ', # 0x7e +'Xiao ', # 0x7f +'Jian ', # 0x80 +'Pu ', # 0x81 +'Lai ', # 0x82 +'Zou ', # 0x83 +'Bi ', # 0x84 +'Bi ', # 0x85 +'Bi ', # 0x86 +'Ge ', # 0x87 +'Chi ', # 0x88 +'Guai ', # 0x89 +'Yu ', # 0x8a +'Jian ', # 0x8b +'Zhao ', # 0x8c +'Gu ', # 0x8d +'Chi ', # 0x8e +'Zheng ', # 0x8f +'Jing ', # 0x90 +'Sha ', # 0x91 +'Zhou ', # 0x92 +'Lu ', # 0x93 +'Bo ', # 0x94 +'Ji ', # 0x95 +'Lin ', # 0x96 +'Suan ', # 0x97 +'Jun ', # 0x98 +'Fu ', # 0x99 +'Zha ', # 0x9a +'Gu ', # 0x9b +'Kong ', # 0x9c +'Qian ', # 0x9d +'Quan ', # 0x9e +'Jun ', # 0x9f +'Chui ', # 0xa0 +'Guan ', # 0xa1 +'Yuan ', # 0xa2 +'Ce ', # 0xa3 +'Ju ', # 0xa4 +'Bo ', # 0xa5 +'Ze ', # 0xa6 +'Qie ', # 0xa7 +'Tuo ', # 0xa8 +'Luo ', # 0xa9 +'Dan ', # 0xaa +'Xiao ', # 0xab +'Ruo ', # 0xac +'Jian ', # 0xad +'Xuan ', # 0xae +'Bian ', # 0xaf +'Sun ', # 0xb0 +'Xiang ', # 0xb1 +'Xian ', # 0xb2 +'Ping ', # 0xb3 +'Zhen ', # 0xb4 +'Sheng ', # 0xb5 +'Hu ', # 0xb6 +'Shi ', # 0xb7 +'Zhu ', # 0xb8 +'Yue ', # 0xb9 +'Chun ', # 0xba +'Lu ', # 0xbb +'Wu ', # 0xbc +'Dong ', # 0xbd +'Xiao ', # 0xbe +'Ji ', # 0xbf +'Jie ', # 0xc0 +'Huang ', # 0xc1 +'Xing ', # 0xc2 +'Mei ', # 0xc3 +'Fan ', # 0xc4 +'Chui ', # 0xc5 +'Zhuan ', # 0xc6 +'Pian ', # 0xc7 +'Feng ', # 0xc8 +'Zhu ', # 0xc9 +'Hong ', # 0xca +'Qie ', # 0xcb +'Hou ', # 0xcc +'Qiu ', # 0xcd +'Miao ', # 0xce +'Qian ', # 0xcf +'[?] ', # 0xd0 +'Kui ', # 0xd1 +'Sik ', # 0xd2 +'Lou ', # 0xd3 +'Yun ', # 0xd4 +'He ', # 0xd5 +'Tang ', # 0xd6 +'Yue ', # 0xd7 +'Chou ', # 0xd8 +'Gao ', # 0xd9 +'Fei ', # 0xda +'Ruo ', # 0xdb +'Zheng ', # 0xdc +'Gou ', # 0xdd +'Nie ', # 0xde +'Qian ', # 0xdf +'Xiao ', # 0xe0 +'Cuan ', # 0xe1 +'Gong ', # 0xe2 +'Pang ', # 0xe3 +'Du ', # 0xe4 +'Li ', # 0xe5 +'Bi ', # 0xe6 +'Zhuo ', # 0xe7 +'Chu ', # 0xe8 +'Shai ', # 0xe9 +'Chi ', # 0xea +'Zhu ', # 0xeb +'Qiang ', # 0xec +'Long ', # 0xed +'Lan ', # 0xee +'Jian ', # 0xef +'Bu ', # 0xf0 +'Li ', # 0xf1 +'Hui ', # 0xf2 +'Bi ', # 0xf3 +'Di ', # 0xf4 +'Cong ', # 0xf5 +'Yan ', # 0xf6 +'Peng ', # 0xf7 +'Sen ', # 0xf8 +'Zhuan ', # 0xf9 +'Pai ', # 0xfa +'Piao ', # 0xfb +'Dou ', # 0xfc +'Yu ', # 0xfd +'Mie ', # 0xfe +'Zhuan ', # 0xff +) diff --git a/nstock/modules/unidecode/x07c.py b/nstock/modules/unidecode/x07c.py new file mode 100644 index 0000000..3379947 --- /dev/null +++ b/nstock/modules/unidecode/x07c.py @@ -0,0 +1,258 @@ +data = ( +'Ze ', # 0x00 +'Xi ', # 0x01 +'Guo ', # 0x02 +'Yi ', # 0x03 +'Hu ', # 0x04 +'Chan ', # 0x05 +'Kou ', # 0x06 +'Cu ', # 0x07 +'Ping ', # 0x08 +'Chou ', # 0x09 +'Ji ', # 0x0a +'Gui ', # 0x0b +'Su ', # 0x0c +'Lou ', # 0x0d +'Zha ', # 0x0e +'Lu ', # 0x0f +'Nian ', # 0x10 +'Suo ', # 0x11 +'Cuan ', # 0x12 +'Sasara ', # 0x13 +'Suo ', # 0x14 +'Le ', # 0x15 +'Duan ', # 0x16 +'Yana ', # 0x17 +'Xiao ', # 0x18 +'Bo ', # 0x19 +'Mi ', # 0x1a +'Si ', # 0x1b +'Dang ', # 0x1c +'Liao ', # 0x1d +'Dan ', # 0x1e +'Dian ', # 0x1f +'Fu ', # 0x20 +'Jian ', # 0x21 +'Min ', # 0x22 +'Kui ', # 0x23 +'Dai ', # 0x24 +'Qiao ', # 0x25 +'Deng ', # 0x26 +'Huang ', # 0x27 +'Sun ', # 0x28 +'Lao ', # 0x29 +'Zan ', # 0x2a +'Xiao ', # 0x2b +'Du ', # 0x2c +'Shi ', # 0x2d +'Zan ', # 0x2e +'[?] ', # 0x2f +'Pai ', # 0x30 +'Hata ', # 0x31 +'Pai ', # 0x32 +'Gan ', # 0x33 +'Ju ', # 0x34 +'Du ', # 0x35 +'Lu ', # 0x36 +'Yan ', # 0x37 +'Bo ', # 0x38 +'Dang ', # 0x39 +'Sai ', # 0x3a +'Ke ', # 0x3b +'Long ', # 0x3c +'Qian ', # 0x3d +'Lian ', # 0x3e +'Bo ', # 0x3f +'Zhou ', # 0x40 +'Lai ', # 0x41 +'[?] ', # 0x42 +'Lan ', # 0x43 +'Kui ', # 0x44 +'Yu ', # 0x45 +'Yue ', # 0x46 +'Hao ', # 0x47 +'Zhen ', # 0x48 +'Tai ', # 0x49 +'Ti ', # 0x4a +'Mi ', # 0x4b +'Chou ', # 0x4c +'Ji ', # 0x4d +'[?] ', # 0x4e +'Hata ', # 0x4f +'Teng ', # 0x50 +'Zhuan ', # 0x51 +'Zhou ', # 0x52 +'Fan ', # 0x53 +'Sou ', # 0x54 +'Zhou ', # 0x55 +'Kuji ', # 0x56 +'Zhuo ', # 0x57 +'Teng ', # 0x58 +'Lu ', # 0x59 +'Lu ', # 0x5a +'Jian ', # 0x5b +'Tuo ', # 0x5c +'Ying ', # 0x5d +'Yu ', # 0x5e +'Lai ', # 0x5f +'Long ', # 0x60 +'Shinshi ', # 0x61 +'Lian ', # 0x62 +'Lan ', # 0x63 +'Qian ', # 0x64 +'Yue ', # 0x65 +'Zhong ', # 0x66 +'Qu ', # 0x67 +'Lian ', # 0x68 +'Bian ', # 0x69 +'Duan ', # 0x6a +'Zuan ', # 0x6b +'Li ', # 0x6c +'Si ', # 0x6d +'Luo ', # 0x6e +'Ying ', # 0x6f +'Yue ', # 0x70 +'Zhuo ', # 0x71 +'Xu ', # 0x72 +'Mi ', # 0x73 +'Di ', # 0x74 +'Fan ', # 0x75 +'Shen ', # 0x76 +'Zhe ', # 0x77 +'Shen ', # 0x78 +'Nu ', # 0x79 +'Xie ', # 0x7a +'Lei ', # 0x7b +'Xian ', # 0x7c +'Zi ', # 0x7d +'Ni ', # 0x7e +'Cun ', # 0x7f +'[?] ', # 0x80 +'Qian ', # 0x81 +'Kume ', # 0x82 +'Bi ', # 0x83 +'Ban ', # 0x84 +'Wu ', # 0x85 +'Sha ', # 0x86 +'Kang ', # 0x87 +'Rou ', # 0x88 +'Fen ', # 0x89 +'Bi ', # 0x8a +'Cui ', # 0x8b +'[?] ', # 0x8c +'Li ', # 0x8d +'Chi ', # 0x8e +'Nukamiso ', # 0x8f +'Ro ', # 0x90 +'Ba ', # 0x91 +'Li ', # 0x92 +'Gan ', # 0x93 +'Ju ', # 0x94 +'Po ', # 0x95 +'Mo ', # 0x96 +'Cu ', # 0x97 +'Nian ', # 0x98 +'Zhou ', # 0x99 +'Li ', # 0x9a +'Su ', # 0x9b +'Tiao ', # 0x9c +'Li ', # 0x9d +'Qi ', # 0x9e +'Su ', # 0x9f +'Hong ', # 0xa0 +'Tong ', # 0xa1 +'Zi ', # 0xa2 +'Ce ', # 0xa3 +'Yue ', # 0xa4 +'Zhou ', # 0xa5 +'Lin ', # 0xa6 +'Zhuang ', # 0xa7 +'Bai ', # 0xa8 +'[?] ', # 0xa9 +'Fen ', # 0xaa +'Ji ', # 0xab +'[?] ', # 0xac +'Sukumo ', # 0xad +'Liang ', # 0xae +'Xian ', # 0xaf +'Fu ', # 0xb0 +'Liang ', # 0xb1 +'Can ', # 0xb2 +'Geng ', # 0xb3 +'Li ', # 0xb4 +'Yue ', # 0xb5 +'Lu ', # 0xb6 +'Ju ', # 0xb7 +'Qi ', # 0xb8 +'Cui ', # 0xb9 +'Bai ', # 0xba +'Zhang ', # 0xbb +'Lin ', # 0xbc +'Zong ', # 0xbd +'Jing ', # 0xbe +'Guo ', # 0xbf +'Kouji ', # 0xc0 +'San ', # 0xc1 +'San ', # 0xc2 +'Tang ', # 0xc3 +'Bian ', # 0xc4 +'Rou ', # 0xc5 +'Mian ', # 0xc6 +'Hou ', # 0xc7 +'Xu ', # 0xc8 +'Zong ', # 0xc9 +'Hu ', # 0xca +'Jian ', # 0xcb +'Zan ', # 0xcc +'Ci ', # 0xcd +'Li ', # 0xce +'Xie ', # 0xcf +'Fu ', # 0xd0 +'Ni ', # 0xd1 +'Bei ', # 0xd2 +'Gu ', # 0xd3 +'Xiu ', # 0xd4 +'Gao ', # 0xd5 +'Tang ', # 0xd6 +'Qiu ', # 0xd7 +'Sukumo ', # 0xd8 +'Cao ', # 0xd9 +'Zhuang ', # 0xda +'Tang ', # 0xdb +'Mi ', # 0xdc +'San ', # 0xdd +'Fen ', # 0xde +'Zao ', # 0xdf +'Kang ', # 0xe0 +'Jiang ', # 0xe1 +'Mo ', # 0xe2 +'San ', # 0xe3 +'San ', # 0xe4 +'Nuo ', # 0xe5 +'Xi ', # 0xe6 +'Liang ', # 0xe7 +'Jiang ', # 0xe8 +'Kuai ', # 0xe9 +'Bo ', # 0xea +'Huan ', # 0xeb +'[?] ', # 0xec +'Zong ', # 0xed +'Xian ', # 0xee +'Nuo ', # 0xef +'Tuan ', # 0xf0 +'Nie ', # 0xf1 +'Li ', # 0xf2 +'Zuo ', # 0xf3 +'Di ', # 0xf4 +'Nie ', # 0xf5 +'Tiao ', # 0xf6 +'Lan ', # 0xf7 +'Mi ', # 0xf8 +'Jiao ', # 0xf9 +'Jiu ', # 0xfa +'Xi ', # 0xfb +'Gong ', # 0xfc +'Zheng ', # 0xfd +'Jiu ', # 0xfe +'You ', # 0xff +) diff --git a/nstock/modules/unidecode/x07d.py b/nstock/modules/unidecode/x07d.py new file mode 100644 index 0000000..241db29 --- /dev/null +++ b/nstock/modules/unidecode/x07d.py @@ -0,0 +1,258 @@ +data = ( +'Ji ', # 0x00 +'Cha ', # 0x01 +'Zhou ', # 0x02 +'Xun ', # 0x03 +'Yue ', # 0x04 +'Hong ', # 0x05 +'Yu ', # 0x06 +'He ', # 0x07 +'Wan ', # 0x08 +'Ren ', # 0x09 +'Wen ', # 0x0a +'Wen ', # 0x0b +'Qiu ', # 0x0c +'Na ', # 0x0d +'Zi ', # 0x0e +'Tou ', # 0x0f +'Niu ', # 0x10 +'Fou ', # 0x11 +'Jie ', # 0x12 +'Shu ', # 0x13 +'Chun ', # 0x14 +'Pi ', # 0x15 +'Yin ', # 0x16 +'Sha ', # 0x17 +'Hong ', # 0x18 +'Zhi ', # 0x19 +'Ji ', # 0x1a +'Fen ', # 0x1b +'Yun ', # 0x1c +'Ren ', # 0x1d +'Dan ', # 0x1e +'Jin ', # 0x1f +'Su ', # 0x20 +'Fang ', # 0x21 +'Suo ', # 0x22 +'Cui ', # 0x23 +'Jiu ', # 0x24 +'Zha ', # 0x25 +'Kinu ', # 0x26 +'Jin ', # 0x27 +'Fu ', # 0x28 +'Zhi ', # 0x29 +'Ci ', # 0x2a +'Zi ', # 0x2b +'Chou ', # 0x2c +'Hong ', # 0x2d +'Zha ', # 0x2e +'Lei ', # 0x2f +'Xi ', # 0x30 +'Fu ', # 0x31 +'Xie ', # 0x32 +'Shen ', # 0x33 +'Bei ', # 0x34 +'Zhu ', # 0x35 +'Qu ', # 0x36 +'Ling ', # 0x37 +'Zhu ', # 0x38 +'Shao ', # 0x39 +'Gan ', # 0x3a +'Yang ', # 0x3b +'Fu ', # 0x3c +'Tuo ', # 0x3d +'Zhen ', # 0x3e +'Dai ', # 0x3f +'Zhuo ', # 0x40 +'Shi ', # 0x41 +'Zhong ', # 0x42 +'Xian ', # 0x43 +'Zu ', # 0x44 +'Jiong ', # 0x45 +'Ban ', # 0x46 +'Ju ', # 0x47 +'Mo ', # 0x48 +'Shu ', # 0x49 +'Zui ', # 0x4a +'Wata ', # 0x4b +'Jing ', # 0x4c +'Ren ', # 0x4d +'Heng ', # 0x4e +'Xie ', # 0x4f +'Jie ', # 0x50 +'Zhu ', # 0x51 +'Chou ', # 0x52 +'Gua ', # 0x53 +'Bai ', # 0x54 +'Jue ', # 0x55 +'Kuang ', # 0x56 +'Hu ', # 0x57 +'Ci ', # 0x58 +'Geng ', # 0x59 +'Geng ', # 0x5a +'Tao ', # 0x5b +'Xie ', # 0x5c +'Ku ', # 0x5d +'Jiao ', # 0x5e +'Quan ', # 0x5f +'Gai ', # 0x60 +'Luo ', # 0x61 +'Xuan ', # 0x62 +'Bing ', # 0x63 +'Xian ', # 0x64 +'Fu ', # 0x65 +'Gei ', # 0x66 +'Tong ', # 0x67 +'Rong ', # 0x68 +'Tiao ', # 0x69 +'Yin ', # 0x6a +'Lei ', # 0x6b +'Xie ', # 0x6c +'Quan ', # 0x6d +'Xu ', # 0x6e +'Lun ', # 0x6f +'Die ', # 0x70 +'Tong ', # 0x71 +'Si ', # 0x72 +'Jiang ', # 0x73 +'Xiang ', # 0x74 +'Hui ', # 0x75 +'Jue ', # 0x76 +'Zhi ', # 0x77 +'Jian ', # 0x78 +'Juan ', # 0x79 +'Chi ', # 0x7a +'Mian ', # 0x7b +'Zhen ', # 0x7c +'Lu ', # 0x7d +'Cheng ', # 0x7e +'Qiu ', # 0x7f +'Shu ', # 0x80 +'Bang ', # 0x81 +'Tong ', # 0x82 +'Xiao ', # 0x83 +'Wan ', # 0x84 +'Qin ', # 0x85 +'Geng ', # 0x86 +'Xiu ', # 0x87 +'Ti ', # 0x88 +'Xiu ', # 0x89 +'Xie ', # 0x8a +'Hong ', # 0x8b +'Xi ', # 0x8c +'Fu ', # 0x8d +'Ting ', # 0x8e +'Sui ', # 0x8f +'Dui ', # 0x90 +'Kun ', # 0x91 +'Fu ', # 0x92 +'Jing ', # 0x93 +'Hu ', # 0x94 +'Zhi ', # 0x95 +'Yan ', # 0x96 +'Jiong ', # 0x97 +'Feng ', # 0x98 +'Ji ', # 0x99 +'Sok ', # 0x9a +'Kase ', # 0x9b +'Zong ', # 0x9c +'Lin ', # 0x9d +'Duo ', # 0x9e +'Li ', # 0x9f +'Lu ', # 0xa0 +'Liang ', # 0xa1 +'Chou ', # 0xa2 +'Quan ', # 0xa3 +'Shao ', # 0xa4 +'Qi ', # 0xa5 +'Qi ', # 0xa6 +'Zhun ', # 0xa7 +'Qi ', # 0xa8 +'Wan ', # 0xa9 +'Qian ', # 0xaa +'Xian ', # 0xab +'Shou ', # 0xac +'Wei ', # 0xad +'Qi ', # 0xae +'Tao ', # 0xaf +'Wan ', # 0xb0 +'Gang ', # 0xb1 +'Wang ', # 0xb2 +'Beng ', # 0xb3 +'Zhui ', # 0xb4 +'Cai ', # 0xb5 +'Guo ', # 0xb6 +'Cui ', # 0xb7 +'Lun ', # 0xb8 +'Liu ', # 0xb9 +'Qi ', # 0xba +'Zhan ', # 0xbb +'Bei ', # 0xbc +'Chuo ', # 0xbd +'Ling ', # 0xbe +'Mian ', # 0xbf +'Qi ', # 0xc0 +'Qie ', # 0xc1 +'Tan ', # 0xc2 +'Zong ', # 0xc3 +'Gun ', # 0xc4 +'Zou ', # 0xc5 +'Yi ', # 0xc6 +'Zi ', # 0xc7 +'Xing ', # 0xc8 +'Liang ', # 0xc9 +'Jin ', # 0xca +'Fei ', # 0xcb +'Rui ', # 0xcc +'Min ', # 0xcd +'Yu ', # 0xce +'Zong ', # 0xcf +'Fan ', # 0xd0 +'Lu ', # 0xd1 +'Xu ', # 0xd2 +'Yingl ', # 0xd3 +'Zhang ', # 0xd4 +'Kasuri ', # 0xd5 +'Xu ', # 0xd6 +'Xiang ', # 0xd7 +'Jian ', # 0xd8 +'Ke ', # 0xd9 +'Xian ', # 0xda +'Ruan ', # 0xdb +'Mian ', # 0xdc +'Qi ', # 0xdd +'Duan ', # 0xde +'Zhong ', # 0xdf +'Di ', # 0xe0 +'Min ', # 0xe1 +'Miao ', # 0xe2 +'Yuan ', # 0xe3 +'Xie ', # 0xe4 +'Bao ', # 0xe5 +'Si ', # 0xe6 +'Qiu ', # 0xe7 +'Bian ', # 0xe8 +'Huan ', # 0xe9 +'Geng ', # 0xea +'Cong ', # 0xeb +'Mian ', # 0xec +'Wei ', # 0xed +'Fu ', # 0xee +'Wei ', # 0xef +'Yu ', # 0xf0 +'Gou ', # 0xf1 +'Miao ', # 0xf2 +'Xie ', # 0xf3 +'Lian ', # 0xf4 +'Zong ', # 0xf5 +'Bian ', # 0xf6 +'Yun ', # 0xf7 +'Yin ', # 0xf8 +'Ti ', # 0xf9 +'Gua ', # 0xfa +'Zhi ', # 0xfb +'Yun ', # 0xfc +'Cheng ', # 0xfd +'Chan ', # 0xfe +'Dai ', # 0xff +) diff --git a/nstock/modules/unidecode/x07e.py b/nstock/modules/unidecode/x07e.py new file mode 100644 index 0000000..131ef35 --- /dev/null +++ b/nstock/modules/unidecode/x07e.py @@ -0,0 +1,258 @@ +data = ( +'Xia ', # 0x00 +'Yuan ', # 0x01 +'Zong ', # 0x02 +'Xu ', # 0x03 +'Nawa ', # 0x04 +'Odoshi ', # 0x05 +'Geng ', # 0x06 +'Sen ', # 0x07 +'Ying ', # 0x08 +'Jin ', # 0x09 +'Yi ', # 0x0a +'Zhui ', # 0x0b +'Ni ', # 0x0c +'Bang ', # 0x0d +'Gu ', # 0x0e +'Pan ', # 0x0f +'Zhou ', # 0x10 +'Jian ', # 0x11 +'Cuo ', # 0x12 +'Quan ', # 0x13 +'Shuang ', # 0x14 +'Yun ', # 0x15 +'Xia ', # 0x16 +'Shuai ', # 0x17 +'Xi ', # 0x18 +'Rong ', # 0x19 +'Tao ', # 0x1a +'Fu ', # 0x1b +'Yun ', # 0x1c +'Zhen ', # 0x1d +'Gao ', # 0x1e +'Ru ', # 0x1f +'Hu ', # 0x20 +'Zai ', # 0x21 +'Teng ', # 0x22 +'Xian ', # 0x23 +'Su ', # 0x24 +'Zhen ', # 0x25 +'Zong ', # 0x26 +'Tao ', # 0x27 +'Horo ', # 0x28 +'Cai ', # 0x29 +'Bi ', # 0x2a +'Feng ', # 0x2b +'Cu ', # 0x2c +'Li ', # 0x2d +'Suo ', # 0x2e +'Yin ', # 0x2f +'Xi ', # 0x30 +'Zong ', # 0x31 +'Lei ', # 0x32 +'Zhuan ', # 0x33 +'Qian ', # 0x34 +'Man ', # 0x35 +'Zhi ', # 0x36 +'Lu ', # 0x37 +'Mo ', # 0x38 +'Piao ', # 0x39 +'Lian ', # 0x3a +'Mi ', # 0x3b +'Xuan ', # 0x3c +'Zong ', # 0x3d +'Ji ', # 0x3e +'Shan ', # 0x3f +'Sui ', # 0x40 +'Fan ', # 0x41 +'Shuai ', # 0x42 +'Beng ', # 0x43 +'Yi ', # 0x44 +'Sao ', # 0x45 +'Mou ', # 0x46 +'Zhou ', # 0x47 +'Qiang ', # 0x48 +'Hun ', # 0x49 +'Sem ', # 0x4a +'Xi ', # 0x4b +'Jung ', # 0x4c +'Xiu ', # 0x4d +'Ran ', # 0x4e +'Xuan ', # 0x4f +'Hui ', # 0x50 +'Qiao ', # 0x51 +'Zeng ', # 0x52 +'Zuo ', # 0x53 +'Zhi ', # 0x54 +'Shan ', # 0x55 +'San ', # 0x56 +'Lin ', # 0x57 +'Yu ', # 0x58 +'Fan ', # 0x59 +'Liao ', # 0x5a +'Chuo ', # 0x5b +'Zun ', # 0x5c +'Jian ', # 0x5d +'Rao ', # 0x5e +'Chan ', # 0x5f +'Rui ', # 0x60 +'Xiu ', # 0x61 +'Hui ', # 0x62 +'Hua ', # 0x63 +'Zuan ', # 0x64 +'Xi ', # 0x65 +'Qiang ', # 0x66 +'Un ', # 0x67 +'Da ', # 0x68 +'Sheng ', # 0x69 +'Hui ', # 0x6a +'Xi ', # 0x6b +'Se ', # 0x6c +'Jian ', # 0x6d +'Jiang ', # 0x6e +'Huan ', # 0x6f +'Zao ', # 0x70 +'Cong ', # 0x71 +'Jie ', # 0x72 +'Jiao ', # 0x73 +'Bo ', # 0x74 +'Chan ', # 0x75 +'Yi ', # 0x76 +'Nao ', # 0x77 +'Sui ', # 0x78 +'Yi ', # 0x79 +'Shai ', # 0x7a +'Xu ', # 0x7b +'Ji ', # 0x7c +'Bin ', # 0x7d +'Qian ', # 0x7e +'Lan ', # 0x7f +'Pu ', # 0x80 +'Xun ', # 0x81 +'Zuan ', # 0x82 +'Qi ', # 0x83 +'Peng ', # 0x84 +'Li ', # 0x85 +'Mo ', # 0x86 +'Lei ', # 0x87 +'Xie ', # 0x88 +'Zuan ', # 0x89 +'Kuang ', # 0x8a +'You ', # 0x8b +'Xu ', # 0x8c +'Lei ', # 0x8d +'Xian ', # 0x8e +'Chan ', # 0x8f +'Kou ', # 0x90 +'Lu ', # 0x91 +'Chan ', # 0x92 +'Ying ', # 0x93 +'Cai ', # 0x94 +'Xiang ', # 0x95 +'Xian ', # 0x96 +'Zui ', # 0x97 +'Zuan ', # 0x98 +'Luo ', # 0x99 +'Xi ', # 0x9a +'Dao ', # 0x9b +'Lan ', # 0x9c +'Lei ', # 0x9d +'Lian ', # 0x9e +'Si ', # 0x9f +'Jiu ', # 0xa0 +'Yu ', # 0xa1 +'Hong ', # 0xa2 +'Zhou ', # 0xa3 +'Xian ', # 0xa4 +'He ', # 0xa5 +'Yue ', # 0xa6 +'Ji ', # 0xa7 +'Wan ', # 0xa8 +'Kuang ', # 0xa9 +'Ji ', # 0xaa +'Ren ', # 0xab +'Wei ', # 0xac +'Yun ', # 0xad +'Hong ', # 0xae +'Chun ', # 0xaf +'Pi ', # 0xb0 +'Sha ', # 0xb1 +'Gang ', # 0xb2 +'Na ', # 0xb3 +'Ren ', # 0xb4 +'Zong ', # 0xb5 +'Lun ', # 0xb6 +'Fen ', # 0xb7 +'Zhi ', # 0xb8 +'Wen ', # 0xb9 +'Fang ', # 0xba +'Zhu ', # 0xbb +'Yin ', # 0xbc +'Niu ', # 0xbd +'Shu ', # 0xbe +'Xian ', # 0xbf +'Gan ', # 0xc0 +'Xie ', # 0xc1 +'Fu ', # 0xc2 +'Lian ', # 0xc3 +'Zu ', # 0xc4 +'Shen ', # 0xc5 +'Xi ', # 0xc6 +'Zhi ', # 0xc7 +'Zhong ', # 0xc8 +'Zhou ', # 0xc9 +'Ban ', # 0xca +'Fu ', # 0xcb +'Zhuo ', # 0xcc +'Shao ', # 0xcd +'Yi ', # 0xce +'Jing ', # 0xcf +'Dai ', # 0xd0 +'Bang ', # 0xd1 +'Rong ', # 0xd2 +'Jie ', # 0xd3 +'Ku ', # 0xd4 +'Rao ', # 0xd5 +'Die ', # 0xd6 +'Heng ', # 0xd7 +'Hui ', # 0xd8 +'Gei ', # 0xd9 +'Xuan ', # 0xda +'Jiang ', # 0xdb +'Luo ', # 0xdc +'Jue ', # 0xdd +'Jiao ', # 0xde +'Tong ', # 0xdf +'Geng ', # 0xe0 +'Xiao ', # 0xe1 +'Juan ', # 0xe2 +'Xiu ', # 0xe3 +'Xi ', # 0xe4 +'Sui ', # 0xe5 +'Tao ', # 0xe6 +'Ji ', # 0xe7 +'Ti ', # 0xe8 +'Ji ', # 0xe9 +'Xu ', # 0xea +'Ling ', # 0xeb +'[?] ', # 0xec +'Xu ', # 0xed +'Qi ', # 0xee +'Fei ', # 0xef +'Chuo ', # 0xf0 +'Zhang ', # 0xf1 +'Gun ', # 0xf2 +'Sheng ', # 0xf3 +'Wei ', # 0xf4 +'Mian ', # 0xf5 +'Shou ', # 0xf6 +'Beng ', # 0xf7 +'Chou ', # 0xf8 +'Tao ', # 0xf9 +'Liu ', # 0xfa +'Quan ', # 0xfb +'Zong ', # 0xfc +'Zhan ', # 0xfd +'Wan ', # 0xfe +'Lu ', # 0xff +) diff --git a/nstock/modules/unidecode/x07f.py b/nstock/modules/unidecode/x07f.py new file mode 100644 index 0000000..0a708d6 --- /dev/null +++ b/nstock/modules/unidecode/x07f.py @@ -0,0 +1,258 @@ +data = ( +'Zhui ', # 0x00 +'Zi ', # 0x01 +'Ke ', # 0x02 +'Xiang ', # 0x03 +'Jian ', # 0x04 +'Mian ', # 0x05 +'Lan ', # 0x06 +'Ti ', # 0x07 +'Miao ', # 0x08 +'Qi ', # 0x09 +'Yun ', # 0x0a +'Hui ', # 0x0b +'Si ', # 0x0c +'Duo ', # 0x0d +'Duan ', # 0x0e +'Bian ', # 0x0f +'Xian ', # 0x10 +'Gou ', # 0x11 +'Zhui ', # 0x12 +'Huan ', # 0x13 +'Di ', # 0x14 +'Lu ', # 0x15 +'Bian ', # 0x16 +'Min ', # 0x17 +'Yuan ', # 0x18 +'Jin ', # 0x19 +'Fu ', # 0x1a +'Ru ', # 0x1b +'Zhen ', # 0x1c +'Feng ', # 0x1d +'Shuai ', # 0x1e +'Gao ', # 0x1f +'Chan ', # 0x20 +'Li ', # 0x21 +'Yi ', # 0x22 +'Jian ', # 0x23 +'Bin ', # 0x24 +'Piao ', # 0x25 +'Man ', # 0x26 +'Lei ', # 0x27 +'Ying ', # 0x28 +'Suo ', # 0x29 +'Mou ', # 0x2a +'Sao ', # 0x2b +'Xie ', # 0x2c +'Liao ', # 0x2d +'Shan ', # 0x2e +'Zeng ', # 0x2f +'Jiang ', # 0x30 +'Qian ', # 0x31 +'Zao ', # 0x32 +'Huan ', # 0x33 +'Jiao ', # 0x34 +'Zuan ', # 0x35 +'Fou ', # 0x36 +'Xie ', # 0x37 +'Gang ', # 0x38 +'Fou ', # 0x39 +'Que ', # 0x3a +'Fou ', # 0x3b +'Kaakeru ', # 0x3c +'Bo ', # 0x3d +'Ping ', # 0x3e +'Hou ', # 0x3f +'[?] ', # 0x40 +'Gang ', # 0x41 +'Ying ', # 0x42 +'Ying ', # 0x43 +'Qing ', # 0x44 +'Xia ', # 0x45 +'Guan ', # 0x46 +'Zun ', # 0x47 +'Tan ', # 0x48 +'Chang ', # 0x49 +'Qi ', # 0x4a +'Weng ', # 0x4b +'Ying ', # 0x4c +'Lei ', # 0x4d +'Tan ', # 0x4e +'Lu ', # 0x4f +'Guan ', # 0x50 +'Wang ', # 0x51 +'Wang ', # 0x52 +'Gang ', # 0x53 +'Wang ', # 0x54 +'Han ', # 0x55 +'[?] ', # 0x56 +'Luo ', # 0x57 +'Fu ', # 0x58 +'Mi ', # 0x59 +'Fa ', # 0x5a +'Gu ', # 0x5b +'Zhu ', # 0x5c +'Ju ', # 0x5d +'Mao ', # 0x5e +'Gu ', # 0x5f +'Min ', # 0x60 +'Gang ', # 0x61 +'Ba ', # 0x62 +'Gua ', # 0x63 +'Ti ', # 0x64 +'Juan ', # 0x65 +'Fu ', # 0x66 +'Lin ', # 0x67 +'Yan ', # 0x68 +'Zhao ', # 0x69 +'Zui ', # 0x6a +'Gua ', # 0x6b +'Zhuo ', # 0x6c +'Yu ', # 0x6d +'Zhi ', # 0x6e +'An ', # 0x6f +'Fa ', # 0x70 +'Nan ', # 0x71 +'Shu ', # 0x72 +'Si ', # 0x73 +'Pi ', # 0x74 +'Ma ', # 0x75 +'Liu ', # 0x76 +'Ba ', # 0x77 +'Fa ', # 0x78 +'Li ', # 0x79 +'Chao ', # 0x7a +'Wei ', # 0x7b +'Bi ', # 0x7c +'Ji ', # 0x7d +'Zeng ', # 0x7e +'Tong ', # 0x7f +'Liu ', # 0x80 +'Ji ', # 0x81 +'Juan ', # 0x82 +'Mi ', # 0x83 +'Zhao ', # 0x84 +'Luo ', # 0x85 +'Pi ', # 0x86 +'Ji ', # 0x87 +'Ji ', # 0x88 +'Luan ', # 0x89 +'Yang ', # 0x8a +'Mie ', # 0x8b +'Qiang ', # 0x8c +'Ta ', # 0x8d +'Mei ', # 0x8e +'Yang ', # 0x8f +'You ', # 0x90 +'You ', # 0x91 +'Fen ', # 0x92 +'Ba ', # 0x93 +'Gao ', # 0x94 +'Yang ', # 0x95 +'Gu ', # 0x96 +'Qiang ', # 0x97 +'Zang ', # 0x98 +'Gao ', # 0x99 +'Ling ', # 0x9a +'Yi ', # 0x9b +'Zhu ', # 0x9c +'Di ', # 0x9d +'Xiu ', # 0x9e +'Qian ', # 0x9f +'Yi ', # 0xa0 +'Xian ', # 0xa1 +'Rong ', # 0xa2 +'Qun ', # 0xa3 +'Qun ', # 0xa4 +'Qian ', # 0xa5 +'Huan ', # 0xa6 +'Zui ', # 0xa7 +'Xian ', # 0xa8 +'Yi ', # 0xa9 +'Yashinau ', # 0xaa +'Qiang ', # 0xab +'Xian ', # 0xac +'Yu ', # 0xad +'Geng ', # 0xae +'Jie ', # 0xaf +'Tang ', # 0xb0 +'Yuan ', # 0xb1 +'Xi ', # 0xb2 +'Fan ', # 0xb3 +'Shan ', # 0xb4 +'Fen ', # 0xb5 +'Shan ', # 0xb6 +'Lian ', # 0xb7 +'Lei ', # 0xb8 +'Geng ', # 0xb9 +'Nou ', # 0xba +'Qiang ', # 0xbb +'Chan ', # 0xbc +'Yu ', # 0xbd +'Gong ', # 0xbe +'Yi ', # 0xbf +'Chong ', # 0xc0 +'Weng ', # 0xc1 +'Fen ', # 0xc2 +'Hong ', # 0xc3 +'Chi ', # 0xc4 +'Chi ', # 0xc5 +'Cui ', # 0xc6 +'Fu ', # 0xc7 +'Xia ', # 0xc8 +'Pen ', # 0xc9 +'Yi ', # 0xca +'La ', # 0xcb +'Yi ', # 0xcc +'Pi ', # 0xcd +'Ling ', # 0xce +'Liu ', # 0xcf +'Zhi ', # 0xd0 +'Qu ', # 0xd1 +'Xi ', # 0xd2 +'Xie ', # 0xd3 +'Xiang ', # 0xd4 +'Xi ', # 0xd5 +'Xi ', # 0xd6 +'Qi ', # 0xd7 +'Qiao ', # 0xd8 +'Hui ', # 0xd9 +'Hui ', # 0xda +'Xiao ', # 0xdb +'Se ', # 0xdc +'Hong ', # 0xdd +'Jiang ', # 0xde +'Di ', # 0xdf +'Cui ', # 0xe0 +'Fei ', # 0xe1 +'Tao ', # 0xe2 +'Sha ', # 0xe3 +'Chi ', # 0xe4 +'Zhu ', # 0xe5 +'Jian ', # 0xe6 +'Xuan ', # 0xe7 +'Shi ', # 0xe8 +'Pian ', # 0xe9 +'Zong ', # 0xea +'Wan ', # 0xeb +'Hui ', # 0xec +'Hou ', # 0xed +'He ', # 0xee +'He ', # 0xef +'Han ', # 0xf0 +'Ao ', # 0xf1 +'Piao ', # 0xf2 +'Yi ', # 0xf3 +'Lian ', # 0xf4 +'Qu ', # 0xf5 +'[?] ', # 0xf6 +'Lin ', # 0xf7 +'Pen ', # 0xf8 +'Qiao ', # 0xf9 +'Ao ', # 0xfa +'Fan ', # 0xfb +'Yi ', # 0xfc +'Hui ', # 0xfd +'Xuan ', # 0xfe +'Dao ', # 0xff +) diff --git a/nstock/modules/unidecode/x080.py b/nstock/modules/unidecode/x080.py new file mode 100644 index 0000000..11f324b --- /dev/null +++ b/nstock/modules/unidecode/x080.py @@ -0,0 +1,258 @@ +data = ( +'Yao ', # 0x00 +'Lao ', # 0x01 +'[?] ', # 0x02 +'Kao ', # 0x03 +'Mao ', # 0x04 +'Zhe ', # 0x05 +'Qi ', # 0x06 +'Gou ', # 0x07 +'Gou ', # 0x08 +'Gou ', # 0x09 +'Die ', # 0x0a +'Die ', # 0x0b +'Er ', # 0x0c +'Shua ', # 0x0d +'Ruan ', # 0x0e +'Er ', # 0x0f +'Nai ', # 0x10 +'Zhuan ', # 0x11 +'Lei ', # 0x12 +'Ting ', # 0x13 +'Zi ', # 0x14 +'Geng ', # 0x15 +'Chao ', # 0x16 +'Hao ', # 0x17 +'Yun ', # 0x18 +'Pa ', # 0x19 +'Pi ', # 0x1a +'Chi ', # 0x1b +'Si ', # 0x1c +'Chu ', # 0x1d +'Jia ', # 0x1e +'Ju ', # 0x1f +'He ', # 0x20 +'Chu ', # 0x21 +'Lao ', # 0x22 +'Lun ', # 0x23 +'Ji ', # 0x24 +'Tang ', # 0x25 +'Ou ', # 0x26 +'Lou ', # 0x27 +'Nou ', # 0x28 +'Gou ', # 0x29 +'Pang ', # 0x2a +'Ze ', # 0x2b +'Lou ', # 0x2c +'Ji ', # 0x2d +'Lao ', # 0x2e +'Huo ', # 0x2f +'You ', # 0x30 +'Mo ', # 0x31 +'Huai ', # 0x32 +'Er ', # 0x33 +'Zhe ', # 0x34 +'Ting ', # 0x35 +'Ye ', # 0x36 +'Da ', # 0x37 +'Song ', # 0x38 +'Qin ', # 0x39 +'Yun ', # 0x3a +'Chi ', # 0x3b +'Dan ', # 0x3c +'Dan ', # 0x3d +'Hong ', # 0x3e +'Geng ', # 0x3f +'Zhi ', # 0x40 +'[?] ', # 0x41 +'Nie ', # 0x42 +'Dan ', # 0x43 +'Zhen ', # 0x44 +'Che ', # 0x45 +'Ling ', # 0x46 +'Zheng ', # 0x47 +'You ', # 0x48 +'Wa ', # 0x49 +'Liao ', # 0x4a +'Long ', # 0x4b +'Zhi ', # 0x4c +'Ning ', # 0x4d +'Tiao ', # 0x4e +'Er ', # 0x4f +'Ya ', # 0x50 +'Die ', # 0x51 +'Gua ', # 0x52 +'[?] ', # 0x53 +'Lian ', # 0x54 +'Hao ', # 0x55 +'Sheng ', # 0x56 +'Lie ', # 0x57 +'Pin ', # 0x58 +'Jing ', # 0x59 +'Ju ', # 0x5a +'Bi ', # 0x5b +'Di ', # 0x5c +'Guo ', # 0x5d +'Wen ', # 0x5e +'Xu ', # 0x5f +'Ping ', # 0x60 +'Cong ', # 0x61 +'Shikato ', # 0x62 +'[?] ', # 0x63 +'Ting ', # 0x64 +'Yu ', # 0x65 +'Cong ', # 0x66 +'Kui ', # 0x67 +'Tsuraneru ', # 0x68 +'Kui ', # 0x69 +'Cong ', # 0x6a +'Lian ', # 0x6b +'Weng ', # 0x6c +'Kui ', # 0x6d +'Lian ', # 0x6e +'Lian ', # 0x6f +'Cong ', # 0x70 +'Ao ', # 0x71 +'Sheng ', # 0x72 +'Song ', # 0x73 +'Ting ', # 0x74 +'Kui ', # 0x75 +'Nie ', # 0x76 +'Zhi ', # 0x77 +'Dan ', # 0x78 +'Ning ', # 0x79 +'Qie ', # 0x7a +'Ji ', # 0x7b +'Ting ', # 0x7c +'Ting ', # 0x7d +'Long ', # 0x7e +'Yu ', # 0x7f +'Yu ', # 0x80 +'Zhao ', # 0x81 +'Si ', # 0x82 +'Su ', # 0x83 +'Yi ', # 0x84 +'Su ', # 0x85 +'Si ', # 0x86 +'Zhao ', # 0x87 +'Zhao ', # 0x88 +'Rou ', # 0x89 +'Yi ', # 0x8a +'Le ', # 0x8b +'Ji ', # 0x8c +'Qiu ', # 0x8d +'Ken ', # 0x8e +'Cao ', # 0x8f +'Ge ', # 0x90 +'Di ', # 0x91 +'Huan ', # 0x92 +'Huang ', # 0x93 +'Yi ', # 0x94 +'Ren ', # 0x95 +'Xiao ', # 0x96 +'Ru ', # 0x97 +'Zhou ', # 0x98 +'Yuan ', # 0x99 +'Du ', # 0x9a +'Gang ', # 0x9b +'Rong ', # 0x9c +'Gan ', # 0x9d +'Cha ', # 0x9e +'Wo ', # 0x9f +'Chang ', # 0xa0 +'Gu ', # 0xa1 +'Zhi ', # 0xa2 +'Han ', # 0xa3 +'Fu ', # 0xa4 +'Fei ', # 0xa5 +'Fen ', # 0xa6 +'Pei ', # 0xa7 +'Pang ', # 0xa8 +'Jian ', # 0xa9 +'Fang ', # 0xaa +'Zhun ', # 0xab +'You ', # 0xac +'Na ', # 0xad +'Hang ', # 0xae +'Ken ', # 0xaf +'Ran ', # 0xb0 +'Gong ', # 0xb1 +'Yu ', # 0xb2 +'Wen ', # 0xb3 +'Yao ', # 0xb4 +'Jin ', # 0xb5 +'Pi ', # 0xb6 +'Qian ', # 0xb7 +'Xi ', # 0xb8 +'Xi ', # 0xb9 +'Fei ', # 0xba +'Ken ', # 0xbb +'Jing ', # 0xbc +'Tai ', # 0xbd +'Shen ', # 0xbe +'Zhong ', # 0xbf +'Zhang ', # 0xc0 +'Xie ', # 0xc1 +'Shen ', # 0xc2 +'Wei ', # 0xc3 +'Zhou ', # 0xc4 +'Die ', # 0xc5 +'Dan ', # 0xc6 +'Fei ', # 0xc7 +'Ba ', # 0xc8 +'Bo ', # 0xc9 +'Qu ', # 0xca +'Tian ', # 0xcb +'Bei ', # 0xcc +'Gua ', # 0xcd +'Tai ', # 0xce +'Zi ', # 0xcf +'Ku ', # 0xd0 +'Zhi ', # 0xd1 +'Ni ', # 0xd2 +'Ping ', # 0xd3 +'Zi ', # 0xd4 +'Fu ', # 0xd5 +'Pang ', # 0xd6 +'Zhen ', # 0xd7 +'Xian ', # 0xd8 +'Zuo ', # 0xd9 +'Pei ', # 0xda +'Jia ', # 0xdb +'Sheng ', # 0xdc +'Zhi ', # 0xdd +'Bao ', # 0xde +'Mu ', # 0xdf +'Qu ', # 0xe0 +'Hu ', # 0xe1 +'Ke ', # 0xe2 +'Yi ', # 0xe3 +'Yin ', # 0xe4 +'Xu ', # 0xe5 +'Yang ', # 0xe6 +'Long ', # 0xe7 +'Dong ', # 0xe8 +'Ka ', # 0xe9 +'Lu ', # 0xea +'Jing ', # 0xeb +'Nu ', # 0xec +'Yan ', # 0xed +'Pang ', # 0xee +'Kua ', # 0xef +'Yi ', # 0xf0 +'Guang ', # 0xf1 +'Gai ', # 0xf2 +'Ge ', # 0xf3 +'Dong ', # 0xf4 +'Zhi ', # 0xf5 +'Xiao ', # 0xf6 +'Xiong ', # 0xf7 +'Xiong ', # 0xf8 +'Er ', # 0xf9 +'E ', # 0xfa +'Xing ', # 0xfb +'Pian ', # 0xfc +'Neng ', # 0xfd +'Zi ', # 0xfe +'Gui ', # 0xff +) diff --git a/nstock/modules/unidecode/x081.py b/nstock/modules/unidecode/x081.py new file mode 100644 index 0000000..01ca95d --- /dev/null +++ b/nstock/modules/unidecode/x081.py @@ -0,0 +1,258 @@ +data = ( +'Cheng ', # 0x00 +'Tiao ', # 0x01 +'Zhi ', # 0x02 +'Cui ', # 0x03 +'Mei ', # 0x04 +'Xie ', # 0x05 +'Cui ', # 0x06 +'Xie ', # 0x07 +'Mo ', # 0x08 +'Mai ', # 0x09 +'Ji ', # 0x0a +'Obiyaakasu ', # 0x0b +'[?] ', # 0x0c +'Kuai ', # 0x0d +'Sa ', # 0x0e +'Zang ', # 0x0f +'Qi ', # 0x10 +'Nao ', # 0x11 +'Mi ', # 0x12 +'Nong ', # 0x13 +'Luan ', # 0x14 +'Wan ', # 0x15 +'Bo ', # 0x16 +'Wen ', # 0x17 +'Guan ', # 0x18 +'Qiu ', # 0x19 +'Jiao ', # 0x1a +'Jing ', # 0x1b +'Rou ', # 0x1c +'Heng ', # 0x1d +'Cuo ', # 0x1e +'Lie ', # 0x1f +'Shan ', # 0x20 +'Ting ', # 0x21 +'Mei ', # 0x22 +'Chun ', # 0x23 +'Shen ', # 0x24 +'Xie ', # 0x25 +'De ', # 0x26 +'Zui ', # 0x27 +'Cu ', # 0x28 +'Xiu ', # 0x29 +'Xin ', # 0x2a +'Tuo ', # 0x2b +'Pao ', # 0x2c +'Cheng ', # 0x2d +'Nei ', # 0x2e +'Fu ', # 0x2f +'Dou ', # 0x30 +'Tuo ', # 0x31 +'Niao ', # 0x32 +'Noy ', # 0x33 +'Pi ', # 0x34 +'Gu ', # 0x35 +'Gua ', # 0x36 +'Li ', # 0x37 +'Lian ', # 0x38 +'Zhang ', # 0x39 +'Cui ', # 0x3a +'Jie ', # 0x3b +'Liang ', # 0x3c +'Zhou ', # 0x3d +'Pi ', # 0x3e +'Biao ', # 0x3f +'Lun ', # 0x40 +'Pian ', # 0x41 +'Guo ', # 0x42 +'Kui ', # 0x43 +'Chui ', # 0x44 +'Dan ', # 0x45 +'Tian ', # 0x46 +'Nei ', # 0x47 +'Jing ', # 0x48 +'Jie ', # 0x49 +'La ', # 0x4a +'Yi ', # 0x4b +'An ', # 0x4c +'Ren ', # 0x4d +'Shen ', # 0x4e +'Chuo ', # 0x4f +'Fu ', # 0x50 +'Fu ', # 0x51 +'Ju ', # 0x52 +'Fei ', # 0x53 +'Qiang ', # 0x54 +'Wan ', # 0x55 +'Dong ', # 0x56 +'Pi ', # 0x57 +'Guo ', # 0x58 +'Zong ', # 0x59 +'Ding ', # 0x5a +'Wu ', # 0x5b +'Mei ', # 0x5c +'Ruan ', # 0x5d +'Zhuan ', # 0x5e +'Zhi ', # 0x5f +'Cou ', # 0x60 +'Gua ', # 0x61 +'Ou ', # 0x62 +'Di ', # 0x63 +'An ', # 0x64 +'Xing ', # 0x65 +'Nao ', # 0x66 +'Yu ', # 0x67 +'Chuan ', # 0x68 +'Nan ', # 0x69 +'Yun ', # 0x6a +'Zhong ', # 0x6b +'Rou ', # 0x6c +'E ', # 0x6d +'Sai ', # 0x6e +'Tu ', # 0x6f +'Yao ', # 0x70 +'Jian ', # 0x71 +'Wei ', # 0x72 +'Jiao ', # 0x73 +'Yu ', # 0x74 +'Jia ', # 0x75 +'Duan ', # 0x76 +'Bi ', # 0x77 +'Chang ', # 0x78 +'Fu ', # 0x79 +'Xian ', # 0x7a +'Ni ', # 0x7b +'Mian ', # 0x7c +'Wa ', # 0x7d +'Teng ', # 0x7e +'Tui ', # 0x7f +'Bang ', # 0x80 +'Qian ', # 0x81 +'Lu ', # 0x82 +'Wa ', # 0x83 +'Sou ', # 0x84 +'Tang ', # 0x85 +'Su ', # 0x86 +'Zhui ', # 0x87 +'Ge ', # 0x88 +'Yi ', # 0x89 +'Bo ', # 0x8a +'Liao ', # 0x8b +'Ji ', # 0x8c +'Pi ', # 0x8d +'Xie ', # 0x8e +'Gao ', # 0x8f +'Lu ', # 0x90 +'Bin ', # 0x91 +'Ou ', # 0x92 +'Chang ', # 0x93 +'Lu ', # 0x94 +'Guo ', # 0x95 +'Pang ', # 0x96 +'Chuai ', # 0x97 +'Piao ', # 0x98 +'Jiang ', # 0x99 +'Fu ', # 0x9a +'Tang ', # 0x9b +'Mo ', # 0x9c +'Xi ', # 0x9d +'Zhuan ', # 0x9e +'Lu ', # 0x9f +'Jiao ', # 0xa0 +'Ying ', # 0xa1 +'Lu ', # 0xa2 +'Zhi ', # 0xa3 +'Tara ', # 0xa4 +'Chun ', # 0xa5 +'Lian ', # 0xa6 +'Tong ', # 0xa7 +'Peng ', # 0xa8 +'Ni ', # 0xa9 +'Zha ', # 0xaa +'Liao ', # 0xab +'Cui ', # 0xac +'Gui ', # 0xad +'Xiao ', # 0xae +'Teng ', # 0xaf +'Fan ', # 0xb0 +'Zhi ', # 0xb1 +'Jiao ', # 0xb2 +'Shan ', # 0xb3 +'Wu ', # 0xb4 +'Cui ', # 0xb5 +'Run ', # 0xb6 +'Xiang ', # 0xb7 +'Sui ', # 0xb8 +'Fen ', # 0xb9 +'Ying ', # 0xba +'Tan ', # 0xbb +'Zhua ', # 0xbc +'Dan ', # 0xbd +'Kuai ', # 0xbe +'Nong ', # 0xbf +'Tun ', # 0xc0 +'Lian ', # 0xc1 +'Bi ', # 0xc2 +'Yong ', # 0xc3 +'Jue ', # 0xc4 +'Chu ', # 0xc5 +'Yi ', # 0xc6 +'Juan ', # 0xc7 +'La ', # 0xc8 +'Lian ', # 0xc9 +'Sao ', # 0xca +'Tun ', # 0xcb +'Gu ', # 0xcc +'Qi ', # 0xcd +'Cui ', # 0xce +'Bin ', # 0xcf +'Xun ', # 0xd0 +'Ru ', # 0xd1 +'Huo ', # 0xd2 +'Zang ', # 0xd3 +'Xian ', # 0xd4 +'Biao ', # 0xd5 +'Xing ', # 0xd6 +'Kuan ', # 0xd7 +'La ', # 0xd8 +'Yan ', # 0xd9 +'Lu ', # 0xda +'Huo ', # 0xdb +'Zang ', # 0xdc +'Luo ', # 0xdd +'Qu ', # 0xde +'Zang ', # 0xdf +'Luan ', # 0xe0 +'Ni ', # 0xe1 +'Zang ', # 0xe2 +'Chen ', # 0xe3 +'Qian ', # 0xe4 +'Wo ', # 0xe5 +'Guang ', # 0xe6 +'Zang ', # 0xe7 +'Lin ', # 0xe8 +'Guang ', # 0xe9 +'Zi ', # 0xea +'Jiao ', # 0xeb +'Nie ', # 0xec +'Chou ', # 0xed +'Ji ', # 0xee +'Gao ', # 0xef +'Chou ', # 0xf0 +'Mian ', # 0xf1 +'Nie ', # 0xf2 +'Zhi ', # 0xf3 +'Zhi ', # 0xf4 +'Ge ', # 0xf5 +'Jian ', # 0xf6 +'Die ', # 0xf7 +'Zhi ', # 0xf8 +'Xiu ', # 0xf9 +'Tai ', # 0xfa +'Zhen ', # 0xfb +'Jiu ', # 0xfc +'Xian ', # 0xfd +'Yu ', # 0xfe +'Cha ', # 0xff +) diff --git a/nstock/modules/unidecode/x082.py b/nstock/modules/unidecode/x082.py new file mode 100644 index 0000000..daea2e2 --- /dev/null +++ b/nstock/modules/unidecode/x082.py @@ -0,0 +1,258 @@ +data = ( +'Yao ', # 0x00 +'Yu ', # 0x01 +'Chong ', # 0x02 +'Xi ', # 0x03 +'Xi ', # 0x04 +'Jiu ', # 0x05 +'Yu ', # 0x06 +'Yu ', # 0x07 +'Xing ', # 0x08 +'Ju ', # 0x09 +'Jiu ', # 0x0a +'Xin ', # 0x0b +'She ', # 0x0c +'She ', # 0x0d +'Yadoru ', # 0x0e +'Jiu ', # 0x0f +'Shi ', # 0x10 +'Tan ', # 0x11 +'Shu ', # 0x12 +'Shi ', # 0x13 +'Tian ', # 0x14 +'Dan ', # 0x15 +'Pu ', # 0x16 +'Pu ', # 0x17 +'Guan ', # 0x18 +'Hua ', # 0x19 +'Tan ', # 0x1a +'Chuan ', # 0x1b +'Shun ', # 0x1c +'Xia ', # 0x1d +'Wu ', # 0x1e +'Zhou ', # 0x1f +'Dao ', # 0x20 +'Gang ', # 0x21 +'Shan ', # 0x22 +'Yi ', # 0x23 +'[?] ', # 0x24 +'Pa ', # 0x25 +'Tai ', # 0x26 +'Fan ', # 0x27 +'Ban ', # 0x28 +'Chuan ', # 0x29 +'Hang ', # 0x2a +'Fang ', # 0x2b +'Ban ', # 0x2c +'Que ', # 0x2d +'Hesaki ', # 0x2e +'Zhong ', # 0x2f +'Jian ', # 0x30 +'Cang ', # 0x31 +'Ling ', # 0x32 +'Zhu ', # 0x33 +'Ze ', # 0x34 +'Duo ', # 0x35 +'Bo ', # 0x36 +'Xian ', # 0x37 +'Ge ', # 0x38 +'Chuan ', # 0x39 +'Jia ', # 0x3a +'Lu ', # 0x3b +'Hong ', # 0x3c +'Pang ', # 0x3d +'Xi ', # 0x3e +'[?] ', # 0x3f +'Fu ', # 0x40 +'Zao ', # 0x41 +'Feng ', # 0x42 +'Li ', # 0x43 +'Shao ', # 0x44 +'Yu ', # 0x45 +'Lang ', # 0x46 +'Ting ', # 0x47 +'[?] ', # 0x48 +'Wei ', # 0x49 +'Bo ', # 0x4a +'Meng ', # 0x4b +'Nian ', # 0x4c +'Ju ', # 0x4d +'Huang ', # 0x4e +'Shou ', # 0x4f +'Zong ', # 0x50 +'Bian ', # 0x51 +'Mao ', # 0x52 +'Die ', # 0x53 +'[?] ', # 0x54 +'Bang ', # 0x55 +'Cha ', # 0x56 +'Yi ', # 0x57 +'Sao ', # 0x58 +'Cang ', # 0x59 +'Cao ', # 0x5a +'Lou ', # 0x5b +'Dai ', # 0x5c +'Sori ', # 0x5d +'Yao ', # 0x5e +'Tong ', # 0x5f +'Yofune ', # 0x60 +'Dang ', # 0x61 +'Tan ', # 0x62 +'Lu ', # 0x63 +'Yi ', # 0x64 +'Jie ', # 0x65 +'Jian ', # 0x66 +'Huo ', # 0x67 +'Meng ', # 0x68 +'Qi ', # 0x69 +'Lu ', # 0x6a +'Lu ', # 0x6b +'Chan ', # 0x6c +'Shuang ', # 0x6d +'Gen ', # 0x6e +'Liang ', # 0x6f +'Jian ', # 0x70 +'Jian ', # 0x71 +'Se ', # 0x72 +'Yan ', # 0x73 +'Fu ', # 0x74 +'Ping ', # 0x75 +'Yan ', # 0x76 +'Yan ', # 0x77 +'Cao ', # 0x78 +'Cao ', # 0x79 +'Yi ', # 0x7a +'Le ', # 0x7b +'Ting ', # 0x7c +'Qiu ', # 0x7d +'Ai ', # 0x7e +'Nai ', # 0x7f +'Tiao ', # 0x80 +'Jiao ', # 0x81 +'Jie ', # 0x82 +'Peng ', # 0x83 +'Wan ', # 0x84 +'Yi ', # 0x85 +'Chai ', # 0x86 +'Mian ', # 0x87 +'Mie ', # 0x88 +'Gan ', # 0x89 +'Qian ', # 0x8a +'Yu ', # 0x8b +'Yu ', # 0x8c +'Shuo ', # 0x8d +'Qiong ', # 0x8e +'Tu ', # 0x8f +'Xia ', # 0x90 +'Qi ', # 0x91 +'Mang ', # 0x92 +'Zi ', # 0x93 +'Hui ', # 0x94 +'Sui ', # 0x95 +'Zhi ', # 0x96 +'Xiang ', # 0x97 +'Bi ', # 0x98 +'Fu ', # 0x99 +'Tun ', # 0x9a +'Wei ', # 0x9b +'Wu ', # 0x9c +'Zhi ', # 0x9d +'Qi ', # 0x9e +'Shan ', # 0x9f +'Wen ', # 0xa0 +'Qian ', # 0xa1 +'Ren ', # 0xa2 +'Fou ', # 0xa3 +'Kou ', # 0xa4 +'Jie ', # 0xa5 +'Lu ', # 0xa6 +'Xu ', # 0xa7 +'Ji ', # 0xa8 +'Qin ', # 0xa9 +'Qi ', # 0xaa +'Yuan ', # 0xab +'Fen ', # 0xac +'Ba ', # 0xad +'Rui ', # 0xae +'Xin ', # 0xaf +'Ji ', # 0xb0 +'Hua ', # 0xb1 +'Hua ', # 0xb2 +'Fang ', # 0xb3 +'Wu ', # 0xb4 +'Jue ', # 0xb5 +'Gou ', # 0xb6 +'Zhi ', # 0xb7 +'Yun ', # 0xb8 +'Qin ', # 0xb9 +'Ao ', # 0xba +'Chu ', # 0xbb +'Mao ', # 0xbc +'Ya ', # 0xbd +'Fei ', # 0xbe +'Reng ', # 0xbf +'Hang ', # 0xc0 +'Cong ', # 0xc1 +'Yin ', # 0xc2 +'You ', # 0xc3 +'Bian ', # 0xc4 +'Yi ', # 0xc5 +'Susa ', # 0xc6 +'Wei ', # 0xc7 +'Li ', # 0xc8 +'Pi ', # 0xc9 +'E ', # 0xca +'Xian ', # 0xcb +'Chang ', # 0xcc +'Cang ', # 0xcd +'Meng ', # 0xce +'Su ', # 0xcf +'Yi ', # 0xd0 +'Yuan ', # 0xd1 +'Ran ', # 0xd2 +'Ling ', # 0xd3 +'Tai ', # 0xd4 +'Tiao ', # 0xd5 +'Di ', # 0xd6 +'Miao ', # 0xd7 +'Qiong ', # 0xd8 +'Li ', # 0xd9 +'Yong ', # 0xda +'Ke ', # 0xdb +'Mu ', # 0xdc +'Pei ', # 0xdd +'Bao ', # 0xde +'Gou ', # 0xdf +'Min ', # 0xe0 +'Yi ', # 0xe1 +'Yi ', # 0xe2 +'Ju ', # 0xe3 +'Pi ', # 0xe4 +'Ruo ', # 0xe5 +'Ku ', # 0xe6 +'Zhu ', # 0xe7 +'Ni ', # 0xe8 +'Bo ', # 0xe9 +'Bing ', # 0xea +'Shan ', # 0xeb +'Qiu ', # 0xec +'Yao ', # 0xed +'Xian ', # 0xee +'Ben ', # 0xef +'Hong ', # 0xf0 +'Ying ', # 0xf1 +'Zha ', # 0xf2 +'Dong ', # 0xf3 +'Ju ', # 0xf4 +'Die ', # 0xf5 +'Nie ', # 0xf6 +'Gan ', # 0xf7 +'Hu ', # 0xf8 +'Ping ', # 0xf9 +'Mei ', # 0xfa +'Fu ', # 0xfb +'Sheng ', # 0xfc +'Gu ', # 0xfd +'Bi ', # 0xfe +'Wei ', # 0xff +) diff --git a/nstock/modules/unidecode/x083.py b/nstock/modules/unidecode/x083.py new file mode 100644 index 0000000..672cd5d --- /dev/null +++ b/nstock/modules/unidecode/x083.py @@ -0,0 +1,258 @@ +data = ( +'Fu ', # 0x00 +'Zhuo ', # 0x01 +'Mao ', # 0x02 +'Fan ', # 0x03 +'Qie ', # 0x04 +'Mao ', # 0x05 +'Mao ', # 0x06 +'Ba ', # 0x07 +'Zi ', # 0x08 +'Mo ', # 0x09 +'Zi ', # 0x0a +'Di ', # 0x0b +'Chi ', # 0x0c +'Ji ', # 0x0d +'Jing ', # 0x0e +'Long ', # 0x0f +'[?] ', # 0x10 +'Niao ', # 0x11 +'[?] ', # 0x12 +'Xue ', # 0x13 +'Ying ', # 0x14 +'Qiong ', # 0x15 +'Ge ', # 0x16 +'Ming ', # 0x17 +'Li ', # 0x18 +'Rong ', # 0x19 +'Yin ', # 0x1a +'Gen ', # 0x1b +'Qian ', # 0x1c +'Chai ', # 0x1d +'Chen ', # 0x1e +'Yu ', # 0x1f +'Xiu ', # 0x20 +'Zi ', # 0x21 +'Lie ', # 0x22 +'Wu ', # 0x23 +'Ji ', # 0x24 +'Kui ', # 0x25 +'Ce ', # 0x26 +'Chong ', # 0x27 +'Ci ', # 0x28 +'Gou ', # 0x29 +'Guang ', # 0x2a +'Mang ', # 0x2b +'Chi ', # 0x2c +'Jiao ', # 0x2d +'Jiao ', # 0x2e +'Fu ', # 0x2f +'Yu ', # 0x30 +'Zhu ', # 0x31 +'Zi ', # 0x32 +'Jiang ', # 0x33 +'Hui ', # 0x34 +'Yin ', # 0x35 +'Cha ', # 0x36 +'Fa ', # 0x37 +'Rong ', # 0x38 +'Ru ', # 0x39 +'Chong ', # 0x3a +'Mang ', # 0x3b +'Tong ', # 0x3c +'Zhong ', # 0x3d +'[?] ', # 0x3e +'Zhu ', # 0x3f +'Xun ', # 0x40 +'Huan ', # 0x41 +'Kua ', # 0x42 +'Quan ', # 0x43 +'Gai ', # 0x44 +'Da ', # 0x45 +'Jing ', # 0x46 +'Xing ', # 0x47 +'Quan ', # 0x48 +'Cao ', # 0x49 +'Jing ', # 0x4a +'Er ', # 0x4b +'An ', # 0x4c +'Shou ', # 0x4d +'Chi ', # 0x4e +'Ren ', # 0x4f +'Jian ', # 0x50 +'Ti ', # 0x51 +'Huang ', # 0x52 +'Ping ', # 0x53 +'Li ', # 0x54 +'Jin ', # 0x55 +'Lao ', # 0x56 +'Shu ', # 0x57 +'Zhuang ', # 0x58 +'Da ', # 0x59 +'Jia ', # 0x5a +'Rao ', # 0x5b +'Bi ', # 0x5c +'Ze ', # 0x5d +'Qiao ', # 0x5e +'Hui ', # 0x5f +'Qi ', # 0x60 +'Dang ', # 0x61 +'[?] ', # 0x62 +'Rong ', # 0x63 +'Hun ', # 0x64 +'Ying ', # 0x65 +'Luo ', # 0x66 +'Ying ', # 0x67 +'Xun ', # 0x68 +'Jin ', # 0x69 +'Sun ', # 0x6a +'Yin ', # 0x6b +'Mai ', # 0x6c +'Hong ', # 0x6d +'Zhou ', # 0x6e +'Yao ', # 0x6f +'Du ', # 0x70 +'Wei ', # 0x71 +'Chu ', # 0x72 +'Dou ', # 0x73 +'Fu ', # 0x74 +'Ren ', # 0x75 +'Yin ', # 0x76 +'He ', # 0x77 +'Bi ', # 0x78 +'Bu ', # 0x79 +'Yun ', # 0x7a +'Di ', # 0x7b +'Tu ', # 0x7c +'Sui ', # 0x7d +'Sui ', # 0x7e +'Cheng ', # 0x7f +'Chen ', # 0x80 +'Wu ', # 0x81 +'Bie ', # 0x82 +'Xi ', # 0x83 +'Geng ', # 0x84 +'Li ', # 0x85 +'Fu ', # 0x86 +'Zhu ', # 0x87 +'Mo ', # 0x88 +'Li ', # 0x89 +'Zhuang ', # 0x8a +'Ji ', # 0x8b +'Duo ', # 0x8c +'Qiu ', # 0x8d +'Sha ', # 0x8e +'Suo ', # 0x8f +'Chen ', # 0x90 +'Feng ', # 0x91 +'Ju ', # 0x92 +'Mei ', # 0x93 +'Meng ', # 0x94 +'Xing ', # 0x95 +'Jing ', # 0x96 +'Che ', # 0x97 +'Xin ', # 0x98 +'Jun ', # 0x99 +'Yan ', # 0x9a +'Ting ', # 0x9b +'Diao ', # 0x9c +'Cuo ', # 0x9d +'Wan ', # 0x9e +'Han ', # 0x9f +'You ', # 0xa0 +'Cuo ', # 0xa1 +'Jia ', # 0xa2 +'Wang ', # 0xa3 +'You ', # 0xa4 +'Niu ', # 0xa5 +'Shao ', # 0xa6 +'Xian ', # 0xa7 +'Lang ', # 0xa8 +'Fu ', # 0xa9 +'E ', # 0xaa +'Mo ', # 0xab +'Wen ', # 0xac +'Jie ', # 0xad +'Nan ', # 0xae +'Mu ', # 0xaf +'Kan ', # 0xb0 +'Lai ', # 0xb1 +'Lian ', # 0xb2 +'Shi ', # 0xb3 +'Wo ', # 0xb4 +'Usagi ', # 0xb5 +'Lian ', # 0xb6 +'Huo ', # 0xb7 +'You ', # 0xb8 +'Ying ', # 0xb9 +'Ying ', # 0xba +'Nuc ', # 0xbb +'Chun ', # 0xbc +'Mang ', # 0xbd +'Mang ', # 0xbe +'Ci ', # 0xbf +'Wan ', # 0xc0 +'Jing ', # 0xc1 +'Di ', # 0xc2 +'Qu ', # 0xc3 +'Dong ', # 0xc4 +'Jian ', # 0xc5 +'Zou ', # 0xc6 +'Gu ', # 0xc7 +'La ', # 0xc8 +'Lu ', # 0xc9 +'Ju ', # 0xca +'Wei ', # 0xcb +'Jun ', # 0xcc +'Nie ', # 0xcd +'Kun ', # 0xce +'He ', # 0xcf +'Pu ', # 0xd0 +'Zi ', # 0xd1 +'Gao ', # 0xd2 +'Guo ', # 0xd3 +'Fu ', # 0xd4 +'Lun ', # 0xd5 +'Chang ', # 0xd6 +'Chou ', # 0xd7 +'Song ', # 0xd8 +'Chui ', # 0xd9 +'Zhan ', # 0xda +'Men ', # 0xdb +'Cai ', # 0xdc +'Ba ', # 0xdd +'Li ', # 0xde +'Tu ', # 0xdf +'Bo ', # 0xe0 +'Han ', # 0xe1 +'Bao ', # 0xe2 +'Qin ', # 0xe3 +'Juan ', # 0xe4 +'Xi ', # 0xe5 +'Qin ', # 0xe6 +'Di ', # 0xe7 +'Jie ', # 0xe8 +'Pu ', # 0xe9 +'Dang ', # 0xea +'Jin ', # 0xeb +'Zhao ', # 0xec +'Tai ', # 0xed +'Geng ', # 0xee +'Hua ', # 0xef +'Gu ', # 0xf0 +'Ling ', # 0xf1 +'Fei ', # 0xf2 +'Jin ', # 0xf3 +'An ', # 0xf4 +'Wang ', # 0xf5 +'Beng ', # 0xf6 +'Zhou ', # 0xf7 +'Yan ', # 0xf8 +'Ju ', # 0xf9 +'Jian ', # 0xfa +'Lin ', # 0xfb +'Tan ', # 0xfc +'Shu ', # 0xfd +'Tian ', # 0xfe +'Dao ', # 0xff +) diff --git a/nstock/modules/unidecode/x084.py b/nstock/modules/unidecode/x084.py new file mode 100644 index 0000000..571a360 --- /dev/null +++ b/nstock/modules/unidecode/x084.py @@ -0,0 +1,258 @@ +data = ( +'Hu ', # 0x00 +'Qi ', # 0x01 +'He ', # 0x02 +'Cui ', # 0x03 +'Tao ', # 0x04 +'Chun ', # 0x05 +'Bei ', # 0x06 +'Chang ', # 0x07 +'Huan ', # 0x08 +'Fei ', # 0x09 +'Lai ', # 0x0a +'Qi ', # 0x0b +'Meng ', # 0x0c +'Ping ', # 0x0d +'Wei ', # 0x0e +'Dan ', # 0x0f +'Sha ', # 0x10 +'Huan ', # 0x11 +'Yan ', # 0x12 +'Yi ', # 0x13 +'Tiao ', # 0x14 +'Qi ', # 0x15 +'Wan ', # 0x16 +'Ce ', # 0x17 +'Nai ', # 0x18 +'Kutabireru ', # 0x19 +'Tuo ', # 0x1a +'Jiu ', # 0x1b +'Tie ', # 0x1c +'Luo ', # 0x1d +'[?] ', # 0x1e +'[?] ', # 0x1f +'Meng ', # 0x20 +'[?] ', # 0x21 +'Yaji ', # 0x22 +'[?] ', # 0x23 +'Ying ', # 0x24 +'Ying ', # 0x25 +'Ying ', # 0x26 +'Xiao ', # 0x27 +'Sa ', # 0x28 +'Qiu ', # 0x29 +'Ke ', # 0x2a +'Xiang ', # 0x2b +'Wan ', # 0x2c +'Yu ', # 0x2d +'Yu ', # 0x2e +'Fu ', # 0x2f +'Lian ', # 0x30 +'Xuan ', # 0x31 +'Yuan ', # 0x32 +'Nan ', # 0x33 +'Ze ', # 0x34 +'Wo ', # 0x35 +'Chun ', # 0x36 +'Xiao ', # 0x37 +'Yu ', # 0x38 +'Pian ', # 0x39 +'Mao ', # 0x3a +'An ', # 0x3b +'E ', # 0x3c +'Luo ', # 0x3d +'Ying ', # 0x3e +'Huo ', # 0x3f +'Gua ', # 0x40 +'Jiang ', # 0x41 +'Mian ', # 0x42 +'Zuo ', # 0x43 +'Zuo ', # 0x44 +'Ju ', # 0x45 +'Bao ', # 0x46 +'Rou ', # 0x47 +'Xi ', # 0x48 +'Xie ', # 0x49 +'An ', # 0x4a +'Qu ', # 0x4b +'Jian ', # 0x4c +'Fu ', # 0x4d +'Lu ', # 0x4e +'Jing ', # 0x4f +'Pen ', # 0x50 +'Feng ', # 0x51 +'Hong ', # 0x52 +'Hong ', # 0x53 +'Hou ', # 0x54 +'Yan ', # 0x55 +'Tu ', # 0x56 +'Zhu ', # 0x57 +'Zi ', # 0x58 +'Xiang ', # 0x59 +'Shen ', # 0x5a +'Ge ', # 0x5b +'Jie ', # 0x5c +'Jing ', # 0x5d +'Mi ', # 0x5e +'Huang ', # 0x5f +'Shen ', # 0x60 +'Pu ', # 0x61 +'Gai ', # 0x62 +'Dong ', # 0x63 +'Zhou ', # 0x64 +'Qian ', # 0x65 +'Wei ', # 0x66 +'Bo ', # 0x67 +'Wei ', # 0x68 +'Pa ', # 0x69 +'Ji ', # 0x6a +'Hu ', # 0x6b +'Zang ', # 0x6c +'Jia ', # 0x6d +'Duan ', # 0x6e +'Yao ', # 0x6f +'Jun ', # 0x70 +'Cong ', # 0x71 +'Quan ', # 0x72 +'Wei ', # 0x73 +'Xian ', # 0x74 +'Kui ', # 0x75 +'Ting ', # 0x76 +'Hun ', # 0x77 +'Xi ', # 0x78 +'Shi ', # 0x79 +'Qi ', # 0x7a +'Lan ', # 0x7b +'Zong ', # 0x7c +'Yao ', # 0x7d +'Yuan ', # 0x7e +'Mei ', # 0x7f +'Yun ', # 0x80 +'Shu ', # 0x81 +'Di ', # 0x82 +'Zhuan ', # 0x83 +'Guan ', # 0x84 +'Sukumo ', # 0x85 +'Xue ', # 0x86 +'Chan ', # 0x87 +'Kai ', # 0x88 +'Kui ', # 0x89 +'[?] ', # 0x8a +'Jiang ', # 0x8b +'Lou ', # 0x8c +'Wei ', # 0x8d +'Pai ', # 0x8e +'[?] ', # 0x8f +'Sou ', # 0x90 +'Yin ', # 0x91 +'Shi ', # 0x92 +'Chun ', # 0x93 +'Shi ', # 0x94 +'Yun ', # 0x95 +'Zhen ', # 0x96 +'Lang ', # 0x97 +'Nu ', # 0x98 +'Meng ', # 0x99 +'He ', # 0x9a +'Que ', # 0x9b +'Suan ', # 0x9c +'Yuan ', # 0x9d +'Li ', # 0x9e +'Ju ', # 0x9f +'Xi ', # 0xa0 +'Pang ', # 0xa1 +'Chu ', # 0xa2 +'Xu ', # 0xa3 +'Tu ', # 0xa4 +'Liu ', # 0xa5 +'Wo ', # 0xa6 +'Zhen ', # 0xa7 +'Qian ', # 0xa8 +'Zu ', # 0xa9 +'Po ', # 0xaa +'Cuo ', # 0xab +'Yuan ', # 0xac +'Chu ', # 0xad +'Yu ', # 0xae +'Kuai ', # 0xaf +'Pan ', # 0xb0 +'Pu ', # 0xb1 +'Pu ', # 0xb2 +'Na ', # 0xb3 +'Shuo ', # 0xb4 +'Xi ', # 0xb5 +'Fen ', # 0xb6 +'Yun ', # 0xb7 +'Zheng ', # 0xb8 +'Jian ', # 0xb9 +'Ji ', # 0xba +'Ruo ', # 0xbb +'Cang ', # 0xbc +'En ', # 0xbd +'Mi ', # 0xbe +'Hao ', # 0xbf +'Sun ', # 0xc0 +'Zhen ', # 0xc1 +'Ming ', # 0xc2 +'Sou ', # 0xc3 +'Xu ', # 0xc4 +'Liu ', # 0xc5 +'Xi ', # 0xc6 +'Gu ', # 0xc7 +'Lang ', # 0xc8 +'Rong ', # 0xc9 +'Weng ', # 0xca +'Gai ', # 0xcb +'Cuo ', # 0xcc +'Shi ', # 0xcd +'Tang ', # 0xce +'Luo ', # 0xcf +'Ru ', # 0xd0 +'Suo ', # 0xd1 +'Xian ', # 0xd2 +'Bei ', # 0xd3 +'Yao ', # 0xd4 +'Gui ', # 0xd5 +'Bi ', # 0xd6 +'Zong ', # 0xd7 +'Gun ', # 0xd8 +'Za ', # 0xd9 +'Xiu ', # 0xda +'Ce ', # 0xdb +'Hai ', # 0xdc +'Lan ', # 0xdd +'[?] ', # 0xde +'Ji ', # 0xdf +'Li ', # 0xe0 +'Can ', # 0xe1 +'Lang ', # 0xe2 +'Yu ', # 0xe3 +'[?] ', # 0xe4 +'Ying ', # 0xe5 +'Mo ', # 0xe6 +'Diao ', # 0xe7 +'Tiao ', # 0xe8 +'Mao ', # 0xe9 +'Tong ', # 0xea +'Zhu ', # 0xeb +'Peng ', # 0xec +'An ', # 0xed +'Lian ', # 0xee +'Cong ', # 0xef +'Xi ', # 0xf0 +'Ping ', # 0xf1 +'Qiu ', # 0xf2 +'Jin ', # 0xf3 +'Chun ', # 0xf4 +'Jie ', # 0xf5 +'Wei ', # 0xf6 +'Tui ', # 0xf7 +'Cao ', # 0xf8 +'Yu ', # 0xf9 +'Yi ', # 0xfa +'Ji ', # 0xfb +'Liao ', # 0xfc +'Bi ', # 0xfd +'Lu ', # 0xfe +'Su ', # 0xff +) diff --git a/nstock/modules/unidecode/x085.py b/nstock/modules/unidecode/x085.py new file mode 100644 index 0000000..c11c513 --- /dev/null +++ b/nstock/modules/unidecode/x085.py @@ -0,0 +1,258 @@ +data = ( +'Bu ', # 0x00 +'Zhang ', # 0x01 +'Luo ', # 0x02 +'Jiang ', # 0x03 +'Man ', # 0x04 +'Yan ', # 0x05 +'Ling ', # 0x06 +'Ji ', # 0x07 +'Piao ', # 0x08 +'Gun ', # 0x09 +'Han ', # 0x0a +'Di ', # 0x0b +'Su ', # 0x0c +'Lu ', # 0x0d +'She ', # 0x0e +'Shang ', # 0x0f +'Di ', # 0x10 +'Mie ', # 0x11 +'Xun ', # 0x12 +'Man ', # 0x13 +'Bo ', # 0x14 +'Di ', # 0x15 +'Cuo ', # 0x16 +'Zhe ', # 0x17 +'Sen ', # 0x18 +'Xuan ', # 0x19 +'Wei ', # 0x1a +'Hu ', # 0x1b +'Ao ', # 0x1c +'Mi ', # 0x1d +'Lou ', # 0x1e +'Cu ', # 0x1f +'Zhong ', # 0x20 +'Cai ', # 0x21 +'Po ', # 0x22 +'Jiang ', # 0x23 +'Mi ', # 0x24 +'Cong ', # 0x25 +'Niao ', # 0x26 +'Hui ', # 0x27 +'Jun ', # 0x28 +'Yin ', # 0x29 +'Jian ', # 0x2a +'Yan ', # 0x2b +'Shu ', # 0x2c +'Yin ', # 0x2d +'Kui ', # 0x2e +'Chen ', # 0x2f +'Hu ', # 0x30 +'Sha ', # 0x31 +'Kou ', # 0x32 +'Qian ', # 0x33 +'Ma ', # 0x34 +'Zang ', # 0x35 +'Sonoko ', # 0x36 +'Qiang ', # 0x37 +'Dou ', # 0x38 +'Lian ', # 0x39 +'Lin ', # 0x3a +'Kou ', # 0x3b +'Ai ', # 0x3c +'Bi ', # 0x3d +'Li ', # 0x3e +'Wei ', # 0x3f +'Ji ', # 0x40 +'Xun ', # 0x41 +'Sheng ', # 0x42 +'Fan ', # 0x43 +'Meng ', # 0x44 +'Ou ', # 0x45 +'Chan ', # 0x46 +'Dian ', # 0x47 +'Xun ', # 0x48 +'Jiao ', # 0x49 +'Rui ', # 0x4a +'Rui ', # 0x4b +'Lei ', # 0x4c +'Yu ', # 0x4d +'Qiao ', # 0x4e +'Chu ', # 0x4f +'Hua ', # 0x50 +'Jian ', # 0x51 +'Mai ', # 0x52 +'Yun ', # 0x53 +'Bao ', # 0x54 +'You ', # 0x55 +'Qu ', # 0x56 +'Lu ', # 0x57 +'Rao ', # 0x58 +'Hui ', # 0x59 +'E ', # 0x5a +'Teng ', # 0x5b +'Fei ', # 0x5c +'Jue ', # 0x5d +'Zui ', # 0x5e +'Fa ', # 0x5f +'Ru ', # 0x60 +'Fen ', # 0x61 +'Kui ', # 0x62 +'Shun ', # 0x63 +'Rui ', # 0x64 +'Ya ', # 0x65 +'Xu ', # 0x66 +'Fu ', # 0x67 +'Jue ', # 0x68 +'Dang ', # 0x69 +'Wu ', # 0x6a +'Tong ', # 0x6b +'Si ', # 0x6c +'Xiao ', # 0x6d +'Xi ', # 0x6e +'Long ', # 0x6f +'Yun ', # 0x70 +'[?] ', # 0x71 +'Qi ', # 0x72 +'Jian ', # 0x73 +'Yun ', # 0x74 +'Sun ', # 0x75 +'Ling ', # 0x76 +'Yu ', # 0x77 +'Xia ', # 0x78 +'Yong ', # 0x79 +'Ji ', # 0x7a +'Hong ', # 0x7b +'Si ', # 0x7c +'Nong ', # 0x7d +'Lei ', # 0x7e +'Xuan ', # 0x7f +'Yun ', # 0x80 +'Yu ', # 0x81 +'Xi ', # 0x82 +'Hao ', # 0x83 +'Bo ', # 0x84 +'Hao ', # 0x85 +'Ai ', # 0x86 +'Wei ', # 0x87 +'Hui ', # 0x88 +'Wei ', # 0x89 +'Ji ', # 0x8a +'Ci ', # 0x8b +'Xiang ', # 0x8c +'Luan ', # 0x8d +'Mie ', # 0x8e +'Yi ', # 0x8f +'Leng ', # 0x90 +'Jiang ', # 0x91 +'Can ', # 0x92 +'Shen ', # 0x93 +'Qiang ', # 0x94 +'Lian ', # 0x95 +'Ke ', # 0x96 +'Yuan ', # 0x97 +'Da ', # 0x98 +'Ti ', # 0x99 +'Tang ', # 0x9a +'Xie ', # 0x9b +'Bi ', # 0x9c +'Zhan ', # 0x9d +'Sun ', # 0x9e +'Lian ', # 0x9f +'Fan ', # 0xa0 +'Ding ', # 0xa1 +'Jie ', # 0xa2 +'Gu ', # 0xa3 +'Xie ', # 0xa4 +'Shu ', # 0xa5 +'Jian ', # 0xa6 +'Kao ', # 0xa7 +'Hong ', # 0xa8 +'Sa ', # 0xa9 +'Xin ', # 0xaa +'Xun ', # 0xab +'Yao ', # 0xac +'Hie ', # 0xad +'Sou ', # 0xae +'Shu ', # 0xaf +'Xun ', # 0xb0 +'Dui ', # 0xb1 +'Pin ', # 0xb2 +'Wei ', # 0xb3 +'Neng ', # 0xb4 +'Chou ', # 0xb5 +'Mai ', # 0xb6 +'Ru ', # 0xb7 +'Piao ', # 0xb8 +'Tai ', # 0xb9 +'Qi ', # 0xba +'Zao ', # 0xbb +'Chen ', # 0xbc +'Zhen ', # 0xbd +'Er ', # 0xbe +'Ni ', # 0xbf +'Ying ', # 0xc0 +'Gao ', # 0xc1 +'Cong ', # 0xc2 +'Xiao ', # 0xc3 +'Qi ', # 0xc4 +'Fa ', # 0xc5 +'Jian ', # 0xc6 +'Xu ', # 0xc7 +'Kui ', # 0xc8 +'Jie ', # 0xc9 +'Bian ', # 0xca +'Diao ', # 0xcb +'Mi ', # 0xcc +'Lan ', # 0xcd +'Jin ', # 0xce +'Cang ', # 0xcf +'Miao ', # 0xd0 +'Qiong ', # 0xd1 +'Qie ', # 0xd2 +'Xian ', # 0xd3 +'[?] ', # 0xd4 +'Ou ', # 0xd5 +'Xian ', # 0xd6 +'Su ', # 0xd7 +'Lu ', # 0xd8 +'Yi ', # 0xd9 +'Xu ', # 0xda +'Xie ', # 0xdb +'Li ', # 0xdc +'Yi ', # 0xdd +'La ', # 0xde +'Lei ', # 0xdf +'Xiao ', # 0xe0 +'Di ', # 0xe1 +'Zhi ', # 0xe2 +'Bei ', # 0xe3 +'Teng ', # 0xe4 +'Yao ', # 0xe5 +'Mo ', # 0xe6 +'Huan ', # 0xe7 +'Piao ', # 0xe8 +'Fan ', # 0xe9 +'Sou ', # 0xea +'Tan ', # 0xeb +'Tui ', # 0xec +'Qiong ', # 0xed +'Qiao ', # 0xee +'Wei ', # 0xef +'Liu ', # 0xf0 +'Hui ', # 0xf1 +'[?] ', # 0xf2 +'Gao ', # 0xf3 +'Yun ', # 0xf4 +'[?] ', # 0xf5 +'Li ', # 0xf6 +'Shu ', # 0xf7 +'Chu ', # 0xf8 +'Ai ', # 0xf9 +'Lin ', # 0xfa +'Zao ', # 0xfb +'Xuan ', # 0xfc +'Chen ', # 0xfd +'Lai ', # 0xfe +'Huo ', # 0xff +) diff --git a/nstock/modules/unidecode/x086.py b/nstock/modules/unidecode/x086.py new file mode 100644 index 0000000..38784a6 --- /dev/null +++ b/nstock/modules/unidecode/x086.py @@ -0,0 +1,258 @@ +data = ( +'Tuo ', # 0x00 +'Wu ', # 0x01 +'Rui ', # 0x02 +'Rui ', # 0x03 +'Qi ', # 0x04 +'Heng ', # 0x05 +'Lu ', # 0x06 +'Su ', # 0x07 +'Tui ', # 0x08 +'Mang ', # 0x09 +'Yun ', # 0x0a +'Pin ', # 0x0b +'Yu ', # 0x0c +'Xun ', # 0x0d +'Ji ', # 0x0e +'Jiong ', # 0x0f +'Xian ', # 0x10 +'Mo ', # 0x11 +'Hagi ', # 0x12 +'Su ', # 0x13 +'Jiong ', # 0x14 +'[?] ', # 0x15 +'Nie ', # 0x16 +'Bo ', # 0x17 +'Rang ', # 0x18 +'Yi ', # 0x19 +'Xian ', # 0x1a +'Yu ', # 0x1b +'Ju ', # 0x1c +'Lian ', # 0x1d +'Lian ', # 0x1e +'Yin ', # 0x1f +'Qiang ', # 0x20 +'Ying ', # 0x21 +'Long ', # 0x22 +'Tong ', # 0x23 +'Wei ', # 0x24 +'Yue ', # 0x25 +'Ling ', # 0x26 +'Qu ', # 0x27 +'Yao ', # 0x28 +'Fan ', # 0x29 +'Mi ', # 0x2a +'Lan ', # 0x2b +'Kui ', # 0x2c +'Lan ', # 0x2d +'Ji ', # 0x2e +'Dang ', # 0x2f +'Katsura ', # 0x30 +'Lei ', # 0x31 +'Lei ', # 0x32 +'Hua ', # 0x33 +'Feng ', # 0x34 +'Zhi ', # 0x35 +'Wei ', # 0x36 +'Kui ', # 0x37 +'Zhan ', # 0x38 +'Huai ', # 0x39 +'Li ', # 0x3a +'Ji ', # 0x3b +'Mi ', # 0x3c +'Lei ', # 0x3d +'Huai ', # 0x3e +'Luo ', # 0x3f +'Ji ', # 0x40 +'Kui ', # 0x41 +'Lu ', # 0x42 +'Jian ', # 0x43 +'San ', # 0x44 +'[?] ', # 0x45 +'Lei ', # 0x46 +'Quan ', # 0x47 +'Xiao ', # 0x48 +'Yi ', # 0x49 +'Luan ', # 0x4a +'Men ', # 0x4b +'Bie ', # 0x4c +'Hu ', # 0x4d +'Hu ', # 0x4e +'Lu ', # 0x4f +'Nue ', # 0x50 +'Lu ', # 0x51 +'Si ', # 0x52 +'Xiao ', # 0x53 +'Qian ', # 0x54 +'Chu ', # 0x55 +'Hu ', # 0x56 +'Xu ', # 0x57 +'Cuo ', # 0x58 +'Fu ', # 0x59 +'Xu ', # 0x5a +'Xu ', # 0x5b +'Lu ', # 0x5c +'Hu ', # 0x5d +'Yu ', # 0x5e +'Hao ', # 0x5f +'Jiao ', # 0x60 +'Ju ', # 0x61 +'Guo ', # 0x62 +'Bao ', # 0x63 +'Yan ', # 0x64 +'Zhan ', # 0x65 +'Zhan ', # 0x66 +'Kui ', # 0x67 +'Ban ', # 0x68 +'Xi ', # 0x69 +'Shu ', # 0x6a +'Chong ', # 0x6b +'Qiu ', # 0x6c +'Diao ', # 0x6d +'Ji ', # 0x6e +'Qiu ', # 0x6f +'Cheng ', # 0x70 +'Shi ', # 0x71 +'[?] ', # 0x72 +'Di ', # 0x73 +'Zhe ', # 0x74 +'She ', # 0x75 +'Yu ', # 0x76 +'Gan ', # 0x77 +'Zi ', # 0x78 +'Hong ', # 0x79 +'Hui ', # 0x7a +'Meng ', # 0x7b +'Ge ', # 0x7c +'Sui ', # 0x7d +'Xia ', # 0x7e +'Chai ', # 0x7f +'Shi ', # 0x80 +'Yi ', # 0x81 +'Ma ', # 0x82 +'Xiang ', # 0x83 +'Fang ', # 0x84 +'E ', # 0x85 +'Pa ', # 0x86 +'Chi ', # 0x87 +'Qian ', # 0x88 +'Wen ', # 0x89 +'Wen ', # 0x8a +'Rui ', # 0x8b +'Bang ', # 0x8c +'Bi ', # 0x8d +'Yue ', # 0x8e +'Yue ', # 0x8f +'Jun ', # 0x90 +'Qi ', # 0x91 +'Ran ', # 0x92 +'Yin ', # 0x93 +'Qi ', # 0x94 +'Tian ', # 0x95 +'Yuan ', # 0x96 +'Jue ', # 0x97 +'Hui ', # 0x98 +'Qin ', # 0x99 +'Qi ', # 0x9a +'Zhong ', # 0x9b +'Ya ', # 0x9c +'Ci ', # 0x9d +'Mu ', # 0x9e +'Wang ', # 0x9f +'Fen ', # 0xa0 +'Fen ', # 0xa1 +'Hang ', # 0xa2 +'Gong ', # 0xa3 +'Zao ', # 0xa4 +'Fu ', # 0xa5 +'Ran ', # 0xa6 +'Jie ', # 0xa7 +'Fu ', # 0xa8 +'Chi ', # 0xa9 +'Dou ', # 0xaa +'Piao ', # 0xab +'Xian ', # 0xac +'Ni ', # 0xad +'Te ', # 0xae +'Qiu ', # 0xaf +'You ', # 0xb0 +'Zha ', # 0xb1 +'Ping ', # 0xb2 +'Chi ', # 0xb3 +'You ', # 0xb4 +'He ', # 0xb5 +'Han ', # 0xb6 +'Ju ', # 0xb7 +'Li ', # 0xb8 +'Fu ', # 0xb9 +'Ran ', # 0xba +'Zha ', # 0xbb +'Gou ', # 0xbc +'Pi ', # 0xbd +'Bo ', # 0xbe +'Xian ', # 0xbf +'Zhu ', # 0xc0 +'Diao ', # 0xc1 +'Bie ', # 0xc2 +'Bing ', # 0xc3 +'Gu ', # 0xc4 +'Ran ', # 0xc5 +'Qu ', # 0xc6 +'She ', # 0xc7 +'Tie ', # 0xc8 +'Ling ', # 0xc9 +'Gu ', # 0xca +'Dan ', # 0xcb +'Gu ', # 0xcc +'Ying ', # 0xcd +'Li ', # 0xce +'Cheng ', # 0xcf +'Qu ', # 0xd0 +'Mou ', # 0xd1 +'Ge ', # 0xd2 +'Ci ', # 0xd3 +'Hui ', # 0xd4 +'Hui ', # 0xd5 +'Mang ', # 0xd6 +'Fu ', # 0xd7 +'Yang ', # 0xd8 +'Wa ', # 0xd9 +'Lie ', # 0xda +'Zhu ', # 0xdb +'Yi ', # 0xdc +'Xian ', # 0xdd +'Kuo ', # 0xde +'Jiao ', # 0xdf +'Li ', # 0xe0 +'Yi ', # 0xe1 +'Ping ', # 0xe2 +'Ji ', # 0xe3 +'Ha ', # 0xe4 +'She ', # 0xe5 +'Yi ', # 0xe6 +'Wang ', # 0xe7 +'Mo ', # 0xe8 +'Qiong ', # 0xe9 +'Qie ', # 0xea +'Gui ', # 0xeb +'Gong ', # 0xec +'Zhi ', # 0xed +'Man ', # 0xee +'Ebi ', # 0xef +'Zhi ', # 0xf0 +'Jia ', # 0xf1 +'Rao ', # 0xf2 +'Si ', # 0xf3 +'Qi ', # 0xf4 +'Xing ', # 0xf5 +'Lie ', # 0xf6 +'Qiu ', # 0xf7 +'Shao ', # 0xf8 +'Yong ', # 0xf9 +'Jia ', # 0xfa +'Shui ', # 0xfb +'Che ', # 0xfc +'Bai ', # 0xfd +'E ', # 0xfe +'Han ', # 0xff +) diff --git a/nstock/modules/unidecode/x087.py b/nstock/modules/unidecode/x087.py new file mode 100644 index 0000000..2a2b79a --- /dev/null +++ b/nstock/modules/unidecode/x087.py @@ -0,0 +1,258 @@ +data = ( +'Shu ', # 0x00 +'Xuan ', # 0x01 +'Feng ', # 0x02 +'Shen ', # 0x03 +'Zhen ', # 0x04 +'Fu ', # 0x05 +'Xian ', # 0x06 +'Zhe ', # 0x07 +'Wu ', # 0x08 +'Fu ', # 0x09 +'Li ', # 0x0a +'Lang ', # 0x0b +'Bi ', # 0x0c +'Chu ', # 0x0d +'Yuan ', # 0x0e +'You ', # 0x0f +'Jie ', # 0x10 +'Dan ', # 0x11 +'Yan ', # 0x12 +'Ting ', # 0x13 +'Dian ', # 0x14 +'Shui ', # 0x15 +'Hui ', # 0x16 +'Gua ', # 0x17 +'Zhi ', # 0x18 +'Song ', # 0x19 +'Fei ', # 0x1a +'Ju ', # 0x1b +'Mi ', # 0x1c +'Qi ', # 0x1d +'Qi ', # 0x1e +'Yu ', # 0x1f +'Jun ', # 0x20 +'Zha ', # 0x21 +'Meng ', # 0x22 +'Qiang ', # 0x23 +'Si ', # 0x24 +'Xi ', # 0x25 +'Lun ', # 0x26 +'Li ', # 0x27 +'Die ', # 0x28 +'Tiao ', # 0x29 +'Tao ', # 0x2a +'Kun ', # 0x2b +'Gan ', # 0x2c +'Han ', # 0x2d +'Yu ', # 0x2e +'Bang ', # 0x2f +'Fei ', # 0x30 +'Pi ', # 0x31 +'Wei ', # 0x32 +'Dun ', # 0x33 +'Yi ', # 0x34 +'Yuan ', # 0x35 +'Su ', # 0x36 +'Quan ', # 0x37 +'Qian ', # 0x38 +'Rui ', # 0x39 +'Ni ', # 0x3a +'Qing ', # 0x3b +'Wei ', # 0x3c +'Liang ', # 0x3d +'Guo ', # 0x3e +'Wan ', # 0x3f +'Dong ', # 0x40 +'E ', # 0x41 +'Ban ', # 0x42 +'Di ', # 0x43 +'Wang ', # 0x44 +'Can ', # 0x45 +'Yang ', # 0x46 +'Ying ', # 0x47 +'Guo ', # 0x48 +'Chan ', # 0x49 +'[?] ', # 0x4a +'La ', # 0x4b +'Ke ', # 0x4c +'Ji ', # 0x4d +'He ', # 0x4e +'Ting ', # 0x4f +'Mai ', # 0x50 +'Xu ', # 0x51 +'Mian ', # 0x52 +'Yu ', # 0x53 +'Jie ', # 0x54 +'Shi ', # 0x55 +'Xuan ', # 0x56 +'Huang ', # 0x57 +'Yan ', # 0x58 +'Bian ', # 0x59 +'Rou ', # 0x5a +'Wei ', # 0x5b +'Fu ', # 0x5c +'Yuan ', # 0x5d +'Mei ', # 0x5e +'Wei ', # 0x5f +'Fu ', # 0x60 +'Ruan ', # 0x61 +'Xie ', # 0x62 +'You ', # 0x63 +'Qiu ', # 0x64 +'Mao ', # 0x65 +'Xia ', # 0x66 +'Ying ', # 0x67 +'Shi ', # 0x68 +'Chong ', # 0x69 +'Tang ', # 0x6a +'Zhu ', # 0x6b +'Zong ', # 0x6c +'Ti ', # 0x6d +'Fu ', # 0x6e +'Yuan ', # 0x6f +'Hui ', # 0x70 +'Meng ', # 0x71 +'La ', # 0x72 +'Du ', # 0x73 +'Hu ', # 0x74 +'Qiu ', # 0x75 +'Die ', # 0x76 +'Li ', # 0x77 +'Gua ', # 0x78 +'Yun ', # 0x79 +'Ju ', # 0x7a +'Nan ', # 0x7b +'Lou ', # 0x7c +'Qun ', # 0x7d +'Rong ', # 0x7e +'Ying ', # 0x7f +'Jiang ', # 0x80 +'[?] ', # 0x81 +'Lang ', # 0x82 +'Pang ', # 0x83 +'Si ', # 0x84 +'Xi ', # 0x85 +'Ci ', # 0x86 +'Xi ', # 0x87 +'Yuan ', # 0x88 +'Weng ', # 0x89 +'Lian ', # 0x8a +'Sou ', # 0x8b +'Ban ', # 0x8c +'Rong ', # 0x8d +'Rong ', # 0x8e +'Ji ', # 0x8f +'Wu ', # 0x90 +'Qiu ', # 0x91 +'Han ', # 0x92 +'Qin ', # 0x93 +'Yi ', # 0x94 +'Bi ', # 0x95 +'Hua ', # 0x96 +'Tang ', # 0x97 +'Yi ', # 0x98 +'Du ', # 0x99 +'Nai ', # 0x9a +'He ', # 0x9b +'Hu ', # 0x9c +'Hui ', # 0x9d +'Ma ', # 0x9e +'Ming ', # 0x9f +'Yi ', # 0xa0 +'Wen ', # 0xa1 +'Ying ', # 0xa2 +'Teng ', # 0xa3 +'Yu ', # 0xa4 +'Cang ', # 0xa5 +'So ', # 0xa6 +'Ebi ', # 0xa7 +'Man ', # 0xa8 +'[?] ', # 0xa9 +'Shang ', # 0xaa +'Zhe ', # 0xab +'Cao ', # 0xac +'Chi ', # 0xad +'Di ', # 0xae +'Ao ', # 0xaf +'Lu ', # 0xb0 +'Wei ', # 0xb1 +'Zhi ', # 0xb2 +'Tang ', # 0xb3 +'Chen ', # 0xb4 +'Piao ', # 0xb5 +'Qu ', # 0xb6 +'Pi ', # 0xb7 +'Yu ', # 0xb8 +'Jian ', # 0xb9 +'Luo ', # 0xba +'Lou ', # 0xbb +'Qin ', # 0xbc +'Zhong ', # 0xbd +'Yin ', # 0xbe +'Jiang ', # 0xbf +'Shuai ', # 0xc0 +'Wen ', # 0xc1 +'Jiao ', # 0xc2 +'Wan ', # 0xc3 +'Zhi ', # 0xc4 +'Zhe ', # 0xc5 +'Ma ', # 0xc6 +'Ma ', # 0xc7 +'Guo ', # 0xc8 +'Liu ', # 0xc9 +'Mao ', # 0xca +'Xi ', # 0xcb +'Cong ', # 0xcc +'Li ', # 0xcd +'Man ', # 0xce +'Xiao ', # 0xcf +'Kamakiri ', # 0xd0 +'Zhang ', # 0xd1 +'Mang ', # 0xd2 +'Xiang ', # 0xd3 +'Mo ', # 0xd4 +'Zui ', # 0xd5 +'Si ', # 0xd6 +'Qiu ', # 0xd7 +'Te ', # 0xd8 +'Zhi ', # 0xd9 +'Peng ', # 0xda +'Peng ', # 0xdb +'Jiao ', # 0xdc +'Qu ', # 0xdd +'Bie ', # 0xde +'Liao ', # 0xdf +'Pan ', # 0xe0 +'Gui ', # 0xe1 +'Xi ', # 0xe2 +'Ji ', # 0xe3 +'Zhuan ', # 0xe4 +'Huang ', # 0xe5 +'Fei ', # 0xe6 +'Lao ', # 0xe7 +'Jue ', # 0xe8 +'Jue ', # 0xe9 +'Hui ', # 0xea +'Yin ', # 0xeb +'Chan ', # 0xec +'Jiao ', # 0xed +'Shan ', # 0xee +'Rao ', # 0xef +'Xiao ', # 0xf0 +'Mou ', # 0xf1 +'Chong ', # 0xf2 +'Xun ', # 0xf3 +'Si ', # 0xf4 +'[?] ', # 0xf5 +'Cheng ', # 0xf6 +'Dang ', # 0xf7 +'Li ', # 0xf8 +'Xie ', # 0xf9 +'Shan ', # 0xfa +'Yi ', # 0xfb +'Jing ', # 0xfc +'Da ', # 0xfd +'Chan ', # 0xfe +'Qi ', # 0xff +) diff --git a/nstock/modules/unidecode/x088.py b/nstock/modules/unidecode/x088.py new file mode 100644 index 0000000..f907ce9 --- /dev/null +++ b/nstock/modules/unidecode/x088.py @@ -0,0 +1,258 @@ +data = ( +'Ci ', # 0x00 +'Xiang ', # 0x01 +'She ', # 0x02 +'Luo ', # 0x03 +'Qin ', # 0x04 +'Ying ', # 0x05 +'Chai ', # 0x06 +'Li ', # 0x07 +'Ze ', # 0x08 +'Xuan ', # 0x09 +'Lian ', # 0x0a +'Zhu ', # 0x0b +'Ze ', # 0x0c +'Xie ', # 0x0d +'Mang ', # 0x0e +'Xie ', # 0x0f +'Qi ', # 0x10 +'Rong ', # 0x11 +'Jian ', # 0x12 +'Meng ', # 0x13 +'Hao ', # 0x14 +'Ruan ', # 0x15 +'Huo ', # 0x16 +'Zhuo ', # 0x17 +'Jie ', # 0x18 +'Bin ', # 0x19 +'He ', # 0x1a +'Mie ', # 0x1b +'Fan ', # 0x1c +'Lei ', # 0x1d +'Jie ', # 0x1e +'La ', # 0x1f +'Mi ', # 0x20 +'Li ', # 0x21 +'Chun ', # 0x22 +'Li ', # 0x23 +'Qiu ', # 0x24 +'Nie ', # 0x25 +'Lu ', # 0x26 +'Du ', # 0x27 +'Xiao ', # 0x28 +'Zhu ', # 0x29 +'Long ', # 0x2a +'Li ', # 0x2b +'Long ', # 0x2c +'Feng ', # 0x2d +'Ye ', # 0x2e +'Beng ', # 0x2f +'Shang ', # 0x30 +'Gu ', # 0x31 +'Juan ', # 0x32 +'Ying ', # 0x33 +'[?] ', # 0x34 +'Xi ', # 0x35 +'Can ', # 0x36 +'Qu ', # 0x37 +'Quan ', # 0x38 +'Du ', # 0x39 +'Can ', # 0x3a +'Man ', # 0x3b +'Jue ', # 0x3c +'Jie ', # 0x3d +'Zhu ', # 0x3e +'Zha ', # 0x3f +'Xie ', # 0x40 +'Huang ', # 0x41 +'Niu ', # 0x42 +'Pei ', # 0x43 +'Nu ', # 0x44 +'Xin ', # 0x45 +'Zhong ', # 0x46 +'Mo ', # 0x47 +'Er ', # 0x48 +'Ke ', # 0x49 +'Mie ', # 0x4a +'Xi ', # 0x4b +'Xing ', # 0x4c +'Yan ', # 0x4d +'Kan ', # 0x4e +'Yuan ', # 0x4f +'[?] ', # 0x50 +'Ling ', # 0x51 +'Xuan ', # 0x52 +'Shu ', # 0x53 +'Xian ', # 0x54 +'Tong ', # 0x55 +'Long ', # 0x56 +'Jie ', # 0x57 +'Xian ', # 0x58 +'Ya ', # 0x59 +'Hu ', # 0x5a +'Wei ', # 0x5b +'Dao ', # 0x5c +'Chong ', # 0x5d +'Wei ', # 0x5e +'Dao ', # 0x5f +'Zhun ', # 0x60 +'Heng ', # 0x61 +'Qu ', # 0x62 +'Yi ', # 0x63 +'Yi ', # 0x64 +'Bu ', # 0x65 +'Gan ', # 0x66 +'Yu ', # 0x67 +'Biao ', # 0x68 +'Cha ', # 0x69 +'Yi ', # 0x6a +'Shan ', # 0x6b +'Chen ', # 0x6c +'Fu ', # 0x6d +'Gun ', # 0x6e +'Fen ', # 0x6f +'Shuai ', # 0x70 +'Jie ', # 0x71 +'Na ', # 0x72 +'Zhong ', # 0x73 +'Dan ', # 0x74 +'Ri ', # 0x75 +'Zhong ', # 0x76 +'Zhong ', # 0x77 +'Xie ', # 0x78 +'Qi ', # 0x79 +'Xie ', # 0x7a +'Ran ', # 0x7b +'Zhi ', # 0x7c +'Ren ', # 0x7d +'Qin ', # 0x7e +'Jin ', # 0x7f +'Jun ', # 0x80 +'Yuan ', # 0x81 +'Mei ', # 0x82 +'Chai ', # 0x83 +'Ao ', # 0x84 +'Niao ', # 0x85 +'Hui ', # 0x86 +'Ran ', # 0x87 +'Jia ', # 0x88 +'Tuo ', # 0x89 +'Ling ', # 0x8a +'Dai ', # 0x8b +'Bao ', # 0x8c +'Pao ', # 0x8d +'Yao ', # 0x8e +'Zuo ', # 0x8f +'Bi ', # 0x90 +'Shao ', # 0x91 +'Tan ', # 0x92 +'Ju ', # 0x93 +'He ', # 0x94 +'Shu ', # 0x95 +'Xiu ', # 0x96 +'Zhen ', # 0x97 +'Yi ', # 0x98 +'Pa ', # 0x99 +'Bo ', # 0x9a +'Di ', # 0x9b +'Wa ', # 0x9c +'Fu ', # 0x9d +'Gun ', # 0x9e +'Zhi ', # 0x9f +'Zhi ', # 0xa0 +'Ran ', # 0xa1 +'Pan ', # 0xa2 +'Yi ', # 0xa3 +'Mao ', # 0xa4 +'Tuo ', # 0xa5 +'Na ', # 0xa6 +'Kou ', # 0xa7 +'Xian ', # 0xa8 +'Chan ', # 0xa9 +'Qu ', # 0xaa +'Bei ', # 0xab +'Gun ', # 0xac +'Xi ', # 0xad +'Ne ', # 0xae +'Bo ', # 0xaf +'Horo ', # 0xb0 +'Fu ', # 0xb1 +'Yi ', # 0xb2 +'Chi ', # 0xb3 +'Ku ', # 0xb4 +'Ren ', # 0xb5 +'Jiang ', # 0xb6 +'Jia ', # 0xb7 +'Cun ', # 0xb8 +'Mo ', # 0xb9 +'Jie ', # 0xba +'Er ', # 0xbb +'Luo ', # 0xbc +'Ru ', # 0xbd +'Zhu ', # 0xbe +'Gui ', # 0xbf +'Yin ', # 0xc0 +'Cai ', # 0xc1 +'Lie ', # 0xc2 +'Kamishimo ', # 0xc3 +'Yuki ', # 0xc4 +'Zhuang ', # 0xc5 +'Dang ', # 0xc6 +'[?] ', # 0xc7 +'Kun ', # 0xc8 +'Ken ', # 0xc9 +'Niao ', # 0xca +'Shu ', # 0xcb +'Jia ', # 0xcc +'Kun ', # 0xcd +'Cheng ', # 0xce +'Li ', # 0xcf +'Juan ', # 0xd0 +'Shen ', # 0xd1 +'Pou ', # 0xd2 +'Ge ', # 0xd3 +'Yi ', # 0xd4 +'Yu ', # 0xd5 +'Zhen ', # 0xd6 +'Liu ', # 0xd7 +'Qiu ', # 0xd8 +'Qun ', # 0xd9 +'Ji ', # 0xda +'Yi ', # 0xdb +'Bu ', # 0xdc +'Zhuang ', # 0xdd +'Shui ', # 0xde +'Sha ', # 0xdf +'Qun ', # 0xe0 +'Li ', # 0xe1 +'Lian ', # 0xe2 +'Lian ', # 0xe3 +'Ku ', # 0xe4 +'Jian ', # 0xe5 +'Fou ', # 0xe6 +'Chan ', # 0xe7 +'Bi ', # 0xe8 +'Gun ', # 0xe9 +'Tao ', # 0xea +'Yuan ', # 0xeb +'Ling ', # 0xec +'Chi ', # 0xed +'Chang ', # 0xee +'Chou ', # 0xef +'Duo ', # 0xf0 +'Biao ', # 0xf1 +'Liang ', # 0xf2 +'Chang ', # 0xf3 +'Pei ', # 0xf4 +'Pei ', # 0xf5 +'Fei ', # 0xf6 +'Yuan ', # 0xf7 +'Luo ', # 0xf8 +'Guo ', # 0xf9 +'Yan ', # 0xfa +'Du ', # 0xfb +'Xi ', # 0xfc +'Zhi ', # 0xfd +'Ju ', # 0xfe +'Qi ', # 0xff +) diff --git a/nstock/modules/unidecode/x089.py b/nstock/modules/unidecode/x089.py new file mode 100644 index 0000000..d23abc3 --- /dev/null +++ b/nstock/modules/unidecode/x089.py @@ -0,0 +1,258 @@ +data = ( +'Ji ', # 0x00 +'Zhi ', # 0x01 +'Gua ', # 0x02 +'Ken ', # 0x03 +'Che ', # 0x04 +'Ti ', # 0x05 +'Ti ', # 0x06 +'Fu ', # 0x07 +'Chong ', # 0x08 +'Xie ', # 0x09 +'Bian ', # 0x0a +'Die ', # 0x0b +'Kun ', # 0x0c +'Duan ', # 0x0d +'Xiu ', # 0x0e +'Xiu ', # 0x0f +'He ', # 0x10 +'Yuan ', # 0x11 +'Bao ', # 0x12 +'Bao ', # 0x13 +'Fu ', # 0x14 +'Yu ', # 0x15 +'Tuan ', # 0x16 +'Yan ', # 0x17 +'Hui ', # 0x18 +'Bei ', # 0x19 +'Chu ', # 0x1a +'Lu ', # 0x1b +'Ena ', # 0x1c +'Hitoe ', # 0x1d +'Yun ', # 0x1e +'Da ', # 0x1f +'Gou ', # 0x20 +'Da ', # 0x21 +'Huai ', # 0x22 +'Rong ', # 0x23 +'Yuan ', # 0x24 +'Ru ', # 0x25 +'Nai ', # 0x26 +'Jiong ', # 0x27 +'Suo ', # 0x28 +'Ban ', # 0x29 +'Tun ', # 0x2a +'Chi ', # 0x2b +'Sang ', # 0x2c +'Niao ', # 0x2d +'Ying ', # 0x2e +'Jie ', # 0x2f +'Qian ', # 0x30 +'Huai ', # 0x31 +'Ku ', # 0x32 +'Lian ', # 0x33 +'Bao ', # 0x34 +'Li ', # 0x35 +'Zhe ', # 0x36 +'Shi ', # 0x37 +'Lu ', # 0x38 +'Yi ', # 0x39 +'Die ', # 0x3a +'Xie ', # 0x3b +'Xian ', # 0x3c +'Wei ', # 0x3d +'Biao ', # 0x3e +'Cao ', # 0x3f +'Ji ', # 0x40 +'Jiang ', # 0x41 +'Sen ', # 0x42 +'Bao ', # 0x43 +'Xiang ', # 0x44 +'Chihaya ', # 0x45 +'Pu ', # 0x46 +'Jian ', # 0x47 +'Zhuan ', # 0x48 +'Jian ', # 0x49 +'Zui ', # 0x4a +'Ji ', # 0x4b +'Dan ', # 0x4c +'Za ', # 0x4d +'Fan ', # 0x4e +'Bo ', # 0x4f +'Xiang ', # 0x50 +'Xin ', # 0x51 +'Bie ', # 0x52 +'Rao ', # 0x53 +'Man ', # 0x54 +'Lan ', # 0x55 +'Ao ', # 0x56 +'Duo ', # 0x57 +'Gui ', # 0x58 +'Cao ', # 0x59 +'Sui ', # 0x5a +'Nong ', # 0x5b +'Chan ', # 0x5c +'Lian ', # 0x5d +'Bi ', # 0x5e +'Jin ', # 0x5f +'Dang ', # 0x60 +'Shu ', # 0x61 +'Tan ', # 0x62 +'Bi ', # 0x63 +'Lan ', # 0x64 +'Pu ', # 0x65 +'Ru ', # 0x66 +'Zhi ', # 0x67 +'[?] ', # 0x68 +'Shu ', # 0x69 +'Wa ', # 0x6a +'Shi ', # 0x6b +'Bai ', # 0x6c +'Xie ', # 0x6d +'Bo ', # 0x6e +'Chen ', # 0x6f +'Lai ', # 0x70 +'Long ', # 0x71 +'Xi ', # 0x72 +'Xian ', # 0x73 +'Lan ', # 0x74 +'Zhe ', # 0x75 +'Dai ', # 0x76 +'Tasuki ', # 0x77 +'Zan ', # 0x78 +'Shi ', # 0x79 +'Jian ', # 0x7a +'Pan ', # 0x7b +'Yi ', # 0x7c +'Ran ', # 0x7d +'Ya ', # 0x7e +'Xi ', # 0x7f +'Xi ', # 0x80 +'Yao ', # 0x81 +'Feng ', # 0x82 +'Tan ', # 0x83 +'[?] ', # 0x84 +'Biao ', # 0x85 +'Fu ', # 0x86 +'Ba ', # 0x87 +'He ', # 0x88 +'Ji ', # 0x89 +'Ji ', # 0x8a +'Jian ', # 0x8b +'Guan ', # 0x8c +'Bian ', # 0x8d +'Yan ', # 0x8e +'Gui ', # 0x8f +'Jue ', # 0x90 +'Pian ', # 0x91 +'Mao ', # 0x92 +'Mi ', # 0x93 +'Mi ', # 0x94 +'Mie ', # 0x95 +'Shi ', # 0x96 +'Si ', # 0x97 +'Zhan ', # 0x98 +'Luo ', # 0x99 +'Jue ', # 0x9a +'Mi ', # 0x9b +'Tiao ', # 0x9c +'Lian ', # 0x9d +'Yao ', # 0x9e +'Zhi ', # 0x9f +'Jun ', # 0xa0 +'Xi ', # 0xa1 +'Shan ', # 0xa2 +'Wei ', # 0xa3 +'Xi ', # 0xa4 +'Tian ', # 0xa5 +'Yu ', # 0xa6 +'Lan ', # 0xa7 +'E ', # 0xa8 +'Du ', # 0xa9 +'Qin ', # 0xaa +'Pang ', # 0xab +'Ji ', # 0xac +'Ming ', # 0xad +'Ying ', # 0xae +'Gou ', # 0xaf +'Qu ', # 0xb0 +'Zhan ', # 0xb1 +'Jin ', # 0xb2 +'Guan ', # 0xb3 +'Deng ', # 0xb4 +'Jian ', # 0xb5 +'Luo ', # 0xb6 +'Qu ', # 0xb7 +'Jian ', # 0xb8 +'Wei ', # 0xb9 +'Jue ', # 0xba +'Qu ', # 0xbb +'Luo ', # 0xbc +'Lan ', # 0xbd +'Shen ', # 0xbe +'Di ', # 0xbf +'Guan ', # 0xc0 +'Jian ', # 0xc1 +'Guan ', # 0xc2 +'Yan ', # 0xc3 +'Gui ', # 0xc4 +'Mi ', # 0xc5 +'Shi ', # 0xc6 +'Zhan ', # 0xc7 +'Lan ', # 0xc8 +'Jue ', # 0xc9 +'Ji ', # 0xca +'Xi ', # 0xcb +'Di ', # 0xcc +'Tian ', # 0xcd +'Yu ', # 0xce +'Gou ', # 0xcf +'Jin ', # 0xd0 +'Qu ', # 0xd1 +'Jiao ', # 0xd2 +'Jiu ', # 0xd3 +'Jin ', # 0xd4 +'Cu ', # 0xd5 +'Jue ', # 0xd6 +'Zhi ', # 0xd7 +'Chao ', # 0xd8 +'Ji ', # 0xd9 +'Gu ', # 0xda +'Dan ', # 0xdb +'Zui ', # 0xdc +'Di ', # 0xdd +'Shang ', # 0xde +'Hua ', # 0xdf +'Quan ', # 0xe0 +'Ge ', # 0xe1 +'Chi ', # 0xe2 +'Jie ', # 0xe3 +'Gui ', # 0xe4 +'Gong ', # 0xe5 +'Hong ', # 0xe6 +'Jie ', # 0xe7 +'Hun ', # 0xe8 +'Qiu ', # 0xe9 +'Xing ', # 0xea +'Su ', # 0xeb +'Ni ', # 0xec +'Ji ', # 0xed +'Lu ', # 0xee +'Zhi ', # 0xef +'Zha ', # 0xf0 +'Bi ', # 0xf1 +'Xing ', # 0xf2 +'Hu ', # 0xf3 +'Shang ', # 0xf4 +'Gong ', # 0xf5 +'Zhi ', # 0xf6 +'Xue ', # 0xf7 +'Chu ', # 0xf8 +'Xi ', # 0xf9 +'Yi ', # 0xfa +'Lu ', # 0xfb +'Jue ', # 0xfc +'Xi ', # 0xfd +'Yan ', # 0xfe +'Xi ', # 0xff +) diff --git a/nstock/modules/unidecode/x08a.py b/nstock/modules/unidecode/x08a.py new file mode 100644 index 0000000..0b0fa0a --- /dev/null +++ b/nstock/modules/unidecode/x08a.py @@ -0,0 +1,258 @@ +data = ( +'Yan ', # 0x00 +'Yan ', # 0x01 +'Ding ', # 0x02 +'Fu ', # 0x03 +'Qiu ', # 0x04 +'Qiu ', # 0x05 +'Jiao ', # 0x06 +'Hong ', # 0x07 +'Ji ', # 0x08 +'Fan ', # 0x09 +'Xun ', # 0x0a +'Diao ', # 0x0b +'Hong ', # 0x0c +'Cha ', # 0x0d +'Tao ', # 0x0e +'Xu ', # 0x0f +'Jie ', # 0x10 +'Yi ', # 0x11 +'Ren ', # 0x12 +'Xun ', # 0x13 +'Yin ', # 0x14 +'Shan ', # 0x15 +'Qi ', # 0x16 +'Tuo ', # 0x17 +'Ji ', # 0x18 +'Xun ', # 0x19 +'Yin ', # 0x1a +'E ', # 0x1b +'Fen ', # 0x1c +'Ya ', # 0x1d +'Yao ', # 0x1e +'Song ', # 0x1f +'Shen ', # 0x20 +'Yin ', # 0x21 +'Xin ', # 0x22 +'Jue ', # 0x23 +'Xiao ', # 0x24 +'Ne ', # 0x25 +'Chen ', # 0x26 +'You ', # 0x27 +'Zhi ', # 0x28 +'Xiong ', # 0x29 +'Fang ', # 0x2a +'Xin ', # 0x2b +'Chao ', # 0x2c +'She ', # 0x2d +'Xian ', # 0x2e +'Sha ', # 0x2f +'Tun ', # 0x30 +'Xu ', # 0x31 +'Yi ', # 0x32 +'Yi ', # 0x33 +'Su ', # 0x34 +'Chi ', # 0x35 +'He ', # 0x36 +'Shen ', # 0x37 +'He ', # 0x38 +'Xu ', # 0x39 +'Zhen ', # 0x3a +'Zhu ', # 0x3b +'Zheng ', # 0x3c +'Gou ', # 0x3d +'Zi ', # 0x3e +'Zi ', # 0x3f +'Zhan ', # 0x40 +'Gu ', # 0x41 +'Fu ', # 0x42 +'Quan ', # 0x43 +'Die ', # 0x44 +'Ling ', # 0x45 +'Di ', # 0x46 +'Yang ', # 0x47 +'Li ', # 0x48 +'Nao ', # 0x49 +'Pan ', # 0x4a +'Zhou ', # 0x4b +'Gan ', # 0x4c +'Yi ', # 0x4d +'Ju ', # 0x4e +'Ao ', # 0x4f +'Zha ', # 0x50 +'Tuo ', # 0x51 +'Yi ', # 0x52 +'Qu ', # 0x53 +'Zhao ', # 0x54 +'Ping ', # 0x55 +'Bi ', # 0x56 +'Xiong ', # 0x57 +'Qu ', # 0x58 +'Ba ', # 0x59 +'Da ', # 0x5a +'Zu ', # 0x5b +'Tao ', # 0x5c +'Zhu ', # 0x5d +'Ci ', # 0x5e +'Zhe ', # 0x5f +'Yong ', # 0x60 +'Xu ', # 0x61 +'Xun ', # 0x62 +'Yi ', # 0x63 +'Huang ', # 0x64 +'He ', # 0x65 +'Shi ', # 0x66 +'Cha ', # 0x67 +'Jiao ', # 0x68 +'Shi ', # 0x69 +'Hen ', # 0x6a +'Cha ', # 0x6b +'Gou ', # 0x6c +'Gui ', # 0x6d +'Quan ', # 0x6e +'Hui ', # 0x6f +'Jie ', # 0x70 +'Hua ', # 0x71 +'Gai ', # 0x72 +'Xiang ', # 0x73 +'Wei ', # 0x74 +'Shen ', # 0x75 +'Chou ', # 0x76 +'Tong ', # 0x77 +'Mi ', # 0x78 +'Zhan ', # 0x79 +'Ming ', # 0x7a +'E ', # 0x7b +'Hui ', # 0x7c +'Yan ', # 0x7d +'Xiong ', # 0x7e +'Gua ', # 0x7f +'Er ', # 0x80 +'Beng ', # 0x81 +'Tiao ', # 0x82 +'Chi ', # 0x83 +'Lei ', # 0x84 +'Zhu ', # 0x85 +'Kuang ', # 0x86 +'Kua ', # 0x87 +'Wu ', # 0x88 +'Yu ', # 0x89 +'Teng ', # 0x8a +'Ji ', # 0x8b +'Zhi ', # 0x8c +'Ren ', # 0x8d +'Su ', # 0x8e +'Lang ', # 0x8f +'E ', # 0x90 +'Kuang ', # 0x91 +'E ', # 0x92 +'Shi ', # 0x93 +'Ting ', # 0x94 +'Dan ', # 0x95 +'Bo ', # 0x96 +'Chan ', # 0x97 +'You ', # 0x98 +'Heng ', # 0x99 +'Qiao ', # 0x9a +'Qin ', # 0x9b +'Shua ', # 0x9c +'An ', # 0x9d +'Yu ', # 0x9e +'Xiao ', # 0x9f +'Cheng ', # 0xa0 +'Jie ', # 0xa1 +'Xian ', # 0xa2 +'Wu ', # 0xa3 +'Wu ', # 0xa4 +'Gao ', # 0xa5 +'Song ', # 0xa6 +'Pu ', # 0xa7 +'Hui ', # 0xa8 +'Jing ', # 0xa9 +'Shuo ', # 0xaa +'Zhen ', # 0xab +'Shuo ', # 0xac +'Du ', # 0xad +'Yasashi ', # 0xae +'Chang ', # 0xaf +'Shui ', # 0xb0 +'Jie ', # 0xb1 +'Ke ', # 0xb2 +'Qu ', # 0xb3 +'Cong ', # 0xb4 +'Xiao ', # 0xb5 +'Sui ', # 0xb6 +'Wang ', # 0xb7 +'Xuan ', # 0xb8 +'Fei ', # 0xb9 +'Chi ', # 0xba +'Ta ', # 0xbb +'Yi ', # 0xbc +'Na ', # 0xbd +'Yin ', # 0xbe +'Diao ', # 0xbf +'Pi ', # 0xc0 +'Chuo ', # 0xc1 +'Chan ', # 0xc2 +'Chen ', # 0xc3 +'Zhun ', # 0xc4 +'Ji ', # 0xc5 +'Qi ', # 0xc6 +'Tan ', # 0xc7 +'Zhui ', # 0xc8 +'Wei ', # 0xc9 +'Ju ', # 0xca +'Qing ', # 0xcb +'Jian ', # 0xcc +'Zheng ', # 0xcd +'Ze ', # 0xce +'Zou ', # 0xcf +'Qian ', # 0xd0 +'Zhuo ', # 0xd1 +'Liang ', # 0xd2 +'Jian ', # 0xd3 +'Zhu ', # 0xd4 +'Hao ', # 0xd5 +'Lun ', # 0xd6 +'Shen ', # 0xd7 +'Biao ', # 0xd8 +'Huai ', # 0xd9 +'Pian ', # 0xda +'Yu ', # 0xdb +'Die ', # 0xdc +'Xu ', # 0xdd +'Pian ', # 0xde +'Shi ', # 0xdf +'Xuan ', # 0xe0 +'Shi ', # 0xe1 +'Hun ', # 0xe2 +'Hua ', # 0xe3 +'E ', # 0xe4 +'Zhong ', # 0xe5 +'Di ', # 0xe6 +'Xie ', # 0xe7 +'Fu ', # 0xe8 +'Pu ', # 0xe9 +'Ting ', # 0xea +'Jian ', # 0xeb +'Qi ', # 0xec +'Yu ', # 0xed +'Zi ', # 0xee +'Chuan ', # 0xef +'Xi ', # 0xf0 +'Hui ', # 0xf1 +'Yin ', # 0xf2 +'An ', # 0xf3 +'Xian ', # 0xf4 +'Nan ', # 0xf5 +'Chen ', # 0xf6 +'Feng ', # 0xf7 +'Zhu ', # 0xf8 +'Yang ', # 0xf9 +'Yan ', # 0xfa +'Heng ', # 0xfb +'Xuan ', # 0xfc +'Ge ', # 0xfd +'Nuo ', # 0xfe +'Qi ', # 0xff +) diff --git a/nstock/modules/unidecode/x08b.py b/nstock/modules/unidecode/x08b.py new file mode 100644 index 0000000..b89c37a --- /dev/null +++ b/nstock/modules/unidecode/x08b.py @@ -0,0 +1,258 @@ +data = ( +'Mou ', # 0x00 +'Ye ', # 0x01 +'Wei ', # 0x02 +'[?] ', # 0x03 +'Teng ', # 0x04 +'Zou ', # 0x05 +'Shan ', # 0x06 +'Jian ', # 0x07 +'Bo ', # 0x08 +'Ku ', # 0x09 +'Huang ', # 0x0a +'Huo ', # 0x0b +'Ge ', # 0x0c +'Ying ', # 0x0d +'Mi ', # 0x0e +'Xiao ', # 0x0f +'Mi ', # 0x10 +'Xi ', # 0x11 +'Qiang ', # 0x12 +'Chen ', # 0x13 +'Nue ', # 0x14 +'Ti ', # 0x15 +'Su ', # 0x16 +'Bang ', # 0x17 +'Chi ', # 0x18 +'Qian ', # 0x19 +'Shi ', # 0x1a +'Jiang ', # 0x1b +'Yuan ', # 0x1c +'Xie ', # 0x1d +'Xue ', # 0x1e +'Tao ', # 0x1f +'Yao ', # 0x20 +'Yao ', # 0x21 +'[?] ', # 0x22 +'Yu ', # 0x23 +'Biao ', # 0x24 +'Cong ', # 0x25 +'Qing ', # 0x26 +'Li ', # 0x27 +'Mo ', # 0x28 +'Mo ', # 0x29 +'Shang ', # 0x2a +'Zhe ', # 0x2b +'Miu ', # 0x2c +'Jian ', # 0x2d +'Ze ', # 0x2e +'Jie ', # 0x2f +'Lian ', # 0x30 +'Lou ', # 0x31 +'Can ', # 0x32 +'Ou ', # 0x33 +'Guan ', # 0x34 +'Xi ', # 0x35 +'Zhuo ', # 0x36 +'Ao ', # 0x37 +'Ao ', # 0x38 +'Jin ', # 0x39 +'Zhe ', # 0x3a +'Yi ', # 0x3b +'Hu ', # 0x3c +'Jiang ', # 0x3d +'Man ', # 0x3e +'Chao ', # 0x3f +'Han ', # 0x40 +'Hua ', # 0x41 +'Chan ', # 0x42 +'Xu ', # 0x43 +'Zeng ', # 0x44 +'Se ', # 0x45 +'Xi ', # 0x46 +'She ', # 0x47 +'Dui ', # 0x48 +'Zheng ', # 0x49 +'Nao ', # 0x4a +'Lan ', # 0x4b +'E ', # 0x4c +'Ying ', # 0x4d +'Jue ', # 0x4e +'Ji ', # 0x4f +'Zun ', # 0x50 +'Jiao ', # 0x51 +'Bo ', # 0x52 +'Hui ', # 0x53 +'Zhuan ', # 0x54 +'Mu ', # 0x55 +'Zen ', # 0x56 +'Zha ', # 0x57 +'Shi ', # 0x58 +'Qiao ', # 0x59 +'Tan ', # 0x5a +'Zen ', # 0x5b +'Pu ', # 0x5c +'Sheng ', # 0x5d +'Xuan ', # 0x5e +'Zao ', # 0x5f +'Tan ', # 0x60 +'Dang ', # 0x61 +'Sui ', # 0x62 +'Qian ', # 0x63 +'Ji ', # 0x64 +'Jiao ', # 0x65 +'Jing ', # 0x66 +'Lian ', # 0x67 +'Nou ', # 0x68 +'Yi ', # 0x69 +'Ai ', # 0x6a +'Zhan ', # 0x6b +'Pi ', # 0x6c +'Hui ', # 0x6d +'Hua ', # 0x6e +'Yi ', # 0x6f +'Yi ', # 0x70 +'Shan ', # 0x71 +'Rang ', # 0x72 +'Nou ', # 0x73 +'Qian ', # 0x74 +'Zhui ', # 0x75 +'Ta ', # 0x76 +'Hu ', # 0x77 +'Zhou ', # 0x78 +'Hao ', # 0x79 +'Ye ', # 0x7a +'Ying ', # 0x7b +'Jian ', # 0x7c +'Yu ', # 0x7d +'Jian ', # 0x7e +'Hui ', # 0x7f +'Du ', # 0x80 +'Zhe ', # 0x81 +'Xuan ', # 0x82 +'Zan ', # 0x83 +'Lei ', # 0x84 +'Shen ', # 0x85 +'Wei ', # 0x86 +'Chan ', # 0x87 +'Li ', # 0x88 +'Yi ', # 0x89 +'Bian ', # 0x8a +'Zhe ', # 0x8b +'Yan ', # 0x8c +'E ', # 0x8d +'Chou ', # 0x8e +'Wei ', # 0x8f +'Chou ', # 0x90 +'Yao ', # 0x91 +'Chan ', # 0x92 +'Rang ', # 0x93 +'Yin ', # 0x94 +'Lan ', # 0x95 +'Chen ', # 0x96 +'Huo ', # 0x97 +'Zhe ', # 0x98 +'Huan ', # 0x99 +'Zan ', # 0x9a +'Yi ', # 0x9b +'Dang ', # 0x9c +'Zhan ', # 0x9d +'Yan ', # 0x9e +'Du ', # 0x9f +'Yan ', # 0xa0 +'Ji ', # 0xa1 +'Ding ', # 0xa2 +'Fu ', # 0xa3 +'Ren ', # 0xa4 +'Ji ', # 0xa5 +'Jie ', # 0xa6 +'Hong ', # 0xa7 +'Tao ', # 0xa8 +'Rang ', # 0xa9 +'Shan ', # 0xaa +'Qi ', # 0xab +'Tuo ', # 0xac +'Xun ', # 0xad +'Yi ', # 0xae +'Xun ', # 0xaf +'Ji ', # 0xb0 +'Ren ', # 0xb1 +'Jiang ', # 0xb2 +'Hui ', # 0xb3 +'Ou ', # 0xb4 +'Ju ', # 0xb5 +'Ya ', # 0xb6 +'Ne ', # 0xb7 +'Xu ', # 0xb8 +'E ', # 0xb9 +'Lun ', # 0xba +'Xiong ', # 0xbb +'Song ', # 0xbc +'Feng ', # 0xbd +'She ', # 0xbe +'Fang ', # 0xbf +'Jue ', # 0xc0 +'Zheng ', # 0xc1 +'Gu ', # 0xc2 +'He ', # 0xc3 +'Ping ', # 0xc4 +'Zu ', # 0xc5 +'Shi ', # 0xc6 +'Xiong ', # 0xc7 +'Zha ', # 0xc8 +'Su ', # 0xc9 +'Zhen ', # 0xca +'Di ', # 0xcb +'Zou ', # 0xcc +'Ci ', # 0xcd +'Qu ', # 0xce +'Zhao ', # 0xcf +'Bi ', # 0xd0 +'Yi ', # 0xd1 +'Yi ', # 0xd2 +'Kuang ', # 0xd3 +'Lei ', # 0xd4 +'Shi ', # 0xd5 +'Gua ', # 0xd6 +'Shi ', # 0xd7 +'Jie ', # 0xd8 +'Hui ', # 0xd9 +'Cheng ', # 0xda +'Zhu ', # 0xdb +'Shen ', # 0xdc +'Hua ', # 0xdd +'Dan ', # 0xde +'Gou ', # 0xdf +'Quan ', # 0xe0 +'Gui ', # 0xe1 +'Xun ', # 0xe2 +'Yi ', # 0xe3 +'Zheng ', # 0xe4 +'Gai ', # 0xe5 +'Xiang ', # 0xe6 +'Cha ', # 0xe7 +'Hun ', # 0xe8 +'Xu ', # 0xe9 +'Zhou ', # 0xea +'Jie ', # 0xeb +'Wu ', # 0xec +'Yu ', # 0xed +'Qiao ', # 0xee +'Wu ', # 0xef +'Gao ', # 0xf0 +'You ', # 0xf1 +'Hui ', # 0xf2 +'Kuang ', # 0xf3 +'Shuo ', # 0xf4 +'Song ', # 0xf5 +'Ai ', # 0xf6 +'Qing ', # 0xf7 +'Zhu ', # 0xf8 +'Zou ', # 0xf9 +'Nuo ', # 0xfa +'Du ', # 0xfb +'Zhuo ', # 0xfc +'Fei ', # 0xfd +'Ke ', # 0xfe +'Wei ', # 0xff +) diff --git a/nstock/modules/unidecode/x08c.py b/nstock/modules/unidecode/x08c.py new file mode 100644 index 0000000..514c446 --- /dev/null +++ b/nstock/modules/unidecode/x08c.py @@ -0,0 +1,258 @@ +data = ( +'Yu ', # 0x00 +'Shui ', # 0x01 +'Shen ', # 0x02 +'Diao ', # 0x03 +'Chan ', # 0x04 +'Liang ', # 0x05 +'Zhun ', # 0x06 +'Sui ', # 0x07 +'Tan ', # 0x08 +'Shen ', # 0x09 +'Yi ', # 0x0a +'Mou ', # 0x0b +'Chen ', # 0x0c +'Die ', # 0x0d +'Huang ', # 0x0e +'Jian ', # 0x0f +'Xie ', # 0x10 +'Nue ', # 0x11 +'Ye ', # 0x12 +'Wei ', # 0x13 +'E ', # 0x14 +'Yu ', # 0x15 +'Xuan ', # 0x16 +'Chan ', # 0x17 +'Zi ', # 0x18 +'An ', # 0x19 +'Yan ', # 0x1a +'Di ', # 0x1b +'Mi ', # 0x1c +'Pian ', # 0x1d +'Xu ', # 0x1e +'Mo ', # 0x1f +'Dang ', # 0x20 +'Su ', # 0x21 +'Xie ', # 0x22 +'Yao ', # 0x23 +'Bang ', # 0x24 +'Shi ', # 0x25 +'Qian ', # 0x26 +'Mi ', # 0x27 +'Jin ', # 0x28 +'Man ', # 0x29 +'Zhe ', # 0x2a +'Jian ', # 0x2b +'Miu ', # 0x2c +'Tan ', # 0x2d +'Zen ', # 0x2e +'Qiao ', # 0x2f +'Lan ', # 0x30 +'Pu ', # 0x31 +'Jue ', # 0x32 +'Yan ', # 0x33 +'Qian ', # 0x34 +'Zhan ', # 0x35 +'Chen ', # 0x36 +'Gu ', # 0x37 +'Qian ', # 0x38 +'Hong ', # 0x39 +'Xia ', # 0x3a +'Jue ', # 0x3b +'Hong ', # 0x3c +'Han ', # 0x3d +'Hong ', # 0x3e +'Xi ', # 0x3f +'Xi ', # 0x40 +'Huo ', # 0x41 +'Liao ', # 0x42 +'Han ', # 0x43 +'Du ', # 0x44 +'Long ', # 0x45 +'Dou ', # 0x46 +'Jiang ', # 0x47 +'Qi ', # 0x48 +'Shi ', # 0x49 +'Li ', # 0x4a +'Deng ', # 0x4b +'Wan ', # 0x4c +'Bi ', # 0x4d +'Shu ', # 0x4e +'Xian ', # 0x4f +'Feng ', # 0x50 +'Zhi ', # 0x51 +'Zhi ', # 0x52 +'Yan ', # 0x53 +'Yan ', # 0x54 +'Shi ', # 0x55 +'Chu ', # 0x56 +'Hui ', # 0x57 +'Tun ', # 0x58 +'Yi ', # 0x59 +'Tun ', # 0x5a +'Yi ', # 0x5b +'Jian ', # 0x5c +'Ba ', # 0x5d +'Hou ', # 0x5e +'E ', # 0x5f +'Cu ', # 0x60 +'Xiang ', # 0x61 +'Huan ', # 0x62 +'Jian ', # 0x63 +'Ken ', # 0x64 +'Gai ', # 0x65 +'Qu ', # 0x66 +'Fu ', # 0x67 +'Xi ', # 0x68 +'Bin ', # 0x69 +'Hao ', # 0x6a +'Yu ', # 0x6b +'Zhu ', # 0x6c +'Jia ', # 0x6d +'[?] ', # 0x6e +'Xi ', # 0x6f +'Bo ', # 0x70 +'Wen ', # 0x71 +'Huan ', # 0x72 +'Bin ', # 0x73 +'Di ', # 0x74 +'Zong ', # 0x75 +'Fen ', # 0x76 +'Yi ', # 0x77 +'Zhi ', # 0x78 +'Bao ', # 0x79 +'Chai ', # 0x7a +'Han ', # 0x7b +'Pi ', # 0x7c +'Na ', # 0x7d +'Pi ', # 0x7e +'Gou ', # 0x7f +'Na ', # 0x80 +'You ', # 0x81 +'Diao ', # 0x82 +'Mo ', # 0x83 +'Si ', # 0x84 +'Xiu ', # 0x85 +'Huan ', # 0x86 +'Kun ', # 0x87 +'He ', # 0x88 +'He ', # 0x89 +'Mo ', # 0x8a +'Han ', # 0x8b +'Mao ', # 0x8c +'Li ', # 0x8d +'Ni ', # 0x8e +'Bi ', # 0x8f +'Yu ', # 0x90 +'Jia ', # 0x91 +'Tuan ', # 0x92 +'Mao ', # 0x93 +'Pi ', # 0x94 +'Xi ', # 0x95 +'E ', # 0x96 +'Ju ', # 0x97 +'Mo ', # 0x98 +'Chu ', # 0x99 +'Tan ', # 0x9a +'Huan ', # 0x9b +'Jue ', # 0x9c +'Bei ', # 0x9d +'Zhen ', # 0x9e +'Yuan ', # 0x9f +'Fu ', # 0xa0 +'Cai ', # 0xa1 +'Gong ', # 0xa2 +'Te ', # 0xa3 +'Yi ', # 0xa4 +'Hang ', # 0xa5 +'Wan ', # 0xa6 +'Pin ', # 0xa7 +'Huo ', # 0xa8 +'Fan ', # 0xa9 +'Tan ', # 0xaa +'Guan ', # 0xab +'Ze ', # 0xac +'Zhi ', # 0xad +'Er ', # 0xae +'Zhu ', # 0xaf +'Shi ', # 0xb0 +'Bi ', # 0xb1 +'Zi ', # 0xb2 +'Er ', # 0xb3 +'Gui ', # 0xb4 +'Pian ', # 0xb5 +'Bian ', # 0xb6 +'Mai ', # 0xb7 +'Dai ', # 0xb8 +'Sheng ', # 0xb9 +'Kuang ', # 0xba +'Fei ', # 0xbb +'Tie ', # 0xbc +'Yi ', # 0xbd +'Chi ', # 0xbe +'Mao ', # 0xbf +'He ', # 0xc0 +'Bi ', # 0xc1 +'Lu ', # 0xc2 +'Ren ', # 0xc3 +'Hui ', # 0xc4 +'Gai ', # 0xc5 +'Pian ', # 0xc6 +'Zi ', # 0xc7 +'Jia ', # 0xc8 +'Xu ', # 0xc9 +'Zei ', # 0xca +'Jiao ', # 0xcb +'Gai ', # 0xcc +'Zang ', # 0xcd +'Jian ', # 0xce +'Ying ', # 0xcf +'Xun ', # 0xd0 +'Zhen ', # 0xd1 +'She ', # 0xd2 +'Bin ', # 0xd3 +'Bin ', # 0xd4 +'Qiu ', # 0xd5 +'She ', # 0xd6 +'Chuan ', # 0xd7 +'Zang ', # 0xd8 +'Zhou ', # 0xd9 +'Lai ', # 0xda +'Zan ', # 0xdb +'Si ', # 0xdc +'Chen ', # 0xdd +'Shang ', # 0xde +'Tian ', # 0xdf +'Pei ', # 0xe0 +'Geng ', # 0xe1 +'Xian ', # 0xe2 +'Mai ', # 0xe3 +'Jian ', # 0xe4 +'Sui ', # 0xe5 +'Fu ', # 0xe6 +'Tan ', # 0xe7 +'Cong ', # 0xe8 +'Cong ', # 0xe9 +'Zhi ', # 0xea +'Ji ', # 0xeb +'Zhang ', # 0xec +'Du ', # 0xed +'Jin ', # 0xee +'Xiong ', # 0xef +'Shun ', # 0xf0 +'Yun ', # 0xf1 +'Bao ', # 0xf2 +'Zai ', # 0xf3 +'Lai ', # 0xf4 +'Feng ', # 0xf5 +'Cang ', # 0xf6 +'Ji ', # 0xf7 +'Sheng ', # 0xf8 +'Ai ', # 0xf9 +'Zhuan ', # 0xfa +'Fu ', # 0xfb +'Gou ', # 0xfc +'Sai ', # 0xfd +'Ze ', # 0xfe +'Liao ', # 0xff +) diff --git a/nstock/modules/unidecode/x08d.py b/nstock/modules/unidecode/x08d.py new file mode 100644 index 0000000..ae63f22 --- /dev/null +++ b/nstock/modules/unidecode/x08d.py @@ -0,0 +1,258 @@ +data = ( +'Wei ', # 0x00 +'Bai ', # 0x01 +'Chen ', # 0x02 +'Zhuan ', # 0x03 +'Zhi ', # 0x04 +'Zhui ', # 0x05 +'Biao ', # 0x06 +'Yun ', # 0x07 +'Zeng ', # 0x08 +'Tan ', # 0x09 +'Zan ', # 0x0a +'Yan ', # 0x0b +'[?] ', # 0x0c +'Shan ', # 0x0d +'Wan ', # 0x0e +'Ying ', # 0x0f +'Jin ', # 0x10 +'Gan ', # 0x11 +'Xian ', # 0x12 +'Zang ', # 0x13 +'Bi ', # 0x14 +'Du ', # 0x15 +'Shu ', # 0x16 +'Yan ', # 0x17 +'[?] ', # 0x18 +'Xuan ', # 0x19 +'Long ', # 0x1a +'Gan ', # 0x1b +'Zang ', # 0x1c +'Bei ', # 0x1d +'Zhen ', # 0x1e +'Fu ', # 0x1f +'Yuan ', # 0x20 +'Gong ', # 0x21 +'Cai ', # 0x22 +'Ze ', # 0x23 +'Xian ', # 0x24 +'Bai ', # 0x25 +'Zhang ', # 0x26 +'Huo ', # 0x27 +'Zhi ', # 0x28 +'Fan ', # 0x29 +'Tan ', # 0x2a +'Pin ', # 0x2b +'Bian ', # 0x2c +'Gou ', # 0x2d +'Zhu ', # 0x2e +'Guan ', # 0x2f +'Er ', # 0x30 +'Jian ', # 0x31 +'Bi ', # 0x32 +'Shi ', # 0x33 +'Tie ', # 0x34 +'Gui ', # 0x35 +'Kuang ', # 0x36 +'Dai ', # 0x37 +'Mao ', # 0x38 +'Fei ', # 0x39 +'He ', # 0x3a +'Yi ', # 0x3b +'Zei ', # 0x3c +'Zhi ', # 0x3d +'Jia ', # 0x3e +'Hui ', # 0x3f +'Zi ', # 0x40 +'Ren ', # 0x41 +'Lu ', # 0x42 +'Zang ', # 0x43 +'Zi ', # 0x44 +'Gai ', # 0x45 +'Jin ', # 0x46 +'Qiu ', # 0x47 +'Zhen ', # 0x48 +'Lai ', # 0x49 +'She ', # 0x4a +'Fu ', # 0x4b +'Du ', # 0x4c +'Ji ', # 0x4d +'Shu ', # 0x4e +'Shang ', # 0x4f +'Si ', # 0x50 +'Bi ', # 0x51 +'Zhou ', # 0x52 +'Geng ', # 0x53 +'Pei ', # 0x54 +'Tan ', # 0x55 +'Lai ', # 0x56 +'Feng ', # 0x57 +'Zhui ', # 0x58 +'Fu ', # 0x59 +'Zhuan ', # 0x5a +'Sai ', # 0x5b +'Ze ', # 0x5c +'Yan ', # 0x5d +'Zan ', # 0x5e +'Yun ', # 0x5f +'Zeng ', # 0x60 +'Shan ', # 0x61 +'Ying ', # 0x62 +'Gan ', # 0x63 +'Chi ', # 0x64 +'Xi ', # 0x65 +'She ', # 0x66 +'Nan ', # 0x67 +'Xiong ', # 0x68 +'Xi ', # 0x69 +'Cheng ', # 0x6a +'He ', # 0x6b +'Cheng ', # 0x6c +'Zhe ', # 0x6d +'Xia ', # 0x6e +'Tang ', # 0x6f +'Zou ', # 0x70 +'Zou ', # 0x71 +'Li ', # 0x72 +'Jiu ', # 0x73 +'Fu ', # 0x74 +'Zhao ', # 0x75 +'Gan ', # 0x76 +'Qi ', # 0x77 +'Shan ', # 0x78 +'Qiong ', # 0x79 +'Qin ', # 0x7a +'Xian ', # 0x7b +'Ci ', # 0x7c +'Jue ', # 0x7d +'Qin ', # 0x7e +'Chi ', # 0x7f +'Ci ', # 0x80 +'Chen ', # 0x81 +'Chen ', # 0x82 +'Die ', # 0x83 +'Ju ', # 0x84 +'Chao ', # 0x85 +'Di ', # 0x86 +'Se ', # 0x87 +'Zhan ', # 0x88 +'Zhu ', # 0x89 +'Yue ', # 0x8a +'Qu ', # 0x8b +'Jie ', # 0x8c +'Chi ', # 0x8d +'Chu ', # 0x8e +'Gua ', # 0x8f +'Xue ', # 0x90 +'Ci ', # 0x91 +'Tiao ', # 0x92 +'Duo ', # 0x93 +'Lie ', # 0x94 +'Gan ', # 0x95 +'Suo ', # 0x96 +'Cu ', # 0x97 +'Xi ', # 0x98 +'Zhao ', # 0x99 +'Su ', # 0x9a +'Yin ', # 0x9b +'Ju ', # 0x9c +'Jian ', # 0x9d +'Que ', # 0x9e +'Tang ', # 0x9f +'Chuo ', # 0xa0 +'Cui ', # 0xa1 +'Lu ', # 0xa2 +'Qu ', # 0xa3 +'Dang ', # 0xa4 +'Qiu ', # 0xa5 +'Zi ', # 0xa6 +'Ti ', # 0xa7 +'Qu ', # 0xa8 +'Chi ', # 0xa9 +'Huang ', # 0xaa +'Qiao ', # 0xab +'Qiao ', # 0xac +'Yao ', # 0xad +'Zao ', # 0xae +'Ti ', # 0xaf +'[?] ', # 0xb0 +'Zan ', # 0xb1 +'Zan ', # 0xb2 +'Zu ', # 0xb3 +'Pa ', # 0xb4 +'Bao ', # 0xb5 +'Ku ', # 0xb6 +'Ke ', # 0xb7 +'Dun ', # 0xb8 +'Jue ', # 0xb9 +'Fu ', # 0xba +'Chen ', # 0xbb +'Jian ', # 0xbc +'Fang ', # 0xbd +'Zhi ', # 0xbe +'Sa ', # 0xbf +'Yue ', # 0xc0 +'Pa ', # 0xc1 +'Qi ', # 0xc2 +'Yue ', # 0xc3 +'Qiang ', # 0xc4 +'Tuo ', # 0xc5 +'Tai ', # 0xc6 +'Yi ', # 0xc7 +'Nian ', # 0xc8 +'Ling ', # 0xc9 +'Mei ', # 0xca +'Ba ', # 0xcb +'Die ', # 0xcc +'Ku ', # 0xcd +'Tuo ', # 0xce +'Jia ', # 0xcf +'Ci ', # 0xd0 +'Pao ', # 0xd1 +'Qia ', # 0xd2 +'Zhu ', # 0xd3 +'Ju ', # 0xd4 +'Die ', # 0xd5 +'Zhi ', # 0xd6 +'Fu ', # 0xd7 +'Pan ', # 0xd8 +'Ju ', # 0xd9 +'Shan ', # 0xda +'Bo ', # 0xdb +'Ni ', # 0xdc +'Ju ', # 0xdd +'Li ', # 0xde +'Gen ', # 0xdf +'Yi ', # 0xe0 +'Ji ', # 0xe1 +'Dai ', # 0xe2 +'Xian ', # 0xe3 +'Jiao ', # 0xe4 +'Duo ', # 0xe5 +'Zhu ', # 0xe6 +'Zhuan ', # 0xe7 +'Kua ', # 0xe8 +'Zhuai ', # 0xe9 +'Gui ', # 0xea +'Qiong ', # 0xeb +'Kui ', # 0xec +'Xiang ', # 0xed +'Chi ', # 0xee +'Lu ', # 0xef +'Beng ', # 0xf0 +'Zhi ', # 0xf1 +'Jia ', # 0xf2 +'Tiao ', # 0xf3 +'Cai ', # 0xf4 +'Jian ', # 0xf5 +'Ta ', # 0xf6 +'Qiao ', # 0xf7 +'Bi ', # 0xf8 +'Xian ', # 0xf9 +'Duo ', # 0xfa +'Ji ', # 0xfb +'Ju ', # 0xfc +'Ji ', # 0xfd +'Shu ', # 0xfe +'Tu ', # 0xff +) diff --git a/nstock/modules/unidecode/x08e.py b/nstock/modules/unidecode/x08e.py new file mode 100644 index 0000000..015ed1e --- /dev/null +++ b/nstock/modules/unidecode/x08e.py @@ -0,0 +1,258 @@ +data = ( +'Chu ', # 0x00 +'Jing ', # 0x01 +'Nie ', # 0x02 +'Xiao ', # 0x03 +'Bo ', # 0x04 +'Chi ', # 0x05 +'Qun ', # 0x06 +'Mou ', # 0x07 +'Shu ', # 0x08 +'Lang ', # 0x09 +'Yong ', # 0x0a +'Jiao ', # 0x0b +'Chou ', # 0x0c +'Qiao ', # 0x0d +'[?] ', # 0x0e +'Ta ', # 0x0f +'Jian ', # 0x10 +'Qi ', # 0x11 +'Wo ', # 0x12 +'Wei ', # 0x13 +'Zhuo ', # 0x14 +'Jie ', # 0x15 +'Ji ', # 0x16 +'Nie ', # 0x17 +'Ju ', # 0x18 +'Ju ', # 0x19 +'Lun ', # 0x1a +'Lu ', # 0x1b +'Leng ', # 0x1c +'Huai ', # 0x1d +'Ju ', # 0x1e +'Chi ', # 0x1f +'Wan ', # 0x20 +'Quan ', # 0x21 +'Ti ', # 0x22 +'Bo ', # 0x23 +'Zu ', # 0x24 +'Qie ', # 0x25 +'Ji ', # 0x26 +'Cu ', # 0x27 +'Zong ', # 0x28 +'Cai ', # 0x29 +'Zong ', # 0x2a +'Peng ', # 0x2b +'Zhi ', # 0x2c +'Zheng ', # 0x2d +'Dian ', # 0x2e +'Zhi ', # 0x2f +'Yu ', # 0x30 +'Duo ', # 0x31 +'Dun ', # 0x32 +'Chun ', # 0x33 +'Yong ', # 0x34 +'Zhong ', # 0x35 +'Di ', # 0x36 +'Zhe ', # 0x37 +'Chen ', # 0x38 +'Chuai ', # 0x39 +'Jian ', # 0x3a +'Gua ', # 0x3b +'Tang ', # 0x3c +'Ju ', # 0x3d +'Fu ', # 0x3e +'Zu ', # 0x3f +'Die ', # 0x40 +'Pian ', # 0x41 +'Rou ', # 0x42 +'Nuo ', # 0x43 +'Ti ', # 0x44 +'Cha ', # 0x45 +'Tui ', # 0x46 +'Jian ', # 0x47 +'Dao ', # 0x48 +'Cuo ', # 0x49 +'Xi ', # 0x4a +'Ta ', # 0x4b +'Qiang ', # 0x4c +'Zhan ', # 0x4d +'Dian ', # 0x4e +'Ti ', # 0x4f +'Ji ', # 0x50 +'Nie ', # 0x51 +'Man ', # 0x52 +'Liu ', # 0x53 +'Zhan ', # 0x54 +'Bi ', # 0x55 +'Chong ', # 0x56 +'Lu ', # 0x57 +'Liao ', # 0x58 +'Cu ', # 0x59 +'Tang ', # 0x5a +'Dai ', # 0x5b +'Suo ', # 0x5c +'Xi ', # 0x5d +'Kui ', # 0x5e +'Ji ', # 0x5f +'Zhi ', # 0x60 +'Qiang ', # 0x61 +'Di ', # 0x62 +'Man ', # 0x63 +'Zong ', # 0x64 +'Lian ', # 0x65 +'Beng ', # 0x66 +'Zao ', # 0x67 +'Nian ', # 0x68 +'Bie ', # 0x69 +'Tui ', # 0x6a +'Ju ', # 0x6b +'Deng ', # 0x6c +'Ceng ', # 0x6d +'Xian ', # 0x6e +'Fan ', # 0x6f +'Chu ', # 0x70 +'Zhong ', # 0x71 +'Dun ', # 0x72 +'Bo ', # 0x73 +'Cu ', # 0x74 +'Zu ', # 0x75 +'Jue ', # 0x76 +'Jue ', # 0x77 +'Lin ', # 0x78 +'Ta ', # 0x79 +'Qiao ', # 0x7a +'Qiao ', # 0x7b +'Pu ', # 0x7c +'Liao ', # 0x7d +'Dun ', # 0x7e +'Cuan ', # 0x7f +'Kuang ', # 0x80 +'Zao ', # 0x81 +'Ta ', # 0x82 +'Bi ', # 0x83 +'Bi ', # 0x84 +'Zhu ', # 0x85 +'Ju ', # 0x86 +'Chu ', # 0x87 +'Qiao ', # 0x88 +'Dun ', # 0x89 +'Chou ', # 0x8a +'Ji ', # 0x8b +'Wu ', # 0x8c +'Yue ', # 0x8d +'Nian ', # 0x8e +'Lin ', # 0x8f +'Lie ', # 0x90 +'Zhi ', # 0x91 +'Li ', # 0x92 +'Zhi ', # 0x93 +'Chan ', # 0x94 +'Chu ', # 0x95 +'Duan ', # 0x96 +'Wei ', # 0x97 +'Long ', # 0x98 +'Lin ', # 0x99 +'Xian ', # 0x9a +'Wei ', # 0x9b +'Zuan ', # 0x9c +'Lan ', # 0x9d +'Xie ', # 0x9e +'Rang ', # 0x9f +'Xie ', # 0xa0 +'Nie ', # 0xa1 +'Ta ', # 0xa2 +'Qu ', # 0xa3 +'Jie ', # 0xa4 +'Cuan ', # 0xa5 +'Zuan ', # 0xa6 +'Xi ', # 0xa7 +'Kui ', # 0xa8 +'Jue ', # 0xa9 +'Lin ', # 0xaa +'Shen ', # 0xab +'Gong ', # 0xac +'Dan ', # 0xad +'Segare ', # 0xae +'Qu ', # 0xaf +'Ti ', # 0xb0 +'Duo ', # 0xb1 +'Duo ', # 0xb2 +'Gong ', # 0xb3 +'Lang ', # 0xb4 +'Nerau ', # 0xb5 +'Luo ', # 0xb6 +'Ai ', # 0xb7 +'Ji ', # 0xb8 +'Ju ', # 0xb9 +'Tang ', # 0xba +'Utsuke ', # 0xbb +'[?] ', # 0xbc +'Yan ', # 0xbd +'Shitsuke ', # 0xbe +'Kang ', # 0xbf +'Qu ', # 0xc0 +'Lou ', # 0xc1 +'Lao ', # 0xc2 +'Tuo ', # 0xc3 +'Zhi ', # 0xc4 +'Yagate ', # 0xc5 +'Ti ', # 0xc6 +'Dao ', # 0xc7 +'Yagate ', # 0xc8 +'Yu ', # 0xc9 +'Che ', # 0xca +'Ya ', # 0xcb +'Gui ', # 0xcc +'Jun ', # 0xcd +'Wei ', # 0xce +'Yue ', # 0xcf +'Xin ', # 0xd0 +'Di ', # 0xd1 +'Xuan ', # 0xd2 +'Fan ', # 0xd3 +'Ren ', # 0xd4 +'Shan ', # 0xd5 +'Qiang ', # 0xd6 +'Shu ', # 0xd7 +'Tun ', # 0xd8 +'Chen ', # 0xd9 +'Dai ', # 0xda +'E ', # 0xdb +'Na ', # 0xdc +'Qi ', # 0xdd +'Mao ', # 0xde +'Ruan ', # 0xdf +'Ren ', # 0xe0 +'Fan ', # 0xe1 +'Zhuan ', # 0xe2 +'Hong ', # 0xe3 +'Hu ', # 0xe4 +'Qu ', # 0xe5 +'Huang ', # 0xe6 +'Di ', # 0xe7 +'Ling ', # 0xe8 +'Dai ', # 0xe9 +'Ao ', # 0xea +'Zhen ', # 0xeb +'Fan ', # 0xec +'Kuang ', # 0xed +'Ang ', # 0xee +'Peng ', # 0xef +'Bei ', # 0xf0 +'Gu ', # 0xf1 +'Ku ', # 0xf2 +'Pao ', # 0xf3 +'Zhu ', # 0xf4 +'Rong ', # 0xf5 +'E ', # 0xf6 +'Ba ', # 0xf7 +'Zhou ', # 0xf8 +'Zhi ', # 0xf9 +'Yao ', # 0xfa +'Ke ', # 0xfb +'Yi ', # 0xfc +'Qing ', # 0xfd +'Shi ', # 0xfe +'Ping ', # 0xff +) diff --git a/nstock/modules/unidecode/x08f.py b/nstock/modules/unidecode/x08f.py new file mode 100644 index 0000000..39d04a9 --- /dev/null +++ b/nstock/modules/unidecode/x08f.py @@ -0,0 +1,258 @@ +data = ( +'Er ', # 0x00 +'Qiong ', # 0x01 +'Ju ', # 0x02 +'Jiao ', # 0x03 +'Guang ', # 0x04 +'Lu ', # 0x05 +'Kai ', # 0x06 +'Quan ', # 0x07 +'Zhou ', # 0x08 +'Zai ', # 0x09 +'Zhi ', # 0x0a +'She ', # 0x0b +'Liang ', # 0x0c +'Yu ', # 0x0d +'Shao ', # 0x0e +'You ', # 0x0f +'Huan ', # 0x10 +'Yun ', # 0x11 +'Zhe ', # 0x12 +'Wan ', # 0x13 +'Fu ', # 0x14 +'Qing ', # 0x15 +'Zhou ', # 0x16 +'Ni ', # 0x17 +'Ling ', # 0x18 +'Zhe ', # 0x19 +'Zhan ', # 0x1a +'Liang ', # 0x1b +'Zi ', # 0x1c +'Hui ', # 0x1d +'Wang ', # 0x1e +'Chuo ', # 0x1f +'Guo ', # 0x20 +'Kan ', # 0x21 +'Yi ', # 0x22 +'Peng ', # 0x23 +'Qian ', # 0x24 +'Gun ', # 0x25 +'Nian ', # 0x26 +'Pian ', # 0x27 +'Guan ', # 0x28 +'Bei ', # 0x29 +'Lun ', # 0x2a +'Pai ', # 0x2b +'Liang ', # 0x2c +'Ruan ', # 0x2d +'Rou ', # 0x2e +'Ji ', # 0x2f +'Yang ', # 0x30 +'Xian ', # 0x31 +'Chuan ', # 0x32 +'Cou ', # 0x33 +'Qun ', # 0x34 +'Ge ', # 0x35 +'You ', # 0x36 +'Hong ', # 0x37 +'Shu ', # 0x38 +'Fu ', # 0x39 +'Zi ', # 0x3a +'Fu ', # 0x3b +'Wen ', # 0x3c +'Ben ', # 0x3d +'Zhan ', # 0x3e +'Yu ', # 0x3f +'Wen ', # 0x40 +'Tao ', # 0x41 +'Gu ', # 0x42 +'Zhen ', # 0x43 +'Xia ', # 0x44 +'Yuan ', # 0x45 +'Lu ', # 0x46 +'Jiu ', # 0x47 +'Chao ', # 0x48 +'Zhuan ', # 0x49 +'Wei ', # 0x4a +'Hun ', # 0x4b +'Sori ', # 0x4c +'Che ', # 0x4d +'Jiao ', # 0x4e +'Zhan ', # 0x4f +'Pu ', # 0x50 +'Lao ', # 0x51 +'Fen ', # 0x52 +'Fan ', # 0x53 +'Lin ', # 0x54 +'Ge ', # 0x55 +'Se ', # 0x56 +'Kan ', # 0x57 +'Huan ', # 0x58 +'Yi ', # 0x59 +'Ji ', # 0x5a +'Dui ', # 0x5b +'Er ', # 0x5c +'Yu ', # 0x5d +'Xian ', # 0x5e +'Hong ', # 0x5f +'Lei ', # 0x60 +'Pei ', # 0x61 +'Li ', # 0x62 +'Li ', # 0x63 +'Lu ', # 0x64 +'Lin ', # 0x65 +'Che ', # 0x66 +'Ya ', # 0x67 +'Gui ', # 0x68 +'Xuan ', # 0x69 +'Di ', # 0x6a +'Ren ', # 0x6b +'Zhuan ', # 0x6c +'E ', # 0x6d +'Lun ', # 0x6e +'Ruan ', # 0x6f +'Hong ', # 0x70 +'Ku ', # 0x71 +'Ke ', # 0x72 +'Lu ', # 0x73 +'Zhou ', # 0x74 +'Zhi ', # 0x75 +'Yi ', # 0x76 +'Hu ', # 0x77 +'Zhen ', # 0x78 +'Li ', # 0x79 +'Yao ', # 0x7a +'Qing ', # 0x7b +'Shi ', # 0x7c +'Zai ', # 0x7d +'Zhi ', # 0x7e +'Jiao ', # 0x7f +'Zhou ', # 0x80 +'Quan ', # 0x81 +'Lu ', # 0x82 +'Jiao ', # 0x83 +'Zhe ', # 0x84 +'Fu ', # 0x85 +'Liang ', # 0x86 +'Nian ', # 0x87 +'Bei ', # 0x88 +'Hui ', # 0x89 +'Gun ', # 0x8a +'Wang ', # 0x8b +'Liang ', # 0x8c +'Chuo ', # 0x8d +'Zi ', # 0x8e +'Cou ', # 0x8f +'Fu ', # 0x90 +'Ji ', # 0x91 +'Wen ', # 0x92 +'Shu ', # 0x93 +'Pei ', # 0x94 +'Yuan ', # 0x95 +'Xia ', # 0x96 +'Zhan ', # 0x97 +'Lu ', # 0x98 +'Che ', # 0x99 +'Lin ', # 0x9a +'Xin ', # 0x9b +'Gu ', # 0x9c +'Ci ', # 0x9d +'Ci ', # 0x9e +'Pi ', # 0x9f +'Zui ', # 0xa0 +'Bian ', # 0xa1 +'La ', # 0xa2 +'La ', # 0xa3 +'Ci ', # 0xa4 +'Xue ', # 0xa5 +'Ban ', # 0xa6 +'Bian ', # 0xa7 +'Bian ', # 0xa8 +'Bian ', # 0xa9 +'[?] ', # 0xaa +'Bian ', # 0xab +'Ban ', # 0xac +'Ci ', # 0xad +'Bian ', # 0xae +'Bian ', # 0xaf +'Chen ', # 0xb0 +'Ru ', # 0xb1 +'Nong ', # 0xb2 +'Nong ', # 0xb3 +'Zhen ', # 0xb4 +'Chuo ', # 0xb5 +'Chuo ', # 0xb6 +'Suberu ', # 0xb7 +'Reng ', # 0xb8 +'Bian ', # 0xb9 +'Bian ', # 0xba +'Sip ', # 0xbb +'Ip ', # 0xbc +'Liao ', # 0xbd +'Da ', # 0xbe +'Chan ', # 0xbf +'Gan ', # 0xc0 +'Qian ', # 0xc1 +'Yu ', # 0xc2 +'Yu ', # 0xc3 +'Qi ', # 0xc4 +'Xun ', # 0xc5 +'Yi ', # 0xc6 +'Guo ', # 0xc7 +'Mai ', # 0xc8 +'Qi ', # 0xc9 +'Za ', # 0xca +'Wang ', # 0xcb +'Jia ', # 0xcc +'Zhun ', # 0xcd +'Ying ', # 0xce +'Ti ', # 0xcf +'Yun ', # 0xd0 +'Jin ', # 0xd1 +'Hang ', # 0xd2 +'Ya ', # 0xd3 +'Fan ', # 0xd4 +'Wu ', # 0xd5 +'Da ', # 0xd6 +'E ', # 0xd7 +'Huan ', # 0xd8 +'Zhe ', # 0xd9 +'Totemo ', # 0xda +'Jin ', # 0xdb +'Yuan ', # 0xdc +'Wei ', # 0xdd +'Lian ', # 0xde +'Chi ', # 0xdf +'Che ', # 0xe0 +'Ni ', # 0xe1 +'Tiao ', # 0xe2 +'Zhi ', # 0xe3 +'Yi ', # 0xe4 +'Jiong ', # 0xe5 +'Jia ', # 0xe6 +'Chen ', # 0xe7 +'Dai ', # 0xe8 +'Er ', # 0xe9 +'Di ', # 0xea +'Po ', # 0xeb +'Wang ', # 0xec +'Die ', # 0xed +'Ze ', # 0xee +'Tao ', # 0xef +'Shu ', # 0xf0 +'Tuo ', # 0xf1 +'Kep ', # 0xf2 +'Jing ', # 0xf3 +'Hui ', # 0xf4 +'Tong ', # 0xf5 +'You ', # 0xf6 +'Mi ', # 0xf7 +'Beng ', # 0xf8 +'Ji ', # 0xf9 +'Nai ', # 0xfa +'Yi ', # 0xfb +'Jie ', # 0xfc +'Zhui ', # 0xfd +'Lie ', # 0xfe +'Xun ', # 0xff +) diff --git a/nstock/modules/unidecode/x090.py b/nstock/modules/unidecode/x090.py new file mode 100644 index 0000000..ade6506 --- /dev/null +++ b/nstock/modules/unidecode/x090.py @@ -0,0 +1,258 @@ +data = ( +'Tui ', # 0x00 +'Song ', # 0x01 +'Gua ', # 0x02 +'Tao ', # 0x03 +'Pang ', # 0x04 +'Hou ', # 0x05 +'Ni ', # 0x06 +'Dun ', # 0x07 +'Jiong ', # 0x08 +'Xuan ', # 0x09 +'Xun ', # 0x0a +'Bu ', # 0x0b +'You ', # 0x0c +'Xiao ', # 0x0d +'Qiu ', # 0x0e +'Tou ', # 0x0f +'Zhu ', # 0x10 +'Qiu ', # 0x11 +'Di ', # 0x12 +'Di ', # 0x13 +'Tu ', # 0x14 +'Jing ', # 0x15 +'Ti ', # 0x16 +'Dou ', # 0x17 +'Yi ', # 0x18 +'Zhe ', # 0x19 +'Tong ', # 0x1a +'Guang ', # 0x1b +'Wu ', # 0x1c +'Shi ', # 0x1d +'Cheng ', # 0x1e +'Su ', # 0x1f +'Zao ', # 0x20 +'Qun ', # 0x21 +'Feng ', # 0x22 +'Lian ', # 0x23 +'Suo ', # 0x24 +'Hui ', # 0x25 +'Li ', # 0x26 +'Sako ', # 0x27 +'Lai ', # 0x28 +'Ben ', # 0x29 +'Cuo ', # 0x2a +'Jue ', # 0x2b +'Beng ', # 0x2c +'Huan ', # 0x2d +'Dai ', # 0x2e +'Lu ', # 0x2f +'You ', # 0x30 +'Zhou ', # 0x31 +'Jin ', # 0x32 +'Yu ', # 0x33 +'Chuo ', # 0x34 +'Kui ', # 0x35 +'Wei ', # 0x36 +'Ti ', # 0x37 +'Yi ', # 0x38 +'Da ', # 0x39 +'Yuan ', # 0x3a +'Luo ', # 0x3b +'Bi ', # 0x3c +'Nuo ', # 0x3d +'Yu ', # 0x3e +'Dang ', # 0x3f +'Sui ', # 0x40 +'Dun ', # 0x41 +'Sui ', # 0x42 +'Yan ', # 0x43 +'Chuan ', # 0x44 +'Chi ', # 0x45 +'Ti ', # 0x46 +'Yu ', # 0x47 +'Shi ', # 0x48 +'Zhen ', # 0x49 +'You ', # 0x4a +'Yun ', # 0x4b +'E ', # 0x4c +'Bian ', # 0x4d +'Guo ', # 0x4e +'E ', # 0x4f +'Xia ', # 0x50 +'Huang ', # 0x51 +'Qiu ', # 0x52 +'Dao ', # 0x53 +'Da ', # 0x54 +'Wei ', # 0x55 +'Appare ', # 0x56 +'Yi ', # 0x57 +'Gou ', # 0x58 +'Yao ', # 0x59 +'Chu ', # 0x5a +'Liu ', # 0x5b +'Xun ', # 0x5c +'Ta ', # 0x5d +'Di ', # 0x5e +'Chi ', # 0x5f +'Yuan ', # 0x60 +'Su ', # 0x61 +'Ta ', # 0x62 +'Qian ', # 0x63 +'[?] ', # 0x64 +'Yao ', # 0x65 +'Guan ', # 0x66 +'Zhang ', # 0x67 +'Ao ', # 0x68 +'Shi ', # 0x69 +'Ce ', # 0x6a +'Chi ', # 0x6b +'Su ', # 0x6c +'Zao ', # 0x6d +'Zhe ', # 0x6e +'Dun ', # 0x6f +'Di ', # 0x70 +'Lou ', # 0x71 +'Chi ', # 0x72 +'Cuo ', # 0x73 +'Lin ', # 0x74 +'Zun ', # 0x75 +'Rao ', # 0x76 +'Qian ', # 0x77 +'Xuan ', # 0x78 +'Yu ', # 0x79 +'Yi ', # 0x7a +'Wu ', # 0x7b +'Liao ', # 0x7c +'Ju ', # 0x7d +'Shi ', # 0x7e +'Bi ', # 0x7f +'Yao ', # 0x80 +'Mai ', # 0x81 +'Xie ', # 0x82 +'Sui ', # 0x83 +'Huan ', # 0x84 +'Zhan ', # 0x85 +'Teng ', # 0x86 +'Er ', # 0x87 +'Miao ', # 0x88 +'Bian ', # 0x89 +'Bian ', # 0x8a +'La ', # 0x8b +'Li ', # 0x8c +'Yuan ', # 0x8d +'Yao ', # 0x8e +'Luo ', # 0x8f +'Li ', # 0x90 +'Yi ', # 0x91 +'Ting ', # 0x92 +'Deng ', # 0x93 +'Qi ', # 0x94 +'Yong ', # 0x95 +'Shan ', # 0x96 +'Han ', # 0x97 +'Yu ', # 0x98 +'Mang ', # 0x99 +'Ru ', # 0x9a +'Qiong ', # 0x9b +'[?] ', # 0x9c +'Kuang ', # 0x9d +'Fu ', # 0x9e +'Kang ', # 0x9f +'Bin ', # 0xa0 +'Fang ', # 0xa1 +'Xing ', # 0xa2 +'Na ', # 0xa3 +'Xin ', # 0xa4 +'Shen ', # 0xa5 +'Bang ', # 0xa6 +'Yuan ', # 0xa7 +'Cun ', # 0xa8 +'Huo ', # 0xa9 +'Xie ', # 0xaa +'Bang ', # 0xab +'Wu ', # 0xac +'Ju ', # 0xad +'You ', # 0xae +'Han ', # 0xaf +'Tai ', # 0xb0 +'Qiu ', # 0xb1 +'Bi ', # 0xb2 +'Pei ', # 0xb3 +'Bing ', # 0xb4 +'Shao ', # 0xb5 +'Bei ', # 0xb6 +'Wa ', # 0xb7 +'Di ', # 0xb8 +'Zou ', # 0xb9 +'Ye ', # 0xba +'Lin ', # 0xbb +'Kuang ', # 0xbc +'Gui ', # 0xbd +'Zhu ', # 0xbe +'Shi ', # 0xbf +'Ku ', # 0xc0 +'Yu ', # 0xc1 +'Gai ', # 0xc2 +'Ge ', # 0xc3 +'Xi ', # 0xc4 +'Zhi ', # 0xc5 +'Ji ', # 0xc6 +'Xun ', # 0xc7 +'Hou ', # 0xc8 +'Xing ', # 0xc9 +'Jiao ', # 0xca +'Xi ', # 0xcb +'Gui ', # 0xcc +'Nuo ', # 0xcd +'Lang ', # 0xce +'Jia ', # 0xcf +'Kuai ', # 0xd0 +'Zheng ', # 0xd1 +'Otoko ', # 0xd2 +'Yun ', # 0xd3 +'Yan ', # 0xd4 +'Cheng ', # 0xd5 +'Dou ', # 0xd6 +'Chi ', # 0xd7 +'Lu ', # 0xd8 +'Fu ', # 0xd9 +'Wu ', # 0xda +'Fu ', # 0xdb +'Gao ', # 0xdc +'Hao ', # 0xdd +'Lang ', # 0xde +'Jia ', # 0xdf +'Geng ', # 0xe0 +'Jun ', # 0xe1 +'Ying ', # 0xe2 +'Bo ', # 0xe3 +'Xi ', # 0xe4 +'Bei ', # 0xe5 +'Li ', # 0xe6 +'Yun ', # 0xe7 +'Bu ', # 0xe8 +'Xiao ', # 0xe9 +'Qi ', # 0xea +'Pi ', # 0xeb +'Qing ', # 0xec +'Guo ', # 0xed +'Zhou ', # 0xee +'Tan ', # 0xef +'Zou ', # 0xf0 +'Ping ', # 0xf1 +'Lai ', # 0xf2 +'Ni ', # 0xf3 +'Chen ', # 0xf4 +'You ', # 0xf5 +'Bu ', # 0xf6 +'Xiang ', # 0xf7 +'Dan ', # 0xf8 +'Ju ', # 0xf9 +'Yong ', # 0xfa +'Qiao ', # 0xfb +'Yi ', # 0xfc +'Du ', # 0xfd +'Yan ', # 0xfe +'Mei ', # 0xff +) diff --git a/nstock/modules/unidecode/x091.py b/nstock/modules/unidecode/x091.py new file mode 100644 index 0000000..fa3dd76 --- /dev/null +++ b/nstock/modules/unidecode/x091.py @@ -0,0 +1,258 @@ +data = ( +'Ruo ', # 0x00 +'Bei ', # 0x01 +'E ', # 0x02 +'Yu ', # 0x03 +'Juan ', # 0x04 +'Yu ', # 0x05 +'Yun ', # 0x06 +'Hou ', # 0x07 +'Kui ', # 0x08 +'Xiang ', # 0x09 +'Xiang ', # 0x0a +'Sou ', # 0x0b +'Tang ', # 0x0c +'Ming ', # 0x0d +'Xi ', # 0x0e +'Ru ', # 0x0f +'Chu ', # 0x10 +'Zi ', # 0x11 +'Zou ', # 0x12 +'Ju ', # 0x13 +'Wu ', # 0x14 +'Xiang ', # 0x15 +'Yun ', # 0x16 +'Hao ', # 0x17 +'Yong ', # 0x18 +'Bi ', # 0x19 +'Mo ', # 0x1a +'Chao ', # 0x1b +'Fu ', # 0x1c +'Liao ', # 0x1d +'Yin ', # 0x1e +'Zhuan ', # 0x1f +'Hu ', # 0x20 +'Qiao ', # 0x21 +'Yan ', # 0x22 +'Zhang ', # 0x23 +'Fan ', # 0x24 +'Qiao ', # 0x25 +'Xu ', # 0x26 +'Deng ', # 0x27 +'Bi ', # 0x28 +'Xin ', # 0x29 +'Bi ', # 0x2a +'Ceng ', # 0x2b +'Wei ', # 0x2c +'Zheng ', # 0x2d +'Mao ', # 0x2e +'Shan ', # 0x2f +'Lin ', # 0x30 +'Po ', # 0x31 +'Dan ', # 0x32 +'Meng ', # 0x33 +'Ye ', # 0x34 +'Cao ', # 0x35 +'Kuai ', # 0x36 +'Feng ', # 0x37 +'Meng ', # 0x38 +'Zou ', # 0x39 +'Kuang ', # 0x3a +'Lian ', # 0x3b +'Zan ', # 0x3c +'Chan ', # 0x3d +'You ', # 0x3e +'Qi ', # 0x3f +'Yan ', # 0x40 +'Chan ', # 0x41 +'Zan ', # 0x42 +'Ling ', # 0x43 +'Huan ', # 0x44 +'Xi ', # 0x45 +'Feng ', # 0x46 +'Zan ', # 0x47 +'Li ', # 0x48 +'You ', # 0x49 +'Ding ', # 0x4a +'Qiu ', # 0x4b +'Zhuo ', # 0x4c +'Pei ', # 0x4d +'Zhou ', # 0x4e +'Yi ', # 0x4f +'Hang ', # 0x50 +'Yu ', # 0x51 +'Jiu ', # 0x52 +'Yan ', # 0x53 +'Zui ', # 0x54 +'Mao ', # 0x55 +'Dan ', # 0x56 +'Xu ', # 0x57 +'Tou ', # 0x58 +'Zhen ', # 0x59 +'Fen ', # 0x5a +'Sakenomoto ', # 0x5b +'[?] ', # 0x5c +'Yun ', # 0x5d +'Tai ', # 0x5e +'Tian ', # 0x5f +'Qia ', # 0x60 +'Tuo ', # 0x61 +'Zuo ', # 0x62 +'Han ', # 0x63 +'Gu ', # 0x64 +'Su ', # 0x65 +'Po ', # 0x66 +'Chou ', # 0x67 +'Zai ', # 0x68 +'Ming ', # 0x69 +'Luo ', # 0x6a +'Chuo ', # 0x6b +'Chou ', # 0x6c +'You ', # 0x6d +'Tong ', # 0x6e +'Zhi ', # 0x6f +'Xian ', # 0x70 +'Jiang ', # 0x71 +'Cheng ', # 0x72 +'Yin ', # 0x73 +'Tu ', # 0x74 +'Xiao ', # 0x75 +'Mei ', # 0x76 +'Ku ', # 0x77 +'Suan ', # 0x78 +'Lei ', # 0x79 +'Pu ', # 0x7a +'Zui ', # 0x7b +'Hai ', # 0x7c +'Yan ', # 0x7d +'Xi ', # 0x7e +'Niang ', # 0x7f +'Wei ', # 0x80 +'Lu ', # 0x81 +'Lan ', # 0x82 +'Yan ', # 0x83 +'Tao ', # 0x84 +'Pei ', # 0x85 +'Zhan ', # 0x86 +'Chun ', # 0x87 +'Tan ', # 0x88 +'Zui ', # 0x89 +'Chuo ', # 0x8a +'Cu ', # 0x8b +'Kun ', # 0x8c +'Ti ', # 0x8d +'Mian ', # 0x8e +'Du ', # 0x8f +'Hu ', # 0x90 +'Xu ', # 0x91 +'Xing ', # 0x92 +'Tan ', # 0x93 +'Jiu ', # 0x94 +'Chun ', # 0x95 +'Yun ', # 0x96 +'Po ', # 0x97 +'Ke ', # 0x98 +'Sou ', # 0x99 +'Mi ', # 0x9a +'Quan ', # 0x9b +'Chou ', # 0x9c +'Cuo ', # 0x9d +'Yun ', # 0x9e +'Yong ', # 0x9f +'Ang ', # 0xa0 +'Zha ', # 0xa1 +'Hai ', # 0xa2 +'Tang ', # 0xa3 +'Jiang ', # 0xa4 +'Piao ', # 0xa5 +'Shan ', # 0xa6 +'Yu ', # 0xa7 +'Li ', # 0xa8 +'Zao ', # 0xa9 +'Lao ', # 0xaa +'Yi ', # 0xab +'Jiang ', # 0xac +'Pu ', # 0xad +'Jiao ', # 0xae +'Xi ', # 0xaf +'Tan ', # 0xb0 +'Po ', # 0xb1 +'Nong ', # 0xb2 +'Yi ', # 0xb3 +'Li ', # 0xb4 +'Ju ', # 0xb5 +'Jiao ', # 0xb6 +'Yi ', # 0xb7 +'Niang ', # 0xb8 +'Ru ', # 0xb9 +'Xun ', # 0xba +'Chou ', # 0xbb +'Yan ', # 0xbc +'Ling ', # 0xbd +'Mi ', # 0xbe +'Mi ', # 0xbf +'Niang ', # 0xc0 +'Xin ', # 0xc1 +'Jiao ', # 0xc2 +'Xi ', # 0xc3 +'Mi ', # 0xc4 +'Yan ', # 0xc5 +'Bian ', # 0xc6 +'Cai ', # 0xc7 +'Shi ', # 0xc8 +'You ', # 0xc9 +'Shi ', # 0xca +'Shi ', # 0xcb +'Li ', # 0xcc +'Zhong ', # 0xcd +'Ye ', # 0xce +'Liang ', # 0xcf +'Li ', # 0xd0 +'Jin ', # 0xd1 +'Jin ', # 0xd2 +'Qiu ', # 0xd3 +'Yi ', # 0xd4 +'Diao ', # 0xd5 +'Dao ', # 0xd6 +'Zhao ', # 0xd7 +'Ding ', # 0xd8 +'Po ', # 0xd9 +'Qiu ', # 0xda +'He ', # 0xdb +'Fu ', # 0xdc +'Zhen ', # 0xdd +'Zhi ', # 0xde +'Ba ', # 0xdf +'Luan ', # 0xe0 +'Fu ', # 0xe1 +'Nai ', # 0xe2 +'Diao ', # 0xe3 +'Shan ', # 0xe4 +'Qiao ', # 0xe5 +'Kou ', # 0xe6 +'Chuan ', # 0xe7 +'Zi ', # 0xe8 +'Fan ', # 0xe9 +'Yu ', # 0xea +'Hua ', # 0xeb +'Han ', # 0xec +'Gong ', # 0xed +'Qi ', # 0xee +'Mang ', # 0xef +'Ri ', # 0xf0 +'Di ', # 0xf1 +'Si ', # 0xf2 +'Xi ', # 0xf3 +'Yi ', # 0xf4 +'Chai ', # 0xf5 +'Shi ', # 0xf6 +'Tu ', # 0xf7 +'Xi ', # 0xf8 +'Nu ', # 0xf9 +'Qian ', # 0xfa +'Ishiyumi ', # 0xfb +'Jian ', # 0xfc +'Pi ', # 0xfd +'Ye ', # 0xfe +'Yin ', # 0xff +) diff --git a/nstock/modules/unidecode/x092.py b/nstock/modules/unidecode/x092.py new file mode 100644 index 0000000..e752f4f --- /dev/null +++ b/nstock/modules/unidecode/x092.py @@ -0,0 +1,258 @@ +data = ( +'Ba ', # 0x00 +'Fang ', # 0x01 +'Chen ', # 0x02 +'Xing ', # 0x03 +'Tou ', # 0x04 +'Yue ', # 0x05 +'Yan ', # 0x06 +'Fu ', # 0x07 +'Pi ', # 0x08 +'Na ', # 0x09 +'Xin ', # 0x0a +'E ', # 0x0b +'Jue ', # 0x0c +'Dun ', # 0x0d +'Gou ', # 0x0e +'Yin ', # 0x0f +'Qian ', # 0x10 +'Ban ', # 0x11 +'Ji ', # 0x12 +'Ren ', # 0x13 +'Chao ', # 0x14 +'Niu ', # 0x15 +'Fen ', # 0x16 +'Yun ', # 0x17 +'Ji ', # 0x18 +'Qin ', # 0x19 +'Pi ', # 0x1a +'Guo ', # 0x1b +'Hong ', # 0x1c +'Yin ', # 0x1d +'Jun ', # 0x1e +'Shi ', # 0x1f +'Yi ', # 0x20 +'Zhong ', # 0x21 +'Nie ', # 0x22 +'Gai ', # 0x23 +'Ri ', # 0x24 +'Huo ', # 0x25 +'Tai ', # 0x26 +'Kang ', # 0x27 +'Habaki ', # 0x28 +'Irori ', # 0x29 +'Ngaak ', # 0x2a +'[?] ', # 0x2b +'Duo ', # 0x2c +'Zi ', # 0x2d +'Ni ', # 0x2e +'Tu ', # 0x2f +'Shi ', # 0x30 +'Min ', # 0x31 +'Gu ', # 0x32 +'E ', # 0x33 +'Ling ', # 0x34 +'Bing ', # 0x35 +'Yi ', # 0x36 +'Gu ', # 0x37 +'Ba ', # 0x38 +'Pi ', # 0x39 +'Yu ', # 0x3a +'Si ', # 0x3b +'Zuo ', # 0x3c +'Bu ', # 0x3d +'You ', # 0x3e +'Dian ', # 0x3f +'Jia ', # 0x40 +'Zhen ', # 0x41 +'Shi ', # 0x42 +'Shi ', # 0x43 +'Tie ', # 0x44 +'Ju ', # 0x45 +'Zhan ', # 0x46 +'Shi ', # 0x47 +'She ', # 0x48 +'Xuan ', # 0x49 +'Zhao ', # 0x4a +'Bao ', # 0x4b +'He ', # 0x4c +'Bi ', # 0x4d +'Sheng ', # 0x4e +'Chu ', # 0x4f +'Shi ', # 0x50 +'Bo ', # 0x51 +'Zhu ', # 0x52 +'Chi ', # 0x53 +'Za ', # 0x54 +'Po ', # 0x55 +'Tong ', # 0x56 +'Qian ', # 0x57 +'Fu ', # 0x58 +'Zhai ', # 0x59 +'Liu ', # 0x5a +'Qian ', # 0x5b +'Fu ', # 0x5c +'Li ', # 0x5d +'Yue ', # 0x5e +'Pi ', # 0x5f +'Yang ', # 0x60 +'Ban ', # 0x61 +'Bo ', # 0x62 +'Jie ', # 0x63 +'Gou ', # 0x64 +'Shu ', # 0x65 +'Zheng ', # 0x66 +'Mu ', # 0x67 +'Ni ', # 0x68 +'Nie ', # 0x69 +'Di ', # 0x6a +'Jia ', # 0x6b +'Mu ', # 0x6c +'Dan ', # 0x6d +'Shen ', # 0x6e +'Yi ', # 0x6f +'Si ', # 0x70 +'Kuang ', # 0x71 +'Ka ', # 0x72 +'Bei ', # 0x73 +'Jian ', # 0x74 +'Tong ', # 0x75 +'Xing ', # 0x76 +'Hong ', # 0x77 +'Jiao ', # 0x78 +'Chi ', # 0x79 +'Er ', # 0x7a +'Ge ', # 0x7b +'Bing ', # 0x7c +'Shi ', # 0x7d +'Mou ', # 0x7e +'Jia ', # 0x7f +'Yin ', # 0x80 +'Jun ', # 0x81 +'Zhou ', # 0x82 +'Chong ', # 0x83 +'Shang ', # 0x84 +'Tong ', # 0x85 +'Mo ', # 0x86 +'Lei ', # 0x87 +'Ji ', # 0x88 +'Yu ', # 0x89 +'Xu ', # 0x8a +'Ren ', # 0x8b +'Zun ', # 0x8c +'Zhi ', # 0x8d +'Qiong ', # 0x8e +'Shan ', # 0x8f +'Chi ', # 0x90 +'Xian ', # 0x91 +'Xing ', # 0x92 +'Quan ', # 0x93 +'Pi ', # 0x94 +'Tie ', # 0x95 +'Zhu ', # 0x96 +'Hou ', # 0x97 +'Ming ', # 0x98 +'Kua ', # 0x99 +'Yao ', # 0x9a +'Xian ', # 0x9b +'Xian ', # 0x9c +'Xiu ', # 0x9d +'Jun ', # 0x9e +'Cha ', # 0x9f +'Lao ', # 0xa0 +'Ji ', # 0xa1 +'Pi ', # 0xa2 +'Ru ', # 0xa3 +'Mi ', # 0xa4 +'Yi ', # 0xa5 +'Yin ', # 0xa6 +'Guang ', # 0xa7 +'An ', # 0xa8 +'Diou ', # 0xa9 +'You ', # 0xaa +'Se ', # 0xab +'Kao ', # 0xac +'Qian ', # 0xad +'Luan ', # 0xae +'Kasugai ', # 0xaf +'Ai ', # 0xb0 +'Diao ', # 0xb1 +'Han ', # 0xb2 +'Rui ', # 0xb3 +'Shi ', # 0xb4 +'Keng ', # 0xb5 +'Qiu ', # 0xb6 +'Xiao ', # 0xb7 +'Zhe ', # 0xb8 +'Xiu ', # 0xb9 +'Zang ', # 0xba +'Ti ', # 0xbb +'Cuo ', # 0xbc +'Gua ', # 0xbd +'Gong ', # 0xbe +'Zhong ', # 0xbf +'Dou ', # 0xc0 +'Lu ', # 0xc1 +'Mei ', # 0xc2 +'Lang ', # 0xc3 +'Wan ', # 0xc4 +'Xin ', # 0xc5 +'Yun ', # 0xc6 +'Bei ', # 0xc7 +'Wu ', # 0xc8 +'Su ', # 0xc9 +'Yu ', # 0xca +'Chan ', # 0xcb +'Ting ', # 0xcc +'Bo ', # 0xcd +'Han ', # 0xce +'Jia ', # 0xcf +'Hong ', # 0xd0 +'Cuan ', # 0xd1 +'Feng ', # 0xd2 +'Chan ', # 0xd3 +'Wan ', # 0xd4 +'Zhi ', # 0xd5 +'Si ', # 0xd6 +'Xuan ', # 0xd7 +'Wu ', # 0xd8 +'Wu ', # 0xd9 +'Tiao ', # 0xda +'Gong ', # 0xdb +'Zhuo ', # 0xdc +'Lue ', # 0xdd +'Xing ', # 0xde +'Qian ', # 0xdf +'Shen ', # 0xe0 +'Han ', # 0xe1 +'Lue ', # 0xe2 +'Xie ', # 0xe3 +'Chu ', # 0xe4 +'Zheng ', # 0xe5 +'Ju ', # 0xe6 +'Xian ', # 0xe7 +'Tie ', # 0xe8 +'Mang ', # 0xe9 +'Pu ', # 0xea +'Li ', # 0xeb +'Pan ', # 0xec +'Rui ', # 0xed +'Cheng ', # 0xee +'Gao ', # 0xef +'Li ', # 0xf0 +'Te ', # 0xf1 +'Pyeng ', # 0xf2 +'Zhu ', # 0xf3 +'[?] ', # 0xf4 +'Tu ', # 0xf5 +'Liu ', # 0xf6 +'Zui ', # 0xf7 +'Ju ', # 0xf8 +'Chang ', # 0xf9 +'Yuan ', # 0xfa +'Jian ', # 0xfb +'Gang ', # 0xfc +'Diao ', # 0xfd +'Tao ', # 0xfe +'Chang ', # 0xff +) diff --git a/nstock/modules/unidecode/x093.py b/nstock/modules/unidecode/x093.py new file mode 100644 index 0000000..82857e9 --- /dev/null +++ b/nstock/modules/unidecode/x093.py @@ -0,0 +1,258 @@ +data = ( +'Lun ', # 0x00 +'Kua ', # 0x01 +'Ling ', # 0x02 +'Bei ', # 0x03 +'Lu ', # 0x04 +'Li ', # 0x05 +'Qiang ', # 0x06 +'Pou ', # 0x07 +'Juan ', # 0x08 +'Min ', # 0x09 +'Zui ', # 0x0a +'Peng ', # 0x0b +'An ', # 0x0c +'Pi ', # 0x0d +'Xian ', # 0x0e +'Ya ', # 0x0f +'Zhui ', # 0x10 +'Lei ', # 0x11 +'A ', # 0x12 +'Kong ', # 0x13 +'Ta ', # 0x14 +'Kun ', # 0x15 +'Du ', # 0x16 +'Wei ', # 0x17 +'Chui ', # 0x18 +'Zi ', # 0x19 +'Zheng ', # 0x1a +'Ben ', # 0x1b +'Nie ', # 0x1c +'Cong ', # 0x1d +'Qun ', # 0x1e +'Tan ', # 0x1f +'Ding ', # 0x20 +'Qi ', # 0x21 +'Qian ', # 0x22 +'Zhuo ', # 0x23 +'Qi ', # 0x24 +'Yu ', # 0x25 +'Jin ', # 0x26 +'Guan ', # 0x27 +'Mao ', # 0x28 +'Chang ', # 0x29 +'Tian ', # 0x2a +'Xi ', # 0x2b +'Lian ', # 0x2c +'Tao ', # 0x2d +'Gu ', # 0x2e +'Cuo ', # 0x2f +'Shu ', # 0x30 +'Zhen ', # 0x31 +'Lu ', # 0x32 +'Meng ', # 0x33 +'Lu ', # 0x34 +'Hua ', # 0x35 +'Biao ', # 0x36 +'Ga ', # 0x37 +'Lai ', # 0x38 +'Ken ', # 0x39 +'Kazari ', # 0x3a +'Bu ', # 0x3b +'Nai ', # 0x3c +'Wan ', # 0x3d +'Zan ', # 0x3e +'[?] ', # 0x3f +'De ', # 0x40 +'Xian ', # 0x41 +'[?] ', # 0x42 +'Huo ', # 0x43 +'Liang ', # 0x44 +'[?] ', # 0x45 +'Men ', # 0x46 +'Kai ', # 0x47 +'Ying ', # 0x48 +'Di ', # 0x49 +'Lian ', # 0x4a +'Guo ', # 0x4b +'Xian ', # 0x4c +'Du ', # 0x4d +'Tu ', # 0x4e +'Wei ', # 0x4f +'Cong ', # 0x50 +'Fu ', # 0x51 +'Rou ', # 0x52 +'Ji ', # 0x53 +'E ', # 0x54 +'Rou ', # 0x55 +'Chen ', # 0x56 +'Ti ', # 0x57 +'Zha ', # 0x58 +'Hong ', # 0x59 +'Yang ', # 0x5a +'Duan ', # 0x5b +'Xia ', # 0x5c +'Yu ', # 0x5d +'Keng ', # 0x5e +'Xing ', # 0x5f +'Huang ', # 0x60 +'Wei ', # 0x61 +'Fu ', # 0x62 +'Zhao ', # 0x63 +'Cha ', # 0x64 +'Qie ', # 0x65 +'She ', # 0x66 +'Hong ', # 0x67 +'Kui ', # 0x68 +'Tian ', # 0x69 +'Mou ', # 0x6a +'Qiao ', # 0x6b +'Qiao ', # 0x6c +'Hou ', # 0x6d +'Tou ', # 0x6e +'Cong ', # 0x6f +'Huan ', # 0x70 +'Ye ', # 0x71 +'Min ', # 0x72 +'Jian ', # 0x73 +'Duan ', # 0x74 +'Jian ', # 0x75 +'Song ', # 0x76 +'Kui ', # 0x77 +'Hu ', # 0x78 +'Xuan ', # 0x79 +'Duo ', # 0x7a +'Jie ', # 0x7b +'Zhen ', # 0x7c +'Bian ', # 0x7d +'Zhong ', # 0x7e +'Zi ', # 0x7f +'Xiu ', # 0x80 +'Ye ', # 0x81 +'Mei ', # 0x82 +'Pai ', # 0x83 +'Ai ', # 0x84 +'Jie ', # 0x85 +'[?] ', # 0x86 +'Mei ', # 0x87 +'Chuo ', # 0x88 +'Ta ', # 0x89 +'Bang ', # 0x8a +'Xia ', # 0x8b +'Lian ', # 0x8c +'Suo ', # 0x8d +'Xi ', # 0x8e +'Liu ', # 0x8f +'Zu ', # 0x90 +'Ye ', # 0x91 +'Nou ', # 0x92 +'Weng ', # 0x93 +'Rong ', # 0x94 +'Tang ', # 0x95 +'Suo ', # 0x96 +'Qiang ', # 0x97 +'Ge ', # 0x98 +'Shuo ', # 0x99 +'Chui ', # 0x9a +'Bo ', # 0x9b +'Pan ', # 0x9c +'Sa ', # 0x9d +'Bi ', # 0x9e +'Sang ', # 0x9f +'Gang ', # 0xa0 +'Zi ', # 0xa1 +'Wu ', # 0xa2 +'Ying ', # 0xa3 +'Huang ', # 0xa4 +'Tiao ', # 0xa5 +'Liu ', # 0xa6 +'Kai ', # 0xa7 +'Sun ', # 0xa8 +'Sha ', # 0xa9 +'Sou ', # 0xaa +'Wan ', # 0xab +'Hao ', # 0xac +'Zhen ', # 0xad +'Zhen ', # 0xae +'Luo ', # 0xaf +'Yi ', # 0xb0 +'Yuan ', # 0xb1 +'Tang ', # 0xb2 +'Nie ', # 0xb3 +'Xi ', # 0xb4 +'Jia ', # 0xb5 +'Ge ', # 0xb6 +'Ma ', # 0xb7 +'Juan ', # 0xb8 +'Kasugai ', # 0xb9 +'Habaki ', # 0xba +'Suo ', # 0xbb +'[?] ', # 0xbc +'[?] ', # 0xbd +'[?] ', # 0xbe +'Na ', # 0xbf +'Lu ', # 0xc0 +'Suo ', # 0xc1 +'Ou ', # 0xc2 +'Zu ', # 0xc3 +'Tuan ', # 0xc4 +'Xiu ', # 0xc5 +'Guan ', # 0xc6 +'Xuan ', # 0xc7 +'Lian ', # 0xc8 +'Shou ', # 0xc9 +'Ao ', # 0xca +'Man ', # 0xcb +'Mo ', # 0xcc +'Luo ', # 0xcd +'Bi ', # 0xce +'Wei ', # 0xcf +'Liu ', # 0xd0 +'Di ', # 0xd1 +'Qiao ', # 0xd2 +'Cong ', # 0xd3 +'Yi ', # 0xd4 +'Lu ', # 0xd5 +'Ao ', # 0xd6 +'Keng ', # 0xd7 +'Qiang ', # 0xd8 +'Cui ', # 0xd9 +'Qi ', # 0xda +'Chang ', # 0xdb +'Tang ', # 0xdc +'Man ', # 0xdd +'Yong ', # 0xde +'Chan ', # 0xdf +'Feng ', # 0xe0 +'Jing ', # 0xe1 +'Biao ', # 0xe2 +'Shu ', # 0xe3 +'Lou ', # 0xe4 +'Xiu ', # 0xe5 +'Cong ', # 0xe6 +'Long ', # 0xe7 +'Zan ', # 0xe8 +'Jian ', # 0xe9 +'Cao ', # 0xea +'Li ', # 0xeb +'Xia ', # 0xec +'Xi ', # 0xed +'Kang ', # 0xee +'[?] ', # 0xef +'Beng ', # 0xf0 +'[?] ', # 0xf1 +'[?] ', # 0xf2 +'Zheng ', # 0xf3 +'Lu ', # 0xf4 +'Hua ', # 0xf5 +'Ji ', # 0xf6 +'Pu ', # 0xf7 +'Hui ', # 0xf8 +'Qiang ', # 0xf9 +'Po ', # 0xfa +'Lin ', # 0xfb +'Suo ', # 0xfc +'Xiu ', # 0xfd +'San ', # 0xfe +'Cheng ', # 0xff +) diff --git a/nstock/modules/unidecode/x094.py b/nstock/modules/unidecode/x094.py new file mode 100644 index 0000000..17eb9dd --- /dev/null +++ b/nstock/modules/unidecode/x094.py @@ -0,0 +1,258 @@ +data = ( +'Kui ', # 0x00 +'Si ', # 0x01 +'Liu ', # 0x02 +'Nao ', # 0x03 +'Heng ', # 0x04 +'Pie ', # 0x05 +'Sui ', # 0x06 +'Fan ', # 0x07 +'Qiao ', # 0x08 +'Quan ', # 0x09 +'Yang ', # 0x0a +'Tang ', # 0x0b +'Xiang ', # 0x0c +'Jue ', # 0x0d +'Jiao ', # 0x0e +'Zun ', # 0x0f +'Liao ', # 0x10 +'Jie ', # 0x11 +'Lao ', # 0x12 +'Dui ', # 0x13 +'Tan ', # 0x14 +'Zan ', # 0x15 +'Ji ', # 0x16 +'Jian ', # 0x17 +'Zhong ', # 0x18 +'Deng ', # 0x19 +'Ya ', # 0x1a +'Ying ', # 0x1b +'Dui ', # 0x1c +'Jue ', # 0x1d +'Nou ', # 0x1e +'Ti ', # 0x1f +'Pu ', # 0x20 +'Tie ', # 0x21 +'[?] ', # 0x22 +'[?] ', # 0x23 +'Ding ', # 0x24 +'Shan ', # 0x25 +'Kai ', # 0x26 +'Jian ', # 0x27 +'Fei ', # 0x28 +'Sui ', # 0x29 +'Lu ', # 0x2a +'Juan ', # 0x2b +'Hui ', # 0x2c +'Yu ', # 0x2d +'Lian ', # 0x2e +'Zhuo ', # 0x2f +'Qiao ', # 0x30 +'Qian ', # 0x31 +'Zhuo ', # 0x32 +'Lei ', # 0x33 +'Bi ', # 0x34 +'Tie ', # 0x35 +'Huan ', # 0x36 +'Ye ', # 0x37 +'Duo ', # 0x38 +'Guo ', # 0x39 +'Dang ', # 0x3a +'Ju ', # 0x3b +'Fen ', # 0x3c +'Da ', # 0x3d +'Bei ', # 0x3e +'Yi ', # 0x3f +'Ai ', # 0x40 +'Zong ', # 0x41 +'Xun ', # 0x42 +'Diao ', # 0x43 +'Zhu ', # 0x44 +'Heng ', # 0x45 +'Zhui ', # 0x46 +'Ji ', # 0x47 +'Nie ', # 0x48 +'Ta ', # 0x49 +'Huo ', # 0x4a +'Qing ', # 0x4b +'Bin ', # 0x4c +'Ying ', # 0x4d +'Kui ', # 0x4e +'Ning ', # 0x4f +'Xu ', # 0x50 +'Jian ', # 0x51 +'Jian ', # 0x52 +'Yari ', # 0x53 +'Cha ', # 0x54 +'Zhi ', # 0x55 +'Mie ', # 0x56 +'Li ', # 0x57 +'Lei ', # 0x58 +'Ji ', # 0x59 +'Zuan ', # 0x5a +'Kuang ', # 0x5b +'Shang ', # 0x5c +'Peng ', # 0x5d +'La ', # 0x5e +'Du ', # 0x5f +'Shuo ', # 0x60 +'Chuo ', # 0x61 +'Lu ', # 0x62 +'Biao ', # 0x63 +'Bao ', # 0x64 +'Lu ', # 0x65 +'[?] ', # 0x66 +'[?] ', # 0x67 +'Long ', # 0x68 +'E ', # 0x69 +'Lu ', # 0x6a +'Xin ', # 0x6b +'Jian ', # 0x6c +'Lan ', # 0x6d +'Bo ', # 0x6e +'Jian ', # 0x6f +'Yao ', # 0x70 +'Chan ', # 0x71 +'Xiang ', # 0x72 +'Jian ', # 0x73 +'Xi ', # 0x74 +'Guan ', # 0x75 +'Cang ', # 0x76 +'Nie ', # 0x77 +'Lei ', # 0x78 +'Cuan ', # 0x79 +'Qu ', # 0x7a +'Pan ', # 0x7b +'Luo ', # 0x7c +'Zuan ', # 0x7d +'Luan ', # 0x7e +'Zao ', # 0x7f +'Nie ', # 0x80 +'Jue ', # 0x81 +'Tang ', # 0x82 +'Shu ', # 0x83 +'Lan ', # 0x84 +'Jin ', # 0x85 +'Qiu ', # 0x86 +'Yi ', # 0x87 +'Zhen ', # 0x88 +'Ding ', # 0x89 +'Zhao ', # 0x8a +'Po ', # 0x8b +'Diao ', # 0x8c +'Tu ', # 0x8d +'Qian ', # 0x8e +'Chuan ', # 0x8f +'Shan ', # 0x90 +'Ji ', # 0x91 +'Fan ', # 0x92 +'Diao ', # 0x93 +'Men ', # 0x94 +'Nu ', # 0x95 +'Xi ', # 0x96 +'Chai ', # 0x97 +'Xing ', # 0x98 +'Gai ', # 0x99 +'Bu ', # 0x9a +'Tai ', # 0x9b +'Ju ', # 0x9c +'Dun ', # 0x9d +'Chao ', # 0x9e +'Zhong ', # 0x9f +'Na ', # 0xa0 +'Bei ', # 0xa1 +'Gang ', # 0xa2 +'Ban ', # 0xa3 +'Qian ', # 0xa4 +'Yao ', # 0xa5 +'Qin ', # 0xa6 +'Jun ', # 0xa7 +'Wu ', # 0xa8 +'Gou ', # 0xa9 +'Kang ', # 0xaa +'Fang ', # 0xab +'Huo ', # 0xac +'Tou ', # 0xad +'Niu ', # 0xae +'Ba ', # 0xaf +'Yu ', # 0xb0 +'Qian ', # 0xb1 +'Zheng ', # 0xb2 +'Qian ', # 0xb3 +'Gu ', # 0xb4 +'Bo ', # 0xb5 +'E ', # 0xb6 +'Po ', # 0xb7 +'Bu ', # 0xb8 +'Ba ', # 0xb9 +'Yue ', # 0xba +'Zuan ', # 0xbb +'Mu ', # 0xbc +'Dan ', # 0xbd +'Jia ', # 0xbe +'Dian ', # 0xbf +'You ', # 0xc0 +'Tie ', # 0xc1 +'Bo ', # 0xc2 +'Ling ', # 0xc3 +'Shuo ', # 0xc4 +'Qian ', # 0xc5 +'Liu ', # 0xc6 +'Bao ', # 0xc7 +'Shi ', # 0xc8 +'Xuan ', # 0xc9 +'She ', # 0xca +'Bi ', # 0xcb +'Ni ', # 0xcc +'Pi ', # 0xcd +'Duo ', # 0xce +'Xing ', # 0xcf +'Kao ', # 0xd0 +'Lao ', # 0xd1 +'Er ', # 0xd2 +'Mang ', # 0xd3 +'Ya ', # 0xd4 +'You ', # 0xd5 +'Cheng ', # 0xd6 +'Jia ', # 0xd7 +'Ye ', # 0xd8 +'Nao ', # 0xd9 +'Zhi ', # 0xda +'Dang ', # 0xdb +'Tong ', # 0xdc +'Lu ', # 0xdd +'Diao ', # 0xde +'Yin ', # 0xdf +'Kai ', # 0xe0 +'Zha ', # 0xe1 +'Zhu ', # 0xe2 +'Xian ', # 0xe3 +'Ting ', # 0xe4 +'Diu ', # 0xe5 +'Xian ', # 0xe6 +'Hua ', # 0xe7 +'Quan ', # 0xe8 +'Sha ', # 0xe9 +'Jia ', # 0xea +'Yao ', # 0xeb +'Ge ', # 0xec +'Ming ', # 0xed +'Zheng ', # 0xee +'Se ', # 0xef +'Jiao ', # 0xf0 +'Yi ', # 0xf1 +'Chan ', # 0xf2 +'Chong ', # 0xf3 +'Tang ', # 0xf4 +'An ', # 0xf5 +'Yin ', # 0xf6 +'Ru ', # 0xf7 +'Zhu ', # 0xf8 +'Lao ', # 0xf9 +'Pu ', # 0xfa +'Wu ', # 0xfb +'Lai ', # 0xfc +'Te ', # 0xfd +'Lian ', # 0xfe +'Keng ', # 0xff +) diff --git a/nstock/modules/unidecode/x095.py b/nstock/modules/unidecode/x095.py new file mode 100644 index 0000000..4b36394 --- /dev/null +++ b/nstock/modules/unidecode/x095.py @@ -0,0 +1,258 @@ +data = ( +'Xiao ', # 0x00 +'Suo ', # 0x01 +'Li ', # 0x02 +'Zheng ', # 0x03 +'Chu ', # 0x04 +'Guo ', # 0x05 +'Gao ', # 0x06 +'Tie ', # 0x07 +'Xiu ', # 0x08 +'Cuo ', # 0x09 +'Lue ', # 0x0a +'Feng ', # 0x0b +'Xin ', # 0x0c +'Liu ', # 0x0d +'Kai ', # 0x0e +'Jian ', # 0x0f +'Rui ', # 0x10 +'Ti ', # 0x11 +'Lang ', # 0x12 +'Qian ', # 0x13 +'Ju ', # 0x14 +'A ', # 0x15 +'Qiang ', # 0x16 +'Duo ', # 0x17 +'Tian ', # 0x18 +'Cuo ', # 0x19 +'Mao ', # 0x1a +'Ben ', # 0x1b +'Qi ', # 0x1c +'De ', # 0x1d +'Kua ', # 0x1e +'Kun ', # 0x1f +'Chang ', # 0x20 +'Xi ', # 0x21 +'Gu ', # 0x22 +'Luo ', # 0x23 +'Chui ', # 0x24 +'Zhui ', # 0x25 +'Jin ', # 0x26 +'Zhi ', # 0x27 +'Xian ', # 0x28 +'Juan ', # 0x29 +'Huo ', # 0x2a +'Pou ', # 0x2b +'Tan ', # 0x2c +'Ding ', # 0x2d +'Jian ', # 0x2e +'Ju ', # 0x2f +'Meng ', # 0x30 +'Zi ', # 0x31 +'Qie ', # 0x32 +'Ying ', # 0x33 +'Kai ', # 0x34 +'Qiang ', # 0x35 +'Song ', # 0x36 +'E ', # 0x37 +'Cha ', # 0x38 +'Qiao ', # 0x39 +'Zhong ', # 0x3a +'Duan ', # 0x3b +'Sou ', # 0x3c +'Huang ', # 0x3d +'Huan ', # 0x3e +'Ai ', # 0x3f +'Du ', # 0x40 +'Mei ', # 0x41 +'Lou ', # 0x42 +'Zi ', # 0x43 +'Fei ', # 0x44 +'Mei ', # 0x45 +'Mo ', # 0x46 +'Zhen ', # 0x47 +'Bo ', # 0x48 +'Ge ', # 0x49 +'Nie ', # 0x4a +'Tang ', # 0x4b +'Juan ', # 0x4c +'Nie ', # 0x4d +'Na ', # 0x4e +'Liu ', # 0x4f +'Hao ', # 0x50 +'Bang ', # 0x51 +'Yi ', # 0x52 +'Jia ', # 0x53 +'Bin ', # 0x54 +'Rong ', # 0x55 +'Biao ', # 0x56 +'Tang ', # 0x57 +'Man ', # 0x58 +'Luo ', # 0x59 +'Beng ', # 0x5a +'Yong ', # 0x5b +'Jing ', # 0x5c +'Di ', # 0x5d +'Zu ', # 0x5e +'Xuan ', # 0x5f +'Liu ', # 0x60 +'Tan ', # 0x61 +'Jue ', # 0x62 +'Liao ', # 0x63 +'Pu ', # 0x64 +'Lu ', # 0x65 +'Dui ', # 0x66 +'Lan ', # 0x67 +'Pu ', # 0x68 +'Cuan ', # 0x69 +'Qiang ', # 0x6a +'Deng ', # 0x6b +'Huo ', # 0x6c +'Lei ', # 0x6d +'Huan ', # 0x6e +'Zhuo ', # 0x6f +'Lian ', # 0x70 +'Yi ', # 0x71 +'Cha ', # 0x72 +'Biao ', # 0x73 +'La ', # 0x74 +'Chan ', # 0x75 +'Xiang ', # 0x76 +'Chang ', # 0x77 +'Chang ', # 0x78 +'Jiu ', # 0x79 +'Ao ', # 0x7a +'Die ', # 0x7b +'Qu ', # 0x7c +'Liao ', # 0x7d +'Mi ', # 0x7e +'Chang ', # 0x7f +'Men ', # 0x80 +'Ma ', # 0x81 +'Shuan ', # 0x82 +'Shan ', # 0x83 +'Huo ', # 0x84 +'Men ', # 0x85 +'Yan ', # 0x86 +'Bi ', # 0x87 +'Han ', # 0x88 +'Bi ', # 0x89 +'San ', # 0x8a +'Kai ', # 0x8b +'Kang ', # 0x8c +'Beng ', # 0x8d +'Hong ', # 0x8e +'Run ', # 0x8f +'San ', # 0x90 +'Xian ', # 0x91 +'Xian ', # 0x92 +'Jian ', # 0x93 +'Min ', # 0x94 +'Xia ', # 0x95 +'Yuru ', # 0x96 +'Dou ', # 0x97 +'Zha ', # 0x98 +'Nao ', # 0x99 +'Jian ', # 0x9a +'Peng ', # 0x9b +'Xia ', # 0x9c +'Ling ', # 0x9d +'Bian ', # 0x9e +'Bi ', # 0x9f +'Run ', # 0xa0 +'He ', # 0xa1 +'Guan ', # 0xa2 +'Ge ', # 0xa3 +'Ge ', # 0xa4 +'Fa ', # 0xa5 +'Chu ', # 0xa6 +'Hong ', # 0xa7 +'Gui ', # 0xa8 +'Min ', # 0xa9 +'Se ', # 0xaa +'Kun ', # 0xab +'Lang ', # 0xac +'Lu ', # 0xad +'Ting ', # 0xae +'Sha ', # 0xaf +'Ju ', # 0xb0 +'Yue ', # 0xb1 +'Yue ', # 0xb2 +'Chan ', # 0xb3 +'Qu ', # 0xb4 +'Lin ', # 0xb5 +'Chang ', # 0xb6 +'Shai ', # 0xb7 +'Kun ', # 0xb8 +'Yan ', # 0xb9 +'Min ', # 0xba +'Yan ', # 0xbb +'E ', # 0xbc +'Hun ', # 0xbd +'Yu ', # 0xbe +'Wen ', # 0xbf +'Xiang ', # 0xc0 +'Bao ', # 0xc1 +'Xiang ', # 0xc2 +'Qu ', # 0xc3 +'Yao ', # 0xc4 +'Wen ', # 0xc5 +'Ban ', # 0xc6 +'An ', # 0xc7 +'Wei ', # 0xc8 +'Yin ', # 0xc9 +'Kuo ', # 0xca +'Que ', # 0xcb +'Lan ', # 0xcc +'Du ', # 0xcd +'[?] ', # 0xce +'Phwung ', # 0xcf +'Tian ', # 0xd0 +'Nie ', # 0xd1 +'Ta ', # 0xd2 +'Kai ', # 0xd3 +'He ', # 0xd4 +'Que ', # 0xd5 +'Chuang ', # 0xd6 +'Guan ', # 0xd7 +'Dou ', # 0xd8 +'Qi ', # 0xd9 +'Kui ', # 0xda +'Tang ', # 0xdb +'Guan ', # 0xdc +'Piao ', # 0xdd +'Kan ', # 0xde +'Xi ', # 0xdf +'Hui ', # 0xe0 +'Chan ', # 0xe1 +'Pi ', # 0xe2 +'Dang ', # 0xe3 +'Huan ', # 0xe4 +'Ta ', # 0xe5 +'Wen ', # 0xe6 +'[?] ', # 0xe7 +'Men ', # 0xe8 +'Shuan ', # 0xe9 +'Shan ', # 0xea +'Yan ', # 0xeb +'Han ', # 0xec +'Bi ', # 0xed +'Wen ', # 0xee +'Chuang ', # 0xef +'Run ', # 0xf0 +'Wei ', # 0xf1 +'Xian ', # 0xf2 +'Hong ', # 0xf3 +'Jian ', # 0xf4 +'Min ', # 0xf5 +'Kang ', # 0xf6 +'Men ', # 0xf7 +'Zha ', # 0xf8 +'Nao ', # 0xf9 +'Gui ', # 0xfa +'Wen ', # 0xfb +'Ta ', # 0xfc +'Min ', # 0xfd +'Lu ', # 0xfe +'Kai ', # 0xff +) diff --git a/nstock/modules/unidecode/x096.py b/nstock/modules/unidecode/x096.py new file mode 100644 index 0000000..738a4ea --- /dev/null +++ b/nstock/modules/unidecode/x096.py @@ -0,0 +1,258 @@ +data = ( +'Fa ', # 0x00 +'Ge ', # 0x01 +'He ', # 0x02 +'Kun ', # 0x03 +'Jiu ', # 0x04 +'Yue ', # 0x05 +'Lang ', # 0x06 +'Du ', # 0x07 +'Yu ', # 0x08 +'Yan ', # 0x09 +'Chang ', # 0x0a +'Xi ', # 0x0b +'Wen ', # 0x0c +'Hun ', # 0x0d +'Yan ', # 0x0e +'E ', # 0x0f +'Chan ', # 0x10 +'Lan ', # 0x11 +'Qu ', # 0x12 +'Hui ', # 0x13 +'Kuo ', # 0x14 +'Que ', # 0x15 +'Ge ', # 0x16 +'Tian ', # 0x17 +'Ta ', # 0x18 +'Que ', # 0x19 +'Kan ', # 0x1a +'Huan ', # 0x1b +'Fu ', # 0x1c +'Fu ', # 0x1d +'Le ', # 0x1e +'Dui ', # 0x1f +'Xin ', # 0x20 +'Qian ', # 0x21 +'Wu ', # 0x22 +'Yi ', # 0x23 +'Tuo ', # 0x24 +'Yin ', # 0x25 +'Yang ', # 0x26 +'Dou ', # 0x27 +'E ', # 0x28 +'Sheng ', # 0x29 +'Ban ', # 0x2a +'Pei ', # 0x2b +'Keng ', # 0x2c +'Yun ', # 0x2d +'Ruan ', # 0x2e +'Zhi ', # 0x2f +'Pi ', # 0x30 +'Jing ', # 0x31 +'Fang ', # 0x32 +'Yang ', # 0x33 +'Yin ', # 0x34 +'Zhen ', # 0x35 +'Jie ', # 0x36 +'Cheng ', # 0x37 +'E ', # 0x38 +'Qu ', # 0x39 +'Di ', # 0x3a +'Zu ', # 0x3b +'Zuo ', # 0x3c +'Dian ', # 0x3d +'Ling ', # 0x3e +'A ', # 0x3f +'Tuo ', # 0x40 +'Tuo ', # 0x41 +'Po ', # 0x42 +'Bing ', # 0x43 +'Fu ', # 0x44 +'Ji ', # 0x45 +'Lu ', # 0x46 +'Long ', # 0x47 +'Chen ', # 0x48 +'Xing ', # 0x49 +'Duo ', # 0x4a +'Lou ', # 0x4b +'Mo ', # 0x4c +'Jiang ', # 0x4d +'Shu ', # 0x4e +'Duo ', # 0x4f +'Xian ', # 0x50 +'Er ', # 0x51 +'Gui ', # 0x52 +'Yu ', # 0x53 +'Gai ', # 0x54 +'Shan ', # 0x55 +'Xun ', # 0x56 +'Qiao ', # 0x57 +'Xing ', # 0x58 +'Chun ', # 0x59 +'Fu ', # 0x5a +'Bi ', # 0x5b +'Xia ', # 0x5c +'Shan ', # 0x5d +'Sheng ', # 0x5e +'Zhi ', # 0x5f +'Pu ', # 0x60 +'Dou ', # 0x61 +'Yuan ', # 0x62 +'Zhen ', # 0x63 +'Chu ', # 0x64 +'Xian ', # 0x65 +'Tou ', # 0x66 +'Nie ', # 0x67 +'Yun ', # 0x68 +'Xian ', # 0x69 +'Pei ', # 0x6a +'Pei ', # 0x6b +'Zou ', # 0x6c +'Yi ', # 0x6d +'Dui ', # 0x6e +'Lun ', # 0x6f +'Yin ', # 0x70 +'Ju ', # 0x71 +'Chui ', # 0x72 +'Chen ', # 0x73 +'Pi ', # 0x74 +'Ling ', # 0x75 +'Tao ', # 0x76 +'Xian ', # 0x77 +'Lu ', # 0x78 +'Sheng ', # 0x79 +'Xian ', # 0x7a +'Yin ', # 0x7b +'Zhu ', # 0x7c +'Yang ', # 0x7d +'Reng ', # 0x7e +'Shan ', # 0x7f +'Chong ', # 0x80 +'Yan ', # 0x81 +'Yin ', # 0x82 +'Yu ', # 0x83 +'Ti ', # 0x84 +'Yu ', # 0x85 +'Long ', # 0x86 +'Wei ', # 0x87 +'Wei ', # 0x88 +'Nie ', # 0x89 +'Dui ', # 0x8a +'Sui ', # 0x8b +'An ', # 0x8c +'Huang ', # 0x8d +'Jie ', # 0x8e +'Sui ', # 0x8f +'Yin ', # 0x90 +'Gai ', # 0x91 +'Yan ', # 0x92 +'Hui ', # 0x93 +'Ge ', # 0x94 +'Yun ', # 0x95 +'Wu ', # 0x96 +'Wei ', # 0x97 +'Ai ', # 0x98 +'Xi ', # 0x99 +'Tang ', # 0x9a +'Ji ', # 0x9b +'Zhang ', # 0x9c +'Dao ', # 0x9d +'Ao ', # 0x9e +'Xi ', # 0x9f +'Yin ', # 0xa0 +'[?] ', # 0xa1 +'Rao ', # 0xa2 +'Lin ', # 0xa3 +'Tui ', # 0xa4 +'Deng ', # 0xa5 +'Pi ', # 0xa6 +'Sui ', # 0xa7 +'Sui ', # 0xa8 +'Yu ', # 0xa9 +'Xian ', # 0xaa +'Fen ', # 0xab +'Ni ', # 0xac +'Er ', # 0xad +'Ji ', # 0xae +'Dao ', # 0xaf +'Xi ', # 0xb0 +'Yin ', # 0xb1 +'E ', # 0xb2 +'Hui ', # 0xb3 +'Long ', # 0xb4 +'Xi ', # 0xb5 +'Li ', # 0xb6 +'Li ', # 0xb7 +'Li ', # 0xb8 +'Zhui ', # 0xb9 +'He ', # 0xba +'Zhi ', # 0xbb +'Zhun ', # 0xbc +'Jun ', # 0xbd +'Nan ', # 0xbe +'Yi ', # 0xbf +'Que ', # 0xc0 +'Yan ', # 0xc1 +'Qian ', # 0xc2 +'Ya ', # 0xc3 +'Xiong ', # 0xc4 +'Ya ', # 0xc5 +'Ji ', # 0xc6 +'Gu ', # 0xc7 +'Huan ', # 0xc8 +'Zhi ', # 0xc9 +'Gou ', # 0xca +'Jun ', # 0xcb +'Ci ', # 0xcc +'Yong ', # 0xcd +'Ju ', # 0xce +'Chu ', # 0xcf +'Hu ', # 0xd0 +'Za ', # 0xd1 +'Luo ', # 0xd2 +'Yu ', # 0xd3 +'Chou ', # 0xd4 +'Diao ', # 0xd5 +'Sui ', # 0xd6 +'Han ', # 0xd7 +'Huo ', # 0xd8 +'Shuang ', # 0xd9 +'Guan ', # 0xda +'Chu ', # 0xdb +'Za ', # 0xdc +'Yong ', # 0xdd +'Ji ', # 0xde +'Xi ', # 0xdf +'Chou ', # 0xe0 +'Liu ', # 0xe1 +'Li ', # 0xe2 +'Nan ', # 0xe3 +'Xue ', # 0xe4 +'Za ', # 0xe5 +'Ji ', # 0xe6 +'Ji ', # 0xe7 +'Yu ', # 0xe8 +'Yu ', # 0xe9 +'Xue ', # 0xea +'Na ', # 0xeb +'Fou ', # 0xec +'Se ', # 0xed +'Mu ', # 0xee +'Wen ', # 0xef +'Fen ', # 0xf0 +'Pang ', # 0xf1 +'Yun ', # 0xf2 +'Li ', # 0xf3 +'Li ', # 0xf4 +'Ang ', # 0xf5 +'Ling ', # 0xf6 +'Lei ', # 0xf7 +'An ', # 0xf8 +'Bao ', # 0xf9 +'Meng ', # 0xfa +'Dian ', # 0xfb +'Dang ', # 0xfc +'Xing ', # 0xfd +'Wu ', # 0xfe +'Zhao ', # 0xff +) diff --git a/nstock/modules/unidecode/x097.py b/nstock/modules/unidecode/x097.py new file mode 100644 index 0000000..7255f0f --- /dev/null +++ b/nstock/modules/unidecode/x097.py @@ -0,0 +1,258 @@ +data = ( +'Xu ', # 0x00 +'Ji ', # 0x01 +'Mu ', # 0x02 +'Chen ', # 0x03 +'Xiao ', # 0x04 +'Zha ', # 0x05 +'Ting ', # 0x06 +'Zhen ', # 0x07 +'Pei ', # 0x08 +'Mei ', # 0x09 +'Ling ', # 0x0a +'Qi ', # 0x0b +'Chou ', # 0x0c +'Huo ', # 0x0d +'Sha ', # 0x0e +'Fei ', # 0x0f +'Weng ', # 0x10 +'Zhan ', # 0x11 +'Yin ', # 0x12 +'Ni ', # 0x13 +'Chou ', # 0x14 +'Tun ', # 0x15 +'Lin ', # 0x16 +'[?] ', # 0x17 +'Dong ', # 0x18 +'Ying ', # 0x19 +'Wu ', # 0x1a +'Ling ', # 0x1b +'Shuang ', # 0x1c +'Ling ', # 0x1d +'Xia ', # 0x1e +'Hong ', # 0x1f +'Yin ', # 0x20 +'Mo ', # 0x21 +'Mai ', # 0x22 +'Yun ', # 0x23 +'Liu ', # 0x24 +'Meng ', # 0x25 +'Bin ', # 0x26 +'Wu ', # 0x27 +'Wei ', # 0x28 +'Huo ', # 0x29 +'Yin ', # 0x2a +'Xi ', # 0x2b +'Yi ', # 0x2c +'Ai ', # 0x2d +'Dan ', # 0x2e +'Deng ', # 0x2f +'Xian ', # 0x30 +'Yu ', # 0x31 +'Lu ', # 0x32 +'Long ', # 0x33 +'Dai ', # 0x34 +'Ji ', # 0x35 +'Pang ', # 0x36 +'Yang ', # 0x37 +'Ba ', # 0x38 +'Pi ', # 0x39 +'Wei ', # 0x3a +'[?] ', # 0x3b +'Xi ', # 0x3c +'Ji ', # 0x3d +'Mai ', # 0x3e +'Meng ', # 0x3f +'Meng ', # 0x40 +'Lei ', # 0x41 +'Li ', # 0x42 +'Huo ', # 0x43 +'Ai ', # 0x44 +'Fei ', # 0x45 +'Dai ', # 0x46 +'Long ', # 0x47 +'Ling ', # 0x48 +'Ai ', # 0x49 +'Feng ', # 0x4a +'Li ', # 0x4b +'Bao ', # 0x4c +'[?] ', # 0x4d +'He ', # 0x4e +'He ', # 0x4f +'Bing ', # 0x50 +'Qing ', # 0x51 +'Qing ', # 0x52 +'Jing ', # 0x53 +'Tian ', # 0x54 +'Zhen ', # 0x55 +'Jing ', # 0x56 +'Cheng ', # 0x57 +'Qing ', # 0x58 +'Jing ', # 0x59 +'Jing ', # 0x5a +'Dian ', # 0x5b +'Jing ', # 0x5c +'Tian ', # 0x5d +'Fei ', # 0x5e +'Fei ', # 0x5f +'Kao ', # 0x60 +'Mi ', # 0x61 +'Mian ', # 0x62 +'Mian ', # 0x63 +'Pao ', # 0x64 +'Ye ', # 0x65 +'Tian ', # 0x66 +'Hui ', # 0x67 +'Ye ', # 0x68 +'Ge ', # 0x69 +'Ding ', # 0x6a +'Cha ', # 0x6b +'Jian ', # 0x6c +'Ren ', # 0x6d +'Di ', # 0x6e +'Du ', # 0x6f +'Wu ', # 0x70 +'Ren ', # 0x71 +'Qin ', # 0x72 +'Jin ', # 0x73 +'Xue ', # 0x74 +'Niu ', # 0x75 +'Ba ', # 0x76 +'Yin ', # 0x77 +'Sa ', # 0x78 +'Na ', # 0x79 +'Mo ', # 0x7a +'Zu ', # 0x7b +'Da ', # 0x7c +'Ban ', # 0x7d +'Yi ', # 0x7e +'Yao ', # 0x7f +'Tao ', # 0x80 +'Tuo ', # 0x81 +'Jia ', # 0x82 +'Hong ', # 0x83 +'Pao ', # 0x84 +'Yang ', # 0x85 +'Tomo ', # 0x86 +'Yin ', # 0x87 +'Jia ', # 0x88 +'Tao ', # 0x89 +'Ji ', # 0x8a +'Xie ', # 0x8b +'An ', # 0x8c +'An ', # 0x8d +'Hen ', # 0x8e +'Gong ', # 0x8f +'Kohaze ', # 0x90 +'Da ', # 0x91 +'Qiao ', # 0x92 +'Ting ', # 0x93 +'Wan ', # 0x94 +'Ying ', # 0x95 +'Sui ', # 0x96 +'Tiao ', # 0x97 +'Qiao ', # 0x98 +'Xuan ', # 0x99 +'Kong ', # 0x9a +'Beng ', # 0x9b +'Ta ', # 0x9c +'Zhang ', # 0x9d +'Bing ', # 0x9e +'Kuo ', # 0x9f +'Ju ', # 0xa0 +'La ', # 0xa1 +'Xie ', # 0xa2 +'Rou ', # 0xa3 +'Bang ', # 0xa4 +'Yi ', # 0xa5 +'Qiu ', # 0xa6 +'Qiu ', # 0xa7 +'He ', # 0xa8 +'Xiao ', # 0xa9 +'Mu ', # 0xaa +'Ju ', # 0xab +'Jian ', # 0xac +'Bian ', # 0xad +'Di ', # 0xae +'Jian ', # 0xaf +'On ', # 0xb0 +'Tao ', # 0xb1 +'Gou ', # 0xb2 +'Ta ', # 0xb3 +'Bei ', # 0xb4 +'Xie ', # 0xb5 +'Pan ', # 0xb6 +'Ge ', # 0xb7 +'Bi ', # 0xb8 +'Kuo ', # 0xb9 +'Tang ', # 0xba +'Lou ', # 0xbb +'Gui ', # 0xbc +'Qiao ', # 0xbd +'Xue ', # 0xbe +'Ji ', # 0xbf +'Jian ', # 0xc0 +'Jiang ', # 0xc1 +'Chan ', # 0xc2 +'Da ', # 0xc3 +'Huo ', # 0xc4 +'Xian ', # 0xc5 +'Qian ', # 0xc6 +'Du ', # 0xc7 +'Wa ', # 0xc8 +'Jian ', # 0xc9 +'Lan ', # 0xca +'Wei ', # 0xcb +'Ren ', # 0xcc +'Fu ', # 0xcd +'Mei ', # 0xce +'Juan ', # 0xcf +'Ge ', # 0xd0 +'Wei ', # 0xd1 +'Qiao ', # 0xd2 +'Han ', # 0xd3 +'Chang ', # 0xd4 +'[?] ', # 0xd5 +'Rou ', # 0xd6 +'Xun ', # 0xd7 +'She ', # 0xd8 +'Wei ', # 0xd9 +'Ge ', # 0xda +'Bei ', # 0xdb +'Tao ', # 0xdc +'Gou ', # 0xdd +'Yun ', # 0xde +'[?] ', # 0xdf +'Bi ', # 0xe0 +'Wei ', # 0xe1 +'Hui ', # 0xe2 +'Du ', # 0xe3 +'Wa ', # 0xe4 +'Du ', # 0xe5 +'Wei ', # 0xe6 +'Ren ', # 0xe7 +'Fu ', # 0xe8 +'Han ', # 0xe9 +'Wei ', # 0xea +'Yun ', # 0xeb +'Tao ', # 0xec +'Jiu ', # 0xed +'Jiu ', # 0xee +'Xian ', # 0xef +'Xie ', # 0xf0 +'Xian ', # 0xf1 +'Ji ', # 0xf2 +'Yin ', # 0xf3 +'Za ', # 0xf4 +'Yun ', # 0xf5 +'Shao ', # 0xf6 +'Le ', # 0xf7 +'Peng ', # 0xf8 +'Heng ', # 0xf9 +'Ying ', # 0xfa +'Yun ', # 0xfb +'Peng ', # 0xfc +'Yin ', # 0xfd +'Yin ', # 0xfe +'Xiang ', # 0xff +) diff --git a/nstock/modules/unidecode/x098.py b/nstock/modules/unidecode/x098.py new file mode 100644 index 0000000..98160e7 --- /dev/null +++ b/nstock/modules/unidecode/x098.py @@ -0,0 +1,258 @@ +data = ( +'Hu ', # 0x00 +'Ye ', # 0x01 +'Ding ', # 0x02 +'Qing ', # 0x03 +'Pan ', # 0x04 +'Xiang ', # 0x05 +'Shun ', # 0x06 +'Han ', # 0x07 +'Xu ', # 0x08 +'Yi ', # 0x09 +'Xu ', # 0x0a +'Gu ', # 0x0b +'Song ', # 0x0c +'Kui ', # 0x0d +'Qi ', # 0x0e +'Hang ', # 0x0f +'Yu ', # 0x10 +'Wan ', # 0x11 +'Ban ', # 0x12 +'Dun ', # 0x13 +'Di ', # 0x14 +'Dan ', # 0x15 +'Pan ', # 0x16 +'Po ', # 0x17 +'Ling ', # 0x18 +'Ce ', # 0x19 +'Jing ', # 0x1a +'Lei ', # 0x1b +'He ', # 0x1c +'Qiao ', # 0x1d +'E ', # 0x1e +'E ', # 0x1f +'Wei ', # 0x20 +'Jie ', # 0x21 +'Gua ', # 0x22 +'Shen ', # 0x23 +'Yi ', # 0x24 +'Shen ', # 0x25 +'Hai ', # 0x26 +'Dui ', # 0x27 +'Pian ', # 0x28 +'Ping ', # 0x29 +'Lei ', # 0x2a +'Fu ', # 0x2b +'Jia ', # 0x2c +'Tou ', # 0x2d +'Hui ', # 0x2e +'Kui ', # 0x2f +'Jia ', # 0x30 +'Le ', # 0x31 +'Tian ', # 0x32 +'Cheng ', # 0x33 +'Ying ', # 0x34 +'Jun ', # 0x35 +'Hu ', # 0x36 +'Han ', # 0x37 +'Jing ', # 0x38 +'Tui ', # 0x39 +'Tui ', # 0x3a +'Pin ', # 0x3b +'Lai ', # 0x3c +'Tui ', # 0x3d +'Zi ', # 0x3e +'Zi ', # 0x3f +'Chui ', # 0x40 +'Ding ', # 0x41 +'Lai ', # 0x42 +'Yan ', # 0x43 +'Han ', # 0x44 +'Jian ', # 0x45 +'Ke ', # 0x46 +'Cui ', # 0x47 +'Jiong ', # 0x48 +'Qin ', # 0x49 +'Yi ', # 0x4a +'Sai ', # 0x4b +'Ti ', # 0x4c +'E ', # 0x4d +'E ', # 0x4e +'Yan ', # 0x4f +'Hun ', # 0x50 +'Kan ', # 0x51 +'Yong ', # 0x52 +'Zhuan ', # 0x53 +'Yan ', # 0x54 +'Xian ', # 0x55 +'Xin ', # 0x56 +'Yi ', # 0x57 +'Yuan ', # 0x58 +'Sang ', # 0x59 +'Dian ', # 0x5a +'Dian ', # 0x5b +'Jiang ', # 0x5c +'Ku ', # 0x5d +'Lei ', # 0x5e +'Liao ', # 0x5f +'Piao ', # 0x60 +'Yi ', # 0x61 +'Man ', # 0x62 +'Qi ', # 0x63 +'Rao ', # 0x64 +'Hao ', # 0x65 +'Qiao ', # 0x66 +'Gu ', # 0x67 +'Xun ', # 0x68 +'Qian ', # 0x69 +'Hui ', # 0x6a +'Zhan ', # 0x6b +'Ru ', # 0x6c +'Hong ', # 0x6d +'Bin ', # 0x6e +'Xian ', # 0x6f +'Pin ', # 0x70 +'Lu ', # 0x71 +'Lan ', # 0x72 +'Nie ', # 0x73 +'Quan ', # 0x74 +'Ye ', # 0x75 +'Ding ', # 0x76 +'Qing ', # 0x77 +'Han ', # 0x78 +'Xiang ', # 0x79 +'Shun ', # 0x7a +'Xu ', # 0x7b +'Xu ', # 0x7c +'Wan ', # 0x7d +'Gu ', # 0x7e +'Dun ', # 0x7f +'Qi ', # 0x80 +'Ban ', # 0x81 +'Song ', # 0x82 +'Hang ', # 0x83 +'Yu ', # 0x84 +'Lu ', # 0x85 +'Ling ', # 0x86 +'Po ', # 0x87 +'Jing ', # 0x88 +'Jie ', # 0x89 +'Jia ', # 0x8a +'Tian ', # 0x8b +'Han ', # 0x8c +'Ying ', # 0x8d +'Jiong ', # 0x8e +'Hai ', # 0x8f +'Yi ', # 0x90 +'Pin ', # 0x91 +'Hui ', # 0x92 +'Tui ', # 0x93 +'Han ', # 0x94 +'Ying ', # 0x95 +'Ying ', # 0x96 +'Ke ', # 0x97 +'Ti ', # 0x98 +'Yong ', # 0x99 +'E ', # 0x9a +'Zhuan ', # 0x9b +'Yan ', # 0x9c +'E ', # 0x9d +'Nie ', # 0x9e +'Man ', # 0x9f +'Dian ', # 0xa0 +'Sang ', # 0xa1 +'Hao ', # 0xa2 +'Lei ', # 0xa3 +'Zhan ', # 0xa4 +'Ru ', # 0xa5 +'Pin ', # 0xa6 +'Quan ', # 0xa7 +'Feng ', # 0xa8 +'Biao ', # 0xa9 +'Oroshi ', # 0xaa +'Fu ', # 0xab +'Xia ', # 0xac +'Zhan ', # 0xad +'Biao ', # 0xae +'Sa ', # 0xaf +'Ba ', # 0xb0 +'Tai ', # 0xb1 +'Lie ', # 0xb2 +'Gua ', # 0xb3 +'Xuan ', # 0xb4 +'Shao ', # 0xb5 +'Ju ', # 0xb6 +'Bi ', # 0xb7 +'Si ', # 0xb8 +'Wei ', # 0xb9 +'Yang ', # 0xba +'Yao ', # 0xbb +'Sou ', # 0xbc +'Kai ', # 0xbd +'Sao ', # 0xbe +'Fan ', # 0xbf +'Liu ', # 0xc0 +'Xi ', # 0xc1 +'Liao ', # 0xc2 +'Piao ', # 0xc3 +'Piao ', # 0xc4 +'Liu ', # 0xc5 +'Biao ', # 0xc6 +'Biao ', # 0xc7 +'Biao ', # 0xc8 +'Liao ', # 0xc9 +'[?] ', # 0xca +'Se ', # 0xcb +'Feng ', # 0xcc +'Biao ', # 0xcd +'Feng ', # 0xce +'Yang ', # 0xcf +'Zhan ', # 0xd0 +'Biao ', # 0xd1 +'Sa ', # 0xd2 +'Ju ', # 0xd3 +'Si ', # 0xd4 +'Sou ', # 0xd5 +'Yao ', # 0xd6 +'Liu ', # 0xd7 +'Piao ', # 0xd8 +'Biao ', # 0xd9 +'Biao ', # 0xda +'Fei ', # 0xdb +'Fan ', # 0xdc +'Fei ', # 0xdd +'Fei ', # 0xde +'Shi ', # 0xdf +'Shi ', # 0xe0 +'Can ', # 0xe1 +'Ji ', # 0xe2 +'Ding ', # 0xe3 +'Si ', # 0xe4 +'Tuo ', # 0xe5 +'Zhan ', # 0xe6 +'Sun ', # 0xe7 +'Xiang ', # 0xe8 +'Tun ', # 0xe9 +'Ren ', # 0xea +'Yu ', # 0xeb +'Juan ', # 0xec +'Chi ', # 0xed +'Yin ', # 0xee +'Fan ', # 0xef +'Fan ', # 0xf0 +'Sun ', # 0xf1 +'Yin ', # 0xf2 +'Zhu ', # 0xf3 +'Yi ', # 0xf4 +'Zhai ', # 0xf5 +'Bi ', # 0xf6 +'Jie ', # 0xf7 +'Tao ', # 0xf8 +'Liu ', # 0xf9 +'Ci ', # 0xfa +'Tie ', # 0xfb +'Si ', # 0xfc +'Bao ', # 0xfd +'Shi ', # 0xfe +'Duo ', # 0xff +) diff --git a/nstock/modules/unidecode/x099.py b/nstock/modules/unidecode/x099.py new file mode 100644 index 0000000..2adf3de --- /dev/null +++ b/nstock/modules/unidecode/x099.py @@ -0,0 +1,258 @@ +data = ( +'Hai ', # 0x00 +'Ren ', # 0x01 +'Tian ', # 0x02 +'Jiao ', # 0x03 +'Jia ', # 0x04 +'Bing ', # 0x05 +'Yao ', # 0x06 +'Tong ', # 0x07 +'Ci ', # 0x08 +'Xiang ', # 0x09 +'Yang ', # 0x0a +'Yang ', # 0x0b +'Er ', # 0x0c +'Yan ', # 0x0d +'Le ', # 0x0e +'Yi ', # 0x0f +'Can ', # 0x10 +'Bo ', # 0x11 +'Nei ', # 0x12 +'E ', # 0x13 +'Bu ', # 0x14 +'Jun ', # 0x15 +'Dou ', # 0x16 +'Su ', # 0x17 +'Yu ', # 0x18 +'Shi ', # 0x19 +'Yao ', # 0x1a +'Hun ', # 0x1b +'Guo ', # 0x1c +'Shi ', # 0x1d +'Jian ', # 0x1e +'Zhui ', # 0x1f +'Bing ', # 0x20 +'Xian ', # 0x21 +'Bu ', # 0x22 +'Ye ', # 0x23 +'Tan ', # 0x24 +'Fei ', # 0x25 +'Zhang ', # 0x26 +'Wei ', # 0x27 +'Guan ', # 0x28 +'E ', # 0x29 +'Nuan ', # 0x2a +'Hun ', # 0x2b +'Hu ', # 0x2c +'Huang ', # 0x2d +'Tie ', # 0x2e +'Hui ', # 0x2f +'Jian ', # 0x30 +'Hou ', # 0x31 +'He ', # 0x32 +'Xing ', # 0x33 +'Fen ', # 0x34 +'Wei ', # 0x35 +'Gu ', # 0x36 +'Cha ', # 0x37 +'Song ', # 0x38 +'Tang ', # 0x39 +'Bo ', # 0x3a +'Gao ', # 0x3b +'Xi ', # 0x3c +'Kui ', # 0x3d +'Liu ', # 0x3e +'Sou ', # 0x3f +'Tao ', # 0x40 +'Ye ', # 0x41 +'Yun ', # 0x42 +'Mo ', # 0x43 +'Tang ', # 0x44 +'Man ', # 0x45 +'Bi ', # 0x46 +'Yu ', # 0x47 +'Xiu ', # 0x48 +'Jin ', # 0x49 +'San ', # 0x4a +'Kui ', # 0x4b +'Zhuan ', # 0x4c +'Shan ', # 0x4d +'Chi ', # 0x4e +'Dan ', # 0x4f +'Yi ', # 0x50 +'Ji ', # 0x51 +'Rao ', # 0x52 +'Cheng ', # 0x53 +'Yong ', # 0x54 +'Tao ', # 0x55 +'Hui ', # 0x56 +'Xiang ', # 0x57 +'Zhan ', # 0x58 +'Fen ', # 0x59 +'Hai ', # 0x5a +'Meng ', # 0x5b +'Yan ', # 0x5c +'Mo ', # 0x5d +'Chan ', # 0x5e +'Xiang ', # 0x5f +'Luo ', # 0x60 +'Zuan ', # 0x61 +'Nang ', # 0x62 +'Shi ', # 0x63 +'Ding ', # 0x64 +'Ji ', # 0x65 +'Tuo ', # 0x66 +'Xing ', # 0x67 +'Tun ', # 0x68 +'Xi ', # 0x69 +'Ren ', # 0x6a +'Yu ', # 0x6b +'Chi ', # 0x6c +'Fan ', # 0x6d +'Yin ', # 0x6e +'Jian ', # 0x6f +'Shi ', # 0x70 +'Bao ', # 0x71 +'Si ', # 0x72 +'Duo ', # 0x73 +'Yi ', # 0x74 +'Er ', # 0x75 +'Rao ', # 0x76 +'Xiang ', # 0x77 +'Jia ', # 0x78 +'Le ', # 0x79 +'Jiao ', # 0x7a +'Yi ', # 0x7b +'Bing ', # 0x7c +'Bo ', # 0x7d +'Dou ', # 0x7e +'E ', # 0x7f +'Yu ', # 0x80 +'Nei ', # 0x81 +'Jun ', # 0x82 +'Guo ', # 0x83 +'Hun ', # 0x84 +'Xian ', # 0x85 +'Guan ', # 0x86 +'Cha ', # 0x87 +'Kui ', # 0x88 +'Gu ', # 0x89 +'Sou ', # 0x8a +'Chan ', # 0x8b +'Ye ', # 0x8c +'Mo ', # 0x8d +'Bo ', # 0x8e +'Liu ', # 0x8f +'Xiu ', # 0x90 +'Jin ', # 0x91 +'Man ', # 0x92 +'San ', # 0x93 +'Zhuan ', # 0x94 +'Nang ', # 0x95 +'Shou ', # 0x96 +'Kui ', # 0x97 +'Guo ', # 0x98 +'Xiang ', # 0x99 +'Fen ', # 0x9a +'Ba ', # 0x9b +'Ni ', # 0x9c +'Bi ', # 0x9d +'Bo ', # 0x9e +'Tu ', # 0x9f +'Han ', # 0xa0 +'Fei ', # 0xa1 +'Jian ', # 0xa2 +'An ', # 0xa3 +'Ai ', # 0xa4 +'Fu ', # 0xa5 +'Xian ', # 0xa6 +'Wen ', # 0xa7 +'Xin ', # 0xa8 +'Fen ', # 0xa9 +'Bin ', # 0xaa +'Xing ', # 0xab +'Ma ', # 0xac +'Yu ', # 0xad +'Feng ', # 0xae +'Han ', # 0xaf +'Di ', # 0xb0 +'Tuo ', # 0xb1 +'Tuo ', # 0xb2 +'Chi ', # 0xb3 +'Xun ', # 0xb4 +'Zhu ', # 0xb5 +'Zhi ', # 0xb6 +'Pei ', # 0xb7 +'Xin ', # 0xb8 +'Ri ', # 0xb9 +'Sa ', # 0xba +'Yin ', # 0xbb +'Wen ', # 0xbc +'Zhi ', # 0xbd +'Dan ', # 0xbe +'Lu ', # 0xbf +'You ', # 0xc0 +'Bo ', # 0xc1 +'Bao ', # 0xc2 +'Kuai ', # 0xc3 +'Tuo ', # 0xc4 +'Yi ', # 0xc5 +'Qu ', # 0xc6 +'[?] ', # 0xc7 +'Qu ', # 0xc8 +'Jiong ', # 0xc9 +'Bo ', # 0xca +'Zhao ', # 0xcb +'Yuan ', # 0xcc +'Peng ', # 0xcd +'Zhou ', # 0xce +'Ju ', # 0xcf +'Zhu ', # 0xd0 +'Nu ', # 0xd1 +'Ju ', # 0xd2 +'Pi ', # 0xd3 +'Zang ', # 0xd4 +'Jia ', # 0xd5 +'Ling ', # 0xd6 +'Zhen ', # 0xd7 +'Tai ', # 0xd8 +'Fu ', # 0xd9 +'Yang ', # 0xda +'Shi ', # 0xdb +'Bi ', # 0xdc +'Tuo ', # 0xdd +'Tuo ', # 0xde +'Si ', # 0xdf +'Liu ', # 0xe0 +'Ma ', # 0xe1 +'Pian ', # 0xe2 +'Tao ', # 0xe3 +'Zhi ', # 0xe4 +'Rong ', # 0xe5 +'Teng ', # 0xe6 +'Dong ', # 0xe7 +'Xun ', # 0xe8 +'Quan ', # 0xe9 +'Shen ', # 0xea +'Jiong ', # 0xeb +'Er ', # 0xec +'Hai ', # 0xed +'Bo ', # 0xee +'Zhu ', # 0xef +'Yin ', # 0xf0 +'Luo ', # 0xf1 +'Shuu ', # 0xf2 +'Dan ', # 0xf3 +'Xie ', # 0xf4 +'Liu ', # 0xf5 +'Ju ', # 0xf6 +'Song ', # 0xf7 +'Qin ', # 0xf8 +'Mang ', # 0xf9 +'Liang ', # 0xfa +'Han ', # 0xfb +'Tu ', # 0xfc +'Xuan ', # 0xfd +'Tui ', # 0xfe +'Jun ', # 0xff +) diff --git a/nstock/modules/unidecode/x09a.py b/nstock/modules/unidecode/x09a.py new file mode 100644 index 0000000..ed9cd93 --- /dev/null +++ b/nstock/modules/unidecode/x09a.py @@ -0,0 +1,258 @@ +data = ( +'E ', # 0x00 +'Cheng ', # 0x01 +'Xin ', # 0x02 +'Ai ', # 0x03 +'Lu ', # 0x04 +'Zhui ', # 0x05 +'Zhou ', # 0x06 +'She ', # 0x07 +'Pian ', # 0x08 +'Kun ', # 0x09 +'Tao ', # 0x0a +'Lai ', # 0x0b +'Zong ', # 0x0c +'Ke ', # 0x0d +'Qi ', # 0x0e +'Qi ', # 0x0f +'Yan ', # 0x10 +'Fei ', # 0x11 +'Sao ', # 0x12 +'Yan ', # 0x13 +'Jie ', # 0x14 +'Yao ', # 0x15 +'Wu ', # 0x16 +'Pian ', # 0x17 +'Cong ', # 0x18 +'Pian ', # 0x19 +'Qian ', # 0x1a +'Fei ', # 0x1b +'Huang ', # 0x1c +'Jian ', # 0x1d +'Huo ', # 0x1e +'Yu ', # 0x1f +'Ti ', # 0x20 +'Quan ', # 0x21 +'Xia ', # 0x22 +'Zong ', # 0x23 +'Kui ', # 0x24 +'Rou ', # 0x25 +'Si ', # 0x26 +'Gua ', # 0x27 +'Tuo ', # 0x28 +'Kui ', # 0x29 +'Sou ', # 0x2a +'Qian ', # 0x2b +'Cheng ', # 0x2c +'Zhi ', # 0x2d +'Liu ', # 0x2e +'Pang ', # 0x2f +'Teng ', # 0x30 +'Xi ', # 0x31 +'Cao ', # 0x32 +'Du ', # 0x33 +'Yan ', # 0x34 +'Yuan ', # 0x35 +'Zou ', # 0x36 +'Sao ', # 0x37 +'Shan ', # 0x38 +'Li ', # 0x39 +'Zhi ', # 0x3a +'Shuang ', # 0x3b +'Lu ', # 0x3c +'Xi ', # 0x3d +'Luo ', # 0x3e +'Zhang ', # 0x3f +'Mo ', # 0x40 +'Ao ', # 0x41 +'Can ', # 0x42 +'Piao ', # 0x43 +'Cong ', # 0x44 +'Qu ', # 0x45 +'Bi ', # 0x46 +'Zhi ', # 0x47 +'Yu ', # 0x48 +'Xu ', # 0x49 +'Hua ', # 0x4a +'Bo ', # 0x4b +'Su ', # 0x4c +'Xiao ', # 0x4d +'Lin ', # 0x4e +'Chan ', # 0x4f +'Dun ', # 0x50 +'Liu ', # 0x51 +'Tuo ', # 0x52 +'Zeng ', # 0x53 +'Tan ', # 0x54 +'Jiao ', # 0x55 +'Tie ', # 0x56 +'Yan ', # 0x57 +'Luo ', # 0x58 +'Zhan ', # 0x59 +'Jing ', # 0x5a +'Yi ', # 0x5b +'Ye ', # 0x5c +'Tuo ', # 0x5d +'Bin ', # 0x5e +'Zou ', # 0x5f +'Yan ', # 0x60 +'Peng ', # 0x61 +'Lu ', # 0x62 +'Teng ', # 0x63 +'Xiang ', # 0x64 +'Ji ', # 0x65 +'Shuang ', # 0x66 +'Ju ', # 0x67 +'Xi ', # 0x68 +'Huan ', # 0x69 +'Li ', # 0x6a +'Biao ', # 0x6b +'Ma ', # 0x6c +'Yu ', # 0x6d +'Tuo ', # 0x6e +'Xun ', # 0x6f +'Chi ', # 0x70 +'Qu ', # 0x71 +'Ri ', # 0x72 +'Bo ', # 0x73 +'Lu ', # 0x74 +'Zang ', # 0x75 +'Shi ', # 0x76 +'Si ', # 0x77 +'Fu ', # 0x78 +'Ju ', # 0x79 +'Zou ', # 0x7a +'Zhu ', # 0x7b +'Tuo ', # 0x7c +'Nu ', # 0x7d +'Jia ', # 0x7e +'Yi ', # 0x7f +'Tai ', # 0x80 +'Xiao ', # 0x81 +'Ma ', # 0x82 +'Yin ', # 0x83 +'Jiao ', # 0x84 +'Hua ', # 0x85 +'Luo ', # 0x86 +'Hai ', # 0x87 +'Pian ', # 0x88 +'Biao ', # 0x89 +'Li ', # 0x8a +'Cheng ', # 0x8b +'Yan ', # 0x8c +'Xin ', # 0x8d +'Qin ', # 0x8e +'Jun ', # 0x8f +'Qi ', # 0x90 +'Qi ', # 0x91 +'Ke ', # 0x92 +'Zhui ', # 0x93 +'Zong ', # 0x94 +'Su ', # 0x95 +'Can ', # 0x96 +'Pian ', # 0x97 +'Zhi ', # 0x98 +'Kui ', # 0x99 +'Sao ', # 0x9a +'Wu ', # 0x9b +'Ao ', # 0x9c +'Liu ', # 0x9d +'Qian ', # 0x9e +'Shan ', # 0x9f +'Piao ', # 0xa0 +'Luo ', # 0xa1 +'Cong ', # 0xa2 +'Chan ', # 0xa3 +'Zou ', # 0xa4 +'Ji ', # 0xa5 +'Shuang ', # 0xa6 +'Xiang ', # 0xa7 +'Gu ', # 0xa8 +'Wei ', # 0xa9 +'Wei ', # 0xaa +'Wei ', # 0xab +'Yu ', # 0xac +'Gan ', # 0xad +'Yi ', # 0xae +'Ang ', # 0xaf +'Tou ', # 0xb0 +'Xie ', # 0xb1 +'Bao ', # 0xb2 +'Bi ', # 0xb3 +'Chi ', # 0xb4 +'Ti ', # 0xb5 +'Di ', # 0xb6 +'Ku ', # 0xb7 +'Hai ', # 0xb8 +'Qiao ', # 0xb9 +'Gou ', # 0xba +'Kua ', # 0xbb +'Ge ', # 0xbc +'Tui ', # 0xbd +'Geng ', # 0xbe +'Pian ', # 0xbf +'Bi ', # 0xc0 +'Ke ', # 0xc1 +'Ka ', # 0xc2 +'Yu ', # 0xc3 +'Sui ', # 0xc4 +'Lou ', # 0xc5 +'Bo ', # 0xc6 +'Xiao ', # 0xc7 +'Pang ', # 0xc8 +'Bo ', # 0xc9 +'Ci ', # 0xca +'Kuan ', # 0xcb +'Bin ', # 0xcc +'Mo ', # 0xcd +'Liao ', # 0xce +'Lou ', # 0xcf +'Nao ', # 0xd0 +'Du ', # 0xd1 +'Zang ', # 0xd2 +'Sui ', # 0xd3 +'Ti ', # 0xd4 +'Bin ', # 0xd5 +'Kuan ', # 0xd6 +'Lu ', # 0xd7 +'Gao ', # 0xd8 +'Gao ', # 0xd9 +'Qiao ', # 0xda +'Kao ', # 0xdb +'Qiao ', # 0xdc +'Lao ', # 0xdd +'Zao ', # 0xde +'Biao ', # 0xdf +'Kun ', # 0xe0 +'Kun ', # 0xe1 +'Ti ', # 0xe2 +'Fang ', # 0xe3 +'Xiu ', # 0xe4 +'Ran ', # 0xe5 +'Mao ', # 0xe6 +'Dan ', # 0xe7 +'Kun ', # 0xe8 +'Bin ', # 0xe9 +'Fa ', # 0xea +'Tiao ', # 0xeb +'Peng ', # 0xec +'Zi ', # 0xed +'Fa ', # 0xee +'Ran ', # 0xef +'Ti ', # 0xf0 +'Pao ', # 0xf1 +'Pi ', # 0xf2 +'Mao ', # 0xf3 +'Fu ', # 0xf4 +'Er ', # 0xf5 +'Rong ', # 0xf6 +'Qu ', # 0xf7 +'Gong ', # 0xf8 +'Xiu ', # 0xf9 +'Gua ', # 0xfa +'Ji ', # 0xfb +'Peng ', # 0xfc +'Zhua ', # 0xfd +'Shao ', # 0xfe +'Sha ', # 0xff +) diff --git a/nstock/modules/unidecode/x09b.py b/nstock/modules/unidecode/x09b.py new file mode 100644 index 0000000..7fd0a2d --- /dev/null +++ b/nstock/modules/unidecode/x09b.py @@ -0,0 +1,258 @@ +data = ( +'Ti ', # 0x00 +'Li ', # 0x01 +'Bin ', # 0x02 +'Zong ', # 0x03 +'Ti ', # 0x04 +'Peng ', # 0x05 +'Song ', # 0x06 +'Zheng ', # 0x07 +'Quan ', # 0x08 +'Zong ', # 0x09 +'Shun ', # 0x0a +'Jian ', # 0x0b +'Duo ', # 0x0c +'Hu ', # 0x0d +'La ', # 0x0e +'Jiu ', # 0x0f +'Qi ', # 0x10 +'Lian ', # 0x11 +'Zhen ', # 0x12 +'Bin ', # 0x13 +'Peng ', # 0x14 +'Mo ', # 0x15 +'San ', # 0x16 +'Man ', # 0x17 +'Man ', # 0x18 +'Seng ', # 0x19 +'Xu ', # 0x1a +'Lie ', # 0x1b +'Qian ', # 0x1c +'Qian ', # 0x1d +'Nong ', # 0x1e +'Huan ', # 0x1f +'Kuai ', # 0x20 +'Ning ', # 0x21 +'Bin ', # 0x22 +'Lie ', # 0x23 +'Rang ', # 0x24 +'Dou ', # 0x25 +'Dou ', # 0x26 +'Nao ', # 0x27 +'Hong ', # 0x28 +'Xi ', # 0x29 +'Dou ', # 0x2a +'Han ', # 0x2b +'Dou ', # 0x2c +'Dou ', # 0x2d +'Jiu ', # 0x2e +'Chang ', # 0x2f +'Yu ', # 0x30 +'Yu ', # 0x31 +'Li ', # 0x32 +'Juan ', # 0x33 +'Fu ', # 0x34 +'Qian ', # 0x35 +'Gui ', # 0x36 +'Zong ', # 0x37 +'Liu ', # 0x38 +'Gui ', # 0x39 +'Shang ', # 0x3a +'Yu ', # 0x3b +'Gui ', # 0x3c +'Mei ', # 0x3d +'Ji ', # 0x3e +'Qi ', # 0x3f +'Jie ', # 0x40 +'Kui ', # 0x41 +'Hun ', # 0x42 +'Ba ', # 0x43 +'Po ', # 0x44 +'Mei ', # 0x45 +'Xu ', # 0x46 +'Yan ', # 0x47 +'Xiao ', # 0x48 +'Liang ', # 0x49 +'Yu ', # 0x4a +'Tui ', # 0x4b +'Qi ', # 0x4c +'Wang ', # 0x4d +'Liang ', # 0x4e +'Wei ', # 0x4f +'Jian ', # 0x50 +'Chi ', # 0x51 +'Piao ', # 0x52 +'Bi ', # 0x53 +'Mo ', # 0x54 +'Ji ', # 0x55 +'Xu ', # 0x56 +'Chou ', # 0x57 +'Yan ', # 0x58 +'Zhan ', # 0x59 +'Yu ', # 0x5a +'Dao ', # 0x5b +'Ren ', # 0x5c +'Ji ', # 0x5d +'Eri ', # 0x5e +'Gong ', # 0x5f +'Tuo ', # 0x60 +'Diao ', # 0x61 +'Ji ', # 0x62 +'Xu ', # 0x63 +'E ', # 0x64 +'E ', # 0x65 +'Sha ', # 0x66 +'Hang ', # 0x67 +'Tun ', # 0x68 +'Mo ', # 0x69 +'Jie ', # 0x6a +'Shen ', # 0x6b +'Fan ', # 0x6c +'Yuan ', # 0x6d +'Bi ', # 0x6e +'Lu ', # 0x6f +'Wen ', # 0x70 +'Hu ', # 0x71 +'Lu ', # 0x72 +'Za ', # 0x73 +'Fang ', # 0x74 +'Fen ', # 0x75 +'Na ', # 0x76 +'You ', # 0x77 +'Namazu ', # 0x78 +'Todo ', # 0x79 +'He ', # 0x7a +'Xia ', # 0x7b +'Qu ', # 0x7c +'Han ', # 0x7d +'Pi ', # 0x7e +'Ling ', # 0x7f +'Tuo ', # 0x80 +'Bo ', # 0x81 +'Qiu ', # 0x82 +'Ping ', # 0x83 +'Fu ', # 0x84 +'Bi ', # 0x85 +'Ji ', # 0x86 +'Wei ', # 0x87 +'Ju ', # 0x88 +'Diao ', # 0x89 +'Bo ', # 0x8a +'You ', # 0x8b +'Gun ', # 0x8c +'Pi ', # 0x8d +'Nian ', # 0x8e +'Xing ', # 0x8f +'Tai ', # 0x90 +'Bao ', # 0x91 +'Fu ', # 0x92 +'Zha ', # 0x93 +'Ju ', # 0x94 +'Gu ', # 0x95 +'Kajika ', # 0x96 +'Tong ', # 0x97 +'[?] ', # 0x98 +'Ta ', # 0x99 +'Jie ', # 0x9a +'Shu ', # 0x9b +'Hou ', # 0x9c +'Xiang ', # 0x9d +'Er ', # 0x9e +'An ', # 0x9f +'Wei ', # 0xa0 +'Tiao ', # 0xa1 +'Zhu ', # 0xa2 +'Yin ', # 0xa3 +'Lie ', # 0xa4 +'Luo ', # 0xa5 +'Tong ', # 0xa6 +'Yi ', # 0xa7 +'Qi ', # 0xa8 +'Bing ', # 0xa9 +'Wei ', # 0xaa +'Jiao ', # 0xab +'Bu ', # 0xac +'Gui ', # 0xad +'Xian ', # 0xae +'Ge ', # 0xaf +'Hui ', # 0xb0 +'Bora ', # 0xb1 +'Mate ', # 0xb2 +'Kao ', # 0xb3 +'Gori ', # 0xb4 +'Duo ', # 0xb5 +'Jun ', # 0xb6 +'Ti ', # 0xb7 +'Man ', # 0xb8 +'Xiao ', # 0xb9 +'Za ', # 0xba +'Sha ', # 0xbb +'Qin ', # 0xbc +'Yu ', # 0xbd +'Nei ', # 0xbe +'Zhe ', # 0xbf +'Gun ', # 0xc0 +'Geng ', # 0xc1 +'Su ', # 0xc2 +'Wu ', # 0xc3 +'Qiu ', # 0xc4 +'Ting ', # 0xc5 +'Fu ', # 0xc6 +'Wan ', # 0xc7 +'You ', # 0xc8 +'Li ', # 0xc9 +'Sha ', # 0xca +'Sha ', # 0xcb +'Gao ', # 0xcc +'Meng ', # 0xcd +'Ugui ', # 0xce +'Asari ', # 0xcf +'Subashiri ', # 0xd0 +'Kazunoko ', # 0xd1 +'Yong ', # 0xd2 +'Ni ', # 0xd3 +'Zi ', # 0xd4 +'Qi ', # 0xd5 +'Qing ', # 0xd6 +'Xiang ', # 0xd7 +'Nei ', # 0xd8 +'Chun ', # 0xd9 +'Ji ', # 0xda +'Diao ', # 0xdb +'Qie ', # 0xdc +'Gu ', # 0xdd +'Zhou ', # 0xde +'Dong ', # 0xdf +'Lai ', # 0xe0 +'Fei ', # 0xe1 +'Ni ', # 0xe2 +'Yi ', # 0xe3 +'Kun ', # 0xe4 +'Lu ', # 0xe5 +'Jiu ', # 0xe6 +'Chang ', # 0xe7 +'Jing ', # 0xe8 +'Lun ', # 0xe9 +'Ling ', # 0xea +'Zou ', # 0xeb +'Li ', # 0xec +'Meng ', # 0xed +'Zong ', # 0xee +'Zhi ', # 0xef +'Nian ', # 0xf0 +'Shachi ', # 0xf1 +'Dojou ', # 0xf2 +'Sukesou ', # 0xf3 +'Shi ', # 0xf4 +'Shen ', # 0xf5 +'Hun ', # 0xf6 +'Shi ', # 0xf7 +'Hou ', # 0xf8 +'Xing ', # 0xf9 +'Zhu ', # 0xfa +'La ', # 0xfb +'Zong ', # 0xfc +'Ji ', # 0xfd +'Bian ', # 0xfe +'Bian ', # 0xff +) diff --git a/nstock/modules/unidecode/x09c.py b/nstock/modules/unidecode/x09c.py new file mode 100644 index 0000000..e7f7937 --- /dev/null +++ b/nstock/modules/unidecode/x09c.py @@ -0,0 +1,258 @@ +data = ( +'Huan ', # 0x00 +'Quan ', # 0x01 +'Ze ', # 0x02 +'Wei ', # 0x03 +'Wei ', # 0x04 +'Yu ', # 0x05 +'Qun ', # 0x06 +'Rou ', # 0x07 +'Die ', # 0x08 +'Huang ', # 0x09 +'Lian ', # 0x0a +'Yan ', # 0x0b +'Qiu ', # 0x0c +'Qiu ', # 0x0d +'Jian ', # 0x0e +'Bi ', # 0x0f +'E ', # 0x10 +'Yang ', # 0x11 +'Fu ', # 0x12 +'Sai ', # 0x13 +'Jian ', # 0x14 +'Xia ', # 0x15 +'Tuo ', # 0x16 +'Hu ', # 0x17 +'Muroaji ', # 0x18 +'Ruo ', # 0x19 +'Haraka ', # 0x1a +'Wen ', # 0x1b +'Jian ', # 0x1c +'Hao ', # 0x1d +'Wu ', # 0x1e +'Fang ', # 0x1f +'Sao ', # 0x20 +'Liu ', # 0x21 +'Ma ', # 0x22 +'Shi ', # 0x23 +'Shi ', # 0x24 +'Yin ', # 0x25 +'Z ', # 0x26 +'Teng ', # 0x27 +'Ta ', # 0x28 +'Yao ', # 0x29 +'Ge ', # 0x2a +'Rong ', # 0x2b +'Qian ', # 0x2c +'Qi ', # 0x2d +'Wen ', # 0x2e +'Ruo ', # 0x2f +'Hatahata ', # 0x30 +'Lian ', # 0x31 +'Ao ', # 0x32 +'Le ', # 0x33 +'Hui ', # 0x34 +'Min ', # 0x35 +'Ji ', # 0x36 +'Tiao ', # 0x37 +'Qu ', # 0x38 +'Jian ', # 0x39 +'Sao ', # 0x3a +'Man ', # 0x3b +'Xi ', # 0x3c +'Qiu ', # 0x3d +'Biao ', # 0x3e +'Ji ', # 0x3f +'Ji ', # 0x40 +'Zhu ', # 0x41 +'Jiang ', # 0x42 +'Qiu ', # 0x43 +'Zhuan ', # 0x44 +'Yong ', # 0x45 +'Zhang ', # 0x46 +'Kang ', # 0x47 +'Xue ', # 0x48 +'Bie ', # 0x49 +'Jue ', # 0x4a +'Qu ', # 0x4b +'Xiang ', # 0x4c +'Bo ', # 0x4d +'Jiao ', # 0x4e +'Xun ', # 0x4f +'Su ', # 0x50 +'Huang ', # 0x51 +'Zun ', # 0x52 +'Shan ', # 0x53 +'Shan ', # 0x54 +'Fan ', # 0x55 +'Jue ', # 0x56 +'Lin ', # 0x57 +'Xun ', # 0x58 +'Miao ', # 0x59 +'Xi ', # 0x5a +'Eso ', # 0x5b +'Kyou ', # 0x5c +'Fen ', # 0x5d +'Guan ', # 0x5e +'Hou ', # 0x5f +'Kuai ', # 0x60 +'Zei ', # 0x61 +'Sao ', # 0x62 +'Zhan ', # 0x63 +'Gan ', # 0x64 +'Gui ', # 0x65 +'Sheng ', # 0x66 +'Li ', # 0x67 +'Chang ', # 0x68 +'Hatahata ', # 0x69 +'Shiira ', # 0x6a +'Mutsu ', # 0x6b +'Ru ', # 0x6c +'Ji ', # 0x6d +'Xu ', # 0x6e +'Huo ', # 0x6f +'Shiira ', # 0x70 +'Li ', # 0x71 +'Lie ', # 0x72 +'Li ', # 0x73 +'Mie ', # 0x74 +'Zhen ', # 0x75 +'Xiang ', # 0x76 +'E ', # 0x77 +'Lu ', # 0x78 +'Guan ', # 0x79 +'Li ', # 0x7a +'Xian ', # 0x7b +'Yu ', # 0x7c +'Dao ', # 0x7d +'Ji ', # 0x7e +'You ', # 0x7f +'Tun ', # 0x80 +'Lu ', # 0x81 +'Fang ', # 0x82 +'Ba ', # 0x83 +'He ', # 0x84 +'Bo ', # 0x85 +'Ping ', # 0x86 +'Nian ', # 0x87 +'Lu ', # 0x88 +'You ', # 0x89 +'Zha ', # 0x8a +'Fu ', # 0x8b +'Bo ', # 0x8c +'Bao ', # 0x8d +'Hou ', # 0x8e +'Pi ', # 0x8f +'Tai ', # 0x90 +'Gui ', # 0x91 +'Jie ', # 0x92 +'Kao ', # 0x93 +'Wei ', # 0x94 +'Er ', # 0x95 +'Tong ', # 0x96 +'Ze ', # 0x97 +'Hou ', # 0x98 +'Kuai ', # 0x99 +'Ji ', # 0x9a +'Jiao ', # 0x9b +'Xian ', # 0x9c +'Za ', # 0x9d +'Xiang ', # 0x9e +'Xun ', # 0x9f +'Geng ', # 0xa0 +'Li ', # 0xa1 +'Lian ', # 0xa2 +'Jian ', # 0xa3 +'Li ', # 0xa4 +'Shi ', # 0xa5 +'Tiao ', # 0xa6 +'Gun ', # 0xa7 +'Sha ', # 0xa8 +'Wan ', # 0xa9 +'Jun ', # 0xaa +'Ji ', # 0xab +'Yong ', # 0xac +'Qing ', # 0xad +'Ling ', # 0xae +'Qi ', # 0xaf +'Zou ', # 0xb0 +'Fei ', # 0xb1 +'Kun ', # 0xb2 +'Chang ', # 0xb3 +'Gu ', # 0xb4 +'Ni ', # 0xb5 +'Nian ', # 0xb6 +'Diao ', # 0xb7 +'Jing ', # 0xb8 +'Shen ', # 0xb9 +'Shi ', # 0xba +'Zi ', # 0xbb +'Fen ', # 0xbc +'Die ', # 0xbd +'Bi ', # 0xbe +'Chang ', # 0xbf +'Shi ', # 0xc0 +'Wen ', # 0xc1 +'Wei ', # 0xc2 +'Sai ', # 0xc3 +'E ', # 0xc4 +'Qiu ', # 0xc5 +'Fu ', # 0xc6 +'Huang ', # 0xc7 +'Quan ', # 0xc8 +'Jiang ', # 0xc9 +'Bian ', # 0xca +'Sao ', # 0xcb +'Ao ', # 0xcc +'Qi ', # 0xcd +'Ta ', # 0xce +'Yin ', # 0xcf +'Yao ', # 0xd0 +'Fang ', # 0xd1 +'Jian ', # 0xd2 +'Le ', # 0xd3 +'Biao ', # 0xd4 +'Xue ', # 0xd5 +'Bie ', # 0xd6 +'Man ', # 0xd7 +'Min ', # 0xd8 +'Yong ', # 0xd9 +'Wei ', # 0xda +'Xi ', # 0xdb +'Jue ', # 0xdc +'Shan ', # 0xdd +'Lin ', # 0xde +'Zun ', # 0xdf +'Huo ', # 0xe0 +'Gan ', # 0xe1 +'Li ', # 0xe2 +'Zhan ', # 0xe3 +'Guan ', # 0xe4 +'Niao ', # 0xe5 +'Yi ', # 0xe6 +'Fu ', # 0xe7 +'Li ', # 0xe8 +'Jiu ', # 0xe9 +'Bu ', # 0xea +'Yan ', # 0xeb +'Fu ', # 0xec +'Diao ', # 0xed +'Ji ', # 0xee +'Feng ', # 0xef +'Nio ', # 0xf0 +'Gan ', # 0xf1 +'Shi ', # 0xf2 +'Feng ', # 0xf3 +'Ming ', # 0xf4 +'Bao ', # 0xf5 +'Yuan ', # 0xf6 +'Zhi ', # 0xf7 +'Hu ', # 0xf8 +'Qin ', # 0xf9 +'Fu ', # 0xfa +'Fen ', # 0xfb +'Wen ', # 0xfc +'Jian ', # 0xfd +'Shi ', # 0xfe +'Yu ', # 0xff +) diff --git a/nstock/modules/unidecode/x09d.py b/nstock/modules/unidecode/x09d.py new file mode 100644 index 0000000..99d5859 --- /dev/null +++ b/nstock/modules/unidecode/x09d.py @@ -0,0 +1,258 @@ +data = ( +'Fou ', # 0x00 +'Yiao ', # 0x01 +'Jue ', # 0x02 +'Jue ', # 0x03 +'Pi ', # 0x04 +'Huan ', # 0x05 +'Zhen ', # 0x06 +'Bao ', # 0x07 +'Yan ', # 0x08 +'Ya ', # 0x09 +'Zheng ', # 0x0a +'Fang ', # 0x0b +'Feng ', # 0x0c +'Wen ', # 0x0d +'Ou ', # 0x0e +'Te ', # 0x0f +'Jia ', # 0x10 +'Nu ', # 0x11 +'Ling ', # 0x12 +'Mie ', # 0x13 +'Fu ', # 0x14 +'Tuo ', # 0x15 +'Wen ', # 0x16 +'Li ', # 0x17 +'Bian ', # 0x18 +'Zhi ', # 0x19 +'Ge ', # 0x1a +'Yuan ', # 0x1b +'Zi ', # 0x1c +'Qu ', # 0x1d +'Xiao ', # 0x1e +'Zhi ', # 0x1f +'Dan ', # 0x20 +'Ju ', # 0x21 +'You ', # 0x22 +'Gu ', # 0x23 +'Zhong ', # 0x24 +'Yu ', # 0x25 +'Yang ', # 0x26 +'Rong ', # 0x27 +'Ya ', # 0x28 +'Tie ', # 0x29 +'Yu ', # 0x2a +'Shigi ', # 0x2b +'Ying ', # 0x2c +'Zhui ', # 0x2d +'Wu ', # 0x2e +'Er ', # 0x2f +'Gua ', # 0x30 +'Ai ', # 0x31 +'Zhi ', # 0x32 +'Yan ', # 0x33 +'Heng ', # 0x34 +'Jiao ', # 0x35 +'Ji ', # 0x36 +'Lie ', # 0x37 +'Zhu ', # 0x38 +'Ren ', # 0x39 +'Yi ', # 0x3a +'Hong ', # 0x3b +'Luo ', # 0x3c +'Ru ', # 0x3d +'Mou ', # 0x3e +'Ge ', # 0x3f +'Ren ', # 0x40 +'Jiao ', # 0x41 +'Xiu ', # 0x42 +'Zhou ', # 0x43 +'Zhi ', # 0x44 +'Luo ', # 0x45 +'Chidori ', # 0x46 +'Toki ', # 0x47 +'Ten ', # 0x48 +'Luan ', # 0x49 +'Jia ', # 0x4a +'Ji ', # 0x4b +'Yu ', # 0x4c +'Huan ', # 0x4d +'Tuo ', # 0x4e +'Bu ', # 0x4f +'Wu ', # 0x50 +'Juan ', # 0x51 +'Yu ', # 0x52 +'Bo ', # 0x53 +'Xun ', # 0x54 +'Xun ', # 0x55 +'Bi ', # 0x56 +'Xi ', # 0x57 +'Jun ', # 0x58 +'Ju ', # 0x59 +'Tu ', # 0x5a +'Jing ', # 0x5b +'Ti ', # 0x5c +'E ', # 0x5d +'E ', # 0x5e +'Kuang ', # 0x5f +'Hu ', # 0x60 +'Wu ', # 0x61 +'Shen ', # 0x62 +'Lai ', # 0x63 +'Ikaruga ', # 0x64 +'Kakesu ', # 0x65 +'Lu ', # 0x66 +'Ping ', # 0x67 +'Shu ', # 0x68 +'Fu ', # 0x69 +'An ', # 0x6a +'Zhao ', # 0x6b +'Peng ', # 0x6c +'Qin ', # 0x6d +'Qian ', # 0x6e +'Bei ', # 0x6f +'Diao ', # 0x70 +'Lu ', # 0x71 +'Que ', # 0x72 +'Jian ', # 0x73 +'Ju ', # 0x74 +'Tu ', # 0x75 +'Ya ', # 0x76 +'Yuan ', # 0x77 +'Qi ', # 0x78 +'Li ', # 0x79 +'Ye ', # 0x7a +'Zhui ', # 0x7b +'Kong ', # 0x7c +'Zhui ', # 0x7d +'Kun ', # 0x7e +'Sheng ', # 0x7f +'Qi ', # 0x80 +'Jing ', # 0x81 +'Yi ', # 0x82 +'Yi ', # 0x83 +'Jing ', # 0x84 +'Zi ', # 0x85 +'Lai ', # 0x86 +'Dong ', # 0x87 +'Qi ', # 0x88 +'Chun ', # 0x89 +'Geng ', # 0x8a +'Ju ', # 0x8b +'Qu ', # 0x8c +'Isuka ', # 0x8d +'Kikuitadaki ', # 0x8e +'Ji ', # 0x8f +'Shu ', # 0x90 +'[?] ', # 0x91 +'Chi ', # 0x92 +'Miao ', # 0x93 +'Rou ', # 0x94 +'An ', # 0x95 +'Qiu ', # 0x96 +'Ti ', # 0x97 +'Hu ', # 0x98 +'Ti ', # 0x99 +'E ', # 0x9a +'Jie ', # 0x9b +'Mao ', # 0x9c +'Fu ', # 0x9d +'Chun ', # 0x9e +'Tu ', # 0x9f +'Yan ', # 0xa0 +'He ', # 0xa1 +'Yuan ', # 0xa2 +'Pian ', # 0xa3 +'Yun ', # 0xa4 +'Mei ', # 0xa5 +'Hu ', # 0xa6 +'Ying ', # 0xa7 +'Dun ', # 0xa8 +'Mu ', # 0xa9 +'Ju ', # 0xaa +'Tsugumi ', # 0xab +'Cang ', # 0xac +'Fang ', # 0xad +'Gu ', # 0xae +'Ying ', # 0xaf +'Yuan ', # 0xb0 +'Xuan ', # 0xb1 +'Weng ', # 0xb2 +'Shi ', # 0xb3 +'He ', # 0xb4 +'Chu ', # 0xb5 +'Tang ', # 0xb6 +'Xia ', # 0xb7 +'Ruo ', # 0xb8 +'Liu ', # 0xb9 +'Ji ', # 0xba +'Gu ', # 0xbb +'Jian ', # 0xbc +'Zhun ', # 0xbd +'Han ', # 0xbe +'Zi ', # 0xbf +'Zi ', # 0xc0 +'Ni ', # 0xc1 +'Yao ', # 0xc2 +'Yan ', # 0xc3 +'Ji ', # 0xc4 +'Li ', # 0xc5 +'Tian ', # 0xc6 +'Kou ', # 0xc7 +'Ti ', # 0xc8 +'Ti ', # 0xc9 +'Ni ', # 0xca +'Tu ', # 0xcb +'Ma ', # 0xcc +'Jiao ', # 0xcd +'Gao ', # 0xce +'Tian ', # 0xcf +'Chen ', # 0xd0 +'Li ', # 0xd1 +'Zhuan ', # 0xd2 +'Zhe ', # 0xd3 +'Ao ', # 0xd4 +'Yao ', # 0xd5 +'Yi ', # 0xd6 +'Ou ', # 0xd7 +'Chi ', # 0xd8 +'Zhi ', # 0xd9 +'Liao ', # 0xda +'Rong ', # 0xdb +'Lou ', # 0xdc +'Bi ', # 0xdd +'Shuang ', # 0xde +'Zhuo ', # 0xdf +'Yu ', # 0xe0 +'Wu ', # 0xe1 +'Jue ', # 0xe2 +'Yin ', # 0xe3 +'Quan ', # 0xe4 +'Si ', # 0xe5 +'Jiao ', # 0xe6 +'Yi ', # 0xe7 +'Hua ', # 0xe8 +'Bi ', # 0xe9 +'Ying ', # 0xea +'Su ', # 0xeb +'Huang ', # 0xec +'Fan ', # 0xed +'Jiao ', # 0xee +'Liao ', # 0xef +'Yan ', # 0xf0 +'Kao ', # 0xf1 +'Jiu ', # 0xf2 +'Xian ', # 0xf3 +'Xian ', # 0xf4 +'Tu ', # 0xf5 +'Mai ', # 0xf6 +'Zun ', # 0xf7 +'Yu ', # 0xf8 +'Ying ', # 0xf9 +'Lu ', # 0xfa +'Tuan ', # 0xfb +'Xian ', # 0xfc +'Xue ', # 0xfd +'Yi ', # 0xfe +'Pi ', # 0xff +) diff --git a/nstock/modules/unidecode/x09e.py b/nstock/modules/unidecode/x09e.py new file mode 100644 index 0000000..8a392a2 --- /dev/null +++ b/nstock/modules/unidecode/x09e.py @@ -0,0 +1,258 @@ +data = ( +'Shu ', # 0x00 +'Luo ', # 0x01 +'Qi ', # 0x02 +'Yi ', # 0x03 +'Ji ', # 0x04 +'Zhe ', # 0x05 +'Yu ', # 0x06 +'Zhan ', # 0x07 +'Ye ', # 0x08 +'Yang ', # 0x09 +'Pi ', # 0x0a +'Ning ', # 0x0b +'Huo ', # 0x0c +'Mi ', # 0x0d +'Ying ', # 0x0e +'Meng ', # 0x0f +'Di ', # 0x10 +'Yue ', # 0x11 +'Yu ', # 0x12 +'Lei ', # 0x13 +'Bao ', # 0x14 +'Lu ', # 0x15 +'He ', # 0x16 +'Long ', # 0x17 +'Shuang ', # 0x18 +'Yue ', # 0x19 +'Ying ', # 0x1a +'Guan ', # 0x1b +'Qu ', # 0x1c +'Li ', # 0x1d +'Luan ', # 0x1e +'Niao ', # 0x1f +'Jiu ', # 0x20 +'Ji ', # 0x21 +'Yuan ', # 0x22 +'Ming ', # 0x23 +'Shi ', # 0x24 +'Ou ', # 0x25 +'Ya ', # 0x26 +'Cang ', # 0x27 +'Bao ', # 0x28 +'Zhen ', # 0x29 +'Gu ', # 0x2a +'Dong ', # 0x2b +'Lu ', # 0x2c +'Ya ', # 0x2d +'Xiao ', # 0x2e +'Yang ', # 0x2f +'Ling ', # 0x30 +'Zhi ', # 0x31 +'Qu ', # 0x32 +'Yuan ', # 0x33 +'Xue ', # 0x34 +'Tuo ', # 0x35 +'Si ', # 0x36 +'Zhi ', # 0x37 +'Er ', # 0x38 +'Gua ', # 0x39 +'Xiu ', # 0x3a +'Heng ', # 0x3b +'Zhou ', # 0x3c +'Ge ', # 0x3d +'Luan ', # 0x3e +'Hong ', # 0x3f +'Wu ', # 0x40 +'Bo ', # 0x41 +'Li ', # 0x42 +'Juan ', # 0x43 +'Hu ', # 0x44 +'E ', # 0x45 +'Yu ', # 0x46 +'Xian ', # 0x47 +'Ti ', # 0x48 +'Wu ', # 0x49 +'Que ', # 0x4a +'Miao ', # 0x4b +'An ', # 0x4c +'Kun ', # 0x4d +'Bei ', # 0x4e +'Peng ', # 0x4f +'Qian ', # 0x50 +'Chun ', # 0x51 +'Geng ', # 0x52 +'Yuan ', # 0x53 +'Su ', # 0x54 +'Hu ', # 0x55 +'He ', # 0x56 +'E ', # 0x57 +'Gu ', # 0x58 +'Qiu ', # 0x59 +'Zi ', # 0x5a +'Mei ', # 0x5b +'Mu ', # 0x5c +'Ni ', # 0x5d +'Yao ', # 0x5e +'Weng ', # 0x5f +'Liu ', # 0x60 +'Ji ', # 0x61 +'Ni ', # 0x62 +'Jian ', # 0x63 +'He ', # 0x64 +'Yi ', # 0x65 +'Ying ', # 0x66 +'Zhe ', # 0x67 +'Liao ', # 0x68 +'Liao ', # 0x69 +'Jiao ', # 0x6a +'Jiu ', # 0x6b +'Yu ', # 0x6c +'Lu ', # 0x6d +'Xuan ', # 0x6e +'Zhan ', # 0x6f +'Ying ', # 0x70 +'Huo ', # 0x71 +'Meng ', # 0x72 +'Guan ', # 0x73 +'Shuang ', # 0x74 +'Lu ', # 0x75 +'Jin ', # 0x76 +'Ling ', # 0x77 +'Jian ', # 0x78 +'Xian ', # 0x79 +'Cuo ', # 0x7a +'Jian ', # 0x7b +'Jian ', # 0x7c +'Yan ', # 0x7d +'Cuo ', # 0x7e +'Lu ', # 0x7f +'You ', # 0x80 +'Cu ', # 0x81 +'Ji ', # 0x82 +'Biao ', # 0x83 +'Cu ', # 0x84 +'Biao ', # 0x85 +'Zhu ', # 0x86 +'Jun ', # 0x87 +'Zhu ', # 0x88 +'Jian ', # 0x89 +'Mi ', # 0x8a +'Mi ', # 0x8b +'Wu ', # 0x8c +'Liu ', # 0x8d +'Chen ', # 0x8e +'Jun ', # 0x8f +'Lin ', # 0x90 +'Ni ', # 0x91 +'Qi ', # 0x92 +'Lu ', # 0x93 +'Jiu ', # 0x94 +'Jun ', # 0x95 +'Jing ', # 0x96 +'Li ', # 0x97 +'Xiang ', # 0x98 +'Yan ', # 0x99 +'Jia ', # 0x9a +'Mi ', # 0x9b +'Li ', # 0x9c +'She ', # 0x9d +'Zhang ', # 0x9e +'Lin ', # 0x9f +'Jing ', # 0xa0 +'Ji ', # 0xa1 +'Ling ', # 0xa2 +'Yan ', # 0xa3 +'Cu ', # 0xa4 +'Mai ', # 0xa5 +'Mai ', # 0xa6 +'Ge ', # 0xa7 +'Chao ', # 0xa8 +'Fu ', # 0xa9 +'Mian ', # 0xaa +'Mian ', # 0xab +'Fu ', # 0xac +'Pao ', # 0xad +'Qu ', # 0xae +'Qu ', # 0xaf +'Mou ', # 0xb0 +'Fu ', # 0xb1 +'Xian ', # 0xb2 +'Lai ', # 0xb3 +'Qu ', # 0xb4 +'Mian ', # 0xb5 +'[?] ', # 0xb6 +'Feng ', # 0xb7 +'Fu ', # 0xb8 +'Qu ', # 0xb9 +'Mian ', # 0xba +'Ma ', # 0xbb +'Mo ', # 0xbc +'Mo ', # 0xbd +'Hui ', # 0xbe +'Ma ', # 0xbf +'Zou ', # 0xc0 +'Nen ', # 0xc1 +'Fen ', # 0xc2 +'Huang ', # 0xc3 +'Huang ', # 0xc4 +'Jin ', # 0xc5 +'Guang ', # 0xc6 +'Tian ', # 0xc7 +'Tou ', # 0xc8 +'Heng ', # 0xc9 +'Xi ', # 0xca +'Kuang ', # 0xcb +'Heng ', # 0xcc +'Shu ', # 0xcd +'Li ', # 0xce +'Nian ', # 0xcf +'Chi ', # 0xd0 +'Hei ', # 0xd1 +'Hei ', # 0xd2 +'Yi ', # 0xd3 +'Qian ', # 0xd4 +'Dan ', # 0xd5 +'Xi ', # 0xd6 +'Tuan ', # 0xd7 +'Mo ', # 0xd8 +'Mo ', # 0xd9 +'Qian ', # 0xda +'Dai ', # 0xdb +'Chu ', # 0xdc +'You ', # 0xdd +'Dian ', # 0xde +'Yi ', # 0xdf +'Xia ', # 0xe0 +'Yan ', # 0xe1 +'Qu ', # 0xe2 +'Mei ', # 0xe3 +'Yan ', # 0xe4 +'Jing ', # 0xe5 +'Yu ', # 0xe6 +'Li ', # 0xe7 +'Dang ', # 0xe8 +'Du ', # 0xe9 +'Can ', # 0xea +'Yin ', # 0xeb +'An ', # 0xec +'Yan ', # 0xed +'Tan ', # 0xee +'An ', # 0xef +'Zhen ', # 0xf0 +'Dai ', # 0xf1 +'Can ', # 0xf2 +'Yi ', # 0xf3 +'Mei ', # 0xf4 +'Dan ', # 0xf5 +'Yan ', # 0xf6 +'Du ', # 0xf7 +'Lu ', # 0xf8 +'Zhi ', # 0xf9 +'Fen ', # 0xfa +'Fu ', # 0xfb +'Fu ', # 0xfc +'Min ', # 0xfd +'Min ', # 0xfe +'Yuan ', # 0xff +) diff --git a/nstock/modules/unidecode/x09f.py b/nstock/modules/unidecode/x09f.py new file mode 100644 index 0000000..acd59a6 --- /dev/null +++ b/nstock/modules/unidecode/x09f.py @@ -0,0 +1,257 @@ +data = ( +'Cu ', # 0x00 +'Qu ', # 0x01 +'Chao ', # 0x02 +'Wa ', # 0x03 +'Zhu ', # 0x04 +'Zhi ', # 0x05 +'Mang ', # 0x06 +'Ao ', # 0x07 +'Bie ', # 0x08 +'Tuo ', # 0x09 +'Bi ', # 0x0a +'Yuan ', # 0x0b +'Chao ', # 0x0c +'Tuo ', # 0x0d +'Ding ', # 0x0e +'Mi ', # 0x0f +'Nai ', # 0x10 +'Ding ', # 0x11 +'Zi ', # 0x12 +'Gu ', # 0x13 +'Gu ', # 0x14 +'Dong ', # 0x15 +'Fen ', # 0x16 +'Tao ', # 0x17 +'Yuan ', # 0x18 +'Pi ', # 0x19 +'Chang ', # 0x1a +'Gao ', # 0x1b +'Qi ', # 0x1c +'Yuan ', # 0x1d +'Tang ', # 0x1e +'Teng ', # 0x1f +'Shu ', # 0x20 +'Shu ', # 0x21 +'Fen ', # 0x22 +'Fei ', # 0x23 +'Wen ', # 0x24 +'Ba ', # 0x25 +'Diao ', # 0x26 +'Tuo ', # 0x27 +'Tong ', # 0x28 +'Qu ', # 0x29 +'Sheng ', # 0x2a +'Shi ', # 0x2b +'You ', # 0x2c +'Shi ', # 0x2d +'Ting ', # 0x2e +'Wu ', # 0x2f +'Nian ', # 0x30 +'Jing ', # 0x31 +'Hun ', # 0x32 +'Ju ', # 0x33 +'Yan ', # 0x34 +'Tu ', # 0x35 +'Ti ', # 0x36 +'Xi ', # 0x37 +'Xian ', # 0x38 +'Yan ', # 0x39 +'Lei ', # 0x3a +'Bi ', # 0x3b +'Yao ', # 0x3c +'Qiu ', # 0x3d +'Han ', # 0x3e +'Wu ', # 0x3f +'Wu ', # 0x40 +'Hou ', # 0x41 +'Xi ', # 0x42 +'Ge ', # 0x43 +'Zha ', # 0x44 +'Xiu ', # 0x45 +'Weng ', # 0x46 +'Zha ', # 0x47 +'Nong ', # 0x48 +'Nang ', # 0x49 +'Qi ', # 0x4a +'Zhai ', # 0x4b +'Ji ', # 0x4c +'Zi ', # 0x4d +'Ji ', # 0x4e +'Ji ', # 0x4f +'Qi ', # 0x50 +'Ji ', # 0x51 +'Chi ', # 0x52 +'Chen ', # 0x53 +'Chen ', # 0x54 +'He ', # 0x55 +'Ya ', # 0x56 +'Ken ', # 0x57 +'Xie ', # 0x58 +'Pao ', # 0x59 +'Cuo ', # 0x5a +'Shi ', # 0x5b +'Zi ', # 0x5c +'Chi ', # 0x5d +'Nian ', # 0x5e +'Ju ', # 0x5f +'Tiao ', # 0x60 +'Ling ', # 0x61 +'Ling ', # 0x62 +'Chu ', # 0x63 +'Quan ', # 0x64 +'Xie ', # 0x65 +'Ken ', # 0x66 +'Nie ', # 0x67 +'Jiu ', # 0x68 +'Yao ', # 0x69 +'Chuo ', # 0x6a +'Kun ', # 0x6b +'Yu ', # 0x6c +'Chu ', # 0x6d +'Yi ', # 0x6e +'Ni ', # 0x6f +'Cuo ', # 0x70 +'Zou ', # 0x71 +'Qu ', # 0x72 +'Nen ', # 0x73 +'Xian ', # 0x74 +'Ou ', # 0x75 +'E ', # 0x76 +'Wo ', # 0x77 +'Yi ', # 0x78 +'Chuo ', # 0x79 +'Zou ', # 0x7a +'Dian ', # 0x7b +'Chu ', # 0x7c +'Jin ', # 0x7d +'Ya ', # 0x7e +'Chi ', # 0x7f +'Chen ', # 0x80 +'He ', # 0x81 +'Ken ', # 0x82 +'Ju ', # 0x83 +'Ling ', # 0x84 +'Pao ', # 0x85 +'Tiao ', # 0x86 +'Zi ', # 0x87 +'Ken ', # 0x88 +'Yu ', # 0x89 +'Chuo ', # 0x8a +'Qu ', # 0x8b +'Wo ', # 0x8c +'Long ', # 0x8d +'Pang ', # 0x8e +'Gong ', # 0x8f +'Pang ', # 0x90 +'Yan ', # 0x91 +'Long ', # 0x92 +'Long ', # 0x93 +'Gong ', # 0x94 +'Kan ', # 0x95 +'Ta ', # 0x96 +'Ling ', # 0x97 +'Ta ', # 0x98 +'Long ', # 0x99 +'Gong ', # 0x9a +'Kan ', # 0x9b +'Gui ', # 0x9c +'Qiu ', # 0x9d +'Bie ', # 0x9e +'Gui ', # 0x9f +'Yue ', # 0xa0 +'Chui ', # 0xa1 +'He ', # 0xa2 +'Jue ', # 0xa3 +'Xie ', # 0xa4 +'Yu ', # 0xa5 +'[?]', # 0xa6 +'[?]', # 0xa7 +'[?]', # 0xa8 +'[?]', # 0xa9 +'[?]', # 0xaa +'[?]', # 0xab +'[?]', # 0xac +'[?]', # 0xad +'[?]', # 0xae +'[?]', # 0xaf +'[?]', # 0xb0 +'[?]', # 0xb1 +'[?]', # 0xb2 +'[?]', # 0xb3 +'[?]', # 0xb4 +'[?]', # 0xb5 +'[?]', # 0xb6 +'[?]', # 0xb7 +'[?]', # 0xb8 +'[?]', # 0xb9 +'[?]', # 0xba +'[?]', # 0xbb +'[?]', # 0xbc +'[?]', # 0xbd +'[?]', # 0xbe +'[?]', # 0xbf +'[?]', # 0xc0 +'[?]', # 0xc1 +'[?]', # 0xc2 +'[?]', # 0xc3 +'[?]', # 0xc4 +'[?]', # 0xc5 +'[?]', # 0xc6 +'[?]', # 0xc7 +'[?]', # 0xc8 +'[?]', # 0xc9 +'[?]', # 0xca +'[?]', # 0xcb +'[?]', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'[?]', # 0xd0 +'[?]', # 0xd1 +'[?]', # 0xd2 +'[?]', # 0xd3 +'[?]', # 0xd4 +'[?]', # 0xd5 +'[?]', # 0xd6 +'[?]', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'[?]', # 0xdc +'[?]', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'[?]', # 0xe0 +'[?]', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'[?]', # 0xe6 +'[?]', # 0xe7 +'[?]', # 0xe8 +'[?]', # 0xe9 +'[?]', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x0a0.py b/nstock/modules/unidecode/x0a0.py new file mode 100644 index 0000000..c25f17b --- /dev/null +++ b/nstock/modules/unidecode/x0a0.py @@ -0,0 +1,258 @@ +data = ( +'it', # 0x00 +'ix', # 0x01 +'i', # 0x02 +'ip', # 0x03 +'iet', # 0x04 +'iex', # 0x05 +'ie', # 0x06 +'iep', # 0x07 +'at', # 0x08 +'ax', # 0x09 +'a', # 0x0a +'ap', # 0x0b +'uox', # 0x0c +'uo', # 0x0d +'uop', # 0x0e +'ot', # 0x0f +'ox', # 0x10 +'o', # 0x11 +'op', # 0x12 +'ex', # 0x13 +'e', # 0x14 +'wu', # 0x15 +'bit', # 0x16 +'bix', # 0x17 +'bi', # 0x18 +'bip', # 0x19 +'biet', # 0x1a +'biex', # 0x1b +'bie', # 0x1c +'biep', # 0x1d +'bat', # 0x1e +'bax', # 0x1f +'ba', # 0x20 +'bap', # 0x21 +'buox', # 0x22 +'buo', # 0x23 +'buop', # 0x24 +'bot', # 0x25 +'box', # 0x26 +'bo', # 0x27 +'bop', # 0x28 +'bex', # 0x29 +'be', # 0x2a +'bep', # 0x2b +'but', # 0x2c +'bux', # 0x2d +'bu', # 0x2e +'bup', # 0x2f +'burx', # 0x30 +'bur', # 0x31 +'byt', # 0x32 +'byx', # 0x33 +'by', # 0x34 +'byp', # 0x35 +'byrx', # 0x36 +'byr', # 0x37 +'pit', # 0x38 +'pix', # 0x39 +'pi', # 0x3a +'pip', # 0x3b +'piex', # 0x3c +'pie', # 0x3d +'piep', # 0x3e +'pat', # 0x3f +'pax', # 0x40 +'pa', # 0x41 +'pap', # 0x42 +'puox', # 0x43 +'puo', # 0x44 +'puop', # 0x45 +'pot', # 0x46 +'pox', # 0x47 +'po', # 0x48 +'pop', # 0x49 +'put', # 0x4a +'pux', # 0x4b +'pu', # 0x4c +'pup', # 0x4d +'purx', # 0x4e +'pur', # 0x4f +'pyt', # 0x50 +'pyx', # 0x51 +'py', # 0x52 +'pyp', # 0x53 +'pyrx', # 0x54 +'pyr', # 0x55 +'bbit', # 0x56 +'bbix', # 0x57 +'bbi', # 0x58 +'bbip', # 0x59 +'bbiet', # 0x5a +'bbiex', # 0x5b +'bbie', # 0x5c +'bbiep', # 0x5d +'bbat', # 0x5e +'bbax', # 0x5f +'bba', # 0x60 +'bbap', # 0x61 +'bbuox', # 0x62 +'bbuo', # 0x63 +'bbuop', # 0x64 +'bbot', # 0x65 +'bbox', # 0x66 +'bbo', # 0x67 +'bbop', # 0x68 +'bbex', # 0x69 +'bbe', # 0x6a +'bbep', # 0x6b +'bbut', # 0x6c +'bbux', # 0x6d +'bbu', # 0x6e +'bbup', # 0x6f +'bburx', # 0x70 +'bbur', # 0x71 +'bbyt', # 0x72 +'bbyx', # 0x73 +'bby', # 0x74 +'bbyp', # 0x75 +'nbit', # 0x76 +'nbix', # 0x77 +'nbi', # 0x78 +'nbip', # 0x79 +'nbiex', # 0x7a +'nbie', # 0x7b +'nbiep', # 0x7c +'nbat', # 0x7d +'nbax', # 0x7e +'nba', # 0x7f +'nbap', # 0x80 +'nbot', # 0x81 +'nbox', # 0x82 +'nbo', # 0x83 +'nbop', # 0x84 +'nbut', # 0x85 +'nbux', # 0x86 +'nbu', # 0x87 +'nbup', # 0x88 +'nburx', # 0x89 +'nbur', # 0x8a +'nbyt', # 0x8b +'nbyx', # 0x8c +'nby', # 0x8d +'nbyp', # 0x8e +'nbyrx', # 0x8f +'nbyr', # 0x90 +'hmit', # 0x91 +'hmix', # 0x92 +'hmi', # 0x93 +'hmip', # 0x94 +'hmiex', # 0x95 +'hmie', # 0x96 +'hmiep', # 0x97 +'hmat', # 0x98 +'hmax', # 0x99 +'hma', # 0x9a +'hmap', # 0x9b +'hmuox', # 0x9c +'hmuo', # 0x9d +'hmuop', # 0x9e +'hmot', # 0x9f +'hmox', # 0xa0 +'hmo', # 0xa1 +'hmop', # 0xa2 +'hmut', # 0xa3 +'hmux', # 0xa4 +'hmu', # 0xa5 +'hmup', # 0xa6 +'hmurx', # 0xa7 +'hmur', # 0xa8 +'hmyx', # 0xa9 +'hmy', # 0xaa +'hmyp', # 0xab +'hmyrx', # 0xac +'hmyr', # 0xad +'mit', # 0xae +'mix', # 0xaf +'mi', # 0xb0 +'mip', # 0xb1 +'miex', # 0xb2 +'mie', # 0xb3 +'miep', # 0xb4 +'mat', # 0xb5 +'max', # 0xb6 +'ma', # 0xb7 +'map', # 0xb8 +'muot', # 0xb9 +'muox', # 0xba +'muo', # 0xbb +'muop', # 0xbc +'mot', # 0xbd +'mox', # 0xbe +'mo', # 0xbf +'mop', # 0xc0 +'mex', # 0xc1 +'me', # 0xc2 +'mut', # 0xc3 +'mux', # 0xc4 +'mu', # 0xc5 +'mup', # 0xc6 +'murx', # 0xc7 +'mur', # 0xc8 +'myt', # 0xc9 +'myx', # 0xca +'my', # 0xcb +'myp', # 0xcc +'fit', # 0xcd +'fix', # 0xce +'fi', # 0xcf +'fip', # 0xd0 +'fat', # 0xd1 +'fax', # 0xd2 +'fa', # 0xd3 +'fap', # 0xd4 +'fox', # 0xd5 +'fo', # 0xd6 +'fop', # 0xd7 +'fut', # 0xd8 +'fux', # 0xd9 +'fu', # 0xda +'fup', # 0xdb +'furx', # 0xdc +'fur', # 0xdd +'fyt', # 0xde +'fyx', # 0xdf +'fy', # 0xe0 +'fyp', # 0xe1 +'vit', # 0xe2 +'vix', # 0xe3 +'vi', # 0xe4 +'vip', # 0xe5 +'viet', # 0xe6 +'viex', # 0xe7 +'vie', # 0xe8 +'viep', # 0xe9 +'vat', # 0xea +'vax', # 0xeb +'va', # 0xec +'vap', # 0xed +'vot', # 0xee +'vox', # 0xef +'vo', # 0xf0 +'vop', # 0xf1 +'vex', # 0xf2 +'vep', # 0xf3 +'vut', # 0xf4 +'vux', # 0xf5 +'vu', # 0xf6 +'vup', # 0xf7 +'vurx', # 0xf8 +'vur', # 0xf9 +'vyt', # 0xfa +'vyx', # 0xfb +'vy', # 0xfc +'vyp', # 0xfd +'vyrx', # 0xfe +'vyr', # 0xff +) diff --git a/nstock/modules/unidecode/x0a1.py b/nstock/modules/unidecode/x0a1.py new file mode 100644 index 0000000..185dc8b --- /dev/null +++ b/nstock/modules/unidecode/x0a1.py @@ -0,0 +1,258 @@ +data = ( +'dit', # 0x00 +'dix', # 0x01 +'di', # 0x02 +'dip', # 0x03 +'diex', # 0x04 +'die', # 0x05 +'diep', # 0x06 +'dat', # 0x07 +'dax', # 0x08 +'da', # 0x09 +'dap', # 0x0a +'duox', # 0x0b +'duo', # 0x0c +'dot', # 0x0d +'dox', # 0x0e +'do', # 0x0f +'dop', # 0x10 +'dex', # 0x11 +'de', # 0x12 +'dep', # 0x13 +'dut', # 0x14 +'dux', # 0x15 +'du', # 0x16 +'dup', # 0x17 +'durx', # 0x18 +'dur', # 0x19 +'tit', # 0x1a +'tix', # 0x1b +'ti', # 0x1c +'tip', # 0x1d +'tiex', # 0x1e +'tie', # 0x1f +'tiep', # 0x20 +'tat', # 0x21 +'tax', # 0x22 +'ta', # 0x23 +'tap', # 0x24 +'tuot', # 0x25 +'tuox', # 0x26 +'tuo', # 0x27 +'tuop', # 0x28 +'tot', # 0x29 +'tox', # 0x2a +'to', # 0x2b +'top', # 0x2c +'tex', # 0x2d +'te', # 0x2e +'tep', # 0x2f +'tut', # 0x30 +'tux', # 0x31 +'tu', # 0x32 +'tup', # 0x33 +'turx', # 0x34 +'tur', # 0x35 +'ddit', # 0x36 +'ddix', # 0x37 +'ddi', # 0x38 +'ddip', # 0x39 +'ddiex', # 0x3a +'ddie', # 0x3b +'ddiep', # 0x3c +'ddat', # 0x3d +'ddax', # 0x3e +'dda', # 0x3f +'ddap', # 0x40 +'dduox', # 0x41 +'dduo', # 0x42 +'dduop', # 0x43 +'ddot', # 0x44 +'ddox', # 0x45 +'ddo', # 0x46 +'ddop', # 0x47 +'ddex', # 0x48 +'dde', # 0x49 +'ddep', # 0x4a +'ddut', # 0x4b +'ddux', # 0x4c +'ddu', # 0x4d +'ddup', # 0x4e +'ddurx', # 0x4f +'ddur', # 0x50 +'ndit', # 0x51 +'ndix', # 0x52 +'ndi', # 0x53 +'ndip', # 0x54 +'ndiex', # 0x55 +'ndie', # 0x56 +'ndat', # 0x57 +'ndax', # 0x58 +'nda', # 0x59 +'ndap', # 0x5a +'ndot', # 0x5b +'ndox', # 0x5c +'ndo', # 0x5d +'ndop', # 0x5e +'ndex', # 0x5f +'nde', # 0x60 +'ndep', # 0x61 +'ndut', # 0x62 +'ndux', # 0x63 +'ndu', # 0x64 +'ndup', # 0x65 +'ndurx', # 0x66 +'ndur', # 0x67 +'hnit', # 0x68 +'hnix', # 0x69 +'hni', # 0x6a +'hnip', # 0x6b +'hniet', # 0x6c +'hniex', # 0x6d +'hnie', # 0x6e +'hniep', # 0x6f +'hnat', # 0x70 +'hnax', # 0x71 +'hna', # 0x72 +'hnap', # 0x73 +'hnuox', # 0x74 +'hnuo', # 0x75 +'hnot', # 0x76 +'hnox', # 0x77 +'hnop', # 0x78 +'hnex', # 0x79 +'hne', # 0x7a +'hnep', # 0x7b +'hnut', # 0x7c +'nit', # 0x7d +'nix', # 0x7e +'ni', # 0x7f +'nip', # 0x80 +'niex', # 0x81 +'nie', # 0x82 +'niep', # 0x83 +'nax', # 0x84 +'na', # 0x85 +'nap', # 0x86 +'nuox', # 0x87 +'nuo', # 0x88 +'nuop', # 0x89 +'not', # 0x8a +'nox', # 0x8b +'no', # 0x8c +'nop', # 0x8d +'nex', # 0x8e +'ne', # 0x8f +'nep', # 0x90 +'nut', # 0x91 +'nux', # 0x92 +'nu', # 0x93 +'nup', # 0x94 +'nurx', # 0x95 +'nur', # 0x96 +'hlit', # 0x97 +'hlix', # 0x98 +'hli', # 0x99 +'hlip', # 0x9a +'hliex', # 0x9b +'hlie', # 0x9c +'hliep', # 0x9d +'hlat', # 0x9e +'hlax', # 0x9f +'hla', # 0xa0 +'hlap', # 0xa1 +'hluox', # 0xa2 +'hluo', # 0xa3 +'hluop', # 0xa4 +'hlox', # 0xa5 +'hlo', # 0xa6 +'hlop', # 0xa7 +'hlex', # 0xa8 +'hle', # 0xa9 +'hlep', # 0xaa +'hlut', # 0xab +'hlux', # 0xac +'hlu', # 0xad +'hlup', # 0xae +'hlurx', # 0xaf +'hlur', # 0xb0 +'hlyt', # 0xb1 +'hlyx', # 0xb2 +'hly', # 0xb3 +'hlyp', # 0xb4 +'hlyrx', # 0xb5 +'hlyr', # 0xb6 +'lit', # 0xb7 +'lix', # 0xb8 +'li', # 0xb9 +'lip', # 0xba +'liet', # 0xbb +'liex', # 0xbc +'lie', # 0xbd +'liep', # 0xbe +'lat', # 0xbf +'lax', # 0xc0 +'la', # 0xc1 +'lap', # 0xc2 +'luot', # 0xc3 +'luox', # 0xc4 +'luo', # 0xc5 +'luop', # 0xc6 +'lot', # 0xc7 +'lox', # 0xc8 +'lo', # 0xc9 +'lop', # 0xca +'lex', # 0xcb +'le', # 0xcc +'lep', # 0xcd +'lut', # 0xce +'lux', # 0xcf +'lu', # 0xd0 +'lup', # 0xd1 +'lurx', # 0xd2 +'lur', # 0xd3 +'lyt', # 0xd4 +'lyx', # 0xd5 +'ly', # 0xd6 +'lyp', # 0xd7 +'lyrx', # 0xd8 +'lyr', # 0xd9 +'git', # 0xda +'gix', # 0xdb +'gi', # 0xdc +'gip', # 0xdd +'giet', # 0xde +'giex', # 0xdf +'gie', # 0xe0 +'giep', # 0xe1 +'gat', # 0xe2 +'gax', # 0xe3 +'ga', # 0xe4 +'gap', # 0xe5 +'guot', # 0xe6 +'guox', # 0xe7 +'guo', # 0xe8 +'guop', # 0xe9 +'got', # 0xea +'gox', # 0xeb +'go', # 0xec +'gop', # 0xed +'get', # 0xee +'gex', # 0xef +'ge', # 0xf0 +'gep', # 0xf1 +'gut', # 0xf2 +'gux', # 0xf3 +'gu', # 0xf4 +'gup', # 0xf5 +'gurx', # 0xf6 +'gur', # 0xf7 +'kit', # 0xf8 +'kix', # 0xf9 +'ki', # 0xfa +'kip', # 0xfb +'kiex', # 0xfc +'kie', # 0xfd +'kiep', # 0xfe +'kat', # 0xff +) diff --git a/nstock/modules/unidecode/x0a2.py b/nstock/modules/unidecode/x0a2.py new file mode 100644 index 0000000..8ea8991 --- /dev/null +++ b/nstock/modules/unidecode/x0a2.py @@ -0,0 +1,258 @@ +data = ( +'kax', # 0x00 +'ka', # 0x01 +'kap', # 0x02 +'kuox', # 0x03 +'kuo', # 0x04 +'kuop', # 0x05 +'kot', # 0x06 +'kox', # 0x07 +'ko', # 0x08 +'kop', # 0x09 +'ket', # 0x0a +'kex', # 0x0b +'ke', # 0x0c +'kep', # 0x0d +'kut', # 0x0e +'kux', # 0x0f +'ku', # 0x10 +'kup', # 0x11 +'kurx', # 0x12 +'kur', # 0x13 +'ggit', # 0x14 +'ggix', # 0x15 +'ggi', # 0x16 +'ggiex', # 0x17 +'ggie', # 0x18 +'ggiep', # 0x19 +'ggat', # 0x1a +'ggax', # 0x1b +'gga', # 0x1c +'ggap', # 0x1d +'gguot', # 0x1e +'gguox', # 0x1f +'gguo', # 0x20 +'gguop', # 0x21 +'ggot', # 0x22 +'ggox', # 0x23 +'ggo', # 0x24 +'ggop', # 0x25 +'gget', # 0x26 +'ggex', # 0x27 +'gge', # 0x28 +'ggep', # 0x29 +'ggut', # 0x2a +'ggux', # 0x2b +'ggu', # 0x2c +'ggup', # 0x2d +'ggurx', # 0x2e +'ggur', # 0x2f +'mgiex', # 0x30 +'mgie', # 0x31 +'mgat', # 0x32 +'mgax', # 0x33 +'mga', # 0x34 +'mgap', # 0x35 +'mguox', # 0x36 +'mguo', # 0x37 +'mguop', # 0x38 +'mgot', # 0x39 +'mgox', # 0x3a +'mgo', # 0x3b +'mgop', # 0x3c +'mgex', # 0x3d +'mge', # 0x3e +'mgep', # 0x3f +'mgut', # 0x40 +'mgux', # 0x41 +'mgu', # 0x42 +'mgup', # 0x43 +'mgurx', # 0x44 +'mgur', # 0x45 +'hxit', # 0x46 +'hxix', # 0x47 +'hxi', # 0x48 +'hxip', # 0x49 +'hxiet', # 0x4a +'hxiex', # 0x4b +'hxie', # 0x4c +'hxiep', # 0x4d +'hxat', # 0x4e +'hxax', # 0x4f +'hxa', # 0x50 +'hxap', # 0x51 +'hxuot', # 0x52 +'hxuox', # 0x53 +'hxuo', # 0x54 +'hxuop', # 0x55 +'hxot', # 0x56 +'hxox', # 0x57 +'hxo', # 0x58 +'hxop', # 0x59 +'hxex', # 0x5a +'hxe', # 0x5b +'hxep', # 0x5c +'ngiex', # 0x5d +'ngie', # 0x5e +'ngiep', # 0x5f +'ngat', # 0x60 +'ngax', # 0x61 +'nga', # 0x62 +'ngap', # 0x63 +'nguot', # 0x64 +'nguox', # 0x65 +'nguo', # 0x66 +'ngot', # 0x67 +'ngox', # 0x68 +'ngo', # 0x69 +'ngop', # 0x6a +'ngex', # 0x6b +'nge', # 0x6c +'ngep', # 0x6d +'hit', # 0x6e +'hiex', # 0x6f +'hie', # 0x70 +'hat', # 0x71 +'hax', # 0x72 +'ha', # 0x73 +'hap', # 0x74 +'huot', # 0x75 +'huox', # 0x76 +'huo', # 0x77 +'huop', # 0x78 +'hot', # 0x79 +'hox', # 0x7a +'ho', # 0x7b +'hop', # 0x7c +'hex', # 0x7d +'he', # 0x7e +'hep', # 0x7f +'wat', # 0x80 +'wax', # 0x81 +'wa', # 0x82 +'wap', # 0x83 +'wuox', # 0x84 +'wuo', # 0x85 +'wuop', # 0x86 +'wox', # 0x87 +'wo', # 0x88 +'wop', # 0x89 +'wex', # 0x8a +'we', # 0x8b +'wep', # 0x8c +'zit', # 0x8d +'zix', # 0x8e +'zi', # 0x8f +'zip', # 0x90 +'ziex', # 0x91 +'zie', # 0x92 +'ziep', # 0x93 +'zat', # 0x94 +'zax', # 0x95 +'za', # 0x96 +'zap', # 0x97 +'zuox', # 0x98 +'zuo', # 0x99 +'zuop', # 0x9a +'zot', # 0x9b +'zox', # 0x9c +'zo', # 0x9d +'zop', # 0x9e +'zex', # 0x9f +'ze', # 0xa0 +'zep', # 0xa1 +'zut', # 0xa2 +'zux', # 0xa3 +'zu', # 0xa4 +'zup', # 0xa5 +'zurx', # 0xa6 +'zur', # 0xa7 +'zyt', # 0xa8 +'zyx', # 0xa9 +'zy', # 0xaa +'zyp', # 0xab +'zyrx', # 0xac +'zyr', # 0xad +'cit', # 0xae +'cix', # 0xaf +'ci', # 0xb0 +'cip', # 0xb1 +'ciet', # 0xb2 +'ciex', # 0xb3 +'cie', # 0xb4 +'ciep', # 0xb5 +'cat', # 0xb6 +'cax', # 0xb7 +'ca', # 0xb8 +'cap', # 0xb9 +'cuox', # 0xba +'cuo', # 0xbb +'cuop', # 0xbc +'cot', # 0xbd +'cox', # 0xbe +'co', # 0xbf +'cop', # 0xc0 +'cex', # 0xc1 +'ce', # 0xc2 +'cep', # 0xc3 +'cut', # 0xc4 +'cux', # 0xc5 +'cu', # 0xc6 +'cup', # 0xc7 +'curx', # 0xc8 +'cur', # 0xc9 +'cyt', # 0xca +'cyx', # 0xcb +'cy', # 0xcc +'cyp', # 0xcd +'cyrx', # 0xce +'cyr', # 0xcf +'zzit', # 0xd0 +'zzix', # 0xd1 +'zzi', # 0xd2 +'zzip', # 0xd3 +'zziet', # 0xd4 +'zziex', # 0xd5 +'zzie', # 0xd6 +'zziep', # 0xd7 +'zzat', # 0xd8 +'zzax', # 0xd9 +'zza', # 0xda +'zzap', # 0xdb +'zzox', # 0xdc +'zzo', # 0xdd +'zzop', # 0xde +'zzex', # 0xdf +'zze', # 0xe0 +'zzep', # 0xe1 +'zzux', # 0xe2 +'zzu', # 0xe3 +'zzup', # 0xe4 +'zzurx', # 0xe5 +'zzur', # 0xe6 +'zzyt', # 0xe7 +'zzyx', # 0xe8 +'zzy', # 0xe9 +'zzyp', # 0xea +'zzyrx', # 0xeb +'zzyr', # 0xec +'nzit', # 0xed +'nzix', # 0xee +'nzi', # 0xef +'nzip', # 0xf0 +'nziex', # 0xf1 +'nzie', # 0xf2 +'nziep', # 0xf3 +'nzat', # 0xf4 +'nzax', # 0xf5 +'nza', # 0xf6 +'nzap', # 0xf7 +'nzuox', # 0xf8 +'nzuo', # 0xf9 +'nzox', # 0xfa +'nzop', # 0xfb +'nzex', # 0xfc +'nze', # 0xfd +'nzux', # 0xfe +'nzu', # 0xff +) diff --git a/nstock/modules/unidecode/x0a3.py b/nstock/modules/unidecode/x0a3.py new file mode 100644 index 0000000..5e77aec --- /dev/null +++ b/nstock/modules/unidecode/x0a3.py @@ -0,0 +1,258 @@ +data = ( +'nzup', # 0x00 +'nzurx', # 0x01 +'nzur', # 0x02 +'nzyt', # 0x03 +'nzyx', # 0x04 +'nzy', # 0x05 +'nzyp', # 0x06 +'nzyrx', # 0x07 +'nzyr', # 0x08 +'sit', # 0x09 +'six', # 0x0a +'si', # 0x0b +'sip', # 0x0c +'siex', # 0x0d +'sie', # 0x0e +'siep', # 0x0f +'sat', # 0x10 +'sax', # 0x11 +'sa', # 0x12 +'sap', # 0x13 +'suox', # 0x14 +'suo', # 0x15 +'suop', # 0x16 +'sot', # 0x17 +'sox', # 0x18 +'so', # 0x19 +'sop', # 0x1a +'sex', # 0x1b +'se', # 0x1c +'sep', # 0x1d +'sut', # 0x1e +'sux', # 0x1f +'su', # 0x20 +'sup', # 0x21 +'surx', # 0x22 +'sur', # 0x23 +'syt', # 0x24 +'syx', # 0x25 +'sy', # 0x26 +'syp', # 0x27 +'syrx', # 0x28 +'syr', # 0x29 +'ssit', # 0x2a +'ssix', # 0x2b +'ssi', # 0x2c +'ssip', # 0x2d +'ssiex', # 0x2e +'ssie', # 0x2f +'ssiep', # 0x30 +'ssat', # 0x31 +'ssax', # 0x32 +'ssa', # 0x33 +'ssap', # 0x34 +'ssot', # 0x35 +'ssox', # 0x36 +'sso', # 0x37 +'ssop', # 0x38 +'ssex', # 0x39 +'sse', # 0x3a +'ssep', # 0x3b +'ssut', # 0x3c +'ssux', # 0x3d +'ssu', # 0x3e +'ssup', # 0x3f +'ssyt', # 0x40 +'ssyx', # 0x41 +'ssy', # 0x42 +'ssyp', # 0x43 +'ssyrx', # 0x44 +'ssyr', # 0x45 +'zhat', # 0x46 +'zhax', # 0x47 +'zha', # 0x48 +'zhap', # 0x49 +'zhuox', # 0x4a +'zhuo', # 0x4b +'zhuop', # 0x4c +'zhot', # 0x4d +'zhox', # 0x4e +'zho', # 0x4f +'zhop', # 0x50 +'zhet', # 0x51 +'zhex', # 0x52 +'zhe', # 0x53 +'zhep', # 0x54 +'zhut', # 0x55 +'zhux', # 0x56 +'zhu', # 0x57 +'zhup', # 0x58 +'zhurx', # 0x59 +'zhur', # 0x5a +'zhyt', # 0x5b +'zhyx', # 0x5c +'zhy', # 0x5d +'zhyp', # 0x5e +'zhyrx', # 0x5f +'zhyr', # 0x60 +'chat', # 0x61 +'chax', # 0x62 +'cha', # 0x63 +'chap', # 0x64 +'chuot', # 0x65 +'chuox', # 0x66 +'chuo', # 0x67 +'chuop', # 0x68 +'chot', # 0x69 +'chox', # 0x6a +'cho', # 0x6b +'chop', # 0x6c +'chet', # 0x6d +'chex', # 0x6e +'che', # 0x6f +'chep', # 0x70 +'chux', # 0x71 +'chu', # 0x72 +'chup', # 0x73 +'churx', # 0x74 +'chur', # 0x75 +'chyt', # 0x76 +'chyx', # 0x77 +'chy', # 0x78 +'chyp', # 0x79 +'chyrx', # 0x7a +'chyr', # 0x7b +'rrax', # 0x7c +'rra', # 0x7d +'rruox', # 0x7e +'rruo', # 0x7f +'rrot', # 0x80 +'rrox', # 0x81 +'rro', # 0x82 +'rrop', # 0x83 +'rret', # 0x84 +'rrex', # 0x85 +'rre', # 0x86 +'rrep', # 0x87 +'rrut', # 0x88 +'rrux', # 0x89 +'rru', # 0x8a +'rrup', # 0x8b +'rrurx', # 0x8c +'rrur', # 0x8d +'rryt', # 0x8e +'rryx', # 0x8f +'rry', # 0x90 +'rryp', # 0x91 +'rryrx', # 0x92 +'rryr', # 0x93 +'nrat', # 0x94 +'nrax', # 0x95 +'nra', # 0x96 +'nrap', # 0x97 +'nrox', # 0x98 +'nro', # 0x99 +'nrop', # 0x9a +'nret', # 0x9b +'nrex', # 0x9c +'nre', # 0x9d +'nrep', # 0x9e +'nrut', # 0x9f +'nrux', # 0xa0 +'nru', # 0xa1 +'nrup', # 0xa2 +'nrurx', # 0xa3 +'nrur', # 0xa4 +'nryt', # 0xa5 +'nryx', # 0xa6 +'nry', # 0xa7 +'nryp', # 0xa8 +'nryrx', # 0xa9 +'nryr', # 0xaa +'shat', # 0xab +'shax', # 0xac +'sha', # 0xad +'shap', # 0xae +'shuox', # 0xaf +'shuo', # 0xb0 +'shuop', # 0xb1 +'shot', # 0xb2 +'shox', # 0xb3 +'sho', # 0xb4 +'shop', # 0xb5 +'shet', # 0xb6 +'shex', # 0xb7 +'she', # 0xb8 +'shep', # 0xb9 +'shut', # 0xba +'shux', # 0xbb +'shu', # 0xbc +'shup', # 0xbd +'shurx', # 0xbe +'shur', # 0xbf +'shyt', # 0xc0 +'shyx', # 0xc1 +'shy', # 0xc2 +'shyp', # 0xc3 +'shyrx', # 0xc4 +'shyr', # 0xc5 +'rat', # 0xc6 +'rax', # 0xc7 +'ra', # 0xc8 +'rap', # 0xc9 +'ruox', # 0xca +'ruo', # 0xcb +'ruop', # 0xcc +'rot', # 0xcd +'rox', # 0xce +'ro', # 0xcf +'rop', # 0xd0 +'rex', # 0xd1 +'re', # 0xd2 +'rep', # 0xd3 +'rut', # 0xd4 +'rux', # 0xd5 +'ru', # 0xd6 +'rup', # 0xd7 +'rurx', # 0xd8 +'rur', # 0xd9 +'ryt', # 0xda +'ryx', # 0xdb +'ry', # 0xdc +'ryp', # 0xdd +'ryrx', # 0xde +'ryr', # 0xdf +'jit', # 0xe0 +'jix', # 0xe1 +'ji', # 0xe2 +'jip', # 0xe3 +'jiet', # 0xe4 +'jiex', # 0xe5 +'jie', # 0xe6 +'jiep', # 0xe7 +'juot', # 0xe8 +'juox', # 0xe9 +'juo', # 0xea +'juop', # 0xeb +'jot', # 0xec +'jox', # 0xed +'jo', # 0xee +'jop', # 0xef +'jut', # 0xf0 +'jux', # 0xf1 +'ju', # 0xf2 +'jup', # 0xf3 +'jurx', # 0xf4 +'jur', # 0xf5 +'jyt', # 0xf6 +'jyx', # 0xf7 +'jy', # 0xf8 +'jyp', # 0xf9 +'jyrx', # 0xfa +'jyr', # 0xfb +'qit', # 0xfc +'qix', # 0xfd +'qi', # 0xfe +'qip', # 0xff +) diff --git a/nstock/modules/unidecode/x0a4.py b/nstock/modules/unidecode/x0a4.py new file mode 100644 index 0000000..4fb6b26 --- /dev/null +++ b/nstock/modules/unidecode/x0a4.py @@ -0,0 +1,257 @@ +data = ( +'qiet', # 0x00 +'qiex', # 0x01 +'qie', # 0x02 +'qiep', # 0x03 +'quot', # 0x04 +'quox', # 0x05 +'quo', # 0x06 +'quop', # 0x07 +'qot', # 0x08 +'qox', # 0x09 +'qo', # 0x0a +'qop', # 0x0b +'qut', # 0x0c +'qux', # 0x0d +'qu', # 0x0e +'qup', # 0x0f +'qurx', # 0x10 +'qur', # 0x11 +'qyt', # 0x12 +'qyx', # 0x13 +'qy', # 0x14 +'qyp', # 0x15 +'qyrx', # 0x16 +'qyr', # 0x17 +'jjit', # 0x18 +'jjix', # 0x19 +'jji', # 0x1a +'jjip', # 0x1b +'jjiet', # 0x1c +'jjiex', # 0x1d +'jjie', # 0x1e +'jjiep', # 0x1f +'jjuox', # 0x20 +'jjuo', # 0x21 +'jjuop', # 0x22 +'jjot', # 0x23 +'jjox', # 0x24 +'jjo', # 0x25 +'jjop', # 0x26 +'jjut', # 0x27 +'jjux', # 0x28 +'jju', # 0x29 +'jjup', # 0x2a +'jjurx', # 0x2b +'jjur', # 0x2c +'jjyt', # 0x2d +'jjyx', # 0x2e +'jjy', # 0x2f +'jjyp', # 0x30 +'njit', # 0x31 +'njix', # 0x32 +'nji', # 0x33 +'njip', # 0x34 +'njiet', # 0x35 +'njiex', # 0x36 +'njie', # 0x37 +'njiep', # 0x38 +'njuox', # 0x39 +'njuo', # 0x3a +'njot', # 0x3b +'njox', # 0x3c +'njo', # 0x3d +'njop', # 0x3e +'njux', # 0x3f +'nju', # 0x40 +'njup', # 0x41 +'njurx', # 0x42 +'njur', # 0x43 +'njyt', # 0x44 +'njyx', # 0x45 +'njy', # 0x46 +'njyp', # 0x47 +'njyrx', # 0x48 +'njyr', # 0x49 +'nyit', # 0x4a +'nyix', # 0x4b +'nyi', # 0x4c +'nyip', # 0x4d +'nyiet', # 0x4e +'nyiex', # 0x4f +'nyie', # 0x50 +'nyiep', # 0x51 +'nyuox', # 0x52 +'nyuo', # 0x53 +'nyuop', # 0x54 +'nyot', # 0x55 +'nyox', # 0x56 +'nyo', # 0x57 +'nyop', # 0x58 +'nyut', # 0x59 +'nyux', # 0x5a +'nyu', # 0x5b +'nyup', # 0x5c +'xit', # 0x5d +'xix', # 0x5e +'xi', # 0x5f +'xip', # 0x60 +'xiet', # 0x61 +'xiex', # 0x62 +'xie', # 0x63 +'xiep', # 0x64 +'xuox', # 0x65 +'xuo', # 0x66 +'xot', # 0x67 +'xox', # 0x68 +'xo', # 0x69 +'xop', # 0x6a +'xyt', # 0x6b +'xyx', # 0x6c +'xy', # 0x6d +'xyp', # 0x6e +'xyrx', # 0x6f +'xyr', # 0x70 +'yit', # 0x71 +'yix', # 0x72 +'yi', # 0x73 +'yip', # 0x74 +'yiet', # 0x75 +'yiex', # 0x76 +'yie', # 0x77 +'yiep', # 0x78 +'yuot', # 0x79 +'yuox', # 0x7a +'yuo', # 0x7b +'yuop', # 0x7c +'yot', # 0x7d +'yox', # 0x7e +'yo', # 0x7f +'yop', # 0x80 +'yut', # 0x81 +'yux', # 0x82 +'yu', # 0x83 +'yup', # 0x84 +'yurx', # 0x85 +'yur', # 0x86 +'yyt', # 0x87 +'yyx', # 0x88 +'yy', # 0x89 +'yyp', # 0x8a +'yyrx', # 0x8b +'yyr', # 0x8c +'[?]', # 0x8d +'[?]', # 0x8e +'[?]', # 0x8f +'Qot', # 0x90 +'Li', # 0x91 +'Kit', # 0x92 +'Nyip', # 0x93 +'Cyp', # 0x94 +'Ssi', # 0x95 +'Ggop', # 0x96 +'Gep', # 0x97 +'Mi', # 0x98 +'Hxit', # 0x99 +'Lyr', # 0x9a +'Bbut', # 0x9b +'Mop', # 0x9c +'Yo', # 0x9d +'Put', # 0x9e +'Hxuo', # 0x9f +'Tat', # 0xa0 +'Ga', # 0xa1 +'[?]', # 0xa2 +'[?]', # 0xa3 +'Ddur', # 0xa4 +'Bur', # 0xa5 +'Gguo', # 0xa6 +'Nyop', # 0xa7 +'Tu', # 0xa8 +'Op', # 0xa9 +'Jjut', # 0xaa +'Zot', # 0xab +'Pyt', # 0xac +'Hmo', # 0xad +'Yit', # 0xae +'Vur', # 0xaf +'Shy', # 0xb0 +'Vep', # 0xb1 +'Za', # 0xb2 +'Jo', # 0xb3 +'[?]', # 0xb4 +'Jjy', # 0xb5 +'Got', # 0xb6 +'Jjie', # 0xb7 +'Wo', # 0xb8 +'Du', # 0xb9 +'Shur', # 0xba +'Lie', # 0xbb +'Cy', # 0xbc +'Cuop', # 0xbd +'Cip', # 0xbe +'Hxop', # 0xbf +'Shat', # 0xc0 +'[?]', # 0xc1 +'Shop', # 0xc2 +'Che', # 0xc3 +'Zziet', # 0xc4 +'[?]', # 0xc5 +'Ke', # 0xc6 +'[?]', # 0xc7 +'[?]', # 0xc8 +'[?]', # 0xc9 +'[?]', # 0xca +'[?]', # 0xcb +'[?]', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'[?]', # 0xd0 +'[?]', # 0xd1 +'[?]', # 0xd2 +'[?]', # 0xd3 +'[?]', # 0xd4 +'[?]', # 0xd5 +'[?]', # 0xd6 +'[?]', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'[?]', # 0xdc +'[?]', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'[?]', # 0xe0 +'[?]', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'[?]', # 0xe6 +'[?]', # 0xe7 +'[?]', # 0xe8 +'[?]', # 0xe9 +'[?]', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x0ac.py b/nstock/modules/unidecode/x0ac.py new file mode 100644 index 0000000..e627fab --- /dev/null +++ b/nstock/modules/unidecode/x0ac.py @@ -0,0 +1,258 @@ +data = ( +'ga', # 0x00 +'gag', # 0x01 +'gagg', # 0x02 +'gags', # 0x03 +'gan', # 0x04 +'ganj', # 0x05 +'ganh', # 0x06 +'gad', # 0x07 +'gal', # 0x08 +'galg', # 0x09 +'galm', # 0x0a +'galb', # 0x0b +'gals', # 0x0c +'galt', # 0x0d +'galp', # 0x0e +'galh', # 0x0f +'gam', # 0x10 +'gab', # 0x11 +'gabs', # 0x12 +'gas', # 0x13 +'gass', # 0x14 +'gang', # 0x15 +'gaj', # 0x16 +'gac', # 0x17 +'gak', # 0x18 +'gat', # 0x19 +'gap', # 0x1a +'gah', # 0x1b +'gae', # 0x1c +'gaeg', # 0x1d +'gaegg', # 0x1e +'gaegs', # 0x1f +'gaen', # 0x20 +'gaenj', # 0x21 +'gaenh', # 0x22 +'gaed', # 0x23 +'gael', # 0x24 +'gaelg', # 0x25 +'gaelm', # 0x26 +'gaelb', # 0x27 +'gaels', # 0x28 +'gaelt', # 0x29 +'gaelp', # 0x2a +'gaelh', # 0x2b +'gaem', # 0x2c +'gaeb', # 0x2d +'gaebs', # 0x2e +'gaes', # 0x2f +'gaess', # 0x30 +'gaeng', # 0x31 +'gaej', # 0x32 +'gaec', # 0x33 +'gaek', # 0x34 +'gaet', # 0x35 +'gaep', # 0x36 +'gaeh', # 0x37 +'gya', # 0x38 +'gyag', # 0x39 +'gyagg', # 0x3a +'gyags', # 0x3b +'gyan', # 0x3c +'gyanj', # 0x3d +'gyanh', # 0x3e +'gyad', # 0x3f +'gyal', # 0x40 +'gyalg', # 0x41 +'gyalm', # 0x42 +'gyalb', # 0x43 +'gyals', # 0x44 +'gyalt', # 0x45 +'gyalp', # 0x46 +'gyalh', # 0x47 +'gyam', # 0x48 +'gyab', # 0x49 +'gyabs', # 0x4a +'gyas', # 0x4b +'gyass', # 0x4c +'gyang', # 0x4d +'gyaj', # 0x4e +'gyac', # 0x4f +'gyak', # 0x50 +'gyat', # 0x51 +'gyap', # 0x52 +'gyah', # 0x53 +'gyae', # 0x54 +'gyaeg', # 0x55 +'gyaegg', # 0x56 +'gyaegs', # 0x57 +'gyaen', # 0x58 +'gyaenj', # 0x59 +'gyaenh', # 0x5a +'gyaed', # 0x5b +'gyael', # 0x5c +'gyaelg', # 0x5d +'gyaelm', # 0x5e +'gyaelb', # 0x5f +'gyaels', # 0x60 +'gyaelt', # 0x61 +'gyaelp', # 0x62 +'gyaelh', # 0x63 +'gyaem', # 0x64 +'gyaeb', # 0x65 +'gyaebs', # 0x66 +'gyaes', # 0x67 +'gyaess', # 0x68 +'gyaeng', # 0x69 +'gyaej', # 0x6a +'gyaec', # 0x6b +'gyaek', # 0x6c +'gyaet', # 0x6d +'gyaep', # 0x6e +'gyaeh', # 0x6f +'geo', # 0x70 +'geog', # 0x71 +'geogg', # 0x72 +'geogs', # 0x73 +'geon', # 0x74 +'geonj', # 0x75 +'geonh', # 0x76 +'geod', # 0x77 +'geol', # 0x78 +'geolg', # 0x79 +'geolm', # 0x7a +'geolb', # 0x7b +'geols', # 0x7c +'geolt', # 0x7d +'geolp', # 0x7e +'geolh', # 0x7f +'geom', # 0x80 +'geob', # 0x81 +'geobs', # 0x82 +'geos', # 0x83 +'geoss', # 0x84 +'geong', # 0x85 +'geoj', # 0x86 +'geoc', # 0x87 +'geok', # 0x88 +'geot', # 0x89 +'geop', # 0x8a +'geoh', # 0x8b +'ge', # 0x8c +'geg', # 0x8d +'gegg', # 0x8e +'gegs', # 0x8f +'gen', # 0x90 +'genj', # 0x91 +'genh', # 0x92 +'ged', # 0x93 +'gel', # 0x94 +'gelg', # 0x95 +'gelm', # 0x96 +'gelb', # 0x97 +'gels', # 0x98 +'gelt', # 0x99 +'gelp', # 0x9a +'gelh', # 0x9b +'gem', # 0x9c +'geb', # 0x9d +'gebs', # 0x9e +'ges', # 0x9f +'gess', # 0xa0 +'geng', # 0xa1 +'gej', # 0xa2 +'gec', # 0xa3 +'gek', # 0xa4 +'get', # 0xa5 +'gep', # 0xa6 +'geh', # 0xa7 +'gyeo', # 0xa8 +'gyeog', # 0xa9 +'gyeogg', # 0xaa +'gyeogs', # 0xab +'gyeon', # 0xac +'gyeonj', # 0xad +'gyeonh', # 0xae +'gyeod', # 0xaf +'gyeol', # 0xb0 +'gyeolg', # 0xb1 +'gyeolm', # 0xb2 +'gyeolb', # 0xb3 +'gyeols', # 0xb4 +'gyeolt', # 0xb5 +'gyeolp', # 0xb6 +'gyeolh', # 0xb7 +'gyeom', # 0xb8 +'gyeob', # 0xb9 +'gyeobs', # 0xba +'gyeos', # 0xbb +'gyeoss', # 0xbc +'gyeong', # 0xbd +'gyeoj', # 0xbe +'gyeoc', # 0xbf +'gyeok', # 0xc0 +'gyeot', # 0xc1 +'gyeop', # 0xc2 +'gyeoh', # 0xc3 +'gye', # 0xc4 +'gyeg', # 0xc5 +'gyegg', # 0xc6 +'gyegs', # 0xc7 +'gyen', # 0xc8 +'gyenj', # 0xc9 +'gyenh', # 0xca +'gyed', # 0xcb +'gyel', # 0xcc +'gyelg', # 0xcd +'gyelm', # 0xce +'gyelb', # 0xcf +'gyels', # 0xd0 +'gyelt', # 0xd1 +'gyelp', # 0xd2 +'gyelh', # 0xd3 +'gyem', # 0xd4 +'gyeb', # 0xd5 +'gyebs', # 0xd6 +'gyes', # 0xd7 +'gyess', # 0xd8 +'gyeng', # 0xd9 +'gyej', # 0xda +'gyec', # 0xdb +'gyek', # 0xdc +'gyet', # 0xdd +'gyep', # 0xde +'gyeh', # 0xdf +'go', # 0xe0 +'gog', # 0xe1 +'gogg', # 0xe2 +'gogs', # 0xe3 +'gon', # 0xe4 +'gonj', # 0xe5 +'gonh', # 0xe6 +'god', # 0xe7 +'gol', # 0xe8 +'golg', # 0xe9 +'golm', # 0xea +'golb', # 0xeb +'gols', # 0xec +'golt', # 0xed +'golp', # 0xee +'golh', # 0xef +'gom', # 0xf0 +'gob', # 0xf1 +'gobs', # 0xf2 +'gos', # 0xf3 +'goss', # 0xf4 +'gong', # 0xf5 +'goj', # 0xf6 +'goc', # 0xf7 +'gok', # 0xf8 +'got', # 0xf9 +'gop', # 0xfa +'goh', # 0xfb +'gwa', # 0xfc +'gwag', # 0xfd +'gwagg', # 0xfe +'gwags', # 0xff +) diff --git a/nstock/modules/unidecode/x0ad.py b/nstock/modules/unidecode/x0ad.py new file mode 100644 index 0000000..ac2cf2a --- /dev/null +++ b/nstock/modules/unidecode/x0ad.py @@ -0,0 +1,258 @@ +data = ( +'gwan', # 0x00 +'gwanj', # 0x01 +'gwanh', # 0x02 +'gwad', # 0x03 +'gwal', # 0x04 +'gwalg', # 0x05 +'gwalm', # 0x06 +'gwalb', # 0x07 +'gwals', # 0x08 +'gwalt', # 0x09 +'gwalp', # 0x0a +'gwalh', # 0x0b +'gwam', # 0x0c +'gwab', # 0x0d +'gwabs', # 0x0e +'gwas', # 0x0f +'gwass', # 0x10 +'gwang', # 0x11 +'gwaj', # 0x12 +'gwac', # 0x13 +'gwak', # 0x14 +'gwat', # 0x15 +'gwap', # 0x16 +'gwah', # 0x17 +'gwae', # 0x18 +'gwaeg', # 0x19 +'gwaegg', # 0x1a +'gwaegs', # 0x1b +'gwaen', # 0x1c +'gwaenj', # 0x1d +'gwaenh', # 0x1e +'gwaed', # 0x1f +'gwael', # 0x20 +'gwaelg', # 0x21 +'gwaelm', # 0x22 +'gwaelb', # 0x23 +'gwaels', # 0x24 +'gwaelt', # 0x25 +'gwaelp', # 0x26 +'gwaelh', # 0x27 +'gwaem', # 0x28 +'gwaeb', # 0x29 +'gwaebs', # 0x2a +'gwaes', # 0x2b +'gwaess', # 0x2c +'gwaeng', # 0x2d +'gwaej', # 0x2e +'gwaec', # 0x2f +'gwaek', # 0x30 +'gwaet', # 0x31 +'gwaep', # 0x32 +'gwaeh', # 0x33 +'goe', # 0x34 +'goeg', # 0x35 +'goegg', # 0x36 +'goegs', # 0x37 +'goen', # 0x38 +'goenj', # 0x39 +'goenh', # 0x3a +'goed', # 0x3b +'goel', # 0x3c +'goelg', # 0x3d +'goelm', # 0x3e +'goelb', # 0x3f +'goels', # 0x40 +'goelt', # 0x41 +'goelp', # 0x42 +'goelh', # 0x43 +'goem', # 0x44 +'goeb', # 0x45 +'goebs', # 0x46 +'goes', # 0x47 +'goess', # 0x48 +'goeng', # 0x49 +'goej', # 0x4a +'goec', # 0x4b +'goek', # 0x4c +'goet', # 0x4d +'goep', # 0x4e +'goeh', # 0x4f +'gyo', # 0x50 +'gyog', # 0x51 +'gyogg', # 0x52 +'gyogs', # 0x53 +'gyon', # 0x54 +'gyonj', # 0x55 +'gyonh', # 0x56 +'gyod', # 0x57 +'gyol', # 0x58 +'gyolg', # 0x59 +'gyolm', # 0x5a +'gyolb', # 0x5b +'gyols', # 0x5c +'gyolt', # 0x5d +'gyolp', # 0x5e +'gyolh', # 0x5f +'gyom', # 0x60 +'gyob', # 0x61 +'gyobs', # 0x62 +'gyos', # 0x63 +'gyoss', # 0x64 +'gyong', # 0x65 +'gyoj', # 0x66 +'gyoc', # 0x67 +'gyok', # 0x68 +'gyot', # 0x69 +'gyop', # 0x6a +'gyoh', # 0x6b +'gu', # 0x6c +'gug', # 0x6d +'gugg', # 0x6e +'gugs', # 0x6f +'gun', # 0x70 +'gunj', # 0x71 +'gunh', # 0x72 +'gud', # 0x73 +'gul', # 0x74 +'gulg', # 0x75 +'gulm', # 0x76 +'gulb', # 0x77 +'guls', # 0x78 +'gult', # 0x79 +'gulp', # 0x7a +'gulh', # 0x7b +'gum', # 0x7c +'gub', # 0x7d +'gubs', # 0x7e +'gus', # 0x7f +'guss', # 0x80 +'gung', # 0x81 +'guj', # 0x82 +'guc', # 0x83 +'guk', # 0x84 +'gut', # 0x85 +'gup', # 0x86 +'guh', # 0x87 +'gweo', # 0x88 +'gweog', # 0x89 +'gweogg', # 0x8a +'gweogs', # 0x8b +'gweon', # 0x8c +'gweonj', # 0x8d +'gweonh', # 0x8e +'gweod', # 0x8f +'gweol', # 0x90 +'gweolg', # 0x91 +'gweolm', # 0x92 +'gweolb', # 0x93 +'gweols', # 0x94 +'gweolt', # 0x95 +'gweolp', # 0x96 +'gweolh', # 0x97 +'gweom', # 0x98 +'gweob', # 0x99 +'gweobs', # 0x9a +'gweos', # 0x9b +'gweoss', # 0x9c +'gweong', # 0x9d +'gweoj', # 0x9e +'gweoc', # 0x9f +'gweok', # 0xa0 +'gweot', # 0xa1 +'gweop', # 0xa2 +'gweoh', # 0xa3 +'gwe', # 0xa4 +'gweg', # 0xa5 +'gwegg', # 0xa6 +'gwegs', # 0xa7 +'gwen', # 0xa8 +'gwenj', # 0xa9 +'gwenh', # 0xaa +'gwed', # 0xab +'gwel', # 0xac +'gwelg', # 0xad +'gwelm', # 0xae +'gwelb', # 0xaf +'gwels', # 0xb0 +'gwelt', # 0xb1 +'gwelp', # 0xb2 +'gwelh', # 0xb3 +'gwem', # 0xb4 +'gweb', # 0xb5 +'gwebs', # 0xb6 +'gwes', # 0xb7 +'gwess', # 0xb8 +'gweng', # 0xb9 +'gwej', # 0xba +'gwec', # 0xbb +'gwek', # 0xbc +'gwet', # 0xbd +'gwep', # 0xbe +'gweh', # 0xbf +'gwi', # 0xc0 +'gwig', # 0xc1 +'gwigg', # 0xc2 +'gwigs', # 0xc3 +'gwin', # 0xc4 +'gwinj', # 0xc5 +'gwinh', # 0xc6 +'gwid', # 0xc7 +'gwil', # 0xc8 +'gwilg', # 0xc9 +'gwilm', # 0xca +'gwilb', # 0xcb +'gwils', # 0xcc +'gwilt', # 0xcd +'gwilp', # 0xce +'gwilh', # 0xcf +'gwim', # 0xd0 +'gwib', # 0xd1 +'gwibs', # 0xd2 +'gwis', # 0xd3 +'gwiss', # 0xd4 +'gwing', # 0xd5 +'gwij', # 0xd6 +'gwic', # 0xd7 +'gwik', # 0xd8 +'gwit', # 0xd9 +'gwip', # 0xda +'gwih', # 0xdb +'gyu', # 0xdc +'gyug', # 0xdd +'gyugg', # 0xde +'gyugs', # 0xdf +'gyun', # 0xe0 +'gyunj', # 0xe1 +'gyunh', # 0xe2 +'gyud', # 0xe3 +'gyul', # 0xe4 +'gyulg', # 0xe5 +'gyulm', # 0xe6 +'gyulb', # 0xe7 +'gyuls', # 0xe8 +'gyult', # 0xe9 +'gyulp', # 0xea +'gyulh', # 0xeb +'gyum', # 0xec +'gyub', # 0xed +'gyubs', # 0xee +'gyus', # 0xef +'gyuss', # 0xf0 +'gyung', # 0xf1 +'gyuj', # 0xf2 +'gyuc', # 0xf3 +'gyuk', # 0xf4 +'gyut', # 0xf5 +'gyup', # 0xf6 +'gyuh', # 0xf7 +'geu', # 0xf8 +'geug', # 0xf9 +'geugg', # 0xfa +'geugs', # 0xfb +'geun', # 0xfc +'geunj', # 0xfd +'geunh', # 0xfe +'geud', # 0xff +) diff --git a/nstock/modules/unidecode/x0ae.py b/nstock/modules/unidecode/x0ae.py new file mode 100644 index 0000000..37a7abc --- /dev/null +++ b/nstock/modules/unidecode/x0ae.py @@ -0,0 +1,258 @@ +data = ( +'geul', # 0x00 +'geulg', # 0x01 +'geulm', # 0x02 +'geulb', # 0x03 +'geuls', # 0x04 +'geult', # 0x05 +'geulp', # 0x06 +'geulh', # 0x07 +'geum', # 0x08 +'geub', # 0x09 +'geubs', # 0x0a +'geus', # 0x0b +'geuss', # 0x0c +'geung', # 0x0d +'geuj', # 0x0e +'geuc', # 0x0f +'geuk', # 0x10 +'geut', # 0x11 +'geup', # 0x12 +'geuh', # 0x13 +'gyi', # 0x14 +'gyig', # 0x15 +'gyigg', # 0x16 +'gyigs', # 0x17 +'gyin', # 0x18 +'gyinj', # 0x19 +'gyinh', # 0x1a +'gyid', # 0x1b +'gyil', # 0x1c +'gyilg', # 0x1d +'gyilm', # 0x1e +'gyilb', # 0x1f +'gyils', # 0x20 +'gyilt', # 0x21 +'gyilp', # 0x22 +'gyilh', # 0x23 +'gyim', # 0x24 +'gyib', # 0x25 +'gyibs', # 0x26 +'gyis', # 0x27 +'gyiss', # 0x28 +'gying', # 0x29 +'gyij', # 0x2a +'gyic', # 0x2b +'gyik', # 0x2c +'gyit', # 0x2d +'gyip', # 0x2e +'gyih', # 0x2f +'gi', # 0x30 +'gig', # 0x31 +'gigg', # 0x32 +'gigs', # 0x33 +'gin', # 0x34 +'ginj', # 0x35 +'ginh', # 0x36 +'gid', # 0x37 +'gil', # 0x38 +'gilg', # 0x39 +'gilm', # 0x3a +'gilb', # 0x3b +'gils', # 0x3c +'gilt', # 0x3d +'gilp', # 0x3e +'gilh', # 0x3f +'gim', # 0x40 +'gib', # 0x41 +'gibs', # 0x42 +'gis', # 0x43 +'giss', # 0x44 +'ging', # 0x45 +'gij', # 0x46 +'gic', # 0x47 +'gik', # 0x48 +'git', # 0x49 +'gip', # 0x4a +'gih', # 0x4b +'gga', # 0x4c +'ggag', # 0x4d +'ggagg', # 0x4e +'ggags', # 0x4f +'ggan', # 0x50 +'gganj', # 0x51 +'gganh', # 0x52 +'ggad', # 0x53 +'ggal', # 0x54 +'ggalg', # 0x55 +'ggalm', # 0x56 +'ggalb', # 0x57 +'ggals', # 0x58 +'ggalt', # 0x59 +'ggalp', # 0x5a +'ggalh', # 0x5b +'ggam', # 0x5c +'ggab', # 0x5d +'ggabs', # 0x5e +'ggas', # 0x5f +'ggass', # 0x60 +'ggang', # 0x61 +'ggaj', # 0x62 +'ggac', # 0x63 +'ggak', # 0x64 +'ggat', # 0x65 +'ggap', # 0x66 +'ggah', # 0x67 +'ggae', # 0x68 +'ggaeg', # 0x69 +'ggaegg', # 0x6a +'ggaegs', # 0x6b +'ggaen', # 0x6c +'ggaenj', # 0x6d +'ggaenh', # 0x6e +'ggaed', # 0x6f +'ggael', # 0x70 +'ggaelg', # 0x71 +'ggaelm', # 0x72 +'ggaelb', # 0x73 +'ggaels', # 0x74 +'ggaelt', # 0x75 +'ggaelp', # 0x76 +'ggaelh', # 0x77 +'ggaem', # 0x78 +'ggaeb', # 0x79 +'ggaebs', # 0x7a +'ggaes', # 0x7b +'ggaess', # 0x7c +'ggaeng', # 0x7d +'ggaej', # 0x7e +'ggaec', # 0x7f +'ggaek', # 0x80 +'ggaet', # 0x81 +'ggaep', # 0x82 +'ggaeh', # 0x83 +'ggya', # 0x84 +'ggyag', # 0x85 +'ggyagg', # 0x86 +'ggyags', # 0x87 +'ggyan', # 0x88 +'ggyanj', # 0x89 +'ggyanh', # 0x8a +'ggyad', # 0x8b +'ggyal', # 0x8c +'ggyalg', # 0x8d +'ggyalm', # 0x8e +'ggyalb', # 0x8f +'ggyals', # 0x90 +'ggyalt', # 0x91 +'ggyalp', # 0x92 +'ggyalh', # 0x93 +'ggyam', # 0x94 +'ggyab', # 0x95 +'ggyabs', # 0x96 +'ggyas', # 0x97 +'ggyass', # 0x98 +'ggyang', # 0x99 +'ggyaj', # 0x9a +'ggyac', # 0x9b +'ggyak', # 0x9c +'ggyat', # 0x9d +'ggyap', # 0x9e +'ggyah', # 0x9f +'ggyae', # 0xa0 +'ggyaeg', # 0xa1 +'ggyaegg', # 0xa2 +'ggyaegs', # 0xa3 +'ggyaen', # 0xa4 +'ggyaenj', # 0xa5 +'ggyaenh', # 0xa6 +'ggyaed', # 0xa7 +'ggyael', # 0xa8 +'ggyaelg', # 0xa9 +'ggyaelm', # 0xaa +'ggyaelb', # 0xab +'ggyaels', # 0xac +'ggyaelt', # 0xad +'ggyaelp', # 0xae +'ggyaelh', # 0xaf +'ggyaem', # 0xb0 +'ggyaeb', # 0xb1 +'ggyaebs', # 0xb2 +'ggyaes', # 0xb3 +'ggyaess', # 0xb4 +'ggyaeng', # 0xb5 +'ggyaej', # 0xb6 +'ggyaec', # 0xb7 +'ggyaek', # 0xb8 +'ggyaet', # 0xb9 +'ggyaep', # 0xba +'ggyaeh', # 0xbb +'ggeo', # 0xbc +'ggeog', # 0xbd +'ggeogg', # 0xbe +'ggeogs', # 0xbf +'ggeon', # 0xc0 +'ggeonj', # 0xc1 +'ggeonh', # 0xc2 +'ggeod', # 0xc3 +'ggeol', # 0xc4 +'ggeolg', # 0xc5 +'ggeolm', # 0xc6 +'ggeolb', # 0xc7 +'ggeols', # 0xc8 +'ggeolt', # 0xc9 +'ggeolp', # 0xca +'ggeolh', # 0xcb +'ggeom', # 0xcc +'ggeob', # 0xcd +'ggeobs', # 0xce +'ggeos', # 0xcf +'ggeoss', # 0xd0 +'ggeong', # 0xd1 +'ggeoj', # 0xd2 +'ggeoc', # 0xd3 +'ggeok', # 0xd4 +'ggeot', # 0xd5 +'ggeop', # 0xd6 +'ggeoh', # 0xd7 +'gge', # 0xd8 +'ggeg', # 0xd9 +'ggegg', # 0xda +'ggegs', # 0xdb +'ggen', # 0xdc +'ggenj', # 0xdd +'ggenh', # 0xde +'gged', # 0xdf +'ggel', # 0xe0 +'ggelg', # 0xe1 +'ggelm', # 0xe2 +'ggelb', # 0xe3 +'ggels', # 0xe4 +'ggelt', # 0xe5 +'ggelp', # 0xe6 +'ggelh', # 0xe7 +'ggem', # 0xe8 +'ggeb', # 0xe9 +'ggebs', # 0xea +'gges', # 0xeb +'ggess', # 0xec +'ggeng', # 0xed +'ggej', # 0xee +'ggec', # 0xef +'ggek', # 0xf0 +'gget', # 0xf1 +'ggep', # 0xf2 +'ggeh', # 0xf3 +'ggyeo', # 0xf4 +'ggyeog', # 0xf5 +'ggyeogg', # 0xf6 +'ggyeogs', # 0xf7 +'ggyeon', # 0xf8 +'ggyeonj', # 0xf9 +'ggyeonh', # 0xfa +'ggyeod', # 0xfb +'ggyeol', # 0xfc +'ggyeolg', # 0xfd +'ggyeolm', # 0xfe +'ggyeolb', # 0xff +) diff --git a/nstock/modules/unidecode/x0af.py b/nstock/modules/unidecode/x0af.py new file mode 100644 index 0000000..448d26b --- /dev/null +++ b/nstock/modules/unidecode/x0af.py @@ -0,0 +1,258 @@ +data = ( +'ggyeols', # 0x00 +'ggyeolt', # 0x01 +'ggyeolp', # 0x02 +'ggyeolh', # 0x03 +'ggyeom', # 0x04 +'ggyeob', # 0x05 +'ggyeobs', # 0x06 +'ggyeos', # 0x07 +'ggyeoss', # 0x08 +'ggyeong', # 0x09 +'ggyeoj', # 0x0a +'ggyeoc', # 0x0b +'ggyeok', # 0x0c +'ggyeot', # 0x0d +'ggyeop', # 0x0e +'ggyeoh', # 0x0f +'ggye', # 0x10 +'ggyeg', # 0x11 +'ggyegg', # 0x12 +'ggyegs', # 0x13 +'ggyen', # 0x14 +'ggyenj', # 0x15 +'ggyenh', # 0x16 +'ggyed', # 0x17 +'ggyel', # 0x18 +'ggyelg', # 0x19 +'ggyelm', # 0x1a +'ggyelb', # 0x1b +'ggyels', # 0x1c +'ggyelt', # 0x1d +'ggyelp', # 0x1e +'ggyelh', # 0x1f +'ggyem', # 0x20 +'ggyeb', # 0x21 +'ggyebs', # 0x22 +'ggyes', # 0x23 +'ggyess', # 0x24 +'ggyeng', # 0x25 +'ggyej', # 0x26 +'ggyec', # 0x27 +'ggyek', # 0x28 +'ggyet', # 0x29 +'ggyep', # 0x2a +'ggyeh', # 0x2b +'ggo', # 0x2c +'ggog', # 0x2d +'ggogg', # 0x2e +'ggogs', # 0x2f +'ggon', # 0x30 +'ggonj', # 0x31 +'ggonh', # 0x32 +'ggod', # 0x33 +'ggol', # 0x34 +'ggolg', # 0x35 +'ggolm', # 0x36 +'ggolb', # 0x37 +'ggols', # 0x38 +'ggolt', # 0x39 +'ggolp', # 0x3a +'ggolh', # 0x3b +'ggom', # 0x3c +'ggob', # 0x3d +'ggobs', # 0x3e +'ggos', # 0x3f +'ggoss', # 0x40 +'ggong', # 0x41 +'ggoj', # 0x42 +'ggoc', # 0x43 +'ggok', # 0x44 +'ggot', # 0x45 +'ggop', # 0x46 +'ggoh', # 0x47 +'ggwa', # 0x48 +'ggwag', # 0x49 +'ggwagg', # 0x4a +'ggwags', # 0x4b +'ggwan', # 0x4c +'ggwanj', # 0x4d +'ggwanh', # 0x4e +'ggwad', # 0x4f +'ggwal', # 0x50 +'ggwalg', # 0x51 +'ggwalm', # 0x52 +'ggwalb', # 0x53 +'ggwals', # 0x54 +'ggwalt', # 0x55 +'ggwalp', # 0x56 +'ggwalh', # 0x57 +'ggwam', # 0x58 +'ggwab', # 0x59 +'ggwabs', # 0x5a +'ggwas', # 0x5b +'ggwass', # 0x5c +'ggwang', # 0x5d +'ggwaj', # 0x5e +'ggwac', # 0x5f +'ggwak', # 0x60 +'ggwat', # 0x61 +'ggwap', # 0x62 +'ggwah', # 0x63 +'ggwae', # 0x64 +'ggwaeg', # 0x65 +'ggwaegg', # 0x66 +'ggwaegs', # 0x67 +'ggwaen', # 0x68 +'ggwaenj', # 0x69 +'ggwaenh', # 0x6a +'ggwaed', # 0x6b +'ggwael', # 0x6c +'ggwaelg', # 0x6d +'ggwaelm', # 0x6e +'ggwaelb', # 0x6f +'ggwaels', # 0x70 +'ggwaelt', # 0x71 +'ggwaelp', # 0x72 +'ggwaelh', # 0x73 +'ggwaem', # 0x74 +'ggwaeb', # 0x75 +'ggwaebs', # 0x76 +'ggwaes', # 0x77 +'ggwaess', # 0x78 +'ggwaeng', # 0x79 +'ggwaej', # 0x7a +'ggwaec', # 0x7b +'ggwaek', # 0x7c +'ggwaet', # 0x7d +'ggwaep', # 0x7e +'ggwaeh', # 0x7f +'ggoe', # 0x80 +'ggoeg', # 0x81 +'ggoegg', # 0x82 +'ggoegs', # 0x83 +'ggoen', # 0x84 +'ggoenj', # 0x85 +'ggoenh', # 0x86 +'ggoed', # 0x87 +'ggoel', # 0x88 +'ggoelg', # 0x89 +'ggoelm', # 0x8a +'ggoelb', # 0x8b +'ggoels', # 0x8c +'ggoelt', # 0x8d +'ggoelp', # 0x8e +'ggoelh', # 0x8f +'ggoem', # 0x90 +'ggoeb', # 0x91 +'ggoebs', # 0x92 +'ggoes', # 0x93 +'ggoess', # 0x94 +'ggoeng', # 0x95 +'ggoej', # 0x96 +'ggoec', # 0x97 +'ggoek', # 0x98 +'ggoet', # 0x99 +'ggoep', # 0x9a +'ggoeh', # 0x9b +'ggyo', # 0x9c +'ggyog', # 0x9d +'ggyogg', # 0x9e +'ggyogs', # 0x9f +'ggyon', # 0xa0 +'ggyonj', # 0xa1 +'ggyonh', # 0xa2 +'ggyod', # 0xa3 +'ggyol', # 0xa4 +'ggyolg', # 0xa5 +'ggyolm', # 0xa6 +'ggyolb', # 0xa7 +'ggyols', # 0xa8 +'ggyolt', # 0xa9 +'ggyolp', # 0xaa +'ggyolh', # 0xab +'ggyom', # 0xac +'ggyob', # 0xad +'ggyobs', # 0xae +'ggyos', # 0xaf +'ggyoss', # 0xb0 +'ggyong', # 0xb1 +'ggyoj', # 0xb2 +'ggyoc', # 0xb3 +'ggyok', # 0xb4 +'ggyot', # 0xb5 +'ggyop', # 0xb6 +'ggyoh', # 0xb7 +'ggu', # 0xb8 +'ggug', # 0xb9 +'ggugg', # 0xba +'ggugs', # 0xbb +'ggun', # 0xbc +'ggunj', # 0xbd +'ggunh', # 0xbe +'ggud', # 0xbf +'ggul', # 0xc0 +'ggulg', # 0xc1 +'ggulm', # 0xc2 +'ggulb', # 0xc3 +'gguls', # 0xc4 +'ggult', # 0xc5 +'ggulp', # 0xc6 +'ggulh', # 0xc7 +'ggum', # 0xc8 +'ggub', # 0xc9 +'ggubs', # 0xca +'ggus', # 0xcb +'gguss', # 0xcc +'ggung', # 0xcd +'gguj', # 0xce +'gguc', # 0xcf +'gguk', # 0xd0 +'ggut', # 0xd1 +'ggup', # 0xd2 +'gguh', # 0xd3 +'ggweo', # 0xd4 +'ggweog', # 0xd5 +'ggweogg', # 0xd6 +'ggweogs', # 0xd7 +'ggweon', # 0xd8 +'ggweonj', # 0xd9 +'ggweonh', # 0xda +'ggweod', # 0xdb +'ggweol', # 0xdc +'ggweolg', # 0xdd +'ggweolm', # 0xde +'ggweolb', # 0xdf +'ggweols', # 0xe0 +'ggweolt', # 0xe1 +'ggweolp', # 0xe2 +'ggweolh', # 0xe3 +'ggweom', # 0xe4 +'ggweob', # 0xe5 +'ggweobs', # 0xe6 +'ggweos', # 0xe7 +'ggweoss', # 0xe8 +'ggweong', # 0xe9 +'ggweoj', # 0xea +'ggweoc', # 0xeb +'ggweok', # 0xec +'ggweot', # 0xed +'ggweop', # 0xee +'ggweoh', # 0xef +'ggwe', # 0xf0 +'ggweg', # 0xf1 +'ggwegg', # 0xf2 +'ggwegs', # 0xf3 +'ggwen', # 0xf4 +'ggwenj', # 0xf5 +'ggwenh', # 0xf6 +'ggwed', # 0xf7 +'ggwel', # 0xf8 +'ggwelg', # 0xf9 +'ggwelm', # 0xfa +'ggwelb', # 0xfb +'ggwels', # 0xfc +'ggwelt', # 0xfd +'ggwelp', # 0xfe +'ggwelh', # 0xff +) diff --git a/nstock/modules/unidecode/x0b0.py b/nstock/modules/unidecode/x0b0.py new file mode 100644 index 0000000..20f41b3 --- /dev/null +++ b/nstock/modules/unidecode/x0b0.py @@ -0,0 +1,258 @@ +data = ( +'ggwem', # 0x00 +'ggweb', # 0x01 +'ggwebs', # 0x02 +'ggwes', # 0x03 +'ggwess', # 0x04 +'ggweng', # 0x05 +'ggwej', # 0x06 +'ggwec', # 0x07 +'ggwek', # 0x08 +'ggwet', # 0x09 +'ggwep', # 0x0a +'ggweh', # 0x0b +'ggwi', # 0x0c +'ggwig', # 0x0d +'ggwigg', # 0x0e +'ggwigs', # 0x0f +'ggwin', # 0x10 +'ggwinj', # 0x11 +'ggwinh', # 0x12 +'ggwid', # 0x13 +'ggwil', # 0x14 +'ggwilg', # 0x15 +'ggwilm', # 0x16 +'ggwilb', # 0x17 +'ggwils', # 0x18 +'ggwilt', # 0x19 +'ggwilp', # 0x1a +'ggwilh', # 0x1b +'ggwim', # 0x1c +'ggwib', # 0x1d +'ggwibs', # 0x1e +'ggwis', # 0x1f +'ggwiss', # 0x20 +'ggwing', # 0x21 +'ggwij', # 0x22 +'ggwic', # 0x23 +'ggwik', # 0x24 +'ggwit', # 0x25 +'ggwip', # 0x26 +'ggwih', # 0x27 +'ggyu', # 0x28 +'ggyug', # 0x29 +'ggyugg', # 0x2a +'ggyugs', # 0x2b +'ggyun', # 0x2c +'ggyunj', # 0x2d +'ggyunh', # 0x2e +'ggyud', # 0x2f +'ggyul', # 0x30 +'ggyulg', # 0x31 +'ggyulm', # 0x32 +'ggyulb', # 0x33 +'ggyuls', # 0x34 +'ggyult', # 0x35 +'ggyulp', # 0x36 +'ggyulh', # 0x37 +'ggyum', # 0x38 +'ggyub', # 0x39 +'ggyubs', # 0x3a +'ggyus', # 0x3b +'ggyuss', # 0x3c +'ggyung', # 0x3d +'ggyuj', # 0x3e +'ggyuc', # 0x3f +'ggyuk', # 0x40 +'ggyut', # 0x41 +'ggyup', # 0x42 +'ggyuh', # 0x43 +'ggeu', # 0x44 +'ggeug', # 0x45 +'ggeugg', # 0x46 +'ggeugs', # 0x47 +'ggeun', # 0x48 +'ggeunj', # 0x49 +'ggeunh', # 0x4a +'ggeud', # 0x4b +'ggeul', # 0x4c +'ggeulg', # 0x4d +'ggeulm', # 0x4e +'ggeulb', # 0x4f +'ggeuls', # 0x50 +'ggeult', # 0x51 +'ggeulp', # 0x52 +'ggeulh', # 0x53 +'ggeum', # 0x54 +'ggeub', # 0x55 +'ggeubs', # 0x56 +'ggeus', # 0x57 +'ggeuss', # 0x58 +'ggeung', # 0x59 +'ggeuj', # 0x5a +'ggeuc', # 0x5b +'ggeuk', # 0x5c +'ggeut', # 0x5d +'ggeup', # 0x5e +'ggeuh', # 0x5f +'ggyi', # 0x60 +'ggyig', # 0x61 +'ggyigg', # 0x62 +'ggyigs', # 0x63 +'ggyin', # 0x64 +'ggyinj', # 0x65 +'ggyinh', # 0x66 +'ggyid', # 0x67 +'ggyil', # 0x68 +'ggyilg', # 0x69 +'ggyilm', # 0x6a +'ggyilb', # 0x6b +'ggyils', # 0x6c +'ggyilt', # 0x6d +'ggyilp', # 0x6e +'ggyilh', # 0x6f +'ggyim', # 0x70 +'ggyib', # 0x71 +'ggyibs', # 0x72 +'ggyis', # 0x73 +'ggyiss', # 0x74 +'ggying', # 0x75 +'ggyij', # 0x76 +'ggyic', # 0x77 +'ggyik', # 0x78 +'ggyit', # 0x79 +'ggyip', # 0x7a +'ggyih', # 0x7b +'ggi', # 0x7c +'ggig', # 0x7d +'ggigg', # 0x7e +'ggigs', # 0x7f +'ggin', # 0x80 +'gginj', # 0x81 +'gginh', # 0x82 +'ggid', # 0x83 +'ggil', # 0x84 +'ggilg', # 0x85 +'ggilm', # 0x86 +'ggilb', # 0x87 +'ggils', # 0x88 +'ggilt', # 0x89 +'ggilp', # 0x8a +'ggilh', # 0x8b +'ggim', # 0x8c +'ggib', # 0x8d +'ggibs', # 0x8e +'ggis', # 0x8f +'ggiss', # 0x90 +'gging', # 0x91 +'ggij', # 0x92 +'ggic', # 0x93 +'ggik', # 0x94 +'ggit', # 0x95 +'ggip', # 0x96 +'ggih', # 0x97 +'na', # 0x98 +'nag', # 0x99 +'nagg', # 0x9a +'nags', # 0x9b +'nan', # 0x9c +'nanj', # 0x9d +'nanh', # 0x9e +'nad', # 0x9f +'nal', # 0xa0 +'nalg', # 0xa1 +'nalm', # 0xa2 +'nalb', # 0xa3 +'nals', # 0xa4 +'nalt', # 0xa5 +'nalp', # 0xa6 +'nalh', # 0xa7 +'nam', # 0xa8 +'nab', # 0xa9 +'nabs', # 0xaa +'nas', # 0xab +'nass', # 0xac +'nang', # 0xad +'naj', # 0xae +'nac', # 0xaf +'nak', # 0xb0 +'nat', # 0xb1 +'nap', # 0xb2 +'nah', # 0xb3 +'nae', # 0xb4 +'naeg', # 0xb5 +'naegg', # 0xb6 +'naegs', # 0xb7 +'naen', # 0xb8 +'naenj', # 0xb9 +'naenh', # 0xba +'naed', # 0xbb +'nael', # 0xbc +'naelg', # 0xbd +'naelm', # 0xbe +'naelb', # 0xbf +'naels', # 0xc0 +'naelt', # 0xc1 +'naelp', # 0xc2 +'naelh', # 0xc3 +'naem', # 0xc4 +'naeb', # 0xc5 +'naebs', # 0xc6 +'naes', # 0xc7 +'naess', # 0xc8 +'naeng', # 0xc9 +'naej', # 0xca +'naec', # 0xcb +'naek', # 0xcc +'naet', # 0xcd +'naep', # 0xce +'naeh', # 0xcf +'nya', # 0xd0 +'nyag', # 0xd1 +'nyagg', # 0xd2 +'nyags', # 0xd3 +'nyan', # 0xd4 +'nyanj', # 0xd5 +'nyanh', # 0xd6 +'nyad', # 0xd7 +'nyal', # 0xd8 +'nyalg', # 0xd9 +'nyalm', # 0xda +'nyalb', # 0xdb +'nyals', # 0xdc +'nyalt', # 0xdd +'nyalp', # 0xde +'nyalh', # 0xdf +'nyam', # 0xe0 +'nyab', # 0xe1 +'nyabs', # 0xe2 +'nyas', # 0xe3 +'nyass', # 0xe4 +'nyang', # 0xe5 +'nyaj', # 0xe6 +'nyac', # 0xe7 +'nyak', # 0xe8 +'nyat', # 0xe9 +'nyap', # 0xea +'nyah', # 0xeb +'nyae', # 0xec +'nyaeg', # 0xed +'nyaegg', # 0xee +'nyaegs', # 0xef +'nyaen', # 0xf0 +'nyaenj', # 0xf1 +'nyaenh', # 0xf2 +'nyaed', # 0xf3 +'nyael', # 0xf4 +'nyaelg', # 0xf5 +'nyaelm', # 0xf6 +'nyaelb', # 0xf7 +'nyaels', # 0xf8 +'nyaelt', # 0xf9 +'nyaelp', # 0xfa +'nyaelh', # 0xfb +'nyaem', # 0xfc +'nyaeb', # 0xfd +'nyaebs', # 0xfe +'nyaes', # 0xff +) diff --git a/nstock/modules/unidecode/x0b1.py b/nstock/modules/unidecode/x0b1.py new file mode 100644 index 0000000..5aabeae --- /dev/null +++ b/nstock/modules/unidecode/x0b1.py @@ -0,0 +1,258 @@ +data = ( +'nyaess', # 0x00 +'nyaeng', # 0x01 +'nyaej', # 0x02 +'nyaec', # 0x03 +'nyaek', # 0x04 +'nyaet', # 0x05 +'nyaep', # 0x06 +'nyaeh', # 0x07 +'neo', # 0x08 +'neog', # 0x09 +'neogg', # 0x0a +'neogs', # 0x0b +'neon', # 0x0c +'neonj', # 0x0d +'neonh', # 0x0e +'neod', # 0x0f +'neol', # 0x10 +'neolg', # 0x11 +'neolm', # 0x12 +'neolb', # 0x13 +'neols', # 0x14 +'neolt', # 0x15 +'neolp', # 0x16 +'neolh', # 0x17 +'neom', # 0x18 +'neob', # 0x19 +'neobs', # 0x1a +'neos', # 0x1b +'neoss', # 0x1c +'neong', # 0x1d +'neoj', # 0x1e +'neoc', # 0x1f +'neok', # 0x20 +'neot', # 0x21 +'neop', # 0x22 +'neoh', # 0x23 +'ne', # 0x24 +'neg', # 0x25 +'negg', # 0x26 +'negs', # 0x27 +'nen', # 0x28 +'nenj', # 0x29 +'nenh', # 0x2a +'ned', # 0x2b +'nel', # 0x2c +'nelg', # 0x2d +'nelm', # 0x2e +'nelb', # 0x2f +'nels', # 0x30 +'nelt', # 0x31 +'nelp', # 0x32 +'nelh', # 0x33 +'nem', # 0x34 +'neb', # 0x35 +'nebs', # 0x36 +'nes', # 0x37 +'ness', # 0x38 +'neng', # 0x39 +'nej', # 0x3a +'nec', # 0x3b +'nek', # 0x3c +'net', # 0x3d +'nep', # 0x3e +'neh', # 0x3f +'nyeo', # 0x40 +'nyeog', # 0x41 +'nyeogg', # 0x42 +'nyeogs', # 0x43 +'nyeon', # 0x44 +'nyeonj', # 0x45 +'nyeonh', # 0x46 +'nyeod', # 0x47 +'nyeol', # 0x48 +'nyeolg', # 0x49 +'nyeolm', # 0x4a +'nyeolb', # 0x4b +'nyeols', # 0x4c +'nyeolt', # 0x4d +'nyeolp', # 0x4e +'nyeolh', # 0x4f +'nyeom', # 0x50 +'nyeob', # 0x51 +'nyeobs', # 0x52 +'nyeos', # 0x53 +'nyeoss', # 0x54 +'nyeong', # 0x55 +'nyeoj', # 0x56 +'nyeoc', # 0x57 +'nyeok', # 0x58 +'nyeot', # 0x59 +'nyeop', # 0x5a +'nyeoh', # 0x5b +'nye', # 0x5c +'nyeg', # 0x5d +'nyegg', # 0x5e +'nyegs', # 0x5f +'nyen', # 0x60 +'nyenj', # 0x61 +'nyenh', # 0x62 +'nyed', # 0x63 +'nyel', # 0x64 +'nyelg', # 0x65 +'nyelm', # 0x66 +'nyelb', # 0x67 +'nyels', # 0x68 +'nyelt', # 0x69 +'nyelp', # 0x6a +'nyelh', # 0x6b +'nyem', # 0x6c +'nyeb', # 0x6d +'nyebs', # 0x6e +'nyes', # 0x6f +'nyess', # 0x70 +'nyeng', # 0x71 +'nyej', # 0x72 +'nyec', # 0x73 +'nyek', # 0x74 +'nyet', # 0x75 +'nyep', # 0x76 +'nyeh', # 0x77 +'no', # 0x78 +'nog', # 0x79 +'nogg', # 0x7a +'nogs', # 0x7b +'non', # 0x7c +'nonj', # 0x7d +'nonh', # 0x7e +'nod', # 0x7f +'nol', # 0x80 +'nolg', # 0x81 +'nolm', # 0x82 +'nolb', # 0x83 +'nols', # 0x84 +'nolt', # 0x85 +'nolp', # 0x86 +'nolh', # 0x87 +'nom', # 0x88 +'nob', # 0x89 +'nobs', # 0x8a +'nos', # 0x8b +'noss', # 0x8c +'nong', # 0x8d +'noj', # 0x8e +'noc', # 0x8f +'nok', # 0x90 +'not', # 0x91 +'nop', # 0x92 +'noh', # 0x93 +'nwa', # 0x94 +'nwag', # 0x95 +'nwagg', # 0x96 +'nwags', # 0x97 +'nwan', # 0x98 +'nwanj', # 0x99 +'nwanh', # 0x9a +'nwad', # 0x9b +'nwal', # 0x9c +'nwalg', # 0x9d +'nwalm', # 0x9e +'nwalb', # 0x9f +'nwals', # 0xa0 +'nwalt', # 0xa1 +'nwalp', # 0xa2 +'nwalh', # 0xa3 +'nwam', # 0xa4 +'nwab', # 0xa5 +'nwabs', # 0xa6 +'nwas', # 0xa7 +'nwass', # 0xa8 +'nwang', # 0xa9 +'nwaj', # 0xaa +'nwac', # 0xab +'nwak', # 0xac +'nwat', # 0xad +'nwap', # 0xae +'nwah', # 0xaf +'nwae', # 0xb0 +'nwaeg', # 0xb1 +'nwaegg', # 0xb2 +'nwaegs', # 0xb3 +'nwaen', # 0xb4 +'nwaenj', # 0xb5 +'nwaenh', # 0xb6 +'nwaed', # 0xb7 +'nwael', # 0xb8 +'nwaelg', # 0xb9 +'nwaelm', # 0xba +'nwaelb', # 0xbb +'nwaels', # 0xbc +'nwaelt', # 0xbd +'nwaelp', # 0xbe +'nwaelh', # 0xbf +'nwaem', # 0xc0 +'nwaeb', # 0xc1 +'nwaebs', # 0xc2 +'nwaes', # 0xc3 +'nwaess', # 0xc4 +'nwaeng', # 0xc5 +'nwaej', # 0xc6 +'nwaec', # 0xc7 +'nwaek', # 0xc8 +'nwaet', # 0xc9 +'nwaep', # 0xca +'nwaeh', # 0xcb +'noe', # 0xcc +'noeg', # 0xcd +'noegg', # 0xce +'noegs', # 0xcf +'noen', # 0xd0 +'noenj', # 0xd1 +'noenh', # 0xd2 +'noed', # 0xd3 +'noel', # 0xd4 +'noelg', # 0xd5 +'noelm', # 0xd6 +'noelb', # 0xd7 +'noels', # 0xd8 +'noelt', # 0xd9 +'noelp', # 0xda +'noelh', # 0xdb +'noem', # 0xdc +'noeb', # 0xdd +'noebs', # 0xde +'noes', # 0xdf +'noess', # 0xe0 +'noeng', # 0xe1 +'noej', # 0xe2 +'noec', # 0xe3 +'noek', # 0xe4 +'noet', # 0xe5 +'noep', # 0xe6 +'noeh', # 0xe7 +'nyo', # 0xe8 +'nyog', # 0xe9 +'nyogg', # 0xea +'nyogs', # 0xeb +'nyon', # 0xec +'nyonj', # 0xed +'nyonh', # 0xee +'nyod', # 0xef +'nyol', # 0xf0 +'nyolg', # 0xf1 +'nyolm', # 0xf2 +'nyolb', # 0xf3 +'nyols', # 0xf4 +'nyolt', # 0xf5 +'nyolp', # 0xf6 +'nyolh', # 0xf7 +'nyom', # 0xf8 +'nyob', # 0xf9 +'nyobs', # 0xfa +'nyos', # 0xfb +'nyoss', # 0xfc +'nyong', # 0xfd +'nyoj', # 0xfe +'nyoc', # 0xff +) diff --git a/nstock/modules/unidecode/x0b2.py b/nstock/modules/unidecode/x0b2.py new file mode 100644 index 0000000..8b8aee4 --- /dev/null +++ b/nstock/modules/unidecode/x0b2.py @@ -0,0 +1,258 @@ +data = ( +'nyok', # 0x00 +'nyot', # 0x01 +'nyop', # 0x02 +'nyoh', # 0x03 +'nu', # 0x04 +'nug', # 0x05 +'nugg', # 0x06 +'nugs', # 0x07 +'nun', # 0x08 +'nunj', # 0x09 +'nunh', # 0x0a +'nud', # 0x0b +'nul', # 0x0c +'nulg', # 0x0d +'nulm', # 0x0e +'nulb', # 0x0f +'nuls', # 0x10 +'nult', # 0x11 +'nulp', # 0x12 +'nulh', # 0x13 +'num', # 0x14 +'nub', # 0x15 +'nubs', # 0x16 +'nus', # 0x17 +'nuss', # 0x18 +'nung', # 0x19 +'nuj', # 0x1a +'nuc', # 0x1b +'nuk', # 0x1c +'nut', # 0x1d +'nup', # 0x1e +'nuh', # 0x1f +'nweo', # 0x20 +'nweog', # 0x21 +'nweogg', # 0x22 +'nweogs', # 0x23 +'nweon', # 0x24 +'nweonj', # 0x25 +'nweonh', # 0x26 +'nweod', # 0x27 +'nweol', # 0x28 +'nweolg', # 0x29 +'nweolm', # 0x2a +'nweolb', # 0x2b +'nweols', # 0x2c +'nweolt', # 0x2d +'nweolp', # 0x2e +'nweolh', # 0x2f +'nweom', # 0x30 +'nweob', # 0x31 +'nweobs', # 0x32 +'nweos', # 0x33 +'nweoss', # 0x34 +'nweong', # 0x35 +'nweoj', # 0x36 +'nweoc', # 0x37 +'nweok', # 0x38 +'nweot', # 0x39 +'nweop', # 0x3a +'nweoh', # 0x3b +'nwe', # 0x3c +'nweg', # 0x3d +'nwegg', # 0x3e +'nwegs', # 0x3f +'nwen', # 0x40 +'nwenj', # 0x41 +'nwenh', # 0x42 +'nwed', # 0x43 +'nwel', # 0x44 +'nwelg', # 0x45 +'nwelm', # 0x46 +'nwelb', # 0x47 +'nwels', # 0x48 +'nwelt', # 0x49 +'nwelp', # 0x4a +'nwelh', # 0x4b +'nwem', # 0x4c +'nweb', # 0x4d +'nwebs', # 0x4e +'nwes', # 0x4f +'nwess', # 0x50 +'nweng', # 0x51 +'nwej', # 0x52 +'nwec', # 0x53 +'nwek', # 0x54 +'nwet', # 0x55 +'nwep', # 0x56 +'nweh', # 0x57 +'nwi', # 0x58 +'nwig', # 0x59 +'nwigg', # 0x5a +'nwigs', # 0x5b +'nwin', # 0x5c +'nwinj', # 0x5d +'nwinh', # 0x5e +'nwid', # 0x5f +'nwil', # 0x60 +'nwilg', # 0x61 +'nwilm', # 0x62 +'nwilb', # 0x63 +'nwils', # 0x64 +'nwilt', # 0x65 +'nwilp', # 0x66 +'nwilh', # 0x67 +'nwim', # 0x68 +'nwib', # 0x69 +'nwibs', # 0x6a +'nwis', # 0x6b +'nwiss', # 0x6c +'nwing', # 0x6d +'nwij', # 0x6e +'nwic', # 0x6f +'nwik', # 0x70 +'nwit', # 0x71 +'nwip', # 0x72 +'nwih', # 0x73 +'nyu', # 0x74 +'nyug', # 0x75 +'nyugg', # 0x76 +'nyugs', # 0x77 +'nyun', # 0x78 +'nyunj', # 0x79 +'nyunh', # 0x7a +'nyud', # 0x7b +'nyul', # 0x7c +'nyulg', # 0x7d +'nyulm', # 0x7e +'nyulb', # 0x7f +'nyuls', # 0x80 +'nyult', # 0x81 +'nyulp', # 0x82 +'nyulh', # 0x83 +'nyum', # 0x84 +'nyub', # 0x85 +'nyubs', # 0x86 +'nyus', # 0x87 +'nyuss', # 0x88 +'nyung', # 0x89 +'nyuj', # 0x8a +'nyuc', # 0x8b +'nyuk', # 0x8c +'nyut', # 0x8d +'nyup', # 0x8e +'nyuh', # 0x8f +'neu', # 0x90 +'neug', # 0x91 +'neugg', # 0x92 +'neugs', # 0x93 +'neun', # 0x94 +'neunj', # 0x95 +'neunh', # 0x96 +'neud', # 0x97 +'neul', # 0x98 +'neulg', # 0x99 +'neulm', # 0x9a +'neulb', # 0x9b +'neuls', # 0x9c +'neult', # 0x9d +'neulp', # 0x9e +'neulh', # 0x9f +'neum', # 0xa0 +'neub', # 0xa1 +'neubs', # 0xa2 +'neus', # 0xa3 +'neuss', # 0xa4 +'neung', # 0xa5 +'neuj', # 0xa6 +'neuc', # 0xa7 +'neuk', # 0xa8 +'neut', # 0xa9 +'neup', # 0xaa +'neuh', # 0xab +'nyi', # 0xac +'nyig', # 0xad +'nyigg', # 0xae +'nyigs', # 0xaf +'nyin', # 0xb0 +'nyinj', # 0xb1 +'nyinh', # 0xb2 +'nyid', # 0xb3 +'nyil', # 0xb4 +'nyilg', # 0xb5 +'nyilm', # 0xb6 +'nyilb', # 0xb7 +'nyils', # 0xb8 +'nyilt', # 0xb9 +'nyilp', # 0xba +'nyilh', # 0xbb +'nyim', # 0xbc +'nyib', # 0xbd +'nyibs', # 0xbe +'nyis', # 0xbf +'nyiss', # 0xc0 +'nying', # 0xc1 +'nyij', # 0xc2 +'nyic', # 0xc3 +'nyik', # 0xc4 +'nyit', # 0xc5 +'nyip', # 0xc6 +'nyih', # 0xc7 +'ni', # 0xc8 +'nig', # 0xc9 +'nigg', # 0xca +'nigs', # 0xcb +'nin', # 0xcc +'ninj', # 0xcd +'ninh', # 0xce +'nid', # 0xcf +'nil', # 0xd0 +'nilg', # 0xd1 +'nilm', # 0xd2 +'nilb', # 0xd3 +'nils', # 0xd4 +'nilt', # 0xd5 +'nilp', # 0xd6 +'nilh', # 0xd7 +'nim', # 0xd8 +'nib', # 0xd9 +'nibs', # 0xda +'nis', # 0xdb +'niss', # 0xdc +'ning', # 0xdd +'nij', # 0xde +'nic', # 0xdf +'nik', # 0xe0 +'nit', # 0xe1 +'nip', # 0xe2 +'nih', # 0xe3 +'da', # 0xe4 +'dag', # 0xe5 +'dagg', # 0xe6 +'dags', # 0xe7 +'dan', # 0xe8 +'danj', # 0xe9 +'danh', # 0xea +'dad', # 0xeb +'dal', # 0xec +'dalg', # 0xed +'dalm', # 0xee +'dalb', # 0xef +'dals', # 0xf0 +'dalt', # 0xf1 +'dalp', # 0xf2 +'dalh', # 0xf3 +'dam', # 0xf4 +'dab', # 0xf5 +'dabs', # 0xf6 +'das', # 0xf7 +'dass', # 0xf8 +'dang', # 0xf9 +'daj', # 0xfa +'dac', # 0xfb +'dak', # 0xfc +'dat', # 0xfd +'dap', # 0xfe +'dah', # 0xff +) diff --git a/nstock/modules/unidecode/x0b3.py b/nstock/modules/unidecode/x0b3.py new file mode 100644 index 0000000..830915a --- /dev/null +++ b/nstock/modules/unidecode/x0b3.py @@ -0,0 +1,258 @@ +data = ( +'dae', # 0x00 +'daeg', # 0x01 +'daegg', # 0x02 +'daegs', # 0x03 +'daen', # 0x04 +'daenj', # 0x05 +'daenh', # 0x06 +'daed', # 0x07 +'dael', # 0x08 +'daelg', # 0x09 +'daelm', # 0x0a +'daelb', # 0x0b +'daels', # 0x0c +'daelt', # 0x0d +'daelp', # 0x0e +'daelh', # 0x0f +'daem', # 0x10 +'daeb', # 0x11 +'daebs', # 0x12 +'daes', # 0x13 +'daess', # 0x14 +'daeng', # 0x15 +'daej', # 0x16 +'daec', # 0x17 +'daek', # 0x18 +'daet', # 0x19 +'daep', # 0x1a +'daeh', # 0x1b +'dya', # 0x1c +'dyag', # 0x1d +'dyagg', # 0x1e +'dyags', # 0x1f +'dyan', # 0x20 +'dyanj', # 0x21 +'dyanh', # 0x22 +'dyad', # 0x23 +'dyal', # 0x24 +'dyalg', # 0x25 +'dyalm', # 0x26 +'dyalb', # 0x27 +'dyals', # 0x28 +'dyalt', # 0x29 +'dyalp', # 0x2a +'dyalh', # 0x2b +'dyam', # 0x2c +'dyab', # 0x2d +'dyabs', # 0x2e +'dyas', # 0x2f +'dyass', # 0x30 +'dyang', # 0x31 +'dyaj', # 0x32 +'dyac', # 0x33 +'dyak', # 0x34 +'dyat', # 0x35 +'dyap', # 0x36 +'dyah', # 0x37 +'dyae', # 0x38 +'dyaeg', # 0x39 +'dyaegg', # 0x3a +'dyaegs', # 0x3b +'dyaen', # 0x3c +'dyaenj', # 0x3d +'dyaenh', # 0x3e +'dyaed', # 0x3f +'dyael', # 0x40 +'dyaelg', # 0x41 +'dyaelm', # 0x42 +'dyaelb', # 0x43 +'dyaels', # 0x44 +'dyaelt', # 0x45 +'dyaelp', # 0x46 +'dyaelh', # 0x47 +'dyaem', # 0x48 +'dyaeb', # 0x49 +'dyaebs', # 0x4a +'dyaes', # 0x4b +'dyaess', # 0x4c +'dyaeng', # 0x4d +'dyaej', # 0x4e +'dyaec', # 0x4f +'dyaek', # 0x50 +'dyaet', # 0x51 +'dyaep', # 0x52 +'dyaeh', # 0x53 +'deo', # 0x54 +'deog', # 0x55 +'deogg', # 0x56 +'deogs', # 0x57 +'deon', # 0x58 +'deonj', # 0x59 +'deonh', # 0x5a +'deod', # 0x5b +'deol', # 0x5c +'deolg', # 0x5d +'deolm', # 0x5e +'deolb', # 0x5f +'deols', # 0x60 +'deolt', # 0x61 +'deolp', # 0x62 +'deolh', # 0x63 +'deom', # 0x64 +'deob', # 0x65 +'deobs', # 0x66 +'deos', # 0x67 +'deoss', # 0x68 +'deong', # 0x69 +'deoj', # 0x6a +'deoc', # 0x6b +'deok', # 0x6c +'deot', # 0x6d +'deop', # 0x6e +'deoh', # 0x6f +'de', # 0x70 +'deg', # 0x71 +'degg', # 0x72 +'degs', # 0x73 +'den', # 0x74 +'denj', # 0x75 +'denh', # 0x76 +'ded', # 0x77 +'del', # 0x78 +'delg', # 0x79 +'delm', # 0x7a +'delb', # 0x7b +'dels', # 0x7c +'delt', # 0x7d +'delp', # 0x7e +'delh', # 0x7f +'dem', # 0x80 +'deb', # 0x81 +'debs', # 0x82 +'des', # 0x83 +'dess', # 0x84 +'deng', # 0x85 +'dej', # 0x86 +'dec', # 0x87 +'dek', # 0x88 +'det', # 0x89 +'dep', # 0x8a +'deh', # 0x8b +'dyeo', # 0x8c +'dyeog', # 0x8d +'dyeogg', # 0x8e +'dyeogs', # 0x8f +'dyeon', # 0x90 +'dyeonj', # 0x91 +'dyeonh', # 0x92 +'dyeod', # 0x93 +'dyeol', # 0x94 +'dyeolg', # 0x95 +'dyeolm', # 0x96 +'dyeolb', # 0x97 +'dyeols', # 0x98 +'dyeolt', # 0x99 +'dyeolp', # 0x9a +'dyeolh', # 0x9b +'dyeom', # 0x9c +'dyeob', # 0x9d +'dyeobs', # 0x9e +'dyeos', # 0x9f +'dyeoss', # 0xa0 +'dyeong', # 0xa1 +'dyeoj', # 0xa2 +'dyeoc', # 0xa3 +'dyeok', # 0xa4 +'dyeot', # 0xa5 +'dyeop', # 0xa6 +'dyeoh', # 0xa7 +'dye', # 0xa8 +'dyeg', # 0xa9 +'dyegg', # 0xaa +'dyegs', # 0xab +'dyen', # 0xac +'dyenj', # 0xad +'dyenh', # 0xae +'dyed', # 0xaf +'dyel', # 0xb0 +'dyelg', # 0xb1 +'dyelm', # 0xb2 +'dyelb', # 0xb3 +'dyels', # 0xb4 +'dyelt', # 0xb5 +'dyelp', # 0xb6 +'dyelh', # 0xb7 +'dyem', # 0xb8 +'dyeb', # 0xb9 +'dyebs', # 0xba +'dyes', # 0xbb +'dyess', # 0xbc +'dyeng', # 0xbd +'dyej', # 0xbe +'dyec', # 0xbf +'dyek', # 0xc0 +'dyet', # 0xc1 +'dyep', # 0xc2 +'dyeh', # 0xc3 +'do', # 0xc4 +'dog', # 0xc5 +'dogg', # 0xc6 +'dogs', # 0xc7 +'don', # 0xc8 +'donj', # 0xc9 +'donh', # 0xca +'dod', # 0xcb +'dol', # 0xcc +'dolg', # 0xcd +'dolm', # 0xce +'dolb', # 0xcf +'dols', # 0xd0 +'dolt', # 0xd1 +'dolp', # 0xd2 +'dolh', # 0xd3 +'dom', # 0xd4 +'dob', # 0xd5 +'dobs', # 0xd6 +'dos', # 0xd7 +'doss', # 0xd8 +'dong', # 0xd9 +'doj', # 0xda +'doc', # 0xdb +'dok', # 0xdc +'dot', # 0xdd +'dop', # 0xde +'doh', # 0xdf +'dwa', # 0xe0 +'dwag', # 0xe1 +'dwagg', # 0xe2 +'dwags', # 0xe3 +'dwan', # 0xe4 +'dwanj', # 0xe5 +'dwanh', # 0xe6 +'dwad', # 0xe7 +'dwal', # 0xe8 +'dwalg', # 0xe9 +'dwalm', # 0xea +'dwalb', # 0xeb +'dwals', # 0xec +'dwalt', # 0xed +'dwalp', # 0xee +'dwalh', # 0xef +'dwam', # 0xf0 +'dwab', # 0xf1 +'dwabs', # 0xf2 +'dwas', # 0xf3 +'dwass', # 0xf4 +'dwang', # 0xf5 +'dwaj', # 0xf6 +'dwac', # 0xf7 +'dwak', # 0xf8 +'dwat', # 0xf9 +'dwap', # 0xfa +'dwah', # 0xfb +'dwae', # 0xfc +'dwaeg', # 0xfd +'dwaegg', # 0xfe +'dwaegs', # 0xff +) diff --git a/nstock/modules/unidecode/x0b4.py b/nstock/modules/unidecode/x0b4.py new file mode 100644 index 0000000..7a6a5aa --- /dev/null +++ b/nstock/modules/unidecode/x0b4.py @@ -0,0 +1,258 @@ +data = ( +'dwaen', # 0x00 +'dwaenj', # 0x01 +'dwaenh', # 0x02 +'dwaed', # 0x03 +'dwael', # 0x04 +'dwaelg', # 0x05 +'dwaelm', # 0x06 +'dwaelb', # 0x07 +'dwaels', # 0x08 +'dwaelt', # 0x09 +'dwaelp', # 0x0a +'dwaelh', # 0x0b +'dwaem', # 0x0c +'dwaeb', # 0x0d +'dwaebs', # 0x0e +'dwaes', # 0x0f +'dwaess', # 0x10 +'dwaeng', # 0x11 +'dwaej', # 0x12 +'dwaec', # 0x13 +'dwaek', # 0x14 +'dwaet', # 0x15 +'dwaep', # 0x16 +'dwaeh', # 0x17 +'doe', # 0x18 +'doeg', # 0x19 +'doegg', # 0x1a +'doegs', # 0x1b +'doen', # 0x1c +'doenj', # 0x1d +'doenh', # 0x1e +'doed', # 0x1f +'doel', # 0x20 +'doelg', # 0x21 +'doelm', # 0x22 +'doelb', # 0x23 +'doels', # 0x24 +'doelt', # 0x25 +'doelp', # 0x26 +'doelh', # 0x27 +'doem', # 0x28 +'doeb', # 0x29 +'doebs', # 0x2a +'does', # 0x2b +'doess', # 0x2c +'doeng', # 0x2d +'doej', # 0x2e +'doec', # 0x2f +'doek', # 0x30 +'doet', # 0x31 +'doep', # 0x32 +'doeh', # 0x33 +'dyo', # 0x34 +'dyog', # 0x35 +'dyogg', # 0x36 +'dyogs', # 0x37 +'dyon', # 0x38 +'dyonj', # 0x39 +'dyonh', # 0x3a +'dyod', # 0x3b +'dyol', # 0x3c +'dyolg', # 0x3d +'dyolm', # 0x3e +'dyolb', # 0x3f +'dyols', # 0x40 +'dyolt', # 0x41 +'dyolp', # 0x42 +'dyolh', # 0x43 +'dyom', # 0x44 +'dyob', # 0x45 +'dyobs', # 0x46 +'dyos', # 0x47 +'dyoss', # 0x48 +'dyong', # 0x49 +'dyoj', # 0x4a +'dyoc', # 0x4b +'dyok', # 0x4c +'dyot', # 0x4d +'dyop', # 0x4e +'dyoh', # 0x4f +'du', # 0x50 +'dug', # 0x51 +'dugg', # 0x52 +'dugs', # 0x53 +'dun', # 0x54 +'dunj', # 0x55 +'dunh', # 0x56 +'dud', # 0x57 +'dul', # 0x58 +'dulg', # 0x59 +'dulm', # 0x5a +'dulb', # 0x5b +'duls', # 0x5c +'dult', # 0x5d +'dulp', # 0x5e +'dulh', # 0x5f +'dum', # 0x60 +'dub', # 0x61 +'dubs', # 0x62 +'dus', # 0x63 +'duss', # 0x64 +'dung', # 0x65 +'duj', # 0x66 +'duc', # 0x67 +'duk', # 0x68 +'dut', # 0x69 +'dup', # 0x6a +'duh', # 0x6b +'dweo', # 0x6c +'dweog', # 0x6d +'dweogg', # 0x6e +'dweogs', # 0x6f +'dweon', # 0x70 +'dweonj', # 0x71 +'dweonh', # 0x72 +'dweod', # 0x73 +'dweol', # 0x74 +'dweolg', # 0x75 +'dweolm', # 0x76 +'dweolb', # 0x77 +'dweols', # 0x78 +'dweolt', # 0x79 +'dweolp', # 0x7a +'dweolh', # 0x7b +'dweom', # 0x7c +'dweob', # 0x7d +'dweobs', # 0x7e +'dweos', # 0x7f +'dweoss', # 0x80 +'dweong', # 0x81 +'dweoj', # 0x82 +'dweoc', # 0x83 +'dweok', # 0x84 +'dweot', # 0x85 +'dweop', # 0x86 +'dweoh', # 0x87 +'dwe', # 0x88 +'dweg', # 0x89 +'dwegg', # 0x8a +'dwegs', # 0x8b +'dwen', # 0x8c +'dwenj', # 0x8d +'dwenh', # 0x8e +'dwed', # 0x8f +'dwel', # 0x90 +'dwelg', # 0x91 +'dwelm', # 0x92 +'dwelb', # 0x93 +'dwels', # 0x94 +'dwelt', # 0x95 +'dwelp', # 0x96 +'dwelh', # 0x97 +'dwem', # 0x98 +'dweb', # 0x99 +'dwebs', # 0x9a +'dwes', # 0x9b +'dwess', # 0x9c +'dweng', # 0x9d +'dwej', # 0x9e +'dwec', # 0x9f +'dwek', # 0xa0 +'dwet', # 0xa1 +'dwep', # 0xa2 +'dweh', # 0xa3 +'dwi', # 0xa4 +'dwig', # 0xa5 +'dwigg', # 0xa6 +'dwigs', # 0xa7 +'dwin', # 0xa8 +'dwinj', # 0xa9 +'dwinh', # 0xaa +'dwid', # 0xab +'dwil', # 0xac +'dwilg', # 0xad +'dwilm', # 0xae +'dwilb', # 0xaf +'dwils', # 0xb0 +'dwilt', # 0xb1 +'dwilp', # 0xb2 +'dwilh', # 0xb3 +'dwim', # 0xb4 +'dwib', # 0xb5 +'dwibs', # 0xb6 +'dwis', # 0xb7 +'dwiss', # 0xb8 +'dwing', # 0xb9 +'dwij', # 0xba +'dwic', # 0xbb +'dwik', # 0xbc +'dwit', # 0xbd +'dwip', # 0xbe +'dwih', # 0xbf +'dyu', # 0xc0 +'dyug', # 0xc1 +'dyugg', # 0xc2 +'dyugs', # 0xc3 +'dyun', # 0xc4 +'dyunj', # 0xc5 +'dyunh', # 0xc6 +'dyud', # 0xc7 +'dyul', # 0xc8 +'dyulg', # 0xc9 +'dyulm', # 0xca +'dyulb', # 0xcb +'dyuls', # 0xcc +'dyult', # 0xcd +'dyulp', # 0xce +'dyulh', # 0xcf +'dyum', # 0xd0 +'dyub', # 0xd1 +'dyubs', # 0xd2 +'dyus', # 0xd3 +'dyuss', # 0xd4 +'dyung', # 0xd5 +'dyuj', # 0xd6 +'dyuc', # 0xd7 +'dyuk', # 0xd8 +'dyut', # 0xd9 +'dyup', # 0xda +'dyuh', # 0xdb +'deu', # 0xdc +'deug', # 0xdd +'deugg', # 0xde +'deugs', # 0xdf +'deun', # 0xe0 +'deunj', # 0xe1 +'deunh', # 0xe2 +'deud', # 0xe3 +'deul', # 0xe4 +'deulg', # 0xe5 +'deulm', # 0xe6 +'deulb', # 0xe7 +'deuls', # 0xe8 +'deult', # 0xe9 +'deulp', # 0xea +'deulh', # 0xeb +'deum', # 0xec +'deub', # 0xed +'deubs', # 0xee +'deus', # 0xef +'deuss', # 0xf0 +'deung', # 0xf1 +'deuj', # 0xf2 +'deuc', # 0xf3 +'deuk', # 0xf4 +'deut', # 0xf5 +'deup', # 0xf6 +'deuh', # 0xf7 +'dyi', # 0xf8 +'dyig', # 0xf9 +'dyigg', # 0xfa +'dyigs', # 0xfb +'dyin', # 0xfc +'dyinj', # 0xfd +'dyinh', # 0xfe +'dyid', # 0xff +) diff --git a/nstock/modules/unidecode/x0b5.py b/nstock/modules/unidecode/x0b5.py new file mode 100644 index 0000000..9d4de3d --- /dev/null +++ b/nstock/modules/unidecode/x0b5.py @@ -0,0 +1,258 @@ +data = ( +'dyil', # 0x00 +'dyilg', # 0x01 +'dyilm', # 0x02 +'dyilb', # 0x03 +'dyils', # 0x04 +'dyilt', # 0x05 +'dyilp', # 0x06 +'dyilh', # 0x07 +'dyim', # 0x08 +'dyib', # 0x09 +'dyibs', # 0x0a +'dyis', # 0x0b +'dyiss', # 0x0c +'dying', # 0x0d +'dyij', # 0x0e +'dyic', # 0x0f +'dyik', # 0x10 +'dyit', # 0x11 +'dyip', # 0x12 +'dyih', # 0x13 +'di', # 0x14 +'dig', # 0x15 +'digg', # 0x16 +'digs', # 0x17 +'din', # 0x18 +'dinj', # 0x19 +'dinh', # 0x1a +'did', # 0x1b +'dil', # 0x1c +'dilg', # 0x1d +'dilm', # 0x1e +'dilb', # 0x1f +'dils', # 0x20 +'dilt', # 0x21 +'dilp', # 0x22 +'dilh', # 0x23 +'dim', # 0x24 +'dib', # 0x25 +'dibs', # 0x26 +'dis', # 0x27 +'diss', # 0x28 +'ding', # 0x29 +'dij', # 0x2a +'dic', # 0x2b +'dik', # 0x2c +'dit', # 0x2d +'dip', # 0x2e +'dih', # 0x2f +'dda', # 0x30 +'ddag', # 0x31 +'ddagg', # 0x32 +'ddags', # 0x33 +'ddan', # 0x34 +'ddanj', # 0x35 +'ddanh', # 0x36 +'ddad', # 0x37 +'ddal', # 0x38 +'ddalg', # 0x39 +'ddalm', # 0x3a +'ddalb', # 0x3b +'ddals', # 0x3c +'ddalt', # 0x3d +'ddalp', # 0x3e +'ddalh', # 0x3f +'ddam', # 0x40 +'ddab', # 0x41 +'ddabs', # 0x42 +'ddas', # 0x43 +'ddass', # 0x44 +'ddang', # 0x45 +'ddaj', # 0x46 +'ddac', # 0x47 +'ddak', # 0x48 +'ddat', # 0x49 +'ddap', # 0x4a +'ddah', # 0x4b +'ddae', # 0x4c +'ddaeg', # 0x4d +'ddaegg', # 0x4e +'ddaegs', # 0x4f +'ddaen', # 0x50 +'ddaenj', # 0x51 +'ddaenh', # 0x52 +'ddaed', # 0x53 +'ddael', # 0x54 +'ddaelg', # 0x55 +'ddaelm', # 0x56 +'ddaelb', # 0x57 +'ddaels', # 0x58 +'ddaelt', # 0x59 +'ddaelp', # 0x5a +'ddaelh', # 0x5b +'ddaem', # 0x5c +'ddaeb', # 0x5d +'ddaebs', # 0x5e +'ddaes', # 0x5f +'ddaess', # 0x60 +'ddaeng', # 0x61 +'ddaej', # 0x62 +'ddaec', # 0x63 +'ddaek', # 0x64 +'ddaet', # 0x65 +'ddaep', # 0x66 +'ddaeh', # 0x67 +'ddya', # 0x68 +'ddyag', # 0x69 +'ddyagg', # 0x6a +'ddyags', # 0x6b +'ddyan', # 0x6c +'ddyanj', # 0x6d +'ddyanh', # 0x6e +'ddyad', # 0x6f +'ddyal', # 0x70 +'ddyalg', # 0x71 +'ddyalm', # 0x72 +'ddyalb', # 0x73 +'ddyals', # 0x74 +'ddyalt', # 0x75 +'ddyalp', # 0x76 +'ddyalh', # 0x77 +'ddyam', # 0x78 +'ddyab', # 0x79 +'ddyabs', # 0x7a +'ddyas', # 0x7b +'ddyass', # 0x7c +'ddyang', # 0x7d +'ddyaj', # 0x7e +'ddyac', # 0x7f +'ddyak', # 0x80 +'ddyat', # 0x81 +'ddyap', # 0x82 +'ddyah', # 0x83 +'ddyae', # 0x84 +'ddyaeg', # 0x85 +'ddyaegg', # 0x86 +'ddyaegs', # 0x87 +'ddyaen', # 0x88 +'ddyaenj', # 0x89 +'ddyaenh', # 0x8a +'ddyaed', # 0x8b +'ddyael', # 0x8c +'ddyaelg', # 0x8d +'ddyaelm', # 0x8e +'ddyaelb', # 0x8f +'ddyaels', # 0x90 +'ddyaelt', # 0x91 +'ddyaelp', # 0x92 +'ddyaelh', # 0x93 +'ddyaem', # 0x94 +'ddyaeb', # 0x95 +'ddyaebs', # 0x96 +'ddyaes', # 0x97 +'ddyaess', # 0x98 +'ddyaeng', # 0x99 +'ddyaej', # 0x9a +'ddyaec', # 0x9b +'ddyaek', # 0x9c +'ddyaet', # 0x9d +'ddyaep', # 0x9e +'ddyaeh', # 0x9f +'ddeo', # 0xa0 +'ddeog', # 0xa1 +'ddeogg', # 0xa2 +'ddeogs', # 0xa3 +'ddeon', # 0xa4 +'ddeonj', # 0xa5 +'ddeonh', # 0xa6 +'ddeod', # 0xa7 +'ddeol', # 0xa8 +'ddeolg', # 0xa9 +'ddeolm', # 0xaa +'ddeolb', # 0xab +'ddeols', # 0xac +'ddeolt', # 0xad +'ddeolp', # 0xae +'ddeolh', # 0xaf +'ddeom', # 0xb0 +'ddeob', # 0xb1 +'ddeobs', # 0xb2 +'ddeos', # 0xb3 +'ddeoss', # 0xb4 +'ddeong', # 0xb5 +'ddeoj', # 0xb6 +'ddeoc', # 0xb7 +'ddeok', # 0xb8 +'ddeot', # 0xb9 +'ddeop', # 0xba +'ddeoh', # 0xbb +'dde', # 0xbc +'ddeg', # 0xbd +'ddegg', # 0xbe +'ddegs', # 0xbf +'dden', # 0xc0 +'ddenj', # 0xc1 +'ddenh', # 0xc2 +'dded', # 0xc3 +'ddel', # 0xc4 +'ddelg', # 0xc5 +'ddelm', # 0xc6 +'ddelb', # 0xc7 +'ddels', # 0xc8 +'ddelt', # 0xc9 +'ddelp', # 0xca +'ddelh', # 0xcb +'ddem', # 0xcc +'ddeb', # 0xcd +'ddebs', # 0xce +'ddes', # 0xcf +'ddess', # 0xd0 +'ddeng', # 0xd1 +'ddej', # 0xd2 +'ddec', # 0xd3 +'ddek', # 0xd4 +'ddet', # 0xd5 +'ddep', # 0xd6 +'ddeh', # 0xd7 +'ddyeo', # 0xd8 +'ddyeog', # 0xd9 +'ddyeogg', # 0xda +'ddyeogs', # 0xdb +'ddyeon', # 0xdc +'ddyeonj', # 0xdd +'ddyeonh', # 0xde +'ddyeod', # 0xdf +'ddyeol', # 0xe0 +'ddyeolg', # 0xe1 +'ddyeolm', # 0xe2 +'ddyeolb', # 0xe3 +'ddyeols', # 0xe4 +'ddyeolt', # 0xe5 +'ddyeolp', # 0xe6 +'ddyeolh', # 0xe7 +'ddyeom', # 0xe8 +'ddyeob', # 0xe9 +'ddyeobs', # 0xea +'ddyeos', # 0xeb +'ddyeoss', # 0xec +'ddyeong', # 0xed +'ddyeoj', # 0xee +'ddyeoc', # 0xef +'ddyeok', # 0xf0 +'ddyeot', # 0xf1 +'ddyeop', # 0xf2 +'ddyeoh', # 0xf3 +'ddye', # 0xf4 +'ddyeg', # 0xf5 +'ddyegg', # 0xf6 +'ddyegs', # 0xf7 +'ddyen', # 0xf8 +'ddyenj', # 0xf9 +'ddyenh', # 0xfa +'ddyed', # 0xfb +'ddyel', # 0xfc +'ddyelg', # 0xfd +'ddyelm', # 0xfe +'ddyelb', # 0xff +) diff --git a/nstock/modules/unidecode/x0b6.py b/nstock/modules/unidecode/x0b6.py new file mode 100644 index 0000000..2800e3b --- /dev/null +++ b/nstock/modules/unidecode/x0b6.py @@ -0,0 +1,258 @@ +data = ( +'ddyels', # 0x00 +'ddyelt', # 0x01 +'ddyelp', # 0x02 +'ddyelh', # 0x03 +'ddyem', # 0x04 +'ddyeb', # 0x05 +'ddyebs', # 0x06 +'ddyes', # 0x07 +'ddyess', # 0x08 +'ddyeng', # 0x09 +'ddyej', # 0x0a +'ddyec', # 0x0b +'ddyek', # 0x0c +'ddyet', # 0x0d +'ddyep', # 0x0e +'ddyeh', # 0x0f +'ddo', # 0x10 +'ddog', # 0x11 +'ddogg', # 0x12 +'ddogs', # 0x13 +'ddon', # 0x14 +'ddonj', # 0x15 +'ddonh', # 0x16 +'ddod', # 0x17 +'ddol', # 0x18 +'ddolg', # 0x19 +'ddolm', # 0x1a +'ddolb', # 0x1b +'ddols', # 0x1c +'ddolt', # 0x1d +'ddolp', # 0x1e +'ddolh', # 0x1f +'ddom', # 0x20 +'ddob', # 0x21 +'ddobs', # 0x22 +'ddos', # 0x23 +'ddoss', # 0x24 +'ddong', # 0x25 +'ddoj', # 0x26 +'ddoc', # 0x27 +'ddok', # 0x28 +'ddot', # 0x29 +'ddop', # 0x2a +'ddoh', # 0x2b +'ddwa', # 0x2c +'ddwag', # 0x2d +'ddwagg', # 0x2e +'ddwags', # 0x2f +'ddwan', # 0x30 +'ddwanj', # 0x31 +'ddwanh', # 0x32 +'ddwad', # 0x33 +'ddwal', # 0x34 +'ddwalg', # 0x35 +'ddwalm', # 0x36 +'ddwalb', # 0x37 +'ddwals', # 0x38 +'ddwalt', # 0x39 +'ddwalp', # 0x3a +'ddwalh', # 0x3b +'ddwam', # 0x3c +'ddwab', # 0x3d +'ddwabs', # 0x3e +'ddwas', # 0x3f +'ddwass', # 0x40 +'ddwang', # 0x41 +'ddwaj', # 0x42 +'ddwac', # 0x43 +'ddwak', # 0x44 +'ddwat', # 0x45 +'ddwap', # 0x46 +'ddwah', # 0x47 +'ddwae', # 0x48 +'ddwaeg', # 0x49 +'ddwaegg', # 0x4a +'ddwaegs', # 0x4b +'ddwaen', # 0x4c +'ddwaenj', # 0x4d +'ddwaenh', # 0x4e +'ddwaed', # 0x4f +'ddwael', # 0x50 +'ddwaelg', # 0x51 +'ddwaelm', # 0x52 +'ddwaelb', # 0x53 +'ddwaels', # 0x54 +'ddwaelt', # 0x55 +'ddwaelp', # 0x56 +'ddwaelh', # 0x57 +'ddwaem', # 0x58 +'ddwaeb', # 0x59 +'ddwaebs', # 0x5a +'ddwaes', # 0x5b +'ddwaess', # 0x5c +'ddwaeng', # 0x5d +'ddwaej', # 0x5e +'ddwaec', # 0x5f +'ddwaek', # 0x60 +'ddwaet', # 0x61 +'ddwaep', # 0x62 +'ddwaeh', # 0x63 +'ddoe', # 0x64 +'ddoeg', # 0x65 +'ddoegg', # 0x66 +'ddoegs', # 0x67 +'ddoen', # 0x68 +'ddoenj', # 0x69 +'ddoenh', # 0x6a +'ddoed', # 0x6b +'ddoel', # 0x6c +'ddoelg', # 0x6d +'ddoelm', # 0x6e +'ddoelb', # 0x6f +'ddoels', # 0x70 +'ddoelt', # 0x71 +'ddoelp', # 0x72 +'ddoelh', # 0x73 +'ddoem', # 0x74 +'ddoeb', # 0x75 +'ddoebs', # 0x76 +'ddoes', # 0x77 +'ddoess', # 0x78 +'ddoeng', # 0x79 +'ddoej', # 0x7a +'ddoec', # 0x7b +'ddoek', # 0x7c +'ddoet', # 0x7d +'ddoep', # 0x7e +'ddoeh', # 0x7f +'ddyo', # 0x80 +'ddyog', # 0x81 +'ddyogg', # 0x82 +'ddyogs', # 0x83 +'ddyon', # 0x84 +'ddyonj', # 0x85 +'ddyonh', # 0x86 +'ddyod', # 0x87 +'ddyol', # 0x88 +'ddyolg', # 0x89 +'ddyolm', # 0x8a +'ddyolb', # 0x8b +'ddyols', # 0x8c +'ddyolt', # 0x8d +'ddyolp', # 0x8e +'ddyolh', # 0x8f +'ddyom', # 0x90 +'ddyob', # 0x91 +'ddyobs', # 0x92 +'ddyos', # 0x93 +'ddyoss', # 0x94 +'ddyong', # 0x95 +'ddyoj', # 0x96 +'ddyoc', # 0x97 +'ddyok', # 0x98 +'ddyot', # 0x99 +'ddyop', # 0x9a +'ddyoh', # 0x9b +'ddu', # 0x9c +'ddug', # 0x9d +'ddugg', # 0x9e +'ddugs', # 0x9f +'ddun', # 0xa0 +'ddunj', # 0xa1 +'ddunh', # 0xa2 +'ddud', # 0xa3 +'ddul', # 0xa4 +'ddulg', # 0xa5 +'ddulm', # 0xa6 +'ddulb', # 0xa7 +'dduls', # 0xa8 +'ddult', # 0xa9 +'ddulp', # 0xaa +'ddulh', # 0xab +'ddum', # 0xac +'ddub', # 0xad +'ddubs', # 0xae +'ddus', # 0xaf +'dduss', # 0xb0 +'ddung', # 0xb1 +'dduj', # 0xb2 +'dduc', # 0xb3 +'dduk', # 0xb4 +'ddut', # 0xb5 +'ddup', # 0xb6 +'dduh', # 0xb7 +'ddweo', # 0xb8 +'ddweog', # 0xb9 +'ddweogg', # 0xba +'ddweogs', # 0xbb +'ddweon', # 0xbc +'ddweonj', # 0xbd +'ddweonh', # 0xbe +'ddweod', # 0xbf +'ddweol', # 0xc0 +'ddweolg', # 0xc1 +'ddweolm', # 0xc2 +'ddweolb', # 0xc3 +'ddweols', # 0xc4 +'ddweolt', # 0xc5 +'ddweolp', # 0xc6 +'ddweolh', # 0xc7 +'ddweom', # 0xc8 +'ddweob', # 0xc9 +'ddweobs', # 0xca +'ddweos', # 0xcb +'ddweoss', # 0xcc +'ddweong', # 0xcd +'ddweoj', # 0xce +'ddweoc', # 0xcf +'ddweok', # 0xd0 +'ddweot', # 0xd1 +'ddweop', # 0xd2 +'ddweoh', # 0xd3 +'ddwe', # 0xd4 +'ddweg', # 0xd5 +'ddwegg', # 0xd6 +'ddwegs', # 0xd7 +'ddwen', # 0xd8 +'ddwenj', # 0xd9 +'ddwenh', # 0xda +'ddwed', # 0xdb +'ddwel', # 0xdc +'ddwelg', # 0xdd +'ddwelm', # 0xde +'ddwelb', # 0xdf +'ddwels', # 0xe0 +'ddwelt', # 0xe1 +'ddwelp', # 0xe2 +'ddwelh', # 0xe3 +'ddwem', # 0xe4 +'ddweb', # 0xe5 +'ddwebs', # 0xe6 +'ddwes', # 0xe7 +'ddwess', # 0xe8 +'ddweng', # 0xe9 +'ddwej', # 0xea +'ddwec', # 0xeb +'ddwek', # 0xec +'ddwet', # 0xed +'ddwep', # 0xee +'ddweh', # 0xef +'ddwi', # 0xf0 +'ddwig', # 0xf1 +'ddwigg', # 0xf2 +'ddwigs', # 0xf3 +'ddwin', # 0xf4 +'ddwinj', # 0xf5 +'ddwinh', # 0xf6 +'ddwid', # 0xf7 +'ddwil', # 0xf8 +'ddwilg', # 0xf9 +'ddwilm', # 0xfa +'ddwilb', # 0xfb +'ddwils', # 0xfc +'ddwilt', # 0xfd +'ddwilp', # 0xfe +'ddwilh', # 0xff +) diff --git a/nstock/modules/unidecode/x0b7.py b/nstock/modules/unidecode/x0b7.py new file mode 100644 index 0000000..483ddde --- /dev/null +++ b/nstock/modules/unidecode/x0b7.py @@ -0,0 +1,258 @@ +data = ( +'ddwim', # 0x00 +'ddwib', # 0x01 +'ddwibs', # 0x02 +'ddwis', # 0x03 +'ddwiss', # 0x04 +'ddwing', # 0x05 +'ddwij', # 0x06 +'ddwic', # 0x07 +'ddwik', # 0x08 +'ddwit', # 0x09 +'ddwip', # 0x0a +'ddwih', # 0x0b +'ddyu', # 0x0c +'ddyug', # 0x0d +'ddyugg', # 0x0e +'ddyugs', # 0x0f +'ddyun', # 0x10 +'ddyunj', # 0x11 +'ddyunh', # 0x12 +'ddyud', # 0x13 +'ddyul', # 0x14 +'ddyulg', # 0x15 +'ddyulm', # 0x16 +'ddyulb', # 0x17 +'ddyuls', # 0x18 +'ddyult', # 0x19 +'ddyulp', # 0x1a +'ddyulh', # 0x1b +'ddyum', # 0x1c +'ddyub', # 0x1d +'ddyubs', # 0x1e +'ddyus', # 0x1f +'ddyuss', # 0x20 +'ddyung', # 0x21 +'ddyuj', # 0x22 +'ddyuc', # 0x23 +'ddyuk', # 0x24 +'ddyut', # 0x25 +'ddyup', # 0x26 +'ddyuh', # 0x27 +'ddeu', # 0x28 +'ddeug', # 0x29 +'ddeugg', # 0x2a +'ddeugs', # 0x2b +'ddeun', # 0x2c +'ddeunj', # 0x2d +'ddeunh', # 0x2e +'ddeud', # 0x2f +'ddeul', # 0x30 +'ddeulg', # 0x31 +'ddeulm', # 0x32 +'ddeulb', # 0x33 +'ddeuls', # 0x34 +'ddeult', # 0x35 +'ddeulp', # 0x36 +'ddeulh', # 0x37 +'ddeum', # 0x38 +'ddeub', # 0x39 +'ddeubs', # 0x3a +'ddeus', # 0x3b +'ddeuss', # 0x3c +'ddeung', # 0x3d +'ddeuj', # 0x3e +'ddeuc', # 0x3f +'ddeuk', # 0x40 +'ddeut', # 0x41 +'ddeup', # 0x42 +'ddeuh', # 0x43 +'ddyi', # 0x44 +'ddyig', # 0x45 +'ddyigg', # 0x46 +'ddyigs', # 0x47 +'ddyin', # 0x48 +'ddyinj', # 0x49 +'ddyinh', # 0x4a +'ddyid', # 0x4b +'ddyil', # 0x4c +'ddyilg', # 0x4d +'ddyilm', # 0x4e +'ddyilb', # 0x4f +'ddyils', # 0x50 +'ddyilt', # 0x51 +'ddyilp', # 0x52 +'ddyilh', # 0x53 +'ddyim', # 0x54 +'ddyib', # 0x55 +'ddyibs', # 0x56 +'ddyis', # 0x57 +'ddyiss', # 0x58 +'ddying', # 0x59 +'ddyij', # 0x5a +'ddyic', # 0x5b +'ddyik', # 0x5c +'ddyit', # 0x5d +'ddyip', # 0x5e +'ddyih', # 0x5f +'ddi', # 0x60 +'ddig', # 0x61 +'ddigg', # 0x62 +'ddigs', # 0x63 +'ddin', # 0x64 +'ddinj', # 0x65 +'ddinh', # 0x66 +'ddid', # 0x67 +'ddil', # 0x68 +'ddilg', # 0x69 +'ddilm', # 0x6a +'ddilb', # 0x6b +'ddils', # 0x6c +'ddilt', # 0x6d +'ddilp', # 0x6e +'ddilh', # 0x6f +'ddim', # 0x70 +'ddib', # 0x71 +'ddibs', # 0x72 +'ddis', # 0x73 +'ddiss', # 0x74 +'dding', # 0x75 +'ddij', # 0x76 +'ddic', # 0x77 +'ddik', # 0x78 +'ddit', # 0x79 +'ddip', # 0x7a +'ddih', # 0x7b +'ra', # 0x7c +'rag', # 0x7d +'ragg', # 0x7e +'rags', # 0x7f +'ran', # 0x80 +'ranj', # 0x81 +'ranh', # 0x82 +'rad', # 0x83 +'ral', # 0x84 +'ralg', # 0x85 +'ralm', # 0x86 +'ralb', # 0x87 +'rals', # 0x88 +'ralt', # 0x89 +'ralp', # 0x8a +'ralh', # 0x8b +'ram', # 0x8c +'rab', # 0x8d +'rabs', # 0x8e +'ras', # 0x8f +'rass', # 0x90 +'rang', # 0x91 +'raj', # 0x92 +'rac', # 0x93 +'rak', # 0x94 +'rat', # 0x95 +'rap', # 0x96 +'rah', # 0x97 +'rae', # 0x98 +'raeg', # 0x99 +'raegg', # 0x9a +'raegs', # 0x9b +'raen', # 0x9c +'raenj', # 0x9d +'raenh', # 0x9e +'raed', # 0x9f +'rael', # 0xa0 +'raelg', # 0xa1 +'raelm', # 0xa2 +'raelb', # 0xa3 +'raels', # 0xa4 +'raelt', # 0xa5 +'raelp', # 0xa6 +'raelh', # 0xa7 +'raem', # 0xa8 +'raeb', # 0xa9 +'raebs', # 0xaa +'raes', # 0xab +'raess', # 0xac +'raeng', # 0xad +'raej', # 0xae +'raec', # 0xaf +'raek', # 0xb0 +'raet', # 0xb1 +'raep', # 0xb2 +'raeh', # 0xb3 +'rya', # 0xb4 +'ryag', # 0xb5 +'ryagg', # 0xb6 +'ryags', # 0xb7 +'ryan', # 0xb8 +'ryanj', # 0xb9 +'ryanh', # 0xba +'ryad', # 0xbb +'ryal', # 0xbc +'ryalg', # 0xbd +'ryalm', # 0xbe +'ryalb', # 0xbf +'ryals', # 0xc0 +'ryalt', # 0xc1 +'ryalp', # 0xc2 +'ryalh', # 0xc3 +'ryam', # 0xc4 +'ryab', # 0xc5 +'ryabs', # 0xc6 +'ryas', # 0xc7 +'ryass', # 0xc8 +'ryang', # 0xc9 +'ryaj', # 0xca +'ryac', # 0xcb +'ryak', # 0xcc +'ryat', # 0xcd +'ryap', # 0xce +'ryah', # 0xcf +'ryae', # 0xd0 +'ryaeg', # 0xd1 +'ryaegg', # 0xd2 +'ryaegs', # 0xd3 +'ryaen', # 0xd4 +'ryaenj', # 0xd5 +'ryaenh', # 0xd6 +'ryaed', # 0xd7 +'ryael', # 0xd8 +'ryaelg', # 0xd9 +'ryaelm', # 0xda +'ryaelb', # 0xdb +'ryaels', # 0xdc +'ryaelt', # 0xdd +'ryaelp', # 0xde +'ryaelh', # 0xdf +'ryaem', # 0xe0 +'ryaeb', # 0xe1 +'ryaebs', # 0xe2 +'ryaes', # 0xe3 +'ryaess', # 0xe4 +'ryaeng', # 0xe5 +'ryaej', # 0xe6 +'ryaec', # 0xe7 +'ryaek', # 0xe8 +'ryaet', # 0xe9 +'ryaep', # 0xea +'ryaeh', # 0xeb +'reo', # 0xec +'reog', # 0xed +'reogg', # 0xee +'reogs', # 0xef +'reon', # 0xf0 +'reonj', # 0xf1 +'reonh', # 0xf2 +'reod', # 0xf3 +'reol', # 0xf4 +'reolg', # 0xf5 +'reolm', # 0xf6 +'reolb', # 0xf7 +'reols', # 0xf8 +'reolt', # 0xf9 +'reolp', # 0xfa +'reolh', # 0xfb +'reom', # 0xfc +'reob', # 0xfd +'reobs', # 0xfe +'reos', # 0xff +) diff --git a/nstock/modules/unidecode/x0b8.py b/nstock/modules/unidecode/x0b8.py new file mode 100644 index 0000000..5c845eb --- /dev/null +++ b/nstock/modules/unidecode/x0b8.py @@ -0,0 +1,258 @@ +data = ( +'reoss', # 0x00 +'reong', # 0x01 +'reoj', # 0x02 +'reoc', # 0x03 +'reok', # 0x04 +'reot', # 0x05 +'reop', # 0x06 +'reoh', # 0x07 +'re', # 0x08 +'reg', # 0x09 +'regg', # 0x0a +'regs', # 0x0b +'ren', # 0x0c +'renj', # 0x0d +'renh', # 0x0e +'red', # 0x0f +'rel', # 0x10 +'relg', # 0x11 +'relm', # 0x12 +'relb', # 0x13 +'rels', # 0x14 +'relt', # 0x15 +'relp', # 0x16 +'relh', # 0x17 +'rem', # 0x18 +'reb', # 0x19 +'rebs', # 0x1a +'res', # 0x1b +'ress', # 0x1c +'reng', # 0x1d +'rej', # 0x1e +'rec', # 0x1f +'rek', # 0x20 +'ret', # 0x21 +'rep', # 0x22 +'reh', # 0x23 +'ryeo', # 0x24 +'ryeog', # 0x25 +'ryeogg', # 0x26 +'ryeogs', # 0x27 +'ryeon', # 0x28 +'ryeonj', # 0x29 +'ryeonh', # 0x2a +'ryeod', # 0x2b +'ryeol', # 0x2c +'ryeolg', # 0x2d +'ryeolm', # 0x2e +'ryeolb', # 0x2f +'ryeols', # 0x30 +'ryeolt', # 0x31 +'ryeolp', # 0x32 +'ryeolh', # 0x33 +'ryeom', # 0x34 +'ryeob', # 0x35 +'ryeobs', # 0x36 +'ryeos', # 0x37 +'ryeoss', # 0x38 +'ryeong', # 0x39 +'ryeoj', # 0x3a +'ryeoc', # 0x3b +'ryeok', # 0x3c +'ryeot', # 0x3d +'ryeop', # 0x3e +'ryeoh', # 0x3f +'rye', # 0x40 +'ryeg', # 0x41 +'ryegg', # 0x42 +'ryegs', # 0x43 +'ryen', # 0x44 +'ryenj', # 0x45 +'ryenh', # 0x46 +'ryed', # 0x47 +'ryel', # 0x48 +'ryelg', # 0x49 +'ryelm', # 0x4a +'ryelb', # 0x4b +'ryels', # 0x4c +'ryelt', # 0x4d +'ryelp', # 0x4e +'ryelh', # 0x4f +'ryem', # 0x50 +'ryeb', # 0x51 +'ryebs', # 0x52 +'ryes', # 0x53 +'ryess', # 0x54 +'ryeng', # 0x55 +'ryej', # 0x56 +'ryec', # 0x57 +'ryek', # 0x58 +'ryet', # 0x59 +'ryep', # 0x5a +'ryeh', # 0x5b +'ro', # 0x5c +'rog', # 0x5d +'rogg', # 0x5e +'rogs', # 0x5f +'ron', # 0x60 +'ronj', # 0x61 +'ronh', # 0x62 +'rod', # 0x63 +'rol', # 0x64 +'rolg', # 0x65 +'rolm', # 0x66 +'rolb', # 0x67 +'rols', # 0x68 +'rolt', # 0x69 +'rolp', # 0x6a +'rolh', # 0x6b +'rom', # 0x6c +'rob', # 0x6d +'robs', # 0x6e +'ros', # 0x6f +'ross', # 0x70 +'rong', # 0x71 +'roj', # 0x72 +'roc', # 0x73 +'rok', # 0x74 +'rot', # 0x75 +'rop', # 0x76 +'roh', # 0x77 +'rwa', # 0x78 +'rwag', # 0x79 +'rwagg', # 0x7a +'rwags', # 0x7b +'rwan', # 0x7c +'rwanj', # 0x7d +'rwanh', # 0x7e +'rwad', # 0x7f +'rwal', # 0x80 +'rwalg', # 0x81 +'rwalm', # 0x82 +'rwalb', # 0x83 +'rwals', # 0x84 +'rwalt', # 0x85 +'rwalp', # 0x86 +'rwalh', # 0x87 +'rwam', # 0x88 +'rwab', # 0x89 +'rwabs', # 0x8a +'rwas', # 0x8b +'rwass', # 0x8c +'rwang', # 0x8d +'rwaj', # 0x8e +'rwac', # 0x8f +'rwak', # 0x90 +'rwat', # 0x91 +'rwap', # 0x92 +'rwah', # 0x93 +'rwae', # 0x94 +'rwaeg', # 0x95 +'rwaegg', # 0x96 +'rwaegs', # 0x97 +'rwaen', # 0x98 +'rwaenj', # 0x99 +'rwaenh', # 0x9a +'rwaed', # 0x9b +'rwael', # 0x9c +'rwaelg', # 0x9d +'rwaelm', # 0x9e +'rwaelb', # 0x9f +'rwaels', # 0xa0 +'rwaelt', # 0xa1 +'rwaelp', # 0xa2 +'rwaelh', # 0xa3 +'rwaem', # 0xa4 +'rwaeb', # 0xa5 +'rwaebs', # 0xa6 +'rwaes', # 0xa7 +'rwaess', # 0xa8 +'rwaeng', # 0xa9 +'rwaej', # 0xaa +'rwaec', # 0xab +'rwaek', # 0xac +'rwaet', # 0xad +'rwaep', # 0xae +'rwaeh', # 0xaf +'roe', # 0xb0 +'roeg', # 0xb1 +'roegg', # 0xb2 +'roegs', # 0xb3 +'roen', # 0xb4 +'roenj', # 0xb5 +'roenh', # 0xb6 +'roed', # 0xb7 +'roel', # 0xb8 +'roelg', # 0xb9 +'roelm', # 0xba +'roelb', # 0xbb +'roels', # 0xbc +'roelt', # 0xbd +'roelp', # 0xbe +'roelh', # 0xbf +'roem', # 0xc0 +'roeb', # 0xc1 +'roebs', # 0xc2 +'roes', # 0xc3 +'roess', # 0xc4 +'roeng', # 0xc5 +'roej', # 0xc6 +'roec', # 0xc7 +'roek', # 0xc8 +'roet', # 0xc9 +'roep', # 0xca +'roeh', # 0xcb +'ryo', # 0xcc +'ryog', # 0xcd +'ryogg', # 0xce +'ryogs', # 0xcf +'ryon', # 0xd0 +'ryonj', # 0xd1 +'ryonh', # 0xd2 +'ryod', # 0xd3 +'ryol', # 0xd4 +'ryolg', # 0xd5 +'ryolm', # 0xd6 +'ryolb', # 0xd7 +'ryols', # 0xd8 +'ryolt', # 0xd9 +'ryolp', # 0xda +'ryolh', # 0xdb +'ryom', # 0xdc +'ryob', # 0xdd +'ryobs', # 0xde +'ryos', # 0xdf +'ryoss', # 0xe0 +'ryong', # 0xe1 +'ryoj', # 0xe2 +'ryoc', # 0xe3 +'ryok', # 0xe4 +'ryot', # 0xe5 +'ryop', # 0xe6 +'ryoh', # 0xe7 +'ru', # 0xe8 +'rug', # 0xe9 +'rugg', # 0xea +'rugs', # 0xeb +'run', # 0xec +'runj', # 0xed +'runh', # 0xee +'rud', # 0xef +'rul', # 0xf0 +'rulg', # 0xf1 +'rulm', # 0xf2 +'rulb', # 0xf3 +'ruls', # 0xf4 +'rult', # 0xf5 +'rulp', # 0xf6 +'rulh', # 0xf7 +'rum', # 0xf8 +'rub', # 0xf9 +'rubs', # 0xfa +'rus', # 0xfb +'russ', # 0xfc +'rung', # 0xfd +'ruj', # 0xfe +'ruc', # 0xff +) diff --git a/nstock/modules/unidecode/x0b9.py b/nstock/modules/unidecode/x0b9.py new file mode 100644 index 0000000..35340dc --- /dev/null +++ b/nstock/modules/unidecode/x0b9.py @@ -0,0 +1,258 @@ +data = ( +'ruk', # 0x00 +'rut', # 0x01 +'rup', # 0x02 +'ruh', # 0x03 +'rweo', # 0x04 +'rweog', # 0x05 +'rweogg', # 0x06 +'rweogs', # 0x07 +'rweon', # 0x08 +'rweonj', # 0x09 +'rweonh', # 0x0a +'rweod', # 0x0b +'rweol', # 0x0c +'rweolg', # 0x0d +'rweolm', # 0x0e +'rweolb', # 0x0f +'rweols', # 0x10 +'rweolt', # 0x11 +'rweolp', # 0x12 +'rweolh', # 0x13 +'rweom', # 0x14 +'rweob', # 0x15 +'rweobs', # 0x16 +'rweos', # 0x17 +'rweoss', # 0x18 +'rweong', # 0x19 +'rweoj', # 0x1a +'rweoc', # 0x1b +'rweok', # 0x1c +'rweot', # 0x1d +'rweop', # 0x1e +'rweoh', # 0x1f +'rwe', # 0x20 +'rweg', # 0x21 +'rwegg', # 0x22 +'rwegs', # 0x23 +'rwen', # 0x24 +'rwenj', # 0x25 +'rwenh', # 0x26 +'rwed', # 0x27 +'rwel', # 0x28 +'rwelg', # 0x29 +'rwelm', # 0x2a +'rwelb', # 0x2b +'rwels', # 0x2c +'rwelt', # 0x2d +'rwelp', # 0x2e +'rwelh', # 0x2f +'rwem', # 0x30 +'rweb', # 0x31 +'rwebs', # 0x32 +'rwes', # 0x33 +'rwess', # 0x34 +'rweng', # 0x35 +'rwej', # 0x36 +'rwec', # 0x37 +'rwek', # 0x38 +'rwet', # 0x39 +'rwep', # 0x3a +'rweh', # 0x3b +'rwi', # 0x3c +'rwig', # 0x3d +'rwigg', # 0x3e +'rwigs', # 0x3f +'rwin', # 0x40 +'rwinj', # 0x41 +'rwinh', # 0x42 +'rwid', # 0x43 +'rwil', # 0x44 +'rwilg', # 0x45 +'rwilm', # 0x46 +'rwilb', # 0x47 +'rwils', # 0x48 +'rwilt', # 0x49 +'rwilp', # 0x4a +'rwilh', # 0x4b +'rwim', # 0x4c +'rwib', # 0x4d +'rwibs', # 0x4e +'rwis', # 0x4f +'rwiss', # 0x50 +'rwing', # 0x51 +'rwij', # 0x52 +'rwic', # 0x53 +'rwik', # 0x54 +'rwit', # 0x55 +'rwip', # 0x56 +'rwih', # 0x57 +'ryu', # 0x58 +'ryug', # 0x59 +'ryugg', # 0x5a +'ryugs', # 0x5b +'ryun', # 0x5c +'ryunj', # 0x5d +'ryunh', # 0x5e +'ryud', # 0x5f +'ryul', # 0x60 +'ryulg', # 0x61 +'ryulm', # 0x62 +'ryulb', # 0x63 +'ryuls', # 0x64 +'ryult', # 0x65 +'ryulp', # 0x66 +'ryulh', # 0x67 +'ryum', # 0x68 +'ryub', # 0x69 +'ryubs', # 0x6a +'ryus', # 0x6b +'ryuss', # 0x6c +'ryung', # 0x6d +'ryuj', # 0x6e +'ryuc', # 0x6f +'ryuk', # 0x70 +'ryut', # 0x71 +'ryup', # 0x72 +'ryuh', # 0x73 +'reu', # 0x74 +'reug', # 0x75 +'reugg', # 0x76 +'reugs', # 0x77 +'reun', # 0x78 +'reunj', # 0x79 +'reunh', # 0x7a +'reud', # 0x7b +'reul', # 0x7c +'reulg', # 0x7d +'reulm', # 0x7e +'reulb', # 0x7f +'reuls', # 0x80 +'reult', # 0x81 +'reulp', # 0x82 +'reulh', # 0x83 +'reum', # 0x84 +'reub', # 0x85 +'reubs', # 0x86 +'reus', # 0x87 +'reuss', # 0x88 +'reung', # 0x89 +'reuj', # 0x8a +'reuc', # 0x8b +'reuk', # 0x8c +'reut', # 0x8d +'reup', # 0x8e +'reuh', # 0x8f +'ryi', # 0x90 +'ryig', # 0x91 +'ryigg', # 0x92 +'ryigs', # 0x93 +'ryin', # 0x94 +'ryinj', # 0x95 +'ryinh', # 0x96 +'ryid', # 0x97 +'ryil', # 0x98 +'ryilg', # 0x99 +'ryilm', # 0x9a +'ryilb', # 0x9b +'ryils', # 0x9c +'ryilt', # 0x9d +'ryilp', # 0x9e +'ryilh', # 0x9f +'ryim', # 0xa0 +'ryib', # 0xa1 +'ryibs', # 0xa2 +'ryis', # 0xa3 +'ryiss', # 0xa4 +'rying', # 0xa5 +'ryij', # 0xa6 +'ryic', # 0xa7 +'ryik', # 0xa8 +'ryit', # 0xa9 +'ryip', # 0xaa +'ryih', # 0xab +'ri', # 0xac +'rig', # 0xad +'rigg', # 0xae +'rigs', # 0xaf +'rin', # 0xb0 +'rinj', # 0xb1 +'rinh', # 0xb2 +'rid', # 0xb3 +'ril', # 0xb4 +'rilg', # 0xb5 +'rilm', # 0xb6 +'rilb', # 0xb7 +'rils', # 0xb8 +'rilt', # 0xb9 +'rilp', # 0xba +'rilh', # 0xbb +'rim', # 0xbc +'rib', # 0xbd +'ribs', # 0xbe +'ris', # 0xbf +'riss', # 0xc0 +'ring', # 0xc1 +'rij', # 0xc2 +'ric', # 0xc3 +'rik', # 0xc4 +'rit', # 0xc5 +'rip', # 0xc6 +'rih', # 0xc7 +'ma', # 0xc8 +'mag', # 0xc9 +'magg', # 0xca +'mags', # 0xcb +'man', # 0xcc +'manj', # 0xcd +'manh', # 0xce +'mad', # 0xcf +'mal', # 0xd0 +'malg', # 0xd1 +'malm', # 0xd2 +'malb', # 0xd3 +'mals', # 0xd4 +'malt', # 0xd5 +'malp', # 0xd6 +'malh', # 0xd7 +'mam', # 0xd8 +'mab', # 0xd9 +'mabs', # 0xda +'mas', # 0xdb +'mass', # 0xdc +'mang', # 0xdd +'maj', # 0xde +'mac', # 0xdf +'mak', # 0xe0 +'mat', # 0xe1 +'map', # 0xe2 +'mah', # 0xe3 +'mae', # 0xe4 +'maeg', # 0xe5 +'maegg', # 0xe6 +'maegs', # 0xe7 +'maen', # 0xe8 +'maenj', # 0xe9 +'maenh', # 0xea +'maed', # 0xeb +'mael', # 0xec +'maelg', # 0xed +'maelm', # 0xee +'maelb', # 0xef +'maels', # 0xf0 +'maelt', # 0xf1 +'maelp', # 0xf2 +'maelh', # 0xf3 +'maem', # 0xf4 +'maeb', # 0xf5 +'maebs', # 0xf6 +'maes', # 0xf7 +'maess', # 0xf8 +'maeng', # 0xf9 +'maej', # 0xfa +'maec', # 0xfb +'maek', # 0xfc +'maet', # 0xfd +'maep', # 0xfe +'maeh', # 0xff +) diff --git a/nstock/modules/unidecode/x0ba.py b/nstock/modules/unidecode/x0ba.py new file mode 100644 index 0000000..9ef8294 --- /dev/null +++ b/nstock/modules/unidecode/x0ba.py @@ -0,0 +1,258 @@ +data = ( +'mya', # 0x00 +'myag', # 0x01 +'myagg', # 0x02 +'myags', # 0x03 +'myan', # 0x04 +'myanj', # 0x05 +'myanh', # 0x06 +'myad', # 0x07 +'myal', # 0x08 +'myalg', # 0x09 +'myalm', # 0x0a +'myalb', # 0x0b +'myals', # 0x0c +'myalt', # 0x0d +'myalp', # 0x0e +'myalh', # 0x0f +'myam', # 0x10 +'myab', # 0x11 +'myabs', # 0x12 +'myas', # 0x13 +'myass', # 0x14 +'myang', # 0x15 +'myaj', # 0x16 +'myac', # 0x17 +'myak', # 0x18 +'myat', # 0x19 +'myap', # 0x1a +'myah', # 0x1b +'myae', # 0x1c +'myaeg', # 0x1d +'myaegg', # 0x1e +'myaegs', # 0x1f +'myaen', # 0x20 +'myaenj', # 0x21 +'myaenh', # 0x22 +'myaed', # 0x23 +'myael', # 0x24 +'myaelg', # 0x25 +'myaelm', # 0x26 +'myaelb', # 0x27 +'myaels', # 0x28 +'myaelt', # 0x29 +'myaelp', # 0x2a +'myaelh', # 0x2b +'myaem', # 0x2c +'myaeb', # 0x2d +'myaebs', # 0x2e +'myaes', # 0x2f +'myaess', # 0x30 +'myaeng', # 0x31 +'myaej', # 0x32 +'myaec', # 0x33 +'myaek', # 0x34 +'myaet', # 0x35 +'myaep', # 0x36 +'myaeh', # 0x37 +'meo', # 0x38 +'meog', # 0x39 +'meogg', # 0x3a +'meogs', # 0x3b +'meon', # 0x3c +'meonj', # 0x3d +'meonh', # 0x3e +'meod', # 0x3f +'meol', # 0x40 +'meolg', # 0x41 +'meolm', # 0x42 +'meolb', # 0x43 +'meols', # 0x44 +'meolt', # 0x45 +'meolp', # 0x46 +'meolh', # 0x47 +'meom', # 0x48 +'meob', # 0x49 +'meobs', # 0x4a +'meos', # 0x4b +'meoss', # 0x4c +'meong', # 0x4d +'meoj', # 0x4e +'meoc', # 0x4f +'meok', # 0x50 +'meot', # 0x51 +'meop', # 0x52 +'meoh', # 0x53 +'me', # 0x54 +'meg', # 0x55 +'megg', # 0x56 +'megs', # 0x57 +'men', # 0x58 +'menj', # 0x59 +'menh', # 0x5a +'med', # 0x5b +'mel', # 0x5c +'melg', # 0x5d +'melm', # 0x5e +'melb', # 0x5f +'mels', # 0x60 +'melt', # 0x61 +'melp', # 0x62 +'melh', # 0x63 +'mem', # 0x64 +'meb', # 0x65 +'mebs', # 0x66 +'mes', # 0x67 +'mess', # 0x68 +'meng', # 0x69 +'mej', # 0x6a +'mec', # 0x6b +'mek', # 0x6c +'met', # 0x6d +'mep', # 0x6e +'meh', # 0x6f +'myeo', # 0x70 +'myeog', # 0x71 +'myeogg', # 0x72 +'myeogs', # 0x73 +'myeon', # 0x74 +'myeonj', # 0x75 +'myeonh', # 0x76 +'myeod', # 0x77 +'myeol', # 0x78 +'myeolg', # 0x79 +'myeolm', # 0x7a +'myeolb', # 0x7b +'myeols', # 0x7c +'myeolt', # 0x7d +'myeolp', # 0x7e +'myeolh', # 0x7f +'myeom', # 0x80 +'myeob', # 0x81 +'myeobs', # 0x82 +'myeos', # 0x83 +'myeoss', # 0x84 +'myeong', # 0x85 +'myeoj', # 0x86 +'myeoc', # 0x87 +'myeok', # 0x88 +'myeot', # 0x89 +'myeop', # 0x8a +'myeoh', # 0x8b +'mye', # 0x8c +'myeg', # 0x8d +'myegg', # 0x8e +'myegs', # 0x8f +'myen', # 0x90 +'myenj', # 0x91 +'myenh', # 0x92 +'myed', # 0x93 +'myel', # 0x94 +'myelg', # 0x95 +'myelm', # 0x96 +'myelb', # 0x97 +'myels', # 0x98 +'myelt', # 0x99 +'myelp', # 0x9a +'myelh', # 0x9b +'myem', # 0x9c +'myeb', # 0x9d +'myebs', # 0x9e +'myes', # 0x9f +'myess', # 0xa0 +'myeng', # 0xa1 +'myej', # 0xa2 +'myec', # 0xa3 +'myek', # 0xa4 +'myet', # 0xa5 +'myep', # 0xa6 +'myeh', # 0xa7 +'mo', # 0xa8 +'mog', # 0xa9 +'mogg', # 0xaa +'mogs', # 0xab +'mon', # 0xac +'monj', # 0xad +'monh', # 0xae +'mod', # 0xaf +'mol', # 0xb0 +'molg', # 0xb1 +'molm', # 0xb2 +'molb', # 0xb3 +'mols', # 0xb4 +'molt', # 0xb5 +'molp', # 0xb6 +'molh', # 0xb7 +'mom', # 0xb8 +'mob', # 0xb9 +'mobs', # 0xba +'mos', # 0xbb +'moss', # 0xbc +'mong', # 0xbd +'moj', # 0xbe +'moc', # 0xbf +'mok', # 0xc0 +'mot', # 0xc1 +'mop', # 0xc2 +'moh', # 0xc3 +'mwa', # 0xc4 +'mwag', # 0xc5 +'mwagg', # 0xc6 +'mwags', # 0xc7 +'mwan', # 0xc8 +'mwanj', # 0xc9 +'mwanh', # 0xca +'mwad', # 0xcb +'mwal', # 0xcc +'mwalg', # 0xcd +'mwalm', # 0xce +'mwalb', # 0xcf +'mwals', # 0xd0 +'mwalt', # 0xd1 +'mwalp', # 0xd2 +'mwalh', # 0xd3 +'mwam', # 0xd4 +'mwab', # 0xd5 +'mwabs', # 0xd6 +'mwas', # 0xd7 +'mwass', # 0xd8 +'mwang', # 0xd9 +'mwaj', # 0xda +'mwac', # 0xdb +'mwak', # 0xdc +'mwat', # 0xdd +'mwap', # 0xde +'mwah', # 0xdf +'mwae', # 0xe0 +'mwaeg', # 0xe1 +'mwaegg', # 0xe2 +'mwaegs', # 0xe3 +'mwaen', # 0xe4 +'mwaenj', # 0xe5 +'mwaenh', # 0xe6 +'mwaed', # 0xe7 +'mwael', # 0xe8 +'mwaelg', # 0xe9 +'mwaelm', # 0xea +'mwaelb', # 0xeb +'mwaels', # 0xec +'mwaelt', # 0xed +'mwaelp', # 0xee +'mwaelh', # 0xef +'mwaem', # 0xf0 +'mwaeb', # 0xf1 +'mwaebs', # 0xf2 +'mwaes', # 0xf3 +'mwaess', # 0xf4 +'mwaeng', # 0xf5 +'mwaej', # 0xf6 +'mwaec', # 0xf7 +'mwaek', # 0xf8 +'mwaet', # 0xf9 +'mwaep', # 0xfa +'mwaeh', # 0xfb +'moe', # 0xfc +'moeg', # 0xfd +'moegg', # 0xfe +'moegs', # 0xff +) diff --git a/nstock/modules/unidecode/x0bb.py b/nstock/modules/unidecode/x0bb.py new file mode 100644 index 0000000..b92031b --- /dev/null +++ b/nstock/modules/unidecode/x0bb.py @@ -0,0 +1,258 @@ +data = ( +'moen', # 0x00 +'moenj', # 0x01 +'moenh', # 0x02 +'moed', # 0x03 +'moel', # 0x04 +'moelg', # 0x05 +'moelm', # 0x06 +'moelb', # 0x07 +'moels', # 0x08 +'moelt', # 0x09 +'moelp', # 0x0a +'moelh', # 0x0b +'moem', # 0x0c +'moeb', # 0x0d +'moebs', # 0x0e +'moes', # 0x0f +'moess', # 0x10 +'moeng', # 0x11 +'moej', # 0x12 +'moec', # 0x13 +'moek', # 0x14 +'moet', # 0x15 +'moep', # 0x16 +'moeh', # 0x17 +'myo', # 0x18 +'myog', # 0x19 +'myogg', # 0x1a +'myogs', # 0x1b +'myon', # 0x1c +'myonj', # 0x1d +'myonh', # 0x1e +'myod', # 0x1f +'myol', # 0x20 +'myolg', # 0x21 +'myolm', # 0x22 +'myolb', # 0x23 +'myols', # 0x24 +'myolt', # 0x25 +'myolp', # 0x26 +'myolh', # 0x27 +'myom', # 0x28 +'myob', # 0x29 +'myobs', # 0x2a +'myos', # 0x2b +'myoss', # 0x2c +'myong', # 0x2d +'myoj', # 0x2e +'myoc', # 0x2f +'myok', # 0x30 +'myot', # 0x31 +'myop', # 0x32 +'myoh', # 0x33 +'mu', # 0x34 +'mug', # 0x35 +'mugg', # 0x36 +'mugs', # 0x37 +'mun', # 0x38 +'munj', # 0x39 +'munh', # 0x3a +'mud', # 0x3b +'mul', # 0x3c +'mulg', # 0x3d +'mulm', # 0x3e +'mulb', # 0x3f +'muls', # 0x40 +'mult', # 0x41 +'mulp', # 0x42 +'mulh', # 0x43 +'mum', # 0x44 +'mub', # 0x45 +'mubs', # 0x46 +'mus', # 0x47 +'muss', # 0x48 +'mung', # 0x49 +'muj', # 0x4a +'muc', # 0x4b +'muk', # 0x4c +'mut', # 0x4d +'mup', # 0x4e +'muh', # 0x4f +'mweo', # 0x50 +'mweog', # 0x51 +'mweogg', # 0x52 +'mweogs', # 0x53 +'mweon', # 0x54 +'mweonj', # 0x55 +'mweonh', # 0x56 +'mweod', # 0x57 +'mweol', # 0x58 +'mweolg', # 0x59 +'mweolm', # 0x5a +'mweolb', # 0x5b +'mweols', # 0x5c +'mweolt', # 0x5d +'mweolp', # 0x5e +'mweolh', # 0x5f +'mweom', # 0x60 +'mweob', # 0x61 +'mweobs', # 0x62 +'mweos', # 0x63 +'mweoss', # 0x64 +'mweong', # 0x65 +'mweoj', # 0x66 +'mweoc', # 0x67 +'mweok', # 0x68 +'mweot', # 0x69 +'mweop', # 0x6a +'mweoh', # 0x6b +'mwe', # 0x6c +'mweg', # 0x6d +'mwegg', # 0x6e +'mwegs', # 0x6f +'mwen', # 0x70 +'mwenj', # 0x71 +'mwenh', # 0x72 +'mwed', # 0x73 +'mwel', # 0x74 +'mwelg', # 0x75 +'mwelm', # 0x76 +'mwelb', # 0x77 +'mwels', # 0x78 +'mwelt', # 0x79 +'mwelp', # 0x7a +'mwelh', # 0x7b +'mwem', # 0x7c +'mweb', # 0x7d +'mwebs', # 0x7e +'mwes', # 0x7f +'mwess', # 0x80 +'mweng', # 0x81 +'mwej', # 0x82 +'mwec', # 0x83 +'mwek', # 0x84 +'mwet', # 0x85 +'mwep', # 0x86 +'mweh', # 0x87 +'mwi', # 0x88 +'mwig', # 0x89 +'mwigg', # 0x8a +'mwigs', # 0x8b +'mwin', # 0x8c +'mwinj', # 0x8d +'mwinh', # 0x8e +'mwid', # 0x8f +'mwil', # 0x90 +'mwilg', # 0x91 +'mwilm', # 0x92 +'mwilb', # 0x93 +'mwils', # 0x94 +'mwilt', # 0x95 +'mwilp', # 0x96 +'mwilh', # 0x97 +'mwim', # 0x98 +'mwib', # 0x99 +'mwibs', # 0x9a +'mwis', # 0x9b +'mwiss', # 0x9c +'mwing', # 0x9d +'mwij', # 0x9e +'mwic', # 0x9f +'mwik', # 0xa0 +'mwit', # 0xa1 +'mwip', # 0xa2 +'mwih', # 0xa3 +'myu', # 0xa4 +'myug', # 0xa5 +'myugg', # 0xa6 +'myugs', # 0xa7 +'myun', # 0xa8 +'myunj', # 0xa9 +'myunh', # 0xaa +'myud', # 0xab +'myul', # 0xac +'myulg', # 0xad +'myulm', # 0xae +'myulb', # 0xaf +'myuls', # 0xb0 +'myult', # 0xb1 +'myulp', # 0xb2 +'myulh', # 0xb3 +'myum', # 0xb4 +'myub', # 0xb5 +'myubs', # 0xb6 +'myus', # 0xb7 +'myuss', # 0xb8 +'myung', # 0xb9 +'myuj', # 0xba +'myuc', # 0xbb +'myuk', # 0xbc +'myut', # 0xbd +'myup', # 0xbe +'myuh', # 0xbf +'meu', # 0xc0 +'meug', # 0xc1 +'meugg', # 0xc2 +'meugs', # 0xc3 +'meun', # 0xc4 +'meunj', # 0xc5 +'meunh', # 0xc6 +'meud', # 0xc7 +'meul', # 0xc8 +'meulg', # 0xc9 +'meulm', # 0xca +'meulb', # 0xcb +'meuls', # 0xcc +'meult', # 0xcd +'meulp', # 0xce +'meulh', # 0xcf +'meum', # 0xd0 +'meub', # 0xd1 +'meubs', # 0xd2 +'meus', # 0xd3 +'meuss', # 0xd4 +'meung', # 0xd5 +'meuj', # 0xd6 +'meuc', # 0xd7 +'meuk', # 0xd8 +'meut', # 0xd9 +'meup', # 0xda +'meuh', # 0xdb +'myi', # 0xdc +'myig', # 0xdd +'myigg', # 0xde +'myigs', # 0xdf +'myin', # 0xe0 +'myinj', # 0xe1 +'myinh', # 0xe2 +'myid', # 0xe3 +'myil', # 0xe4 +'myilg', # 0xe5 +'myilm', # 0xe6 +'myilb', # 0xe7 +'myils', # 0xe8 +'myilt', # 0xe9 +'myilp', # 0xea +'myilh', # 0xeb +'myim', # 0xec +'myib', # 0xed +'myibs', # 0xee +'myis', # 0xef +'myiss', # 0xf0 +'mying', # 0xf1 +'myij', # 0xf2 +'myic', # 0xf3 +'myik', # 0xf4 +'myit', # 0xf5 +'myip', # 0xf6 +'myih', # 0xf7 +'mi', # 0xf8 +'mig', # 0xf9 +'migg', # 0xfa +'migs', # 0xfb +'min', # 0xfc +'minj', # 0xfd +'minh', # 0xfe +'mid', # 0xff +) diff --git a/nstock/modules/unidecode/x0bc.py b/nstock/modules/unidecode/x0bc.py new file mode 100644 index 0000000..c0b3f32 --- /dev/null +++ b/nstock/modules/unidecode/x0bc.py @@ -0,0 +1,258 @@ +data = ( +'mil', # 0x00 +'milg', # 0x01 +'milm', # 0x02 +'milb', # 0x03 +'mils', # 0x04 +'milt', # 0x05 +'milp', # 0x06 +'milh', # 0x07 +'mim', # 0x08 +'mib', # 0x09 +'mibs', # 0x0a +'mis', # 0x0b +'miss', # 0x0c +'ming', # 0x0d +'mij', # 0x0e +'mic', # 0x0f +'mik', # 0x10 +'mit', # 0x11 +'mip', # 0x12 +'mih', # 0x13 +'ba', # 0x14 +'bag', # 0x15 +'bagg', # 0x16 +'bags', # 0x17 +'ban', # 0x18 +'banj', # 0x19 +'banh', # 0x1a +'bad', # 0x1b +'bal', # 0x1c +'balg', # 0x1d +'balm', # 0x1e +'balb', # 0x1f +'bals', # 0x20 +'balt', # 0x21 +'balp', # 0x22 +'balh', # 0x23 +'bam', # 0x24 +'bab', # 0x25 +'babs', # 0x26 +'bas', # 0x27 +'bass', # 0x28 +'bang', # 0x29 +'baj', # 0x2a +'bac', # 0x2b +'bak', # 0x2c +'bat', # 0x2d +'bap', # 0x2e +'bah', # 0x2f +'bae', # 0x30 +'baeg', # 0x31 +'baegg', # 0x32 +'baegs', # 0x33 +'baen', # 0x34 +'baenj', # 0x35 +'baenh', # 0x36 +'baed', # 0x37 +'bael', # 0x38 +'baelg', # 0x39 +'baelm', # 0x3a +'baelb', # 0x3b +'baels', # 0x3c +'baelt', # 0x3d +'baelp', # 0x3e +'baelh', # 0x3f +'baem', # 0x40 +'baeb', # 0x41 +'baebs', # 0x42 +'baes', # 0x43 +'baess', # 0x44 +'baeng', # 0x45 +'baej', # 0x46 +'baec', # 0x47 +'baek', # 0x48 +'baet', # 0x49 +'baep', # 0x4a +'baeh', # 0x4b +'bya', # 0x4c +'byag', # 0x4d +'byagg', # 0x4e +'byags', # 0x4f +'byan', # 0x50 +'byanj', # 0x51 +'byanh', # 0x52 +'byad', # 0x53 +'byal', # 0x54 +'byalg', # 0x55 +'byalm', # 0x56 +'byalb', # 0x57 +'byals', # 0x58 +'byalt', # 0x59 +'byalp', # 0x5a +'byalh', # 0x5b +'byam', # 0x5c +'byab', # 0x5d +'byabs', # 0x5e +'byas', # 0x5f +'byass', # 0x60 +'byang', # 0x61 +'byaj', # 0x62 +'byac', # 0x63 +'byak', # 0x64 +'byat', # 0x65 +'byap', # 0x66 +'byah', # 0x67 +'byae', # 0x68 +'byaeg', # 0x69 +'byaegg', # 0x6a +'byaegs', # 0x6b +'byaen', # 0x6c +'byaenj', # 0x6d +'byaenh', # 0x6e +'byaed', # 0x6f +'byael', # 0x70 +'byaelg', # 0x71 +'byaelm', # 0x72 +'byaelb', # 0x73 +'byaels', # 0x74 +'byaelt', # 0x75 +'byaelp', # 0x76 +'byaelh', # 0x77 +'byaem', # 0x78 +'byaeb', # 0x79 +'byaebs', # 0x7a +'byaes', # 0x7b +'byaess', # 0x7c +'byaeng', # 0x7d +'byaej', # 0x7e +'byaec', # 0x7f +'byaek', # 0x80 +'byaet', # 0x81 +'byaep', # 0x82 +'byaeh', # 0x83 +'beo', # 0x84 +'beog', # 0x85 +'beogg', # 0x86 +'beogs', # 0x87 +'beon', # 0x88 +'beonj', # 0x89 +'beonh', # 0x8a +'beod', # 0x8b +'beol', # 0x8c +'beolg', # 0x8d +'beolm', # 0x8e +'beolb', # 0x8f +'beols', # 0x90 +'beolt', # 0x91 +'beolp', # 0x92 +'beolh', # 0x93 +'beom', # 0x94 +'beob', # 0x95 +'beobs', # 0x96 +'beos', # 0x97 +'beoss', # 0x98 +'beong', # 0x99 +'beoj', # 0x9a +'beoc', # 0x9b +'beok', # 0x9c +'beot', # 0x9d +'beop', # 0x9e +'beoh', # 0x9f +'be', # 0xa0 +'beg', # 0xa1 +'begg', # 0xa2 +'begs', # 0xa3 +'ben', # 0xa4 +'benj', # 0xa5 +'benh', # 0xa6 +'bed', # 0xa7 +'bel', # 0xa8 +'belg', # 0xa9 +'belm', # 0xaa +'belb', # 0xab +'bels', # 0xac +'belt', # 0xad +'belp', # 0xae +'belh', # 0xaf +'bem', # 0xb0 +'beb', # 0xb1 +'bebs', # 0xb2 +'bes', # 0xb3 +'bess', # 0xb4 +'beng', # 0xb5 +'bej', # 0xb6 +'bec', # 0xb7 +'bek', # 0xb8 +'bet', # 0xb9 +'bep', # 0xba +'beh', # 0xbb +'byeo', # 0xbc +'byeog', # 0xbd +'byeogg', # 0xbe +'byeogs', # 0xbf +'byeon', # 0xc0 +'byeonj', # 0xc1 +'byeonh', # 0xc2 +'byeod', # 0xc3 +'byeol', # 0xc4 +'byeolg', # 0xc5 +'byeolm', # 0xc6 +'byeolb', # 0xc7 +'byeols', # 0xc8 +'byeolt', # 0xc9 +'byeolp', # 0xca +'byeolh', # 0xcb +'byeom', # 0xcc +'byeob', # 0xcd +'byeobs', # 0xce +'byeos', # 0xcf +'byeoss', # 0xd0 +'byeong', # 0xd1 +'byeoj', # 0xd2 +'byeoc', # 0xd3 +'byeok', # 0xd4 +'byeot', # 0xd5 +'byeop', # 0xd6 +'byeoh', # 0xd7 +'bye', # 0xd8 +'byeg', # 0xd9 +'byegg', # 0xda +'byegs', # 0xdb +'byen', # 0xdc +'byenj', # 0xdd +'byenh', # 0xde +'byed', # 0xdf +'byel', # 0xe0 +'byelg', # 0xe1 +'byelm', # 0xe2 +'byelb', # 0xe3 +'byels', # 0xe4 +'byelt', # 0xe5 +'byelp', # 0xe6 +'byelh', # 0xe7 +'byem', # 0xe8 +'byeb', # 0xe9 +'byebs', # 0xea +'byes', # 0xeb +'byess', # 0xec +'byeng', # 0xed +'byej', # 0xee +'byec', # 0xef +'byek', # 0xf0 +'byet', # 0xf1 +'byep', # 0xf2 +'byeh', # 0xf3 +'bo', # 0xf4 +'bog', # 0xf5 +'bogg', # 0xf6 +'bogs', # 0xf7 +'bon', # 0xf8 +'bonj', # 0xf9 +'bonh', # 0xfa +'bod', # 0xfb +'bol', # 0xfc +'bolg', # 0xfd +'bolm', # 0xfe +'bolb', # 0xff +) diff --git a/nstock/modules/unidecode/x0bd.py b/nstock/modules/unidecode/x0bd.py new file mode 100644 index 0000000..6473883 --- /dev/null +++ b/nstock/modules/unidecode/x0bd.py @@ -0,0 +1,258 @@ +data = ( +'bols', # 0x00 +'bolt', # 0x01 +'bolp', # 0x02 +'bolh', # 0x03 +'bom', # 0x04 +'bob', # 0x05 +'bobs', # 0x06 +'bos', # 0x07 +'boss', # 0x08 +'bong', # 0x09 +'boj', # 0x0a +'boc', # 0x0b +'bok', # 0x0c +'bot', # 0x0d +'bop', # 0x0e +'boh', # 0x0f +'bwa', # 0x10 +'bwag', # 0x11 +'bwagg', # 0x12 +'bwags', # 0x13 +'bwan', # 0x14 +'bwanj', # 0x15 +'bwanh', # 0x16 +'bwad', # 0x17 +'bwal', # 0x18 +'bwalg', # 0x19 +'bwalm', # 0x1a +'bwalb', # 0x1b +'bwals', # 0x1c +'bwalt', # 0x1d +'bwalp', # 0x1e +'bwalh', # 0x1f +'bwam', # 0x20 +'bwab', # 0x21 +'bwabs', # 0x22 +'bwas', # 0x23 +'bwass', # 0x24 +'bwang', # 0x25 +'bwaj', # 0x26 +'bwac', # 0x27 +'bwak', # 0x28 +'bwat', # 0x29 +'bwap', # 0x2a +'bwah', # 0x2b +'bwae', # 0x2c +'bwaeg', # 0x2d +'bwaegg', # 0x2e +'bwaegs', # 0x2f +'bwaen', # 0x30 +'bwaenj', # 0x31 +'bwaenh', # 0x32 +'bwaed', # 0x33 +'bwael', # 0x34 +'bwaelg', # 0x35 +'bwaelm', # 0x36 +'bwaelb', # 0x37 +'bwaels', # 0x38 +'bwaelt', # 0x39 +'bwaelp', # 0x3a +'bwaelh', # 0x3b +'bwaem', # 0x3c +'bwaeb', # 0x3d +'bwaebs', # 0x3e +'bwaes', # 0x3f +'bwaess', # 0x40 +'bwaeng', # 0x41 +'bwaej', # 0x42 +'bwaec', # 0x43 +'bwaek', # 0x44 +'bwaet', # 0x45 +'bwaep', # 0x46 +'bwaeh', # 0x47 +'boe', # 0x48 +'boeg', # 0x49 +'boegg', # 0x4a +'boegs', # 0x4b +'boen', # 0x4c +'boenj', # 0x4d +'boenh', # 0x4e +'boed', # 0x4f +'boel', # 0x50 +'boelg', # 0x51 +'boelm', # 0x52 +'boelb', # 0x53 +'boels', # 0x54 +'boelt', # 0x55 +'boelp', # 0x56 +'boelh', # 0x57 +'boem', # 0x58 +'boeb', # 0x59 +'boebs', # 0x5a +'boes', # 0x5b +'boess', # 0x5c +'boeng', # 0x5d +'boej', # 0x5e +'boec', # 0x5f +'boek', # 0x60 +'boet', # 0x61 +'boep', # 0x62 +'boeh', # 0x63 +'byo', # 0x64 +'byog', # 0x65 +'byogg', # 0x66 +'byogs', # 0x67 +'byon', # 0x68 +'byonj', # 0x69 +'byonh', # 0x6a +'byod', # 0x6b +'byol', # 0x6c +'byolg', # 0x6d +'byolm', # 0x6e +'byolb', # 0x6f +'byols', # 0x70 +'byolt', # 0x71 +'byolp', # 0x72 +'byolh', # 0x73 +'byom', # 0x74 +'byob', # 0x75 +'byobs', # 0x76 +'byos', # 0x77 +'byoss', # 0x78 +'byong', # 0x79 +'byoj', # 0x7a +'byoc', # 0x7b +'byok', # 0x7c +'byot', # 0x7d +'byop', # 0x7e +'byoh', # 0x7f +'bu', # 0x80 +'bug', # 0x81 +'bugg', # 0x82 +'bugs', # 0x83 +'bun', # 0x84 +'bunj', # 0x85 +'bunh', # 0x86 +'bud', # 0x87 +'bul', # 0x88 +'bulg', # 0x89 +'bulm', # 0x8a +'bulb', # 0x8b +'buls', # 0x8c +'bult', # 0x8d +'bulp', # 0x8e +'bulh', # 0x8f +'bum', # 0x90 +'bub', # 0x91 +'bubs', # 0x92 +'bus', # 0x93 +'buss', # 0x94 +'bung', # 0x95 +'buj', # 0x96 +'buc', # 0x97 +'buk', # 0x98 +'but', # 0x99 +'bup', # 0x9a +'buh', # 0x9b +'bweo', # 0x9c +'bweog', # 0x9d +'bweogg', # 0x9e +'bweogs', # 0x9f +'bweon', # 0xa0 +'bweonj', # 0xa1 +'bweonh', # 0xa2 +'bweod', # 0xa3 +'bweol', # 0xa4 +'bweolg', # 0xa5 +'bweolm', # 0xa6 +'bweolb', # 0xa7 +'bweols', # 0xa8 +'bweolt', # 0xa9 +'bweolp', # 0xaa +'bweolh', # 0xab +'bweom', # 0xac +'bweob', # 0xad +'bweobs', # 0xae +'bweos', # 0xaf +'bweoss', # 0xb0 +'bweong', # 0xb1 +'bweoj', # 0xb2 +'bweoc', # 0xb3 +'bweok', # 0xb4 +'bweot', # 0xb5 +'bweop', # 0xb6 +'bweoh', # 0xb7 +'bwe', # 0xb8 +'bweg', # 0xb9 +'bwegg', # 0xba +'bwegs', # 0xbb +'bwen', # 0xbc +'bwenj', # 0xbd +'bwenh', # 0xbe +'bwed', # 0xbf +'bwel', # 0xc0 +'bwelg', # 0xc1 +'bwelm', # 0xc2 +'bwelb', # 0xc3 +'bwels', # 0xc4 +'bwelt', # 0xc5 +'bwelp', # 0xc6 +'bwelh', # 0xc7 +'bwem', # 0xc8 +'bweb', # 0xc9 +'bwebs', # 0xca +'bwes', # 0xcb +'bwess', # 0xcc +'bweng', # 0xcd +'bwej', # 0xce +'bwec', # 0xcf +'bwek', # 0xd0 +'bwet', # 0xd1 +'bwep', # 0xd2 +'bweh', # 0xd3 +'bwi', # 0xd4 +'bwig', # 0xd5 +'bwigg', # 0xd6 +'bwigs', # 0xd7 +'bwin', # 0xd8 +'bwinj', # 0xd9 +'bwinh', # 0xda +'bwid', # 0xdb +'bwil', # 0xdc +'bwilg', # 0xdd +'bwilm', # 0xde +'bwilb', # 0xdf +'bwils', # 0xe0 +'bwilt', # 0xe1 +'bwilp', # 0xe2 +'bwilh', # 0xe3 +'bwim', # 0xe4 +'bwib', # 0xe5 +'bwibs', # 0xe6 +'bwis', # 0xe7 +'bwiss', # 0xe8 +'bwing', # 0xe9 +'bwij', # 0xea +'bwic', # 0xeb +'bwik', # 0xec +'bwit', # 0xed +'bwip', # 0xee +'bwih', # 0xef +'byu', # 0xf0 +'byug', # 0xf1 +'byugg', # 0xf2 +'byugs', # 0xf3 +'byun', # 0xf4 +'byunj', # 0xf5 +'byunh', # 0xf6 +'byud', # 0xf7 +'byul', # 0xf8 +'byulg', # 0xf9 +'byulm', # 0xfa +'byulb', # 0xfb +'byuls', # 0xfc +'byult', # 0xfd +'byulp', # 0xfe +'byulh', # 0xff +) diff --git a/nstock/modules/unidecode/x0be.py b/nstock/modules/unidecode/x0be.py new file mode 100644 index 0000000..85c184e --- /dev/null +++ b/nstock/modules/unidecode/x0be.py @@ -0,0 +1,258 @@ +data = ( +'byum', # 0x00 +'byub', # 0x01 +'byubs', # 0x02 +'byus', # 0x03 +'byuss', # 0x04 +'byung', # 0x05 +'byuj', # 0x06 +'byuc', # 0x07 +'byuk', # 0x08 +'byut', # 0x09 +'byup', # 0x0a +'byuh', # 0x0b +'beu', # 0x0c +'beug', # 0x0d +'beugg', # 0x0e +'beugs', # 0x0f +'beun', # 0x10 +'beunj', # 0x11 +'beunh', # 0x12 +'beud', # 0x13 +'beul', # 0x14 +'beulg', # 0x15 +'beulm', # 0x16 +'beulb', # 0x17 +'beuls', # 0x18 +'beult', # 0x19 +'beulp', # 0x1a +'beulh', # 0x1b +'beum', # 0x1c +'beub', # 0x1d +'beubs', # 0x1e +'beus', # 0x1f +'beuss', # 0x20 +'beung', # 0x21 +'beuj', # 0x22 +'beuc', # 0x23 +'beuk', # 0x24 +'beut', # 0x25 +'beup', # 0x26 +'beuh', # 0x27 +'byi', # 0x28 +'byig', # 0x29 +'byigg', # 0x2a +'byigs', # 0x2b +'byin', # 0x2c +'byinj', # 0x2d +'byinh', # 0x2e +'byid', # 0x2f +'byil', # 0x30 +'byilg', # 0x31 +'byilm', # 0x32 +'byilb', # 0x33 +'byils', # 0x34 +'byilt', # 0x35 +'byilp', # 0x36 +'byilh', # 0x37 +'byim', # 0x38 +'byib', # 0x39 +'byibs', # 0x3a +'byis', # 0x3b +'byiss', # 0x3c +'bying', # 0x3d +'byij', # 0x3e +'byic', # 0x3f +'byik', # 0x40 +'byit', # 0x41 +'byip', # 0x42 +'byih', # 0x43 +'bi', # 0x44 +'big', # 0x45 +'bigg', # 0x46 +'bigs', # 0x47 +'bin', # 0x48 +'binj', # 0x49 +'binh', # 0x4a +'bid', # 0x4b +'bil', # 0x4c +'bilg', # 0x4d +'bilm', # 0x4e +'bilb', # 0x4f +'bils', # 0x50 +'bilt', # 0x51 +'bilp', # 0x52 +'bilh', # 0x53 +'bim', # 0x54 +'bib', # 0x55 +'bibs', # 0x56 +'bis', # 0x57 +'biss', # 0x58 +'bing', # 0x59 +'bij', # 0x5a +'bic', # 0x5b +'bik', # 0x5c +'bit', # 0x5d +'bip', # 0x5e +'bih', # 0x5f +'bba', # 0x60 +'bbag', # 0x61 +'bbagg', # 0x62 +'bbags', # 0x63 +'bban', # 0x64 +'bbanj', # 0x65 +'bbanh', # 0x66 +'bbad', # 0x67 +'bbal', # 0x68 +'bbalg', # 0x69 +'bbalm', # 0x6a +'bbalb', # 0x6b +'bbals', # 0x6c +'bbalt', # 0x6d +'bbalp', # 0x6e +'bbalh', # 0x6f +'bbam', # 0x70 +'bbab', # 0x71 +'bbabs', # 0x72 +'bbas', # 0x73 +'bbass', # 0x74 +'bbang', # 0x75 +'bbaj', # 0x76 +'bbac', # 0x77 +'bbak', # 0x78 +'bbat', # 0x79 +'bbap', # 0x7a +'bbah', # 0x7b +'bbae', # 0x7c +'bbaeg', # 0x7d +'bbaegg', # 0x7e +'bbaegs', # 0x7f +'bbaen', # 0x80 +'bbaenj', # 0x81 +'bbaenh', # 0x82 +'bbaed', # 0x83 +'bbael', # 0x84 +'bbaelg', # 0x85 +'bbaelm', # 0x86 +'bbaelb', # 0x87 +'bbaels', # 0x88 +'bbaelt', # 0x89 +'bbaelp', # 0x8a +'bbaelh', # 0x8b +'bbaem', # 0x8c +'bbaeb', # 0x8d +'bbaebs', # 0x8e +'bbaes', # 0x8f +'bbaess', # 0x90 +'bbaeng', # 0x91 +'bbaej', # 0x92 +'bbaec', # 0x93 +'bbaek', # 0x94 +'bbaet', # 0x95 +'bbaep', # 0x96 +'bbaeh', # 0x97 +'bbya', # 0x98 +'bbyag', # 0x99 +'bbyagg', # 0x9a +'bbyags', # 0x9b +'bbyan', # 0x9c +'bbyanj', # 0x9d +'bbyanh', # 0x9e +'bbyad', # 0x9f +'bbyal', # 0xa0 +'bbyalg', # 0xa1 +'bbyalm', # 0xa2 +'bbyalb', # 0xa3 +'bbyals', # 0xa4 +'bbyalt', # 0xa5 +'bbyalp', # 0xa6 +'bbyalh', # 0xa7 +'bbyam', # 0xa8 +'bbyab', # 0xa9 +'bbyabs', # 0xaa +'bbyas', # 0xab +'bbyass', # 0xac +'bbyang', # 0xad +'bbyaj', # 0xae +'bbyac', # 0xaf +'bbyak', # 0xb0 +'bbyat', # 0xb1 +'bbyap', # 0xb2 +'bbyah', # 0xb3 +'bbyae', # 0xb4 +'bbyaeg', # 0xb5 +'bbyaegg', # 0xb6 +'bbyaegs', # 0xb7 +'bbyaen', # 0xb8 +'bbyaenj', # 0xb9 +'bbyaenh', # 0xba +'bbyaed', # 0xbb +'bbyael', # 0xbc +'bbyaelg', # 0xbd +'bbyaelm', # 0xbe +'bbyaelb', # 0xbf +'bbyaels', # 0xc0 +'bbyaelt', # 0xc1 +'bbyaelp', # 0xc2 +'bbyaelh', # 0xc3 +'bbyaem', # 0xc4 +'bbyaeb', # 0xc5 +'bbyaebs', # 0xc6 +'bbyaes', # 0xc7 +'bbyaess', # 0xc8 +'bbyaeng', # 0xc9 +'bbyaej', # 0xca +'bbyaec', # 0xcb +'bbyaek', # 0xcc +'bbyaet', # 0xcd +'bbyaep', # 0xce +'bbyaeh', # 0xcf +'bbeo', # 0xd0 +'bbeog', # 0xd1 +'bbeogg', # 0xd2 +'bbeogs', # 0xd3 +'bbeon', # 0xd4 +'bbeonj', # 0xd5 +'bbeonh', # 0xd6 +'bbeod', # 0xd7 +'bbeol', # 0xd8 +'bbeolg', # 0xd9 +'bbeolm', # 0xda +'bbeolb', # 0xdb +'bbeols', # 0xdc +'bbeolt', # 0xdd +'bbeolp', # 0xde +'bbeolh', # 0xdf +'bbeom', # 0xe0 +'bbeob', # 0xe1 +'bbeobs', # 0xe2 +'bbeos', # 0xe3 +'bbeoss', # 0xe4 +'bbeong', # 0xe5 +'bbeoj', # 0xe6 +'bbeoc', # 0xe7 +'bbeok', # 0xe8 +'bbeot', # 0xe9 +'bbeop', # 0xea +'bbeoh', # 0xeb +'bbe', # 0xec +'bbeg', # 0xed +'bbegg', # 0xee +'bbegs', # 0xef +'bben', # 0xf0 +'bbenj', # 0xf1 +'bbenh', # 0xf2 +'bbed', # 0xf3 +'bbel', # 0xf4 +'bbelg', # 0xf5 +'bbelm', # 0xf6 +'bbelb', # 0xf7 +'bbels', # 0xf8 +'bbelt', # 0xf9 +'bbelp', # 0xfa +'bbelh', # 0xfb +'bbem', # 0xfc +'bbeb', # 0xfd +'bbebs', # 0xfe +'bbes', # 0xff +) diff --git a/nstock/modules/unidecode/x0bf.py b/nstock/modules/unidecode/x0bf.py new file mode 100644 index 0000000..a7b3a71 --- /dev/null +++ b/nstock/modules/unidecode/x0bf.py @@ -0,0 +1,258 @@ +data = ( +'bbess', # 0x00 +'bbeng', # 0x01 +'bbej', # 0x02 +'bbec', # 0x03 +'bbek', # 0x04 +'bbet', # 0x05 +'bbep', # 0x06 +'bbeh', # 0x07 +'bbyeo', # 0x08 +'bbyeog', # 0x09 +'bbyeogg', # 0x0a +'bbyeogs', # 0x0b +'bbyeon', # 0x0c +'bbyeonj', # 0x0d +'bbyeonh', # 0x0e +'bbyeod', # 0x0f +'bbyeol', # 0x10 +'bbyeolg', # 0x11 +'bbyeolm', # 0x12 +'bbyeolb', # 0x13 +'bbyeols', # 0x14 +'bbyeolt', # 0x15 +'bbyeolp', # 0x16 +'bbyeolh', # 0x17 +'bbyeom', # 0x18 +'bbyeob', # 0x19 +'bbyeobs', # 0x1a +'bbyeos', # 0x1b +'bbyeoss', # 0x1c +'bbyeong', # 0x1d +'bbyeoj', # 0x1e +'bbyeoc', # 0x1f +'bbyeok', # 0x20 +'bbyeot', # 0x21 +'bbyeop', # 0x22 +'bbyeoh', # 0x23 +'bbye', # 0x24 +'bbyeg', # 0x25 +'bbyegg', # 0x26 +'bbyegs', # 0x27 +'bbyen', # 0x28 +'bbyenj', # 0x29 +'bbyenh', # 0x2a +'bbyed', # 0x2b +'bbyel', # 0x2c +'bbyelg', # 0x2d +'bbyelm', # 0x2e +'bbyelb', # 0x2f +'bbyels', # 0x30 +'bbyelt', # 0x31 +'bbyelp', # 0x32 +'bbyelh', # 0x33 +'bbyem', # 0x34 +'bbyeb', # 0x35 +'bbyebs', # 0x36 +'bbyes', # 0x37 +'bbyess', # 0x38 +'bbyeng', # 0x39 +'bbyej', # 0x3a +'bbyec', # 0x3b +'bbyek', # 0x3c +'bbyet', # 0x3d +'bbyep', # 0x3e +'bbyeh', # 0x3f +'bbo', # 0x40 +'bbog', # 0x41 +'bbogg', # 0x42 +'bbogs', # 0x43 +'bbon', # 0x44 +'bbonj', # 0x45 +'bbonh', # 0x46 +'bbod', # 0x47 +'bbol', # 0x48 +'bbolg', # 0x49 +'bbolm', # 0x4a +'bbolb', # 0x4b +'bbols', # 0x4c +'bbolt', # 0x4d +'bbolp', # 0x4e +'bbolh', # 0x4f +'bbom', # 0x50 +'bbob', # 0x51 +'bbobs', # 0x52 +'bbos', # 0x53 +'bboss', # 0x54 +'bbong', # 0x55 +'bboj', # 0x56 +'bboc', # 0x57 +'bbok', # 0x58 +'bbot', # 0x59 +'bbop', # 0x5a +'bboh', # 0x5b +'bbwa', # 0x5c +'bbwag', # 0x5d +'bbwagg', # 0x5e +'bbwags', # 0x5f +'bbwan', # 0x60 +'bbwanj', # 0x61 +'bbwanh', # 0x62 +'bbwad', # 0x63 +'bbwal', # 0x64 +'bbwalg', # 0x65 +'bbwalm', # 0x66 +'bbwalb', # 0x67 +'bbwals', # 0x68 +'bbwalt', # 0x69 +'bbwalp', # 0x6a +'bbwalh', # 0x6b +'bbwam', # 0x6c +'bbwab', # 0x6d +'bbwabs', # 0x6e +'bbwas', # 0x6f +'bbwass', # 0x70 +'bbwang', # 0x71 +'bbwaj', # 0x72 +'bbwac', # 0x73 +'bbwak', # 0x74 +'bbwat', # 0x75 +'bbwap', # 0x76 +'bbwah', # 0x77 +'bbwae', # 0x78 +'bbwaeg', # 0x79 +'bbwaegg', # 0x7a +'bbwaegs', # 0x7b +'bbwaen', # 0x7c +'bbwaenj', # 0x7d +'bbwaenh', # 0x7e +'bbwaed', # 0x7f +'bbwael', # 0x80 +'bbwaelg', # 0x81 +'bbwaelm', # 0x82 +'bbwaelb', # 0x83 +'bbwaels', # 0x84 +'bbwaelt', # 0x85 +'bbwaelp', # 0x86 +'bbwaelh', # 0x87 +'bbwaem', # 0x88 +'bbwaeb', # 0x89 +'bbwaebs', # 0x8a +'bbwaes', # 0x8b +'bbwaess', # 0x8c +'bbwaeng', # 0x8d +'bbwaej', # 0x8e +'bbwaec', # 0x8f +'bbwaek', # 0x90 +'bbwaet', # 0x91 +'bbwaep', # 0x92 +'bbwaeh', # 0x93 +'bboe', # 0x94 +'bboeg', # 0x95 +'bboegg', # 0x96 +'bboegs', # 0x97 +'bboen', # 0x98 +'bboenj', # 0x99 +'bboenh', # 0x9a +'bboed', # 0x9b +'bboel', # 0x9c +'bboelg', # 0x9d +'bboelm', # 0x9e +'bboelb', # 0x9f +'bboels', # 0xa0 +'bboelt', # 0xa1 +'bboelp', # 0xa2 +'bboelh', # 0xa3 +'bboem', # 0xa4 +'bboeb', # 0xa5 +'bboebs', # 0xa6 +'bboes', # 0xa7 +'bboess', # 0xa8 +'bboeng', # 0xa9 +'bboej', # 0xaa +'bboec', # 0xab +'bboek', # 0xac +'bboet', # 0xad +'bboep', # 0xae +'bboeh', # 0xaf +'bbyo', # 0xb0 +'bbyog', # 0xb1 +'bbyogg', # 0xb2 +'bbyogs', # 0xb3 +'bbyon', # 0xb4 +'bbyonj', # 0xb5 +'bbyonh', # 0xb6 +'bbyod', # 0xb7 +'bbyol', # 0xb8 +'bbyolg', # 0xb9 +'bbyolm', # 0xba +'bbyolb', # 0xbb +'bbyols', # 0xbc +'bbyolt', # 0xbd +'bbyolp', # 0xbe +'bbyolh', # 0xbf +'bbyom', # 0xc0 +'bbyob', # 0xc1 +'bbyobs', # 0xc2 +'bbyos', # 0xc3 +'bbyoss', # 0xc4 +'bbyong', # 0xc5 +'bbyoj', # 0xc6 +'bbyoc', # 0xc7 +'bbyok', # 0xc8 +'bbyot', # 0xc9 +'bbyop', # 0xca +'bbyoh', # 0xcb +'bbu', # 0xcc +'bbug', # 0xcd +'bbugg', # 0xce +'bbugs', # 0xcf +'bbun', # 0xd0 +'bbunj', # 0xd1 +'bbunh', # 0xd2 +'bbud', # 0xd3 +'bbul', # 0xd4 +'bbulg', # 0xd5 +'bbulm', # 0xd6 +'bbulb', # 0xd7 +'bbuls', # 0xd8 +'bbult', # 0xd9 +'bbulp', # 0xda +'bbulh', # 0xdb +'bbum', # 0xdc +'bbub', # 0xdd +'bbubs', # 0xde +'bbus', # 0xdf +'bbuss', # 0xe0 +'bbung', # 0xe1 +'bbuj', # 0xe2 +'bbuc', # 0xe3 +'bbuk', # 0xe4 +'bbut', # 0xe5 +'bbup', # 0xe6 +'bbuh', # 0xe7 +'bbweo', # 0xe8 +'bbweog', # 0xe9 +'bbweogg', # 0xea +'bbweogs', # 0xeb +'bbweon', # 0xec +'bbweonj', # 0xed +'bbweonh', # 0xee +'bbweod', # 0xef +'bbweol', # 0xf0 +'bbweolg', # 0xf1 +'bbweolm', # 0xf2 +'bbweolb', # 0xf3 +'bbweols', # 0xf4 +'bbweolt', # 0xf5 +'bbweolp', # 0xf6 +'bbweolh', # 0xf7 +'bbweom', # 0xf8 +'bbweob', # 0xf9 +'bbweobs', # 0xfa +'bbweos', # 0xfb +'bbweoss', # 0xfc +'bbweong', # 0xfd +'bbweoj', # 0xfe +'bbweoc', # 0xff +) diff --git a/nstock/modules/unidecode/x0c0.py b/nstock/modules/unidecode/x0c0.py new file mode 100644 index 0000000..35e5039 --- /dev/null +++ b/nstock/modules/unidecode/x0c0.py @@ -0,0 +1,258 @@ +data = ( +'bbweok', # 0x00 +'bbweot', # 0x01 +'bbweop', # 0x02 +'bbweoh', # 0x03 +'bbwe', # 0x04 +'bbweg', # 0x05 +'bbwegg', # 0x06 +'bbwegs', # 0x07 +'bbwen', # 0x08 +'bbwenj', # 0x09 +'bbwenh', # 0x0a +'bbwed', # 0x0b +'bbwel', # 0x0c +'bbwelg', # 0x0d +'bbwelm', # 0x0e +'bbwelb', # 0x0f +'bbwels', # 0x10 +'bbwelt', # 0x11 +'bbwelp', # 0x12 +'bbwelh', # 0x13 +'bbwem', # 0x14 +'bbweb', # 0x15 +'bbwebs', # 0x16 +'bbwes', # 0x17 +'bbwess', # 0x18 +'bbweng', # 0x19 +'bbwej', # 0x1a +'bbwec', # 0x1b +'bbwek', # 0x1c +'bbwet', # 0x1d +'bbwep', # 0x1e +'bbweh', # 0x1f +'bbwi', # 0x20 +'bbwig', # 0x21 +'bbwigg', # 0x22 +'bbwigs', # 0x23 +'bbwin', # 0x24 +'bbwinj', # 0x25 +'bbwinh', # 0x26 +'bbwid', # 0x27 +'bbwil', # 0x28 +'bbwilg', # 0x29 +'bbwilm', # 0x2a +'bbwilb', # 0x2b +'bbwils', # 0x2c +'bbwilt', # 0x2d +'bbwilp', # 0x2e +'bbwilh', # 0x2f +'bbwim', # 0x30 +'bbwib', # 0x31 +'bbwibs', # 0x32 +'bbwis', # 0x33 +'bbwiss', # 0x34 +'bbwing', # 0x35 +'bbwij', # 0x36 +'bbwic', # 0x37 +'bbwik', # 0x38 +'bbwit', # 0x39 +'bbwip', # 0x3a +'bbwih', # 0x3b +'bbyu', # 0x3c +'bbyug', # 0x3d +'bbyugg', # 0x3e +'bbyugs', # 0x3f +'bbyun', # 0x40 +'bbyunj', # 0x41 +'bbyunh', # 0x42 +'bbyud', # 0x43 +'bbyul', # 0x44 +'bbyulg', # 0x45 +'bbyulm', # 0x46 +'bbyulb', # 0x47 +'bbyuls', # 0x48 +'bbyult', # 0x49 +'bbyulp', # 0x4a +'bbyulh', # 0x4b +'bbyum', # 0x4c +'bbyub', # 0x4d +'bbyubs', # 0x4e +'bbyus', # 0x4f +'bbyuss', # 0x50 +'bbyung', # 0x51 +'bbyuj', # 0x52 +'bbyuc', # 0x53 +'bbyuk', # 0x54 +'bbyut', # 0x55 +'bbyup', # 0x56 +'bbyuh', # 0x57 +'bbeu', # 0x58 +'bbeug', # 0x59 +'bbeugg', # 0x5a +'bbeugs', # 0x5b +'bbeun', # 0x5c +'bbeunj', # 0x5d +'bbeunh', # 0x5e +'bbeud', # 0x5f +'bbeul', # 0x60 +'bbeulg', # 0x61 +'bbeulm', # 0x62 +'bbeulb', # 0x63 +'bbeuls', # 0x64 +'bbeult', # 0x65 +'bbeulp', # 0x66 +'bbeulh', # 0x67 +'bbeum', # 0x68 +'bbeub', # 0x69 +'bbeubs', # 0x6a +'bbeus', # 0x6b +'bbeuss', # 0x6c +'bbeung', # 0x6d +'bbeuj', # 0x6e +'bbeuc', # 0x6f +'bbeuk', # 0x70 +'bbeut', # 0x71 +'bbeup', # 0x72 +'bbeuh', # 0x73 +'bbyi', # 0x74 +'bbyig', # 0x75 +'bbyigg', # 0x76 +'bbyigs', # 0x77 +'bbyin', # 0x78 +'bbyinj', # 0x79 +'bbyinh', # 0x7a +'bbyid', # 0x7b +'bbyil', # 0x7c +'bbyilg', # 0x7d +'bbyilm', # 0x7e +'bbyilb', # 0x7f +'bbyils', # 0x80 +'bbyilt', # 0x81 +'bbyilp', # 0x82 +'bbyilh', # 0x83 +'bbyim', # 0x84 +'bbyib', # 0x85 +'bbyibs', # 0x86 +'bbyis', # 0x87 +'bbyiss', # 0x88 +'bbying', # 0x89 +'bbyij', # 0x8a +'bbyic', # 0x8b +'bbyik', # 0x8c +'bbyit', # 0x8d +'bbyip', # 0x8e +'bbyih', # 0x8f +'bbi', # 0x90 +'bbig', # 0x91 +'bbigg', # 0x92 +'bbigs', # 0x93 +'bbin', # 0x94 +'bbinj', # 0x95 +'bbinh', # 0x96 +'bbid', # 0x97 +'bbil', # 0x98 +'bbilg', # 0x99 +'bbilm', # 0x9a +'bbilb', # 0x9b +'bbils', # 0x9c +'bbilt', # 0x9d +'bbilp', # 0x9e +'bbilh', # 0x9f +'bbim', # 0xa0 +'bbib', # 0xa1 +'bbibs', # 0xa2 +'bbis', # 0xa3 +'bbiss', # 0xa4 +'bbing', # 0xa5 +'bbij', # 0xa6 +'bbic', # 0xa7 +'bbik', # 0xa8 +'bbit', # 0xa9 +'bbip', # 0xaa +'bbih', # 0xab +'sa', # 0xac +'sag', # 0xad +'sagg', # 0xae +'sags', # 0xaf +'san', # 0xb0 +'sanj', # 0xb1 +'sanh', # 0xb2 +'sad', # 0xb3 +'sal', # 0xb4 +'salg', # 0xb5 +'salm', # 0xb6 +'salb', # 0xb7 +'sals', # 0xb8 +'salt', # 0xb9 +'salp', # 0xba +'salh', # 0xbb +'sam', # 0xbc +'sab', # 0xbd +'sabs', # 0xbe +'sas', # 0xbf +'sass', # 0xc0 +'sang', # 0xc1 +'saj', # 0xc2 +'sac', # 0xc3 +'sak', # 0xc4 +'sat', # 0xc5 +'sap', # 0xc6 +'sah', # 0xc7 +'sae', # 0xc8 +'saeg', # 0xc9 +'saegg', # 0xca +'saegs', # 0xcb +'saen', # 0xcc +'saenj', # 0xcd +'saenh', # 0xce +'saed', # 0xcf +'sael', # 0xd0 +'saelg', # 0xd1 +'saelm', # 0xd2 +'saelb', # 0xd3 +'saels', # 0xd4 +'saelt', # 0xd5 +'saelp', # 0xd6 +'saelh', # 0xd7 +'saem', # 0xd8 +'saeb', # 0xd9 +'saebs', # 0xda +'saes', # 0xdb +'saess', # 0xdc +'saeng', # 0xdd +'saej', # 0xde +'saec', # 0xdf +'saek', # 0xe0 +'saet', # 0xe1 +'saep', # 0xe2 +'saeh', # 0xe3 +'sya', # 0xe4 +'syag', # 0xe5 +'syagg', # 0xe6 +'syags', # 0xe7 +'syan', # 0xe8 +'syanj', # 0xe9 +'syanh', # 0xea +'syad', # 0xeb +'syal', # 0xec +'syalg', # 0xed +'syalm', # 0xee +'syalb', # 0xef +'syals', # 0xf0 +'syalt', # 0xf1 +'syalp', # 0xf2 +'syalh', # 0xf3 +'syam', # 0xf4 +'syab', # 0xf5 +'syabs', # 0xf6 +'syas', # 0xf7 +'syass', # 0xf8 +'syang', # 0xf9 +'syaj', # 0xfa +'syac', # 0xfb +'syak', # 0xfc +'syat', # 0xfd +'syap', # 0xfe +'syah', # 0xff +) diff --git a/nstock/modules/unidecode/x0c1.py b/nstock/modules/unidecode/x0c1.py new file mode 100644 index 0000000..776847f --- /dev/null +++ b/nstock/modules/unidecode/x0c1.py @@ -0,0 +1,258 @@ +data = ( +'syae', # 0x00 +'syaeg', # 0x01 +'syaegg', # 0x02 +'syaegs', # 0x03 +'syaen', # 0x04 +'syaenj', # 0x05 +'syaenh', # 0x06 +'syaed', # 0x07 +'syael', # 0x08 +'syaelg', # 0x09 +'syaelm', # 0x0a +'syaelb', # 0x0b +'syaels', # 0x0c +'syaelt', # 0x0d +'syaelp', # 0x0e +'syaelh', # 0x0f +'syaem', # 0x10 +'syaeb', # 0x11 +'syaebs', # 0x12 +'syaes', # 0x13 +'syaess', # 0x14 +'syaeng', # 0x15 +'syaej', # 0x16 +'syaec', # 0x17 +'syaek', # 0x18 +'syaet', # 0x19 +'syaep', # 0x1a +'syaeh', # 0x1b +'seo', # 0x1c +'seog', # 0x1d +'seogg', # 0x1e +'seogs', # 0x1f +'seon', # 0x20 +'seonj', # 0x21 +'seonh', # 0x22 +'seod', # 0x23 +'seol', # 0x24 +'seolg', # 0x25 +'seolm', # 0x26 +'seolb', # 0x27 +'seols', # 0x28 +'seolt', # 0x29 +'seolp', # 0x2a +'seolh', # 0x2b +'seom', # 0x2c +'seob', # 0x2d +'seobs', # 0x2e +'seos', # 0x2f +'seoss', # 0x30 +'seong', # 0x31 +'seoj', # 0x32 +'seoc', # 0x33 +'seok', # 0x34 +'seot', # 0x35 +'seop', # 0x36 +'seoh', # 0x37 +'se', # 0x38 +'seg', # 0x39 +'segg', # 0x3a +'segs', # 0x3b +'sen', # 0x3c +'senj', # 0x3d +'senh', # 0x3e +'sed', # 0x3f +'sel', # 0x40 +'selg', # 0x41 +'selm', # 0x42 +'selb', # 0x43 +'sels', # 0x44 +'selt', # 0x45 +'selp', # 0x46 +'selh', # 0x47 +'sem', # 0x48 +'seb', # 0x49 +'sebs', # 0x4a +'ses', # 0x4b +'sess', # 0x4c +'seng', # 0x4d +'sej', # 0x4e +'sec', # 0x4f +'sek', # 0x50 +'set', # 0x51 +'sep', # 0x52 +'seh', # 0x53 +'syeo', # 0x54 +'syeog', # 0x55 +'syeogg', # 0x56 +'syeogs', # 0x57 +'syeon', # 0x58 +'syeonj', # 0x59 +'syeonh', # 0x5a +'syeod', # 0x5b +'syeol', # 0x5c +'syeolg', # 0x5d +'syeolm', # 0x5e +'syeolb', # 0x5f +'syeols', # 0x60 +'syeolt', # 0x61 +'syeolp', # 0x62 +'syeolh', # 0x63 +'syeom', # 0x64 +'syeob', # 0x65 +'syeobs', # 0x66 +'syeos', # 0x67 +'syeoss', # 0x68 +'syeong', # 0x69 +'syeoj', # 0x6a +'syeoc', # 0x6b +'syeok', # 0x6c +'syeot', # 0x6d +'syeop', # 0x6e +'syeoh', # 0x6f +'sye', # 0x70 +'syeg', # 0x71 +'syegg', # 0x72 +'syegs', # 0x73 +'syen', # 0x74 +'syenj', # 0x75 +'syenh', # 0x76 +'syed', # 0x77 +'syel', # 0x78 +'syelg', # 0x79 +'syelm', # 0x7a +'syelb', # 0x7b +'syels', # 0x7c +'syelt', # 0x7d +'syelp', # 0x7e +'syelh', # 0x7f +'syem', # 0x80 +'syeb', # 0x81 +'syebs', # 0x82 +'syes', # 0x83 +'syess', # 0x84 +'syeng', # 0x85 +'syej', # 0x86 +'syec', # 0x87 +'syek', # 0x88 +'syet', # 0x89 +'syep', # 0x8a +'syeh', # 0x8b +'so', # 0x8c +'sog', # 0x8d +'sogg', # 0x8e +'sogs', # 0x8f +'son', # 0x90 +'sonj', # 0x91 +'sonh', # 0x92 +'sod', # 0x93 +'sol', # 0x94 +'solg', # 0x95 +'solm', # 0x96 +'solb', # 0x97 +'sols', # 0x98 +'solt', # 0x99 +'solp', # 0x9a +'solh', # 0x9b +'som', # 0x9c +'sob', # 0x9d +'sobs', # 0x9e +'sos', # 0x9f +'soss', # 0xa0 +'song', # 0xa1 +'soj', # 0xa2 +'soc', # 0xa3 +'sok', # 0xa4 +'sot', # 0xa5 +'sop', # 0xa6 +'soh', # 0xa7 +'swa', # 0xa8 +'swag', # 0xa9 +'swagg', # 0xaa +'swags', # 0xab +'swan', # 0xac +'swanj', # 0xad +'swanh', # 0xae +'swad', # 0xaf +'swal', # 0xb0 +'swalg', # 0xb1 +'swalm', # 0xb2 +'swalb', # 0xb3 +'swals', # 0xb4 +'swalt', # 0xb5 +'swalp', # 0xb6 +'swalh', # 0xb7 +'swam', # 0xb8 +'swab', # 0xb9 +'swabs', # 0xba +'swas', # 0xbb +'swass', # 0xbc +'swang', # 0xbd +'swaj', # 0xbe +'swac', # 0xbf +'swak', # 0xc0 +'swat', # 0xc1 +'swap', # 0xc2 +'swah', # 0xc3 +'swae', # 0xc4 +'swaeg', # 0xc5 +'swaegg', # 0xc6 +'swaegs', # 0xc7 +'swaen', # 0xc8 +'swaenj', # 0xc9 +'swaenh', # 0xca +'swaed', # 0xcb +'swael', # 0xcc +'swaelg', # 0xcd +'swaelm', # 0xce +'swaelb', # 0xcf +'swaels', # 0xd0 +'swaelt', # 0xd1 +'swaelp', # 0xd2 +'swaelh', # 0xd3 +'swaem', # 0xd4 +'swaeb', # 0xd5 +'swaebs', # 0xd6 +'swaes', # 0xd7 +'swaess', # 0xd8 +'swaeng', # 0xd9 +'swaej', # 0xda +'swaec', # 0xdb +'swaek', # 0xdc +'swaet', # 0xdd +'swaep', # 0xde +'swaeh', # 0xdf +'soe', # 0xe0 +'soeg', # 0xe1 +'soegg', # 0xe2 +'soegs', # 0xe3 +'soen', # 0xe4 +'soenj', # 0xe5 +'soenh', # 0xe6 +'soed', # 0xe7 +'soel', # 0xe8 +'soelg', # 0xe9 +'soelm', # 0xea +'soelb', # 0xeb +'soels', # 0xec +'soelt', # 0xed +'soelp', # 0xee +'soelh', # 0xef +'soem', # 0xf0 +'soeb', # 0xf1 +'soebs', # 0xf2 +'soes', # 0xf3 +'soess', # 0xf4 +'soeng', # 0xf5 +'soej', # 0xf6 +'soec', # 0xf7 +'soek', # 0xf8 +'soet', # 0xf9 +'soep', # 0xfa +'soeh', # 0xfb +'syo', # 0xfc +'syog', # 0xfd +'syogg', # 0xfe +'syogs', # 0xff +) diff --git a/nstock/modules/unidecode/x0c2.py b/nstock/modules/unidecode/x0c2.py new file mode 100644 index 0000000..5b799cb --- /dev/null +++ b/nstock/modules/unidecode/x0c2.py @@ -0,0 +1,258 @@ +data = ( +'syon', # 0x00 +'syonj', # 0x01 +'syonh', # 0x02 +'syod', # 0x03 +'syol', # 0x04 +'syolg', # 0x05 +'syolm', # 0x06 +'syolb', # 0x07 +'syols', # 0x08 +'syolt', # 0x09 +'syolp', # 0x0a +'syolh', # 0x0b +'syom', # 0x0c +'syob', # 0x0d +'syobs', # 0x0e +'syos', # 0x0f +'syoss', # 0x10 +'syong', # 0x11 +'syoj', # 0x12 +'syoc', # 0x13 +'syok', # 0x14 +'syot', # 0x15 +'syop', # 0x16 +'syoh', # 0x17 +'su', # 0x18 +'sug', # 0x19 +'sugg', # 0x1a +'sugs', # 0x1b +'sun', # 0x1c +'sunj', # 0x1d +'sunh', # 0x1e +'sud', # 0x1f +'sul', # 0x20 +'sulg', # 0x21 +'sulm', # 0x22 +'sulb', # 0x23 +'suls', # 0x24 +'sult', # 0x25 +'sulp', # 0x26 +'sulh', # 0x27 +'sum', # 0x28 +'sub', # 0x29 +'subs', # 0x2a +'sus', # 0x2b +'suss', # 0x2c +'sung', # 0x2d +'suj', # 0x2e +'suc', # 0x2f +'suk', # 0x30 +'sut', # 0x31 +'sup', # 0x32 +'suh', # 0x33 +'sweo', # 0x34 +'sweog', # 0x35 +'sweogg', # 0x36 +'sweogs', # 0x37 +'sweon', # 0x38 +'sweonj', # 0x39 +'sweonh', # 0x3a +'sweod', # 0x3b +'sweol', # 0x3c +'sweolg', # 0x3d +'sweolm', # 0x3e +'sweolb', # 0x3f +'sweols', # 0x40 +'sweolt', # 0x41 +'sweolp', # 0x42 +'sweolh', # 0x43 +'sweom', # 0x44 +'sweob', # 0x45 +'sweobs', # 0x46 +'sweos', # 0x47 +'sweoss', # 0x48 +'sweong', # 0x49 +'sweoj', # 0x4a +'sweoc', # 0x4b +'sweok', # 0x4c +'sweot', # 0x4d +'sweop', # 0x4e +'sweoh', # 0x4f +'swe', # 0x50 +'sweg', # 0x51 +'swegg', # 0x52 +'swegs', # 0x53 +'swen', # 0x54 +'swenj', # 0x55 +'swenh', # 0x56 +'swed', # 0x57 +'swel', # 0x58 +'swelg', # 0x59 +'swelm', # 0x5a +'swelb', # 0x5b +'swels', # 0x5c +'swelt', # 0x5d +'swelp', # 0x5e +'swelh', # 0x5f +'swem', # 0x60 +'sweb', # 0x61 +'swebs', # 0x62 +'swes', # 0x63 +'swess', # 0x64 +'sweng', # 0x65 +'swej', # 0x66 +'swec', # 0x67 +'swek', # 0x68 +'swet', # 0x69 +'swep', # 0x6a +'sweh', # 0x6b +'swi', # 0x6c +'swig', # 0x6d +'swigg', # 0x6e +'swigs', # 0x6f +'swin', # 0x70 +'swinj', # 0x71 +'swinh', # 0x72 +'swid', # 0x73 +'swil', # 0x74 +'swilg', # 0x75 +'swilm', # 0x76 +'swilb', # 0x77 +'swils', # 0x78 +'swilt', # 0x79 +'swilp', # 0x7a +'swilh', # 0x7b +'swim', # 0x7c +'swib', # 0x7d +'swibs', # 0x7e +'swis', # 0x7f +'swiss', # 0x80 +'swing', # 0x81 +'swij', # 0x82 +'swic', # 0x83 +'swik', # 0x84 +'swit', # 0x85 +'swip', # 0x86 +'swih', # 0x87 +'syu', # 0x88 +'syug', # 0x89 +'syugg', # 0x8a +'syugs', # 0x8b +'syun', # 0x8c +'syunj', # 0x8d +'syunh', # 0x8e +'syud', # 0x8f +'syul', # 0x90 +'syulg', # 0x91 +'syulm', # 0x92 +'syulb', # 0x93 +'syuls', # 0x94 +'syult', # 0x95 +'syulp', # 0x96 +'syulh', # 0x97 +'syum', # 0x98 +'syub', # 0x99 +'syubs', # 0x9a +'syus', # 0x9b +'syuss', # 0x9c +'syung', # 0x9d +'syuj', # 0x9e +'syuc', # 0x9f +'syuk', # 0xa0 +'syut', # 0xa1 +'syup', # 0xa2 +'syuh', # 0xa3 +'seu', # 0xa4 +'seug', # 0xa5 +'seugg', # 0xa6 +'seugs', # 0xa7 +'seun', # 0xa8 +'seunj', # 0xa9 +'seunh', # 0xaa +'seud', # 0xab +'seul', # 0xac +'seulg', # 0xad +'seulm', # 0xae +'seulb', # 0xaf +'seuls', # 0xb0 +'seult', # 0xb1 +'seulp', # 0xb2 +'seulh', # 0xb3 +'seum', # 0xb4 +'seub', # 0xb5 +'seubs', # 0xb6 +'seus', # 0xb7 +'seuss', # 0xb8 +'seung', # 0xb9 +'seuj', # 0xba +'seuc', # 0xbb +'seuk', # 0xbc +'seut', # 0xbd +'seup', # 0xbe +'seuh', # 0xbf +'syi', # 0xc0 +'syig', # 0xc1 +'syigg', # 0xc2 +'syigs', # 0xc3 +'syin', # 0xc4 +'syinj', # 0xc5 +'syinh', # 0xc6 +'syid', # 0xc7 +'syil', # 0xc8 +'syilg', # 0xc9 +'syilm', # 0xca +'syilb', # 0xcb +'syils', # 0xcc +'syilt', # 0xcd +'syilp', # 0xce +'syilh', # 0xcf +'syim', # 0xd0 +'syib', # 0xd1 +'syibs', # 0xd2 +'syis', # 0xd3 +'syiss', # 0xd4 +'sying', # 0xd5 +'syij', # 0xd6 +'syic', # 0xd7 +'syik', # 0xd8 +'syit', # 0xd9 +'syip', # 0xda +'syih', # 0xdb +'si', # 0xdc +'sig', # 0xdd +'sigg', # 0xde +'sigs', # 0xdf +'sin', # 0xe0 +'sinj', # 0xe1 +'sinh', # 0xe2 +'sid', # 0xe3 +'sil', # 0xe4 +'silg', # 0xe5 +'silm', # 0xe6 +'silb', # 0xe7 +'sils', # 0xe8 +'silt', # 0xe9 +'silp', # 0xea +'silh', # 0xeb +'sim', # 0xec +'sib', # 0xed +'sibs', # 0xee +'sis', # 0xef +'siss', # 0xf0 +'sing', # 0xf1 +'sij', # 0xf2 +'sic', # 0xf3 +'sik', # 0xf4 +'sit', # 0xf5 +'sip', # 0xf6 +'sih', # 0xf7 +'ssa', # 0xf8 +'ssag', # 0xf9 +'ssagg', # 0xfa +'ssags', # 0xfb +'ssan', # 0xfc +'ssanj', # 0xfd +'ssanh', # 0xfe +'ssad', # 0xff +) diff --git a/nstock/modules/unidecode/x0c3.py b/nstock/modules/unidecode/x0c3.py new file mode 100644 index 0000000..bc81d64 --- /dev/null +++ b/nstock/modules/unidecode/x0c3.py @@ -0,0 +1,258 @@ +data = ( +'ssal', # 0x00 +'ssalg', # 0x01 +'ssalm', # 0x02 +'ssalb', # 0x03 +'ssals', # 0x04 +'ssalt', # 0x05 +'ssalp', # 0x06 +'ssalh', # 0x07 +'ssam', # 0x08 +'ssab', # 0x09 +'ssabs', # 0x0a +'ssas', # 0x0b +'ssass', # 0x0c +'ssang', # 0x0d +'ssaj', # 0x0e +'ssac', # 0x0f +'ssak', # 0x10 +'ssat', # 0x11 +'ssap', # 0x12 +'ssah', # 0x13 +'ssae', # 0x14 +'ssaeg', # 0x15 +'ssaegg', # 0x16 +'ssaegs', # 0x17 +'ssaen', # 0x18 +'ssaenj', # 0x19 +'ssaenh', # 0x1a +'ssaed', # 0x1b +'ssael', # 0x1c +'ssaelg', # 0x1d +'ssaelm', # 0x1e +'ssaelb', # 0x1f +'ssaels', # 0x20 +'ssaelt', # 0x21 +'ssaelp', # 0x22 +'ssaelh', # 0x23 +'ssaem', # 0x24 +'ssaeb', # 0x25 +'ssaebs', # 0x26 +'ssaes', # 0x27 +'ssaess', # 0x28 +'ssaeng', # 0x29 +'ssaej', # 0x2a +'ssaec', # 0x2b +'ssaek', # 0x2c +'ssaet', # 0x2d +'ssaep', # 0x2e +'ssaeh', # 0x2f +'ssya', # 0x30 +'ssyag', # 0x31 +'ssyagg', # 0x32 +'ssyags', # 0x33 +'ssyan', # 0x34 +'ssyanj', # 0x35 +'ssyanh', # 0x36 +'ssyad', # 0x37 +'ssyal', # 0x38 +'ssyalg', # 0x39 +'ssyalm', # 0x3a +'ssyalb', # 0x3b +'ssyals', # 0x3c +'ssyalt', # 0x3d +'ssyalp', # 0x3e +'ssyalh', # 0x3f +'ssyam', # 0x40 +'ssyab', # 0x41 +'ssyabs', # 0x42 +'ssyas', # 0x43 +'ssyass', # 0x44 +'ssyang', # 0x45 +'ssyaj', # 0x46 +'ssyac', # 0x47 +'ssyak', # 0x48 +'ssyat', # 0x49 +'ssyap', # 0x4a +'ssyah', # 0x4b +'ssyae', # 0x4c +'ssyaeg', # 0x4d +'ssyaegg', # 0x4e +'ssyaegs', # 0x4f +'ssyaen', # 0x50 +'ssyaenj', # 0x51 +'ssyaenh', # 0x52 +'ssyaed', # 0x53 +'ssyael', # 0x54 +'ssyaelg', # 0x55 +'ssyaelm', # 0x56 +'ssyaelb', # 0x57 +'ssyaels', # 0x58 +'ssyaelt', # 0x59 +'ssyaelp', # 0x5a +'ssyaelh', # 0x5b +'ssyaem', # 0x5c +'ssyaeb', # 0x5d +'ssyaebs', # 0x5e +'ssyaes', # 0x5f +'ssyaess', # 0x60 +'ssyaeng', # 0x61 +'ssyaej', # 0x62 +'ssyaec', # 0x63 +'ssyaek', # 0x64 +'ssyaet', # 0x65 +'ssyaep', # 0x66 +'ssyaeh', # 0x67 +'sseo', # 0x68 +'sseog', # 0x69 +'sseogg', # 0x6a +'sseogs', # 0x6b +'sseon', # 0x6c +'sseonj', # 0x6d +'sseonh', # 0x6e +'sseod', # 0x6f +'sseol', # 0x70 +'sseolg', # 0x71 +'sseolm', # 0x72 +'sseolb', # 0x73 +'sseols', # 0x74 +'sseolt', # 0x75 +'sseolp', # 0x76 +'sseolh', # 0x77 +'sseom', # 0x78 +'sseob', # 0x79 +'sseobs', # 0x7a +'sseos', # 0x7b +'sseoss', # 0x7c +'sseong', # 0x7d +'sseoj', # 0x7e +'sseoc', # 0x7f +'sseok', # 0x80 +'sseot', # 0x81 +'sseop', # 0x82 +'sseoh', # 0x83 +'sse', # 0x84 +'sseg', # 0x85 +'ssegg', # 0x86 +'ssegs', # 0x87 +'ssen', # 0x88 +'ssenj', # 0x89 +'ssenh', # 0x8a +'ssed', # 0x8b +'ssel', # 0x8c +'sselg', # 0x8d +'sselm', # 0x8e +'sselb', # 0x8f +'ssels', # 0x90 +'sselt', # 0x91 +'sselp', # 0x92 +'sselh', # 0x93 +'ssem', # 0x94 +'sseb', # 0x95 +'ssebs', # 0x96 +'sses', # 0x97 +'ssess', # 0x98 +'sseng', # 0x99 +'ssej', # 0x9a +'ssec', # 0x9b +'ssek', # 0x9c +'sset', # 0x9d +'ssep', # 0x9e +'sseh', # 0x9f +'ssyeo', # 0xa0 +'ssyeog', # 0xa1 +'ssyeogg', # 0xa2 +'ssyeogs', # 0xa3 +'ssyeon', # 0xa4 +'ssyeonj', # 0xa5 +'ssyeonh', # 0xa6 +'ssyeod', # 0xa7 +'ssyeol', # 0xa8 +'ssyeolg', # 0xa9 +'ssyeolm', # 0xaa +'ssyeolb', # 0xab +'ssyeols', # 0xac +'ssyeolt', # 0xad +'ssyeolp', # 0xae +'ssyeolh', # 0xaf +'ssyeom', # 0xb0 +'ssyeob', # 0xb1 +'ssyeobs', # 0xb2 +'ssyeos', # 0xb3 +'ssyeoss', # 0xb4 +'ssyeong', # 0xb5 +'ssyeoj', # 0xb6 +'ssyeoc', # 0xb7 +'ssyeok', # 0xb8 +'ssyeot', # 0xb9 +'ssyeop', # 0xba +'ssyeoh', # 0xbb +'ssye', # 0xbc +'ssyeg', # 0xbd +'ssyegg', # 0xbe +'ssyegs', # 0xbf +'ssyen', # 0xc0 +'ssyenj', # 0xc1 +'ssyenh', # 0xc2 +'ssyed', # 0xc3 +'ssyel', # 0xc4 +'ssyelg', # 0xc5 +'ssyelm', # 0xc6 +'ssyelb', # 0xc7 +'ssyels', # 0xc8 +'ssyelt', # 0xc9 +'ssyelp', # 0xca +'ssyelh', # 0xcb +'ssyem', # 0xcc +'ssyeb', # 0xcd +'ssyebs', # 0xce +'ssyes', # 0xcf +'ssyess', # 0xd0 +'ssyeng', # 0xd1 +'ssyej', # 0xd2 +'ssyec', # 0xd3 +'ssyek', # 0xd4 +'ssyet', # 0xd5 +'ssyep', # 0xd6 +'ssyeh', # 0xd7 +'sso', # 0xd8 +'ssog', # 0xd9 +'ssogg', # 0xda +'ssogs', # 0xdb +'sson', # 0xdc +'ssonj', # 0xdd +'ssonh', # 0xde +'ssod', # 0xdf +'ssol', # 0xe0 +'ssolg', # 0xe1 +'ssolm', # 0xe2 +'ssolb', # 0xe3 +'ssols', # 0xe4 +'ssolt', # 0xe5 +'ssolp', # 0xe6 +'ssolh', # 0xe7 +'ssom', # 0xe8 +'ssob', # 0xe9 +'ssobs', # 0xea +'ssos', # 0xeb +'ssoss', # 0xec +'ssong', # 0xed +'ssoj', # 0xee +'ssoc', # 0xef +'ssok', # 0xf0 +'ssot', # 0xf1 +'ssop', # 0xf2 +'ssoh', # 0xf3 +'sswa', # 0xf4 +'sswag', # 0xf5 +'sswagg', # 0xf6 +'sswags', # 0xf7 +'sswan', # 0xf8 +'sswanj', # 0xf9 +'sswanh', # 0xfa +'sswad', # 0xfb +'sswal', # 0xfc +'sswalg', # 0xfd +'sswalm', # 0xfe +'sswalb', # 0xff +) diff --git a/nstock/modules/unidecode/x0c4.py b/nstock/modules/unidecode/x0c4.py new file mode 100644 index 0000000..6288ca6 --- /dev/null +++ b/nstock/modules/unidecode/x0c4.py @@ -0,0 +1,258 @@ +data = ( +'sswals', # 0x00 +'sswalt', # 0x01 +'sswalp', # 0x02 +'sswalh', # 0x03 +'sswam', # 0x04 +'sswab', # 0x05 +'sswabs', # 0x06 +'sswas', # 0x07 +'sswass', # 0x08 +'sswang', # 0x09 +'sswaj', # 0x0a +'sswac', # 0x0b +'sswak', # 0x0c +'sswat', # 0x0d +'sswap', # 0x0e +'sswah', # 0x0f +'sswae', # 0x10 +'sswaeg', # 0x11 +'sswaegg', # 0x12 +'sswaegs', # 0x13 +'sswaen', # 0x14 +'sswaenj', # 0x15 +'sswaenh', # 0x16 +'sswaed', # 0x17 +'sswael', # 0x18 +'sswaelg', # 0x19 +'sswaelm', # 0x1a +'sswaelb', # 0x1b +'sswaels', # 0x1c +'sswaelt', # 0x1d +'sswaelp', # 0x1e +'sswaelh', # 0x1f +'sswaem', # 0x20 +'sswaeb', # 0x21 +'sswaebs', # 0x22 +'sswaes', # 0x23 +'sswaess', # 0x24 +'sswaeng', # 0x25 +'sswaej', # 0x26 +'sswaec', # 0x27 +'sswaek', # 0x28 +'sswaet', # 0x29 +'sswaep', # 0x2a +'sswaeh', # 0x2b +'ssoe', # 0x2c +'ssoeg', # 0x2d +'ssoegg', # 0x2e +'ssoegs', # 0x2f +'ssoen', # 0x30 +'ssoenj', # 0x31 +'ssoenh', # 0x32 +'ssoed', # 0x33 +'ssoel', # 0x34 +'ssoelg', # 0x35 +'ssoelm', # 0x36 +'ssoelb', # 0x37 +'ssoels', # 0x38 +'ssoelt', # 0x39 +'ssoelp', # 0x3a +'ssoelh', # 0x3b +'ssoem', # 0x3c +'ssoeb', # 0x3d +'ssoebs', # 0x3e +'ssoes', # 0x3f +'ssoess', # 0x40 +'ssoeng', # 0x41 +'ssoej', # 0x42 +'ssoec', # 0x43 +'ssoek', # 0x44 +'ssoet', # 0x45 +'ssoep', # 0x46 +'ssoeh', # 0x47 +'ssyo', # 0x48 +'ssyog', # 0x49 +'ssyogg', # 0x4a +'ssyogs', # 0x4b +'ssyon', # 0x4c +'ssyonj', # 0x4d +'ssyonh', # 0x4e +'ssyod', # 0x4f +'ssyol', # 0x50 +'ssyolg', # 0x51 +'ssyolm', # 0x52 +'ssyolb', # 0x53 +'ssyols', # 0x54 +'ssyolt', # 0x55 +'ssyolp', # 0x56 +'ssyolh', # 0x57 +'ssyom', # 0x58 +'ssyob', # 0x59 +'ssyobs', # 0x5a +'ssyos', # 0x5b +'ssyoss', # 0x5c +'ssyong', # 0x5d +'ssyoj', # 0x5e +'ssyoc', # 0x5f +'ssyok', # 0x60 +'ssyot', # 0x61 +'ssyop', # 0x62 +'ssyoh', # 0x63 +'ssu', # 0x64 +'ssug', # 0x65 +'ssugg', # 0x66 +'ssugs', # 0x67 +'ssun', # 0x68 +'ssunj', # 0x69 +'ssunh', # 0x6a +'ssud', # 0x6b +'ssul', # 0x6c +'ssulg', # 0x6d +'ssulm', # 0x6e +'ssulb', # 0x6f +'ssuls', # 0x70 +'ssult', # 0x71 +'ssulp', # 0x72 +'ssulh', # 0x73 +'ssum', # 0x74 +'ssub', # 0x75 +'ssubs', # 0x76 +'ssus', # 0x77 +'ssuss', # 0x78 +'ssung', # 0x79 +'ssuj', # 0x7a +'ssuc', # 0x7b +'ssuk', # 0x7c +'ssut', # 0x7d +'ssup', # 0x7e +'ssuh', # 0x7f +'ssweo', # 0x80 +'ssweog', # 0x81 +'ssweogg', # 0x82 +'ssweogs', # 0x83 +'ssweon', # 0x84 +'ssweonj', # 0x85 +'ssweonh', # 0x86 +'ssweod', # 0x87 +'ssweol', # 0x88 +'ssweolg', # 0x89 +'ssweolm', # 0x8a +'ssweolb', # 0x8b +'ssweols', # 0x8c +'ssweolt', # 0x8d +'ssweolp', # 0x8e +'ssweolh', # 0x8f +'ssweom', # 0x90 +'ssweob', # 0x91 +'ssweobs', # 0x92 +'ssweos', # 0x93 +'ssweoss', # 0x94 +'ssweong', # 0x95 +'ssweoj', # 0x96 +'ssweoc', # 0x97 +'ssweok', # 0x98 +'ssweot', # 0x99 +'ssweop', # 0x9a +'ssweoh', # 0x9b +'sswe', # 0x9c +'ssweg', # 0x9d +'sswegg', # 0x9e +'sswegs', # 0x9f +'sswen', # 0xa0 +'sswenj', # 0xa1 +'sswenh', # 0xa2 +'sswed', # 0xa3 +'sswel', # 0xa4 +'sswelg', # 0xa5 +'sswelm', # 0xa6 +'sswelb', # 0xa7 +'sswels', # 0xa8 +'sswelt', # 0xa9 +'sswelp', # 0xaa +'sswelh', # 0xab +'sswem', # 0xac +'ssweb', # 0xad +'sswebs', # 0xae +'sswes', # 0xaf +'sswess', # 0xb0 +'ssweng', # 0xb1 +'sswej', # 0xb2 +'sswec', # 0xb3 +'sswek', # 0xb4 +'sswet', # 0xb5 +'sswep', # 0xb6 +'ssweh', # 0xb7 +'sswi', # 0xb8 +'sswig', # 0xb9 +'sswigg', # 0xba +'sswigs', # 0xbb +'sswin', # 0xbc +'sswinj', # 0xbd +'sswinh', # 0xbe +'sswid', # 0xbf +'sswil', # 0xc0 +'sswilg', # 0xc1 +'sswilm', # 0xc2 +'sswilb', # 0xc3 +'sswils', # 0xc4 +'sswilt', # 0xc5 +'sswilp', # 0xc6 +'sswilh', # 0xc7 +'sswim', # 0xc8 +'sswib', # 0xc9 +'sswibs', # 0xca +'sswis', # 0xcb +'sswiss', # 0xcc +'sswing', # 0xcd +'sswij', # 0xce +'sswic', # 0xcf +'sswik', # 0xd0 +'sswit', # 0xd1 +'sswip', # 0xd2 +'sswih', # 0xd3 +'ssyu', # 0xd4 +'ssyug', # 0xd5 +'ssyugg', # 0xd6 +'ssyugs', # 0xd7 +'ssyun', # 0xd8 +'ssyunj', # 0xd9 +'ssyunh', # 0xda +'ssyud', # 0xdb +'ssyul', # 0xdc +'ssyulg', # 0xdd +'ssyulm', # 0xde +'ssyulb', # 0xdf +'ssyuls', # 0xe0 +'ssyult', # 0xe1 +'ssyulp', # 0xe2 +'ssyulh', # 0xe3 +'ssyum', # 0xe4 +'ssyub', # 0xe5 +'ssyubs', # 0xe6 +'ssyus', # 0xe7 +'ssyuss', # 0xe8 +'ssyung', # 0xe9 +'ssyuj', # 0xea +'ssyuc', # 0xeb +'ssyuk', # 0xec +'ssyut', # 0xed +'ssyup', # 0xee +'ssyuh', # 0xef +'sseu', # 0xf0 +'sseug', # 0xf1 +'sseugg', # 0xf2 +'sseugs', # 0xf3 +'sseun', # 0xf4 +'sseunj', # 0xf5 +'sseunh', # 0xf6 +'sseud', # 0xf7 +'sseul', # 0xf8 +'sseulg', # 0xf9 +'sseulm', # 0xfa +'sseulb', # 0xfb +'sseuls', # 0xfc +'sseult', # 0xfd +'sseulp', # 0xfe +'sseulh', # 0xff +) diff --git a/nstock/modules/unidecode/x0c5.py b/nstock/modules/unidecode/x0c5.py new file mode 100644 index 0000000..3f4778e --- /dev/null +++ b/nstock/modules/unidecode/x0c5.py @@ -0,0 +1,258 @@ +data = ( +'sseum', # 0x00 +'sseub', # 0x01 +'sseubs', # 0x02 +'sseus', # 0x03 +'sseuss', # 0x04 +'sseung', # 0x05 +'sseuj', # 0x06 +'sseuc', # 0x07 +'sseuk', # 0x08 +'sseut', # 0x09 +'sseup', # 0x0a +'sseuh', # 0x0b +'ssyi', # 0x0c +'ssyig', # 0x0d +'ssyigg', # 0x0e +'ssyigs', # 0x0f +'ssyin', # 0x10 +'ssyinj', # 0x11 +'ssyinh', # 0x12 +'ssyid', # 0x13 +'ssyil', # 0x14 +'ssyilg', # 0x15 +'ssyilm', # 0x16 +'ssyilb', # 0x17 +'ssyils', # 0x18 +'ssyilt', # 0x19 +'ssyilp', # 0x1a +'ssyilh', # 0x1b +'ssyim', # 0x1c +'ssyib', # 0x1d +'ssyibs', # 0x1e +'ssyis', # 0x1f +'ssyiss', # 0x20 +'ssying', # 0x21 +'ssyij', # 0x22 +'ssyic', # 0x23 +'ssyik', # 0x24 +'ssyit', # 0x25 +'ssyip', # 0x26 +'ssyih', # 0x27 +'ssi', # 0x28 +'ssig', # 0x29 +'ssigg', # 0x2a +'ssigs', # 0x2b +'ssin', # 0x2c +'ssinj', # 0x2d +'ssinh', # 0x2e +'ssid', # 0x2f +'ssil', # 0x30 +'ssilg', # 0x31 +'ssilm', # 0x32 +'ssilb', # 0x33 +'ssils', # 0x34 +'ssilt', # 0x35 +'ssilp', # 0x36 +'ssilh', # 0x37 +'ssim', # 0x38 +'ssib', # 0x39 +'ssibs', # 0x3a +'ssis', # 0x3b +'ssiss', # 0x3c +'ssing', # 0x3d +'ssij', # 0x3e +'ssic', # 0x3f +'ssik', # 0x40 +'ssit', # 0x41 +'ssip', # 0x42 +'ssih', # 0x43 +'a', # 0x44 +'ag', # 0x45 +'agg', # 0x46 +'ags', # 0x47 +'an', # 0x48 +'anj', # 0x49 +'anh', # 0x4a +'ad', # 0x4b +'al', # 0x4c +'alg', # 0x4d +'alm', # 0x4e +'alb', # 0x4f +'als', # 0x50 +'alt', # 0x51 +'alp', # 0x52 +'alh', # 0x53 +'am', # 0x54 +'ab', # 0x55 +'abs', # 0x56 +'as', # 0x57 +'ass', # 0x58 +'ang', # 0x59 +'aj', # 0x5a +'ac', # 0x5b +'ak', # 0x5c +'at', # 0x5d +'ap', # 0x5e +'ah', # 0x5f +'ae', # 0x60 +'aeg', # 0x61 +'aegg', # 0x62 +'aegs', # 0x63 +'aen', # 0x64 +'aenj', # 0x65 +'aenh', # 0x66 +'aed', # 0x67 +'ael', # 0x68 +'aelg', # 0x69 +'aelm', # 0x6a +'aelb', # 0x6b +'aels', # 0x6c +'aelt', # 0x6d +'aelp', # 0x6e +'aelh', # 0x6f +'aem', # 0x70 +'aeb', # 0x71 +'aebs', # 0x72 +'aes', # 0x73 +'aess', # 0x74 +'aeng', # 0x75 +'aej', # 0x76 +'aec', # 0x77 +'aek', # 0x78 +'aet', # 0x79 +'aep', # 0x7a +'aeh', # 0x7b +'ya', # 0x7c +'yag', # 0x7d +'yagg', # 0x7e +'yags', # 0x7f +'yan', # 0x80 +'yanj', # 0x81 +'yanh', # 0x82 +'yad', # 0x83 +'yal', # 0x84 +'yalg', # 0x85 +'yalm', # 0x86 +'yalb', # 0x87 +'yals', # 0x88 +'yalt', # 0x89 +'yalp', # 0x8a +'yalh', # 0x8b +'yam', # 0x8c +'yab', # 0x8d +'yabs', # 0x8e +'yas', # 0x8f +'yass', # 0x90 +'yang', # 0x91 +'yaj', # 0x92 +'yac', # 0x93 +'yak', # 0x94 +'yat', # 0x95 +'yap', # 0x96 +'yah', # 0x97 +'yae', # 0x98 +'yaeg', # 0x99 +'yaegg', # 0x9a +'yaegs', # 0x9b +'yaen', # 0x9c +'yaenj', # 0x9d +'yaenh', # 0x9e +'yaed', # 0x9f +'yael', # 0xa0 +'yaelg', # 0xa1 +'yaelm', # 0xa2 +'yaelb', # 0xa3 +'yaels', # 0xa4 +'yaelt', # 0xa5 +'yaelp', # 0xa6 +'yaelh', # 0xa7 +'yaem', # 0xa8 +'yaeb', # 0xa9 +'yaebs', # 0xaa +'yaes', # 0xab +'yaess', # 0xac +'yaeng', # 0xad +'yaej', # 0xae +'yaec', # 0xaf +'yaek', # 0xb0 +'yaet', # 0xb1 +'yaep', # 0xb2 +'yaeh', # 0xb3 +'eo', # 0xb4 +'eog', # 0xb5 +'eogg', # 0xb6 +'eogs', # 0xb7 +'eon', # 0xb8 +'eonj', # 0xb9 +'eonh', # 0xba +'eod', # 0xbb +'eol', # 0xbc +'eolg', # 0xbd +'eolm', # 0xbe +'eolb', # 0xbf +'eols', # 0xc0 +'eolt', # 0xc1 +'eolp', # 0xc2 +'eolh', # 0xc3 +'eom', # 0xc4 +'eob', # 0xc5 +'eobs', # 0xc6 +'eos', # 0xc7 +'eoss', # 0xc8 +'eong', # 0xc9 +'eoj', # 0xca +'eoc', # 0xcb +'eok', # 0xcc +'eot', # 0xcd +'eop', # 0xce +'eoh', # 0xcf +'e', # 0xd0 +'eg', # 0xd1 +'egg', # 0xd2 +'egs', # 0xd3 +'en', # 0xd4 +'enj', # 0xd5 +'enh', # 0xd6 +'ed', # 0xd7 +'el', # 0xd8 +'elg', # 0xd9 +'elm', # 0xda +'elb', # 0xdb +'els', # 0xdc +'elt', # 0xdd +'elp', # 0xde +'elh', # 0xdf +'em', # 0xe0 +'eb', # 0xe1 +'ebs', # 0xe2 +'es', # 0xe3 +'ess', # 0xe4 +'eng', # 0xe5 +'ej', # 0xe6 +'ec', # 0xe7 +'ek', # 0xe8 +'et', # 0xe9 +'ep', # 0xea +'eh', # 0xeb +'yeo', # 0xec +'yeog', # 0xed +'yeogg', # 0xee +'yeogs', # 0xef +'yeon', # 0xf0 +'yeonj', # 0xf1 +'yeonh', # 0xf2 +'yeod', # 0xf3 +'yeol', # 0xf4 +'yeolg', # 0xf5 +'yeolm', # 0xf6 +'yeolb', # 0xf7 +'yeols', # 0xf8 +'yeolt', # 0xf9 +'yeolp', # 0xfa +'yeolh', # 0xfb +'yeom', # 0xfc +'yeob', # 0xfd +'yeobs', # 0xfe +'yeos', # 0xff +) diff --git a/nstock/modules/unidecode/x0c6.py b/nstock/modules/unidecode/x0c6.py new file mode 100644 index 0000000..c6eeaeb --- /dev/null +++ b/nstock/modules/unidecode/x0c6.py @@ -0,0 +1,258 @@ +data = ( +'yeoss', # 0x00 +'yeong', # 0x01 +'yeoj', # 0x02 +'yeoc', # 0x03 +'yeok', # 0x04 +'yeot', # 0x05 +'yeop', # 0x06 +'yeoh', # 0x07 +'ye', # 0x08 +'yeg', # 0x09 +'yegg', # 0x0a +'yegs', # 0x0b +'yen', # 0x0c +'yenj', # 0x0d +'yenh', # 0x0e +'yed', # 0x0f +'yel', # 0x10 +'yelg', # 0x11 +'yelm', # 0x12 +'yelb', # 0x13 +'yels', # 0x14 +'yelt', # 0x15 +'yelp', # 0x16 +'yelh', # 0x17 +'yem', # 0x18 +'yeb', # 0x19 +'yebs', # 0x1a +'yes', # 0x1b +'yess', # 0x1c +'yeng', # 0x1d +'yej', # 0x1e +'yec', # 0x1f +'yek', # 0x20 +'yet', # 0x21 +'yep', # 0x22 +'yeh', # 0x23 +'o', # 0x24 +'og', # 0x25 +'ogg', # 0x26 +'ogs', # 0x27 +'on', # 0x28 +'onj', # 0x29 +'onh', # 0x2a +'od', # 0x2b +'ol', # 0x2c +'olg', # 0x2d +'olm', # 0x2e +'olb', # 0x2f +'ols', # 0x30 +'olt', # 0x31 +'olp', # 0x32 +'olh', # 0x33 +'om', # 0x34 +'ob', # 0x35 +'obs', # 0x36 +'os', # 0x37 +'oss', # 0x38 +'ong', # 0x39 +'oj', # 0x3a +'oc', # 0x3b +'ok', # 0x3c +'ot', # 0x3d +'op', # 0x3e +'oh', # 0x3f +'wa', # 0x40 +'wag', # 0x41 +'wagg', # 0x42 +'wags', # 0x43 +'wan', # 0x44 +'wanj', # 0x45 +'wanh', # 0x46 +'wad', # 0x47 +'wal', # 0x48 +'walg', # 0x49 +'walm', # 0x4a +'walb', # 0x4b +'wals', # 0x4c +'walt', # 0x4d +'walp', # 0x4e +'walh', # 0x4f +'wam', # 0x50 +'wab', # 0x51 +'wabs', # 0x52 +'was', # 0x53 +'wass', # 0x54 +'wang', # 0x55 +'waj', # 0x56 +'wac', # 0x57 +'wak', # 0x58 +'wat', # 0x59 +'wap', # 0x5a +'wah', # 0x5b +'wae', # 0x5c +'waeg', # 0x5d +'waegg', # 0x5e +'waegs', # 0x5f +'waen', # 0x60 +'waenj', # 0x61 +'waenh', # 0x62 +'waed', # 0x63 +'wael', # 0x64 +'waelg', # 0x65 +'waelm', # 0x66 +'waelb', # 0x67 +'waels', # 0x68 +'waelt', # 0x69 +'waelp', # 0x6a +'waelh', # 0x6b +'waem', # 0x6c +'waeb', # 0x6d +'waebs', # 0x6e +'waes', # 0x6f +'waess', # 0x70 +'waeng', # 0x71 +'waej', # 0x72 +'waec', # 0x73 +'waek', # 0x74 +'waet', # 0x75 +'waep', # 0x76 +'waeh', # 0x77 +'oe', # 0x78 +'oeg', # 0x79 +'oegg', # 0x7a +'oegs', # 0x7b +'oen', # 0x7c +'oenj', # 0x7d +'oenh', # 0x7e +'oed', # 0x7f +'oel', # 0x80 +'oelg', # 0x81 +'oelm', # 0x82 +'oelb', # 0x83 +'oels', # 0x84 +'oelt', # 0x85 +'oelp', # 0x86 +'oelh', # 0x87 +'oem', # 0x88 +'oeb', # 0x89 +'oebs', # 0x8a +'oes', # 0x8b +'oess', # 0x8c +'oeng', # 0x8d +'oej', # 0x8e +'oec', # 0x8f +'oek', # 0x90 +'oet', # 0x91 +'oep', # 0x92 +'oeh', # 0x93 +'yo', # 0x94 +'yog', # 0x95 +'yogg', # 0x96 +'yogs', # 0x97 +'yon', # 0x98 +'yonj', # 0x99 +'yonh', # 0x9a +'yod', # 0x9b +'yol', # 0x9c +'yolg', # 0x9d +'yolm', # 0x9e +'yolb', # 0x9f +'yols', # 0xa0 +'yolt', # 0xa1 +'yolp', # 0xa2 +'yolh', # 0xa3 +'yom', # 0xa4 +'yob', # 0xa5 +'yobs', # 0xa6 +'yos', # 0xa7 +'yoss', # 0xa8 +'yong', # 0xa9 +'yoj', # 0xaa +'yoc', # 0xab +'yok', # 0xac +'yot', # 0xad +'yop', # 0xae +'yoh', # 0xaf +'u', # 0xb0 +'ug', # 0xb1 +'ugg', # 0xb2 +'ugs', # 0xb3 +'un', # 0xb4 +'unj', # 0xb5 +'unh', # 0xb6 +'ud', # 0xb7 +'ul', # 0xb8 +'ulg', # 0xb9 +'ulm', # 0xba +'ulb', # 0xbb +'uls', # 0xbc +'ult', # 0xbd +'ulp', # 0xbe +'ulh', # 0xbf +'um', # 0xc0 +'ub', # 0xc1 +'ubs', # 0xc2 +'us', # 0xc3 +'uss', # 0xc4 +'ung', # 0xc5 +'uj', # 0xc6 +'uc', # 0xc7 +'uk', # 0xc8 +'ut', # 0xc9 +'up', # 0xca +'uh', # 0xcb +'weo', # 0xcc +'weog', # 0xcd +'weogg', # 0xce +'weogs', # 0xcf +'weon', # 0xd0 +'weonj', # 0xd1 +'weonh', # 0xd2 +'weod', # 0xd3 +'weol', # 0xd4 +'weolg', # 0xd5 +'weolm', # 0xd6 +'weolb', # 0xd7 +'weols', # 0xd8 +'weolt', # 0xd9 +'weolp', # 0xda +'weolh', # 0xdb +'weom', # 0xdc +'weob', # 0xdd +'weobs', # 0xde +'weos', # 0xdf +'weoss', # 0xe0 +'weong', # 0xe1 +'weoj', # 0xe2 +'weoc', # 0xe3 +'weok', # 0xe4 +'weot', # 0xe5 +'weop', # 0xe6 +'weoh', # 0xe7 +'we', # 0xe8 +'weg', # 0xe9 +'wegg', # 0xea +'wegs', # 0xeb +'wen', # 0xec +'wenj', # 0xed +'wenh', # 0xee +'wed', # 0xef +'wel', # 0xf0 +'welg', # 0xf1 +'welm', # 0xf2 +'welb', # 0xf3 +'wels', # 0xf4 +'welt', # 0xf5 +'welp', # 0xf6 +'welh', # 0xf7 +'wem', # 0xf8 +'web', # 0xf9 +'webs', # 0xfa +'wes', # 0xfb +'wess', # 0xfc +'weng', # 0xfd +'wej', # 0xfe +'wec', # 0xff +) diff --git a/nstock/modules/unidecode/x0c7.py b/nstock/modules/unidecode/x0c7.py new file mode 100644 index 0000000..4c1a9e1 --- /dev/null +++ b/nstock/modules/unidecode/x0c7.py @@ -0,0 +1,258 @@ +data = ( +'wek', # 0x00 +'wet', # 0x01 +'wep', # 0x02 +'weh', # 0x03 +'wi', # 0x04 +'wig', # 0x05 +'wigg', # 0x06 +'wigs', # 0x07 +'win', # 0x08 +'winj', # 0x09 +'winh', # 0x0a +'wid', # 0x0b +'wil', # 0x0c +'wilg', # 0x0d +'wilm', # 0x0e +'wilb', # 0x0f +'wils', # 0x10 +'wilt', # 0x11 +'wilp', # 0x12 +'wilh', # 0x13 +'wim', # 0x14 +'wib', # 0x15 +'wibs', # 0x16 +'wis', # 0x17 +'wiss', # 0x18 +'wing', # 0x19 +'wij', # 0x1a +'wic', # 0x1b +'wik', # 0x1c +'wit', # 0x1d +'wip', # 0x1e +'wih', # 0x1f +'yu', # 0x20 +'yug', # 0x21 +'yugg', # 0x22 +'yugs', # 0x23 +'yun', # 0x24 +'yunj', # 0x25 +'yunh', # 0x26 +'yud', # 0x27 +'yul', # 0x28 +'yulg', # 0x29 +'yulm', # 0x2a +'yulb', # 0x2b +'yuls', # 0x2c +'yult', # 0x2d +'yulp', # 0x2e +'yulh', # 0x2f +'yum', # 0x30 +'yub', # 0x31 +'yubs', # 0x32 +'yus', # 0x33 +'yuss', # 0x34 +'yung', # 0x35 +'yuj', # 0x36 +'yuc', # 0x37 +'yuk', # 0x38 +'yut', # 0x39 +'yup', # 0x3a +'yuh', # 0x3b +'eu', # 0x3c +'eug', # 0x3d +'eugg', # 0x3e +'eugs', # 0x3f +'eun', # 0x40 +'eunj', # 0x41 +'eunh', # 0x42 +'eud', # 0x43 +'eul', # 0x44 +'eulg', # 0x45 +'eulm', # 0x46 +'eulb', # 0x47 +'euls', # 0x48 +'eult', # 0x49 +'eulp', # 0x4a +'eulh', # 0x4b +'eum', # 0x4c +'eub', # 0x4d +'eubs', # 0x4e +'eus', # 0x4f +'euss', # 0x50 +'eung', # 0x51 +'euj', # 0x52 +'euc', # 0x53 +'euk', # 0x54 +'eut', # 0x55 +'eup', # 0x56 +'euh', # 0x57 +'yi', # 0x58 +'yig', # 0x59 +'yigg', # 0x5a +'yigs', # 0x5b +'yin', # 0x5c +'yinj', # 0x5d +'yinh', # 0x5e +'yid', # 0x5f +'yil', # 0x60 +'yilg', # 0x61 +'yilm', # 0x62 +'yilb', # 0x63 +'yils', # 0x64 +'yilt', # 0x65 +'yilp', # 0x66 +'yilh', # 0x67 +'yim', # 0x68 +'yib', # 0x69 +'yibs', # 0x6a +'yis', # 0x6b +'yiss', # 0x6c +'ying', # 0x6d +'yij', # 0x6e +'yic', # 0x6f +'yik', # 0x70 +'yit', # 0x71 +'yip', # 0x72 +'yih', # 0x73 +'i', # 0x74 +'ig', # 0x75 +'igg', # 0x76 +'igs', # 0x77 +'in', # 0x78 +'inj', # 0x79 +'inh', # 0x7a +'id', # 0x7b +'il', # 0x7c +'ilg', # 0x7d +'ilm', # 0x7e +'ilb', # 0x7f +'ils', # 0x80 +'ilt', # 0x81 +'ilp', # 0x82 +'ilh', # 0x83 +'im', # 0x84 +'ib', # 0x85 +'ibs', # 0x86 +'is', # 0x87 +'iss', # 0x88 +'ing', # 0x89 +'ij', # 0x8a +'ic', # 0x8b +'ik', # 0x8c +'it', # 0x8d +'ip', # 0x8e +'ih', # 0x8f +'ja', # 0x90 +'jag', # 0x91 +'jagg', # 0x92 +'jags', # 0x93 +'jan', # 0x94 +'janj', # 0x95 +'janh', # 0x96 +'jad', # 0x97 +'jal', # 0x98 +'jalg', # 0x99 +'jalm', # 0x9a +'jalb', # 0x9b +'jals', # 0x9c +'jalt', # 0x9d +'jalp', # 0x9e +'jalh', # 0x9f +'jam', # 0xa0 +'jab', # 0xa1 +'jabs', # 0xa2 +'jas', # 0xa3 +'jass', # 0xa4 +'jang', # 0xa5 +'jaj', # 0xa6 +'jac', # 0xa7 +'jak', # 0xa8 +'jat', # 0xa9 +'jap', # 0xaa +'jah', # 0xab +'jae', # 0xac +'jaeg', # 0xad +'jaegg', # 0xae +'jaegs', # 0xaf +'jaen', # 0xb0 +'jaenj', # 0xb1 +'jaenh', # 0xb2 +'jaed', # 0xb3 +'jael', # 0xb4 +'jaelg', # 0xb5 +'jaelm', # 0xb6 +'jaelb', # 0xb7 +'jaels', # 0xb8 +'jaelt', # 0xb9 +'jaelp', # 0xba +'jaelh', # 0xbb +'jaem', # 0xbc +'jaeb', # 0xbd +'jaebs', # 0xbe +'jaes', # 0xbf +'jaess', # 0xc0 +'jaeng', # 0xc1 +'jaej', # 0xc2 +'jaec', # 0xc3 +'jaek', # 0xc4 +'jaet', # 0xc5 +'jaep', # 0xc6 +'jaeh', # 0xc7 +'jya', # 0xc8 +'jyag', # 0xc9 +'jyagg', # 0xca +'jyags', # 0xcb +'jyan', # 0xcc +'jyanj', # 0xcd +'jyanh', # 0xce +'jyad', # 0xcf +'jyal', # 0xd0 +'jyalg', # 0xd1 +'jyalm', # 0xd2 +'jyalb', # 0xd3 +'jyals', # 0xd4 +'jyalt', # 0xd5 +'jyalp', # 0xd6 +'jyalh', # 0xd7 +'jyam', # 0xd8 +'jyab', # 0xd9 +'jyabs', # 0xda +'jyas', # 0xdb +'jyass', # 0xdc +'jyang', # 0xdd +'jyaj', # 0xde +'jyac', # 0xdf +'jyak', # 0xe0 +'jyat', # 0xe1 +'jyap', # 0xe2 +'jyah', # 0xe3 +'jyae', # 0xe4 +'jyaeg', # 0xe5 +'jyaegg', # 0xe6 +'jyaegs', # 0xe7 +'jyaen', # 0xe8 +'jyaenj', # 0xe9 +'jyaenh', # 0xea +'jyaed', # 0xeb +'jyael', # 0xec +'jyaelg', # 0xed +'jyaelm', # 0xee +'jyaelb', # 0xef +'jyaels', # 0xf0 +'jyaelt', # 0xf1 +'jyaelp', # 0xf2 +'jyaelh', # 0xf3 +'jyaem', # 0xf4 +'jyaeb', # 0xf5 +'jyaebs', # 0xf6 +'jyaes', # 0xf7 +'jyaess', # 0xf8 +'jyaeng', # 0xf9 +'jyaej', # 0xfa +'jyaec', # 0xfb +'jyaek', # 0xfc +'jyaet', # 0xfd +'jyaep', # 0xfe +'jyaeh', # 0xff +) diff --git a/nstock/modules/unidecode/x0c8.py b/nstock/modules/unidecode/x0c8.py new file mode 100644 index 0000000..2dc7564 --- /dev/null +++ b/nstock/modules/unidecode/x0c8.py @@ -0,0 +1,258 @@ +data = ( +'jeo', # 0x00 +'jeog', # 0x01 +'jeogg', # 0x02 +'jeogs', # 0x03 +'jeon', # 0x04 +'jeonj', # 0x05 +'jeonh', # 0x06 +'jeod', # 0x07 +'jeol', # 0x08 +'jeolg', # 0x09 +'jeolm', # 0x0a +'jeolb', # 0x0b +'jeols', # 0x0c +'jeolt', # 0x0d +'jeolp', # 0x0e +'jeolh', # 0x0f +'jeom', # 0x10 +'jeob', # 0x11 +'jeobs', # 0x12 +'jeos', # 0x13 +'jeoss', # 0x14 +'jeong', # 0x15 +'jeoj', # 0x16 +'jeoc', # 0x17 +'jeok', # 0x18 +'jeot', # 0x19 +'jeop', # 0x1a +'jeoh', # 0x1b +'je', # 0x1c +'jeg', # 0x1d +'jegg', # 0x1e +'jegs', # 0x1f +'jen', # 0x20 +'jenj', # 0x21 +'jenh', # 0x22 +'jed', # 0x23 +'jel', # 0x24 +'jelg', # 0x25 +'jelm', # 0x26 +'jelb', # 0x27 +'jels', # 0x28 +'jelt', # 0x29 +'jelp', # 0x2a +'jelh', # 0x2b +'jem', # 0x2c +'jeb', # 0x2d +'jebs', # 0x2e +'jes', # 0x2f +'jess', # 0x30 +'jeng', # 0x31 +'jej', # 0x32 +'jec', # 0x33 +'jek', # 0x34 +'jet', # 0x35 +'jep', # 0x36 +'jeh', # 0x37 +'jyeo', # 0x38 +'jyeog', # 0x39 +'jyeogg', # 0x3a +'jyeogs', # 0x3b +'jyeon', # 0x3c +'jyeonj', # 0x3d +'jyeonh', # 0x3e +'jyeod', # 0x3f +'jyeol', # 0x40 +'jyeolg', # 0x41 +'jyeolm', # 0x42 +'jyeolb', # 0x43 +'jyeols', # 0x44 +'jyeolt', # 0x45 +'jyeolp', # 0x46 +'jyeolh', # 0x47 +'jyeom', # 0x48 +'jyeob', # 0x49 +'jyeobs', # 0x4a +'jyeos', # 0x4b +'jyeoss', # 0x4c +'jyeong', # 0x4d +'jyeoj', # 0x4e +'jyeoc', # 0x4f +'jyeok', # 0x50 +'jyeot', # 0x51 +'jyeop', # 0x52 +'jyeoh', # 0x53 +'jye', # 0x54 +'jyeg', # 0x55 +'jyegg', # 0x56 +'jyegs', # 0x57 +'jyen', # 0x58 +'jyenj', # 0x59 +'jyenh', # 0x5a +'jyed', # 0x5b +'jyel', # 0x5c +'jyelg', # 0x5d +'jyelm', # 0x5e +'jyelb', # 0x5f +'jyels', # 0x60 +'jyelt', # 0x61 +'jyelp', # 0x62 +'jyelh', # 0x63 +'jyem', # 0x64 +'jyeb', # 0x65 +'jyebs', # 0x66 +'jyes', # 0x67 +'jyess', # 0x68 +'jyeng', # 0x69 +'jyej', # 0x6a +'jyec', # 0x6b +'jyek', # 0x6c +'jyet', # 0x6d +'jyep', # 0x6e +'jyeh', # 0x6f +'jo', # 0x70 +'jog', # 0x71 +'jogg', # 0x72 +'jogs', # 0x73 +'jon', # 0x74 +'jonj', # 0x75 +'jonh', # 0x76 +'jod', # 0x77 +'jol', # 0x78 +'jolg', # 0x79 +'jolm', # 0x7a +'jolb', # 0x7b +'jols', # 0x7c +'jolt', # 0x7d +'jolp', # 0x7e +'jolh', # 0x7f +'jom', # 0x80 +'job', # 0x81 +'jobs', # 0x82 +'jos', # 0x83 +'joss', # 0x84 +'jong', # 0x85 +'joj', # 0x86 +'joc', # 0x87 +'jok', # 0x88 +'jot', # 0x89 +'jop', # 0x8a +'joh', # 0x8b +'jwa', # 0x8c +'jwag', # 0x8d +'jwagg', # 0x8e +'jwags', # 0x8f +'jwan', # 0x90 +'jwanj', # 0x91 +'jwanh', # 0x92 +'jwad', # 0x93 +'jwal', # 0x94 +'jwalg', # 0x95 +'jwalm', # 0x96 +'jwalb', # 0x97 +'jwals', # 0x98 +'jwalt', # 0x99 +'jwalp', # 0x9a +'jwalh', # 0x9b +'jwam', # 0x9c +'jwab', # 0x9d +'jwabs', # 0x9e +'jwas', # 0x9f +'jwass', # 0xa0 +'jwang', # 0xa1 +'jwaj', # 0xa2 +'jwac', # 0xa3 +'jwak', # 0xa4 +'jwat', # 0xa5 +'jwap', # 0xa6 +'jwah', # 0xa7 +'jwae', # 0xa8 +'jwaeg', # 0xa9 +'jwaegg', # 0xaa +'jwaegs', # 0xab +'jwaen', # 0xac +'jwaenj', # 0xad +'jwaenh', # 0xae +'jwaed', # 0xaf +'jwael', # 0xb0 +'jwaelg', # 0xb1 +'jwaelm', # 0xb2 +'jwaelb', # 0xb3 +'jwaels', # 0xb4 +'jwaelt', # 0xb5 +'jwaelp', # 0xb6 +'jwaelh', # 0xb7 +'jwaem', # 0xb8 +'jwaeb', # 0xb9 +'jwaebs', # 0xba +'jwaes', # 0xbb +'jwaess', # 0xbc +'jwaeng', # 0xbd +'jwaej', # 0xbe +'jwaec', # 0xbf +'jwaek', # 0xc0 +'jwaet', # 0xc1 +'jwaep', # 0xc2 +'jwaeh', # 0xc3 +'joe', # 0xc4 +'joeg', # 0xc5 +'joegg', # 0xc6 +'joegs', # 0xc7 +'joen', # 0xc8 +'joenj', # 0xc9 +'joenh', # 0xca +'joed', # 0xcb +'joel', # 0xcc +'joelg', # 0xcd +'joelm', # 0xce +'joelb', # 0xcf +'joels', # 0xd0 +'joelt', # 0xd1 +'joelp', # 0xd2 +'joelh', # 0xd3 +'joem', # 0xd4 +'joeb', # 0xd5 +'joebs', # 0xd6 +'joes', # 0xd7 +'joess', # 0xd8 +'joeng', # 0xd9 +'joej', # 0xda +'joec', # 0xdb +'joek', # 0xdc +'joet', # 0xdd +'joep', # 0xde +'joeh', # 0xdf +'jyo', # 0xe0 +'jyog', # 0xe1 +'jyogg', # 0xe2 +'jyogs', # 0xe3 +'jyon', # 0xe4 +'jyonj', # 0xe5 +'jyonh', # 0xe6 +'jyod', # 0xe7 +'jyol', # 0xe8 +'jyolg', # 0xe9 +'jyolm', # 0xea +'jyolb', # 0xeb +'jyols', # 0xec +'jyolt', # 0xed +'jyolp', # 0xee +'jyolh', # 0xef +'jyom', # 0xf0 +'jyob', # 0xf1 +'jyobs', # 0xf2 +'jyos', # 0xf3 +'jyoss', # 0xf4 +'jyong', # 0xf5 +'jyoj', # 0xf6 +'jyoc', # 0xf7 +'jyok', # 0xf8 +'jyot', # 0xf9 +'jyop', # 0xfa +'jyoh', # 0xfb +'ju', # 0xfc +'jug', # 0xfd +'jugg', # 0xfe +'jugs', # 0xff +) diff --git a/nstock/modules/unidecode/x0c9.py b/nstock/modules/unidecode/x0c9.py new file mode 100644 index 0000000..7e09832 --- /dev/null +++ b/nstock/modules/unidecode/x0c9.py @@ -0,0 +1,258 @@ +data = ( +'jun', # 0x00 +'junj', # 0x01 +'junh', # 0x02 +'jud', # 0x03 +'jul', # 0x04 +'julg', # 0x05 +'julm', # 0x06 +'julb', # 0x07 +'juls', # 0x08 +'jult', # 0x09 +'julp', # 0x0a +'julh', # 0x0b +'jum', # 0x0c +'jub', # 0x0d +'jubs', # 0x0e +'jus', # 0x0f +'juss', # 0x10 +'jung', # 0x11 +'juj', # 0x12 +'juc', # 0x13 +'juk', # 0x14 +'jut', # 0x15 +'jup', # 0x16 +'juh', # 0x17 +'jweo', # 0x18 +'jweog', # 0x19 +'jweogg', # 0x1a +'jweogs', # 0x1b +'jweon', # 0x1c +'jweonj', # 0x1d +'jweonh', # 0x1e +'jweod', # 0x1f +'jweol', # 0x20 +'jweolg', # 0x21 +'jweolm', # 0x22 +'jweolb', # 0x23 +'jweols', # 0x24 +'jweolt', # 0x25 +'jweolp', # 0x26 +'jweolh', # 0x27 +'jweom', # 0x28 +'jweob', # 0x29 +'jweobs', # 0x2a +'jweos', # 0x2b +'jweoss', # 0x2c +'jweong', # 0x2d +'jweoj', # 0x2e +'jweoc', # 0x2f +'jweok', # 0x30 +'jweot', # 0x31 +'jweop', # 0x32 +'jweoh', # 0x33 +'jwe', # 0x34 +'jweg', # 0x35 +'jwegg', # 0x36 +'jwegs', # 0x37 +'jwen', # 0x38 +'jwenj', # 0x39 +'jwenh', # 0x3a +'jwed', # 0x3b +'jwel', # 0x3c +'jwelg', # 0x3d +'jwelm', # 0x3e +'jwelb', # 0x3f +'jwels', # 0x40 +'jwelt', # 0x41 +'jwelp', # 0x42 +'jwelh', # 0x43 +'jwem', # 0x44 +'jweb', # 0x45 +'jwebs', # 0x46 +'jwes', # 0x47 +'jwess', # 0x48 +'jweng', # 0x49 +'jwej', # 0x4a +'jwec', # 0x4b +'jwek', # 0x4c +'jwet', # 0x4d +'jwep', # 0x4e +'jweh', # 0x4f +'jwi', # 0x50 +'jwig', # 0x51 +'jwigg', # 0x52 +'jwigs', # 0x53 +'jwin', # 0x54 +'jwinj', # 0x55 +'jwinh', # 0x56 +'jwid', # 0x57 +'jwil', # 0x58 +'jwilg', # 0x59 +'jwilm', # 0x5a +'jwilb', # 0x5b +'jwils', # 0x5c +'jwilt', # 0x5d +'jwilp', # 0x5e +'jwilh', # 0x5f +'jwim', # 0x60 +'jwib', # 0x61 +'jwibs', # 0x62 +'jwis', # 0x63 +'jwiss', # 0x64 +'jwing', # 0x65 +'jwij', # 0x66 +'jwic', # 0x67 +'jwik', # 0x68 +'jwit', # 0x69 +'jwip', # 0x6a +'jwih', # 0x6b +'jyu', # 0x6c +'jyug', # 0x6d +'jyugg', # 0x6e +'jyugs', # 0x6f +'jyun', # 0x70 +'jyunj', # 0x71 +'jyunh', # 0x72 +'jyud', # 0x73 +'jyul', # 0x74 +'jyulg', # 0x75 +'jyulm', # 0x76 +'jyulb', # 0x77 +'jyuls', # 0x78 +'jyult', # 0x79 +'jyulp', # 0x7a +'jyulh', # 0x7b +'jyum', # 0x7c +'jyub', # 0x7d +'jyubs', # 0x7e +'jyus', # 0x7f +'jyuss', # 0x80 +'jyung', # 0x81 +'jyuj', # 0x82 +'jyuc', # 0x83 +'jyuk', # 0x84 +'jyut', # 0x85 +'jyup', # 0x86 +'jyuh', # 0x87 +'jeu', # 0x88 +'jeug', # 0x89 +'jeugg', # 0x8a +'jeugs', # 0x8b +'jeun', # 0x8c +'jeunj', # 0x8d +'jeunh', # 0x8e +'jeud', # 0x8f +'jeul', # 0x90 +'jeulg', # 0x91 +'jeulm', # 0x92 +'jeulb', # 0x93 +'jeuls', # 0x94 +'jeult', # 0x95 +'jeulp', # 0x96 +'jeulh', # 0x97 +'jeum', # 0x98 +'jeub', # 0x99 +'jeubs', # 0x9a +'jeus', # 0x9b +'jeuss', # 0x9c +'jeung', # 0x9d +'jeuj', # 0x9e +'jeuc', # 0x9f +'jeuk', # 0xa0 +'jeut', # 0xa1 +'jeup', # 0xa2 +'jeuh', # 0xa3 +'jyi', # 0xa4 +'jyig', # 0xa5 +'jyigg', # 0xa6 +'jyigs', # 0xa7 +'jyin', # 0xa8 +'jyinj', # 0xa9 +'jyinh', # 0xaa +'jyid', # 0xab +'jyil', # 0xac +'jyilg', # 0xad +'jyilm', # 0xae +'jyilb', # 0xaf +'jyils', # 0xb0 +'jyilt', # 0xb1 +'jyilp', # 0xb2 +'jyilh', # 0xb3 +'jyim', # 0xb4 +'jyib', # 0xb5 +'jyibs', # 0xb6 +'jyis', # 0xb7 +'jyiss', # 0xb8 +'jying', # 0xb9 +'jyij', # 0xba +'jyic', # 0xbb +'jyik', # 0xbc +'jyit', # 0xbd +'jyip', # 0xbe +'jyih', # 0xbf +'ji', # 0xc0 +'jig', # 0xc1 +'jigg', # 0xc2 +'jigs', # 0xc3 +'jin', # 0xc4 +'jinj', # 0xc5 +'jinh', # 0xc6 +'jid', # 0xc7 +'jil', # 0xc8 +'jilg', # 0xc9 +'jilm', # 0xca +'jilb', # 0xcb +'jils', # 0xcc +'jilt', # 0xcd +'jilp', # 0xce +'jilh', # 0xcf +'jim', # 0xd0 +'jib', # 0xd1 +'jibs', # 0xd2 +'jis', # 0xd3 +'jiss', # 0xd4 +'jing', # 0xd5 +'jij', # 0xd6 +'jic', # 0xd7 +'jik', # 0xd8 +'jit', # 0xd9 +'jip', # 0xda +'jih', # 0xdb +'jja', # 0xdc +'jjag', # 0xdd +'jjagg', # 0xde +'jjags', # 0xdf +'jjan', # 0xe0 +'jjanj', # 0xe1 +'jjanh', # 0xe2 +'jjad', # 0xe3 +'jjal', # 0xe4 +'jjalg', # 0xe5 +'jjalm', # 0xe6 +'jjalb', # 0xe7 +'jjals', # 0xe8 +'jjalt', # 0xe9 +'jjalp', # 0xea +'jjalh', # 0xeb +'jjam', # 0xec +'jjab', # 0xed +'jjabs', # 0xee +'jjas', # 0xef +'jjass', # 0xf0 +'jjang', # 0xf1 +'jjaj', # 0xf2 +'jjac', # 0xf3 +'jjak', # 0xf4 +'jjat', # 0xf5 +'jjap', # 0xf6 +'jjah', # 0xf7 +'jjae', # 0xf8 +'jjaeg', # 0xf9 +'jjaegg', # 0xfa +'jjaegs', # 0xfb +'jjaen', # 0xfc +'jjaenj', # 0xfd +'jjaenh', # 0xfe +'jjaed', # 0xff +) diff --git a/nstock/modules/unidecode/x0ca.py b/nstock/modules/unidecode/x0ca.py new file mode 100644 index 0000000..20239b7 --- /dev/null +++ b/nstock/modules/unidecode/x0ca.py @@ -0,0 +1,258 @@ +data = ( +'jjael', # 0x00 +'jjaelg', # 0x01 +'jjaelm', # 0x02 +'jjaelb', # 0x03 +'jjaels', # 0x04 +'jjaelt', # 0x05 +'jjaelp', # 0x06 +'jjaelh', # 0x07 +'jjaem', # 0x08 +'jjaeb', # 0x09 +'jjaebs', # 0x0a +'jjaes', # 0x0b +'jjaess', # 0x0c +'jjaeng', # 0x0d +'jjaej', # 0x0e +'jjaec', # 0x0f +'jjaek', # 0x10 +'jjaet', # 0x11 +'jjaep', # 0x12 +'jjaeh', # 0x13 +'jjya', # 0x14 +'jjyag', # 0x15 +'jjyagg', # 0x16 +'jjyags', # 0x17 +'jjyan', # 0x18 +'jjyanj', # 0x19 +'jjyanh', # 0x1a +'jjyad', # 0x1b +'jjyal', # 0x1c +'jjyalg', # 0x1d +'jjyalm', # 0x1e +'jjyalb', # 0x1f +'jjyals', # 0x20 +'jjyalt', # 0x21 +'jjyalp', # 0x22 +'jjyalh', # 0x23 +'jjyam', # 0x24 +'jjyab', # 0x25 +'jjyabs', # 0x26 +'jjyas', # 0x27 +'jjyass', # 0x28 +'jjyang', # 0x29 +'jjyaj', # 0x2a +'jjyac', # 0x2b +'jjyak', # 0x2c +'jjyat', # 0x2d +'jjyap', # 0x2e +'jjyah', # 0x2f +'jjyae', # 0x30 +'jjyaeg', # 0x31 +'jjyaegg', # 0x32 +'jjyaegs', # 0x33 +'jjyaen', # 0x34 +'jjyaenj', # 0x35 +'jjyaenh', # 0x36 +'jjyaed', # 0x37 +'jjyael', # 0x38 +'jjyaelg', # 0x39 +'jjyaelm', # 0x3a +'jjyaelb', # 0x3b +'jjyaels', # 0x3c +'jjyaelt', # 0x3d +'jjyaelp', # 0x3e +'jjyaelh', # 0x3f +'jjyaem', # 0x40 +'jjyaeb', # 0x41 +'jjyaebs', # 0x42 +'jjyaes', # 0x43 +'jjyaess', # 0x44 +'jjyaeng', # 0x45 +'jjyaej', # 0x46 +'jjyaec', # 0x47 +'jjyaek', # 0x48 +'jjyaet', # 0x49 +'jjyaep', # 0x4a +'jjyaeh', # 0x4b +'jjeo', # 0x4c +'jjeog', # 0x4d +'jjeogg', # 0x4e +'jjeogs', # 0x4f +'jjeon', # 0x50 +'jjeonj', # 0x51 +'jjeonh', # 0x52 +'jjeod', # 0x53 +'jjeol', # 0x54 +'jjeolg', # 0x55 +'jjeolm', # 0x56 +'jjeolb', # 0x57 +'jjeols', # 0x58 +'jjeolt', # 0x59 +'jjeolp', # 0x5a +'jjeolh', # 0x5b +'jjeom', # 0x5c +'jjeob', # 0x5d +'jjeobs', # 0x5e +'jjeos', # 0x5f +'jjeoss', # 0x60 +'jjeong', # 0x61 +'jjeoj', # 0x62 +'jjeoc', # 0x63 +'jjeok', # 0x64 +'jjeot', # 0x65 +'jjeop', # 0x66 +'jjeoh', # 0x67 +'jje', # 0x68 +'jjeg', # 0x69 +'jjegg', # 0x6a +'jjegs', # 0x6b +'jjen', # 0x6c +'jjenj', # 0x6d +'jjenh', # 0x6e +'jjed', # 0x6f +'jjel', # 0x70 +'jjelg', # 0x71 +'jjelm', # 0x72 +'jjelb', # 0x73 +'jjels', # 0x74 +'jjelt', # 0x75 +'jjelp', # 0x76 +'jjelh', # 0x77 +'jjem', # 0x78 +'jjeb', # 0x79 +'jjebs', # 0x7a +'jjes', # 0x7b +'jjess', # 0x7c +'jjeng', # 0x7d +'jjej', # 0x7e +'jjec', # 0x7f +'jjek', # 0x80 +'jjet', # 0x81 +'jjep', # 0x82 +'jjeh', # 0x83 +'jjyeo', # 0x84 +'jjyeog', # 0x85 +'jjyeogg', # 0x86 +'jjyeogs', # 0x87 +'jjyeon', # 0x88 +'jjyeonj', # 0x89 +'jjyeonh', # 0x8a +'jjyeod', # 0x8b +'jjyeol', # 0x8c +'jjyeolg', # 0x8d +'jjyeolm', # 0x8e +'jjyeolb', # 0x8f +'jjyeols', # 0x90 +'jjyeolt', # 0x91 +'jjyeolp', # 0x92 +'jjyeolh', # 0x93 +'jjyeom', # 0x94 +'jjyeob', # 0x95 +'jjyeobs', # 0x96 +'jjyeos', # 0x97 +'jjyeoss', # 0x98 +'jjyeong', # 0x99 +'jjyeoj', # 0x9a +'jjyeoc', # 0x9b +'jjyeok', # 0x9c +'jjyeot', # 0x9d +'jjyeop', # 0x9e +'jjyeoh', # 0x9f +'jjye', # 0xa0 +'jjyeg', # 0xa1 +'jjyegg', # 0xa2 +'jjyegs', # 0xa3 +'jjyen', # 0xa4 +'jjyenj', # 0xa5 +'jjyenh', # 0xa6 +'jjyed', # 0xa7 +'jjyel', # 0xa8 +'jjyelg', # 0xa9 +'jjyelm', # 0xaa +'jjyelb', # 0xab +'jjyels', # 0xac +'jjyelt', # 0xad +'jjyelp', # 0xae +'jjyelh', # 0xaf +'jjyem', # 0xb0 +'jjyeb', # 0xb1 +'jjyebs', # 0xb2 +'jjyes', # 0xb3 +'jjyess', # 0xb4 +'jjyeng', # 0xb5 +'jjyej', # 0xb6 +'jjyec', # 0xb7 +'jjyek', # 0xb8 +'jjyet', # 0xb9 +'jjyep', # 0xba +'jjyeh', # 0xbb +'jjo', # 0xbc +'jjog', # 0xbd +'jjogg', # 0xbe +'jjogs', # 0xbf +'jjon', # 0xc0 +'jjonj', # 0xc1 +'jjonh', # 0xc2 +'jjod', # 0xc3 +'jjol', # 0xc4 +'jjolg', # 0xc5 +'jjolm', # 0xc6 +'jjolb', # 0xc7 +'jjols', # 0xc8 +'jjolt', # 0xc9 +'jjolp', # 0xca +'jjolh', # 0xcb +'jjom', # 0xcc +'jjob', # 0xcd +'jjobs', # 0xce +'jjos', # 0xcf +'jjoss', # 0xd0 +'jjong', # 0xd1 +'jjoj', # 0xd2 +'jjoc', # 0xd3 +'jjok', # 0xd4 +'jjot', # 0xd5 +'jjop', # 0xd6 +'jjoh', # 0xd7 +'jjwa', # 0xd8 +'jjwag', # 0xd9 +'jjwagg', # 0xda +'jjwags', # 0xdb +'jjwan', # 0xdc +'jjwanj', # 0xdd +'jjwanh', # 0xde +'jjwad', # 0xdf +'jjwal', # 0xe0 +'jjwalg', # 0xe1 +'jjwalm', # 0xe2 +'jjwalb', # 0xe3 +'jjwals', # 0xe4 +'jjwalt', # 0xe5 +'jjwalp', # 0xe6 +'jjwalh', # 0xe7 +'jjwam', # 0xe8 +'jjwab', # 0xe9 +'jjwabs', # 0xea +'jjwas', # 0xeb +'jjwass', # 0xec +'jjwang', # 0xed +'jjwaj', # 0xee +'jjwac', # 0xef +'jjwak', # 0xf0 +'jjwat', # 0xf1 +'jjwap', # 0xf2 +'jjwah', # 0xf3 +'jjwae', # 0xf4 +'jjwaeg', # 0xf5 +'jjwaegg', # 0xf6 +'jjwaegs', # 0xf7 +'jjwaen', # 0xf8 +'jjwaenj', # 0xf9 +'jjwaenh', # 0xfa +'jjwaed', # 0xfb +'jjwael', # 0xfc +'jjwaelg', # 0xfd +'jjwaelm', # 0xfe +'jjwaelb', # 0xff +) diff --git a/nstock/modules/unidecode/x0cb.py b/nstock/modules/unidecode/x0cb.py new file mode 100644 index 0000000..96d9c18 --- /dev/null +++ b/nstock/modules/unidecode/x0cb.py @@ -0,0 +1,258 @@ +data = ( +'jjwaels', # 0x00 +'jjwaelt', # 0x01 +'jjwaelp', # 0x02 +'jjwaelh', # 0x03 +'jjwaem', # 0x04 +'jjwaeb', # 0x05 +'jjwaebs', # 0x06 +'jjwaes', # 0x07 +'jjwaess', # 0x08 +'jjwaeng', # 0x09 +'jjwaej', # 0x0a +'jjwaec', # 0x0b +'jjwaek', # 0x0c +'jjwaet', # 0x0d +'jjwaep', # 0x0e +'jjwaeh', # 0x0f +'jjoe', # 0x10 +'jjoeg', # 0x11 +'jjoegg', # 0x12 +'jjoegs', # 0x13 +'jjoen', # 0x14 +'jjoenj', # 0x15 +'jjoenh', # 0x16 +'jjoed', # 0x17 +'jjoel', # 0x18 +'jjoelg', # 0x19 +'jjoelm', # 0x1a +'jjoelb', # 0x1b +'jjoels', # 0x1c +'jjoelt', # 0x1d +'jjoelp', # 0x1e +'jjoelh', # 0x1f +'jjoem', # 0x20 +'jjoeb', # 0x21 +'jjoebs', # 0x22 +'jjoes', # 0x23 +'jjoess', # 0x24 +'jjoeng', # 0x25 +'jjoej', # 0x26 +'jjoec', # 0x27 +'jjoek', # 0x28 +'jjoet', # 0x29 +'jjoep', # 0x2a +'jjoeh', # 0x2b +'jjyo', # 0x2c +'jjyog', # 0x2d +'jjyogg', # 0x2e +'jjyogs', # 0x2f +'jjyon', # 0x30 +'jjyonj', # 0x31 +'jjyonh', # 0x32 +'jjyod', # 0x33 +'jjyol', # 0x34 +'jjyolg', # 0x35 +'jjyolm', # 0x36 +'jjyolb', # 0x37 +'jjyols', # 0x38 +'jjyolt', # 0x39 +'jjyolp', # 0x3a +'jjyolh', # 0x3b +'jjyom', # 0x3c +'jjyob', # 0x3d +'jjyobs', # 0x3e +'jjyos', # 0x3f +'jjyoss', # 0x40 +'jjyong', # 0x41 +'jjyoj', # 0x42 +'jjyoc', # 0x43 +'jjyok', # 0x44 +'jjyot', # 0x45 +'jjyop', # 0x46 +'jjyoh', # 0x47 +'jju', # 0x48 +'jjug', # 0x49 +'jjugg', # 0x4a +'jjugs', # 0x4b +'jjun', # 0x4c +'jjunj', # 0x4d +'jjunh', # 0x4e +'jjud', # 0x4f +'jjul', # 0x50 +'jjulg', # 0x51 +'jjulm', # 0x52 +'jjulb', # 0x53 +'jjuls', # 0x54 +'jjult', # 0x55 +'jjulp', # 0x56 +'jjulh', # 0x57 +'jjum', # 0x58 +'jjub', # 0x59 +'jjubs', # 0x5a +'jjus', # 0x5b +'jjuss', # 0x5c +'jjung', # 0x5d +'jjuj', # 0x5e +'jjuc', # 0x5f +'jjuk', # 0x60 +'jjut', # 0x61 +'jjup', # 0x62 +'jjuh', # 0x63 +'jjweo', # 0x64 +'jjweog', # 0x65 +'jjweogg', # 0x66 +'jjweogs', # 0x67 +'jjweon', # 0x68 +'jjweonj', # 0x69 +'jjweonh', # 0x6a +'jjweod', # 0x6b +'jjweol', # 0x6c +'jjweolg', # 0x6d +'jjweolm', # 0x6e +'jjweolb', # 0x6f +'jjweols', # 0x70 +'jjweolt', # 0x71 +'jjweolp', # 0x72 +'jjweolh', # 0x73 +'jjweom', # 0x74 +'jjweob', # 0x75 +'jjweobs', # 0x76 +'jjweos', # 0x77 +'jjweoss', # 0x78 +'jjweong', # 0x79 +'jjweoj', # 0x7a +'jjweoc', # 0x7b +'jjweok', # 0x7c +'jjweot', # 0x7d +'jjweop', # 0x7e +'jjweoh', # 0x7f +'jjwe', # 0x80 +'jjweg', # 0x81 +'jjwegg', # 0x82 +'jjwegs', # 0x83 +'jjwen', # 0x84 +'jjwenj', # 0x85 +'jjwenh', # 0x86 +'jjwed', # 0x87 +'jjwel', # 0x88 +'jjwelg', # 0x89 +'jjwelm', # 0x8a +'jjwelb', # 0x8b +'jjwels', # 0x8c +'jjwelt', # 0x8d +'jjwelp', # 0x8e +'jjwelh', # 0x8f +'jjwem', # 0x90 +'jjweb', # 0x91 +'jjwebs', # 0x92 +'jjwes', # 0x93 +'jjwess', # 0x94 +'jjweng', # 0x95 +'jjwej', # 0x96 +'jjwec', # 0x97 +'jjwek', # 0x98 +'jjwet', # 0x99 +'jjwep', # 0x9a +'jjweh', # 0x9b +'jjwi', # 0x9c +'jjwig', # 0x9d +'jjwigg', # 0x9e +'jjwigs', # 0x9f +'jjwin', # 0xa0 +'jjwinj', # 0xa1 +'jjwinh', # 0xa2 +'jjwid', # 0xa3 +'jjwil', # 0xa4 +'jjwilg', # 0xa5 +'jjwilm', # 0xa6 +'jjwilb', # 0xa7 +'jjwils', # 0xa8 +'jjwilt', # 0xa9 +'jjwilp', # 0xaa +'jjwilh', # 0xab +'jjwim', # 0xac +'jjwib', # 0xad +'jjwibs', # 0xae +'jjwis', # 0xaf +'jjwiss', # 0xb0 +'jjwing', # 0xb1 +'jjwij', # 0xb2 +'jjwic', # 0xb3 +'jjwik', # 0xb4 +'jjwit', # 0xb5 +'jjwip', # 0xb6 +'jjwih', # 0xb7 +'jjyu', # 0xb8 +'jjyug', # 0xb9 +'jjyugg', # 0xba +'jjyugs', # 0xbb +'jjyun', # 0xbc +'jjyunj', # 0xbd +'jjyunh', # 0xbe +'jjyud', # 0xbf +'jjyul', # 0xc0 +'jjyulg', # 0xc1 +'jjyulm', # 0xc2 +'jjyulb', # 0xc3 +'jjyuls', # 0xc4 +'jjyult', # 0xc5 +'jjyulp', # 0xc6 +'jjyulh', # 0xc7 +'jjyum', # 0xc8 +'jjyub', # 0xc9 +'jjyubs', # 0xca +'jjyus', # 0xcb +'jjyuss', # 0xcc +'jjyung', # 0xcd +'jjyuj', # 0xce +'jjyuc', # 0xcf +'jjyuk', # 0xd0 +'jjyut', # 0xd1 +'jjyup', # 0xd2 +'jjyuh', # 0xd3 +'jjeu', # 0xd4 +'jjeug', # 0xd5 +'jjeugg', # 0xd6 +'jjeugs', # 0xd7 +'jjeun', # 0xd8 +'jjeunj', # 0xd9 +'jjeunh', # 0xda +'jjeud', # 0xdb +'jjeul', # 0xdc +'jjeulg', # 0xdd +'jjeulm', # 0xde +'jjeulb', # 0xdf +'jjeuls', # 0xe0 +'jjeult', # 0xe1 +'jjeulp', # 0xe2 +'jjeulh', # 0xe3 +'jjeum', # 0xe4 +'jjeub', # 0xe5 +'jjeubs', # 0xe6 +'jjeus', # 0xe7 +'jjeuss', # 0xe8 +'jjeung', # 0xe9 +'jjeuj', # 0xea +'jjeuc', # 0xeb +'jjeuk', # 0xec +'jjeut', # 0xed +'jjeup', # 0xee +'jjeuh', # 0xef +'jjyi', # 0xf0 +'jjyig', # 0xf1 +'jjyigg', # 0xf2 +'jjyigs', # 0xf3 +'jjyin', # 0xf4 +'jjyinj', # 0xf5 +'jjyinh', # 0xf6 +'jjyid', # 0xf7 +'jjyil', # 0xf8 +'jjyilg', # 0xf9 +'jjyilm', # 0xfa +'jjyilb', # 0xfb +'jjyils', # 0xfc +'jjyilt', # 0xfd +'jjyilp', # 0xfe +'jjyilh', # 0xff +) diff --git a/nstock/modules/unidecode/x0cc.py b/nstock/modules/unidecode/x0cc.py new file mode 100644 index 0000000..58f819a --- /dev/null +++ b/nstock/modules/unidecode/x0cc.py @@ -0,0 +1,258 @@ +data = ( +'jjyim', # 0x00 +'jjyib', # 0x01 +'jjyibs', # 0x02 +'jjyis', # 0x03 +'jjyiss', # 0x04 +'jjying', # 0x05 +'jjyij', # 0x06 +'jjyic', # 0x07 +'jjyik', # 0x08 +'jjyit', # 0x09 +'jjyip', # 0x0a +'jjyih', # 0x0b +'jji', # 0x0c +'jjig', # 0x0d +'jjigg', # 0x0e +'jjigs', # 0x0f +'jjin', # 0x10 +'jjinj', # 0x11 +'jjinh', # 0x12 +'jjid', # 0x13 +'jjil', # 0x14 +'jjilg', # 0x15 +'jjilm', # 0x16 +'jjilb', # 0x17 +'jjils', # 0x18 +'jjilt', # 0x19 +'jjilp', # 0x1a +'jjilh', # 0x1b +'jjim', # 0x1c +'jjib', # 0x1d +'jjibs', # 0x1e +'jjis', # 0x1f +'jjiss', # 0x20 +'jjing', # 0x21 +'jjij', # 0x22 +'jjic', # 0x23 +'jjik', # 0x24 +'jjit', # 0x25 +'jjip', # 0x26 +'jjih', # 0x27 +'ca', # 0x28 +'cag', # 0x29 +'cagg', # 0x2a +'cags', # 0x2b +'can', # 0x2c +'canj', # 0x2d +'canh', # 0x2e +'cad', # 0x2f +'cal', # 0x30 +'calg', # 0x31 +'calm', # 0x32 +'calb', # 0x33 +'cals', # 0x34 +'calt', # 0x35 +'calp', # 0x36 +'calh', # 0x37 +'cam', # 0x38 +'cab', # 0x39 +'cabs', # 0x3a +'cas', # 0x3b +'cass', # 0x3c +'cang', # 0x3d +'caj', # 0x3e +'cac', # 0x3f +'cak', # 0x40 +'cat', # 0x41 +'cap', # 0x42 +'cah', # 0x43 +'cae', # 0x44 +'caeg', # 0x45 +'caegg', # 0x46 +'caegs', # 0x47 +'caen', # 0x48 +'caenj', # 0x49 +'caenh', # 0x4a +'caed', # 0x4b +'cael', # 0x4c +'caelg', # 0x4d +'caelm', # 0x4e +'caelb', # 0x4f +'caels', # 0x50 +'caelt', # 0x51 +'caelp', # 0x52 +'caelh', # 0x53 +'caem', # 0x54 +'caeb', # 0x55 +'caebs', # 0x56 +'caes', # 0x57 +'caess', # 0x58 +'caeng', # 0x59 +'caej', # 0x5a +'caec', # 0x5b +'caek', # 0x5c +'caet', # 0x5d +'caep', # 0x5e +'caeh', # 0x5f +'cya', # 0x60 +'cyag', # 0x61 +'cyagg', # 0x62 +'cyags', # 0x63 +'cyan', # 0x64 +'cyanj', # 0x65 +'cyanh', # 0x66 +'cyad', # 0x67 +'cyal', # 0x68 +'cyalg', # 0x69 +'cyalm', # 0x6a +'cyalb', # 0x6b +'cyals', # 0x6c +'cyalt', # 0x6d +'cyalp', # 0x6e +'cyalh', # 0x6f +'cyam', # 0x70 +'cyab', # 0x71 +'cyabs', # 0x72 +'cyas', # 0x73 +'cyass', # 0x74 +'cyang', # 0x75 +'cyaj', # 0x76 +'cyac', # 0x77 +'cyak', # 0x78 +'cyat', # 0x79 +'cyap', # 0x7a +'cyah', # 0x7b +'cyae', # 0x7c +'cyaeg', # 0x7d +'cyaegg', # 0x7e +'cyaegs', # 0x7f +'cyaen', # 0x80 +'cyaenj', # 0x81 +'cyaenh', # 0x82 +'cyaed', # 0x83 +'cyael', # 0x84 +'cyaelg', # 0x85 +'cyaelm', # 0x86 +'cyaelb', # 0x87 +'cyaels', # 0x88 +'cyaelt', # 0x89 +'cyaelp', # 0x8a +'cyaelh', # 0x8b +'cyaem', # 0x8c +'cyaeb', # 0x8d +'cyaebs', # 0x8e +'cyaes', # 0x8f +'cyaess', # 0x90 +'cyaeng', # 0x91 +'cyaej', # 0x92 +'cyaec', # 0x93 +'cyaek', # 0x94 +'cyaet', # 0x95 +'cyaep', # 0x96 +'cyaeh', # 0x97 +'ceo', # 0x98 +'ceog', # 0x99 +'ceogg', # 0x9a +'ceogs', # 0x9b +'ceon', # 0x9c +'ceonj', # 0x9d +'ceonh', # 0x9e +'ceod', # 0x9f +'ceol', # 0xa0 +'ceolg', # 0xa1 +'ceolm', # 0xa2 +'ceolb', # 0xa3 +'ceols', # 0xa4 +'ceolt', # 0xa5 +'ceolp', # 0xa6 +'ceolh', # 0xa7 +'ceom', # 0xa8 +'ceob', # 0xa9 +'ceobs', # 0xaa +'ceos', # 0xab +'ceoss', # 0xac +'ceong', # 0xad +'ceoj', # 0xae +'ceoc', # 0xaf +'ceok', # 0xb0 +'ceot', # 0xb1 +'ceop', # 0xb2 +'ceoh', # 0xb3 +'ce', # 0xb4 +'ceg', # 0xb5 +'cegg', # 0xb6 +'cegs', # 0xb7 +'cen', # 0xb8 +'cenj', # 0xb9 +'cenh', # 0xba +'ced', # 0xbb +'cel', # 0xbc +'celg', # 0xbd +'celm', # 0xbe +'celb', # 0xbf +'cels', # 0xc0 +'celt', # 0xc1 +'celp', # 0xc2 +'celh', # 0xc3 +'cem', # 0xc4 +'ceb', # 0xc5 +'cebs', # 0xc6 +'ces', # 0xc7 +'cess', # 0xc8 +'ceng', # 0xc9 +'cej', # 0xca +'cec', # 0xcb +'cek', # 0xcc +'cet', # 0xcd +'cep', # 0xce +'ceh', # 0xcf +'cyeo', # 0xd0 +'cyeog', # 0xd1 +'cyeogg', # 0xd2 +'cyeogs', # 0xd3 +'cyeon', # 0xd4 +'cyeonj', # 0xd5 +'cyeonh', # 0xd6 +'cyeod', # 0xd7 +'cyeol', # 0xd8 +'cyeolg', # 0xd9 +'cyeolm', # 0xda +'cyeolb', # 0xdb +'cyeols', # 0xdc +'cyeolt', # 0xdd +'cyeolp', # 0xde +'cyeolh', # 0xdf +'cyeom', # 0xe0 +'cyeob', # 0xe1 +'cyeobs', # 0xe2 +'cyeos', # 0xe3 +'cyeoss', # 0xe4 +'cyeong', # 0xe5 +'cyeoj', # 0xe6 +'cyeoc', # 0xe7 +'cyeok', # 0xe8 +'cyeot', # 0xe9 +'cyeop', # 0xea +'cyeoh', # 0xeb +'cye', # 0xec +'cyeg', # 0xed +'cyegg', # 0xee +'cyegs', # 0xef +'cyen', # 0xf0 +'cyenj', # 0xf1 +'cyenh', # 0xf2 +'cyed', # 0xf3 +'cyel', # 0xf4 +'cyelg', # 0xf5 +'cyelm', # 0xf6 +'cyelb', # 0xf7 +'cyels', # 0xf8 +'cyelt', # 0xf9 +'cyelp', # 0xfa +'cyelh', # 0xfb +'cyem', # 0xfc +'cyeb', # 0xfd +'cyebs', # 0xfe +'cyes', # 0xff +) diff --git a/nstock/modules/unidecode/x0cd.py b/nstock/modules/unidecode/x0cd.py new file mode 100644 index 0000000..dd6909a --- /dev/null +++ b/nstock/modules/unidecode/x0cd.py @@ -0,0 +1,258 @@ +data = ( +'cyess', # 0x00 +'cyeng', # 0x01 +'cyej', # 0x02 +'cyec', # 0x03 +'cyek', # 0x04 +'cyet', # 0x05 +'cyep', # 0x06 +'cyeh', # 0x07 +'co', # 0x08 +'cog', # 0x09 +'cogg', # 0x0a +'cogs', # 0x0b +'con', # 0x0c +'conj', # 0x0d +'conh', # 0x0e +'cod', # 0x0f +'col', # 0x10 +'colg', # 0x11 +'colm', # 0x12 +'colb', # 0x13 +'cols', # 0x14 +'colt', # 0x15 +'colp', # 0x16 +'colh', # 0x17 +'com', # 0x18 +'cob', # 0x19 +'cobs', # 0x1a +'cos', # 0x1b +'coss', # 0x1c +'cong', # 0x1d +'coj', # 0x1e +'coc', # 0x1f +'cok', # 0x20 +'cot', # 0x21 +'cop', # 0x22 +'coh', # 0x23 +'cwa', # 0x24 +'cwag', # 0x25 +'cwagg', # 0x26 +'cwags', # 0x27 +'cwan', # 0x28 +'cwanj', # 0x29 +'cwanh', # 0x2a +'cwad', # 0x2b +'cwal', # 0x2c +'cwalg', # 0x2d +'cwalm', # 0x2e +'cwalb', # 0x2f +'cwals', # 0x30 +'cwalt', # 0x31 +'cwalp', # 0x32 +'cwalh', # 0x33 +'cwam', # 0x34 +'cwab', # 0x35 +'cwabs', # 0x36 +'cwas', # 0x37 +'cwass', # 0x38 +'cwang', # 0x39 +'cwaj', # 0x3a +'cwac', # 0x3b +'cwak', # 0x3c +'cwat', # 0x3d +'cwap', # 0x3e +'cwah', # 0x3f +'cwae', # 0x40 +'cwaeg', # 0x41 +'cwaegg', # 0x42 +'cwaegs', # 0x43 +'cwaen', # 0x44 +'cwaenj', # 0x45 +'cwaenh', # 0x46 +'cwaed', # 0x47 +'cwael', # 0x48 +'cwaelg', # 0x49 +'cwaelm', # 0x4a +'cwaelb', # 0x4b +'cwaels', # 0x4c +'cwaelt', # 0x4d +'cwaelp', # 0x4e +'cwaelh', # 0x4f +'cwaem', # 0x50 +'cwaeb', # 0x51 +'cwaebs', # 0x52 +'cwaes', # 0x53 +'cwaess', # 0x54 +'cwaeng', # 0x55 +'cwaej', # 0x56 +'cwaec', # 0x57 +'cwaek', # 0x58 +'cwaet', # 0x59 +'cwaep', # 0x5a +'cwaeh', # 0x5b +'coe', # 0x5c +'coeg', # 0x5d +'coegg', # 0x5e +'coegs', # 0x5f +'coen', # 0x60 +'coenj', # 0x61 +'coenh', # 0x62 +'coed', # 0x63 +'coel', # 0x64 +'coelg', # 0x65 +'coelm', # 0x66 +'coelb', # 0x67 +'coels', # 0x68 +'coelt', # 0x69 +'coelp', # 0x6a +'coelh', # 0x6b +'coem', # 0x6c +'coeb', # 0x6d +'coebs', # 0x6e +'coes', # 0x6f +'coess', # 0x70 +'coeng', # 0x71 +'coej', # 0x72 +'coec', # 0x73 +'coek', # 0x74 +'coet', # 0x75 +'coep', # 0x76 +'coeh', # 0x77 +'cyo', # 0x78 +'cyog', # 0x79 +'cyogg', # 0x7a +'cyogs', # 0x7b +'cyon', # 0x7c +'cyonj', # 0x7d +'cyonh', # 0x7e +'cyod', # 0x7f +'cyol', # 0x80 +'cyolg', # 0x81 +'cyolm', # 0x82 +'cyolb', # 0x83 +'cyols', # 0x84 +'cyolt', # 0x85 +'cyolp', # 0x86 +'cyolh', # 0x87 +'cyom', # 0x88 +'cyob', # 0x89 +'cyobs', # 0x8a +'cyos', # 0x8b +'cyoss', # 0x8c +'cyong', # 0x8d +'cyoj', # 0x8e +'cyoc', # 0x8f +'cyok', # 0x90 +'cyot', # 0x91 +'cyop', # 0x92 +'cyoh', # 0x93 +'cu', # 0x94 +'cug', # 0x95 +'cugg', # 0x96 +'cugs', # 0x97 +'cun', # 0x98 +'cunj', # 0x99 +'cunh', # 0x9a +'cud', # 0x9b +'cul', # 0x9c +'culg', # 0x9d +'culm', # 0x9e +'culb', # 0x9f +'culs', # 0xa0 +'cult', # 0xa1 +'culp', # 0xa2 +'culh', # 0xa3 +'cum', # 0xa4 +'cub', # 0xa5 +'cubs', # 0xa6 +'cus', # 0xa7 +'cuss', # 0xa8 +'cung', # 0xa9 +'cuj', # 0xaa +'cuc', # 0xab +'cuk', # 0xac +'cut', # 0xad +'cup', # 0xae +'cuh', # 0xaf +'cweo', # 0xb0 +'cweog', # 0xb1 +'cweogg', # 0xb2 +'cweogs', # 0xb3 +'cweon', # 0xb4 +'cweonj', # 0xb5 +'cweonh', # 0xb6 +'cweod', # 0xb7 +'cweol', # 0xb8 +'cweolg', # 0xb9 +'cweolm', # 0xba +'cweolb', # 0xbb +'cweols', # 0xbc +'cweolt', # 0xbd +'cweolp', # 0xbe +'cweolh', # 0xbf +'cweom', # 0xc0 +'cweob', # 0xc1 +'cweobs', # 0xc2 +'cweos', # 0xc3 +'cweoss', # 0xc4 +'cweong', # 0xc5 +'cweoj', # 0xc6 +'cweoc', # 0xc7 +'cweok', # 0xc8 +'cweot', # 0xc9 +'cweop', # 0xca +'cweoh', # 0xcb +'cwe', # 0xcc +'cweg', # 0xcd +'cwegg', # 0xce +'cwegs', # 0xcf +'cwen', # 0xd0 +'cwenj', # 0xd1 +'cwenh', # 0xd2 +'cwed', # 0xd3 +'cwel', # 0xd4 +'cwelg', # 0xd5 +'cwelm', # 0xd6 +'cwelb', # 0xd7 +'cwels', # 0xd8 +'cwelt', # 0xd9 +'cwelp', # 0xda +'cwelh', # 0xdb +'cwem', # 0xdc +'cweb', # 0xdd +'cwebs', # 0xde +'cwes', # 0xdf +'cwess', # 0xe0 +'cweng', # 0xe1 +'cwej', # 0xe2 +'cwec', # 0xe3 +'cwek', # 0xe4 +'cwet', # 0xe5 +'cwep', # 0xe6 +'cweh', # 0xe7 +'cwi', # 0xe8 +'cwig', # 0xe9 +'cwigg', # 0xea +'cwigs', # 0xeb +'cwin', # 0xec +'cwinj', # 0xed +'cwinh', # 0xee +'cwid', # 0xef +'cwil', # 0xf0 +'cwilg', # 0xf1 +'cwilm', # 0xf2 +'cwilb', # 0xf3 +'cwils', # 0xf4 +'cwilt', # 0xf5 +'cwilp', # 0xf6 +'cwilh', # 0xf7 +'cwim', # 0xf8 +'cwib', # 0xf9 +'cwibs', # 0xfa +'cwis', # 0xfb +'cwiss', # 0xfc +'cwing', # 0xfd +'cwij', # 0xfe +'cwic', # 0xff +) diff --git a/nstock/modules/unidecode/x0ce.py b/nstock/modules/unidecode/x0ce.py new file mode 100644 index 0000000..4b993e8 --- /dev/null +++ b/nstock/modules/unidecode/x0ce.py @@ -0,0 +1,258 @@ +data = ( +'cwik', # 0x00 +'cwit', # 0x01 +'cwip', # 0x02 +'cwih', # 0x03 +'cyu', # 0x04 +'cyug', # 0x05 +'cyugg', # 0x06 +'cyugs', # 0x07 +'cyun', # 0x08 +'cyunj', # 0x09 +'cyunh', # 0x0a +'cyud', # 0x0b +'cyul', # 0x0c +'cyulg', # 0x0d +'cyulm', # 0x0e +'cyulb', # 0x0f +'cyuls', # 0x10 +'cyult', # 0x11 +'cyulp', # 0x12 +'cyulh', # 0x13 +'cyum', # 0x14 +'cyub', # 0x15 +'cyubs', # 0x16 +'cyus', # 0x17 +'cyuss', # 0x18 +'cyung', # 0x19 +'cyuj', # 0x1a +'cyuc', # 0x1b +'cyuk', # 0x1c +'cyut', # 0x1d +'cyup', # 0x1e +'cyuh', # 0x1f +'ceu', # 0x20 +'ceug', # 0x21 +'ceugg', # 0x22 +'ceugs', # 0x23 +'ceun', # 0x24 +'ceunj', # 0x25 +'ceunh', # 0x26 +'ceud', # 0x27 +'ceul', # 0x28 +'ceulg', # 0x29 +'ceulm', # 0x2a +'ceulb', # 0x2b +'ceuls', # 0x2c +'ceult', # 0x2d +'ceulp', # 0x2e +'ceulh', # 0x2f +'ceum', # 0x30 +'ceub', # 0x31 +'ceubs', # 0x32 +'ceus', # 0x33 +'ceuss', # 0x34 +'ceung', # 0x35 +'ceuj', # 0x36 +'ceuc', # 0x37 +'ceuk', # 0x38 +'ceut', # 0x39 +'ceup', # 0x3a +'ceuh', # 0x3b +'cyi', # 0x3c +'cyig', # 0x3d +'cyigg', # 0x3e +'cyigs', # 0x3f +'cyin', # 0x40 +'cyinj', # 0x41 +'cyinh', # 0x42 +'cyid', # 0x43 +'cyil', # 0x44 +'cyilg', # 0x45 +'cyilm', # 0x46 +'cyilb', # 0x47 +'cyils', # 0x48 +'cyilt', # 0x49 +'cyilp', # 0x4a +'cyilh', # 0x4b +'cyim', # 0x4c +'cyib', # 0x4d +'cyibs', # 0x4e +'cyis', # 0x4f +'cyiss', # 0x50 +'cying', # 0x51 +'cyij', # 0x52 +'cyic', # 0x53 +'cyik', # 0x54 +'cyit', # 0x55 +'cyip', # 0x56 +'cyih', # 0x57 +'ci', # 0x58 +'cig', # 0x59 +'cigg', # 0x5a +'cigs', # 0x5b +'cin', # 0x5c +'cinj', # 0x5d +'cinh', # 0x5e +'cid', # 0x5f +'cil', # 0x60 +'cilg', # 0x61 +'cilm', # 0x62 +'cilb', # 0x63 +'cils', # 0x64 +'cilt', # 0x65 +'cilp', # 0x66 +'cilh', # 0x67 +'cim', # 0x68 +'cib', # 0x69 +'cibs', # 0x6a +'cis', # 0x6b +'ciss', # 0x6c +'cing', # 0x6d +'cij', # 0x6e +'cic', # 0x6f +'cik', # 0x70 +'cit', # 0x71 +'cip', # 0x72 +'cih', # 0x73 +'ka', # 0x74 +'kag', # 0x75 +'kagg', # 0x76 +'kags', # 0x77 +'kan', # 0x78 +'kanj', # 0x79 +'kanh', # 0x7a +'kad', # 0x7b +'kal', # 0x7c +'kalg', # 0x7d +'kalm', # 0x7e +'kalb', # 0x7f +'kals', # 0x80 +'kalt', # 0x81 +'kalp', # 0x82 +'kalh', # 0x83 +'kam', # 0x84 +'kab', # 0x85 +'kabs', # 0x86 +'kas', # 0x87 +'kass', # 0x88 +'kang', # 0x89 +'kaj', # 0x8a +'kac', # 0x8b +'kak', # 0x8c +'kat', # 0x8d +'kap', # 0x8e +'kah', # 0x8f +'kae', # 0x90 +'kaeg', # 0x91 +'kaegg', # 0x92 +'kaegs', # 0x93 +'kaen', # 0x94 +'kaenj', # 0x95 +'kaenh', # 0x96 +'kaed', # 0x97 +'kael', # 0x98 +'kaelg', # 0x99 +'kaelm', # 0x9a +'kaelb', # 0x9b +'kaels', # 0x9c +'kaelt', # 0x9d +'kaelp', # 0x9e +'kaelh', # 0x9f +'kaem', # 0xa0 +'kaeb', # 0xa1 +'kaebs', # 0xa2 +'kaes', # 0xa3 +'kaess', # 0xa4 +'kaeng', # 0xa5 +'kaej', # 0xa6 +'kaec', # 0xa7 +'kaek', # 0xa8 +'kaet', # 0xa9 +'kaep', # 0xaa +'kaeh', # 0xab +'kya', # 0xac +'kyag', # 0xad +'kyagg', # 0xae +'kyags', # 0xaf +'kyan', # 0xb0 +'kyanj', # 0xb1 +'kyanh', # 0xb2 +'kyad', # 0xb3 +'kyal', # 0xb4 +'kyalg', # 0xb5 +'kyalm', # 0xb6 +'kyalb', # 0xb7 +'kyals', # 0xb8 +'kyalt', # 0xb9 +'kyalp', # 0xba +'kyalh', # 0xbb +'kyam', # 0xbc +'kyab', # 0xbd +'kyabs', # 0xbe +'kyas', # 0xbf +'kyass', # 0xc0 +'kyang', # 0xc1 +'kyaj', # 0xc2 +'kyac', # 0xc3 +'kyak', # 0xc4 +'kyat', # 0xc5 +'kyap', # 0xc6 +'kyah', # 0xc7 +'kyae', # 0xc8 +'kyaeg', # 0xc9 +'kyaegg', # 0xca +'kyaegs', # 0xcb +'kyaen', # 0xcc +'kyaenj', # 0xcd +'kyaenh', # 0xce +'kyaed', # 0xcf +'kyael', # 0xd0 +'kyaelg', # 0xd1 +'kyaelm', # 0xd2 +'kyaelb', # 0xd3 +'kyaels', # 0xd4 +'kyaelt', # 0xd5 +'kyaelp', # 0xd6 +'kyaelh', # 0xd7 +'kyaem', # 0xd8 +'kyaeb', # 0xd9 +'kyaebs', # 0xda +'kyaes', # 0xdb +'kyaess', # 0xdc +'kyaeng', # 0xdd +'kyaej', # 0xde +'kyaec', # 0xdf +'kyaek', # 0xe0 +'kyaet', # 0xe1 +'kyaep', # 0xe2 +'kyaeh', # 0xe3 +'keo', # 0xe4 +'keog', # 0xe5 +'keogg', # 0xe6 +'keogs', # 0xe7 +'keon', # 0xe8 +'keonj', # 0xe9 +'keonh', # 0xea +'keod', # 0xeb +'keol', # 0xec +'keolg', # 0xed +'keolm', # 0xee +'keolb', # 0xef +'keols', # 0xf0 +'keolt', # 0xf1 +'keolp', # 0xf2 +'keolh', # 0xf3 +'keom', # 0xf4 +'keob', # 0xf5 +'keobs', # 0xf6 +'keos', # 0xf7 +'keoss', # 0xf8 +'keong', # 0xf9 +'keoj', # 0xfa +'keoc', # 0xfb +'keok', # 0xfc +'keot', # 0xfd +'keop', # 0xfe +'keoh', # 0xff +) diff --git a/nstock/modules/unidecode/x0cf.py b/nstock/modules/unidecode/x0cf.py new file mode 100644 index 0000000..e825983 --- /dev/null +++ b/nstock/modules/unidecode/x0cf.py @@ -0,0 +1,258 @@ +data = ( +'ke', # 0x00 +'keg', # 0x01 +'kegg', # 0x02 +'kegs', # 0x03 +'ken', # 0x04 +'kenj', # 0x05 +'kenh', # 0x06 +'ked', # 0x07 +'kel', # 0x08 +'kelg', # 0x09 +'kelm', # 0x0a +'kelb', # 0x0b +'kels', # 0x0c +'kelt', # 0x0d +'kelp', # 0x0e +'kelh', # 0x0f +'kem', # 0x10 +'keb', # 0x11 +'kebs', # 0x12 +'kes', # 0x13 +'kess', # 0x14 +'keng', # 0x15 +'kej', # 0x16 +'kec', # 0x17 +'kek', # 0x18 +'ket', # 0x19 +'kep', # 0x1a +'keh', # 0x1b +'kyeo', # 0x1c +'kyeog', # 0x1d +'kyeogg', # 0x1e +'kyeogs', # 0x1f +'kyeon', # 0x20 +'kyeonj', # 0x21 +'kyeonh', # 0x22 +'kyeod', # 0x23 +'kyeol', # 0x24 +'kyeolg', # 0x25 +'kyeolm', # 0x26 +'kyeolb', # 0x27 +'kyeols', # 0x28 +'kyeolt', # 0x29 +'kyeolp', # 0x2a +'kyeolh', # 0x2b +'kyeom', # 0x2c +'kyeob', # 0x2d +'kyeobs', # 0x2e +'kyeos', # 0x2f +'kyeoss', # 0x30 +'kyeong', # 0x31 +'kyeoj', # 0x32 +'kyeoc', # 0x33 +'kyeok', # 0x34 +'kyeot', # 0x35 +'kyeop', # 0x36 +'kyeoh', # 0x37 +'kye', # 0x38 +'kyeg', # 0x39 +'kyegg', # 0x3a +'kyegs', # 0x3b +'kyen', # 0x3c +'kyenj', # 0x3d +'kyenh', # 0x3e +'kyed', # 0x3f +'kyel', # 0x40 +'kyelg', # 0x41 +'kyelm', # 0x42 +'kyelb', # 0x43 +'kyels', # 0x44 +'kyelt', # 0x45 +'kyelp', # 0x46 +'kyelh', # 0x47 +'kyem', # 0x48 +'kyeb', # 0x49 +'kyebs', # 0x4a +'kyes', # 0x4b +'kyess', # 0x4c +'kyeng', # 0x4d +'kyej', # 0x4e +'kyec', # 0x4f +'kyek', # 0x50 +'kyet', # 0x51 +'kyep', # 0x52 +'kyeh', # 0x53 +'ko', # 0x54 +'kog', # 0x55 +'kogg', # 0x56 +'kogs', # 0x57 +'kon', # 0x58 +'konj', # 0x59 +'konh', # 0x5a +'kod', # 0x5b +'kol', # 0x5c +'kolg', # 0x5d +'kolm', # 0x5e +'kolb', # 0x5f +'kols', # 0x60 +'kolt', # 0x61 +'kolp', # 0x62 +'kolh', # 0x63 +'kom', # 0x64 +'kob', # 0x65 +'kobs', # 0x66 +'kos', # 0x67 +'koss', # 0x68 +'kong', # 0x69 +'koj', # 0x6a +'koc', # 0x6b +'kok', # 0x6c +'kot', # 0x6d +'kop', # 0x6e +'koh', # 0x6f +'kwa', # 0x70 +'kwag', # 0x71 +'kwagg', # 0x72 +'kwags', # 0x73 +'kwan', # 0x74 +'kwanj', # 0x75 +'kwanh', # 0x76 +'kwad', # 0x77 +'kwal', # 0x78 +'kwalg', # 0x79 +'kwalm', # 0x7a +'kwalb', # 0x7b +'kwals', # 0x7c +'kwalt', # 0x7d +'kwalp', # 0x7e +'kwalh', # 0x7f +'kwam', # 0x80 +'kwab', # 0x81 +'kwabs', # 0x82 +'kwas', # 0x83 +'kwass', # 0x84 +'kwang', # 0x85 +'kwaj', # 0x86 +'kwac', # 0x87 +'kwak', # 0x88 +'kwat', # 0x89 +'kwap', # 0x8a +'kwah', # 0x8b +'kwae', # 0x8c +'kwaeg', # 0x8d +'kwaegg', # 0x8e +'kwaegs', # 0x8f +'kwaen', # 0x90 +'kwaenj', # 0x91 +'kwaenh', # 0x92 +'kwaed', # 0x93 +'kwael', # 0x94 +'kwaelg', # 0x95 +'kwaelm', # 0x96 +'kwaelb', # 0x97 +'kwaels', # 0x98 +'kwaelt', # 0x99 +'kwaelp', # 0x9a +'kwaelh', # 0x9b +'kwaem', # 0x9c +'kwaeb', # 0x9d +'kwaebs', # 0x9e +'kwaes', # 0x9f +'kwaess', # 0xa0 +'kwaeng', # 0xa1 +'kwaej', # 0xa2 +'kwaec', # 0xa3 +'kwaek', # 0xa4 +'kwaet', # 0xa5 +'kwaep', # 0xa6 +'kwaeh', # 0xa7 +'koe', # 0xa8 +'koeg', # 0xa9 +'koegg', # 0xaa +'koegs', # 0xab +'koen', # 0xac +'koenj', # 0xad +'koenh', # 0xae +'koed', # 0xaf +'koel', # 0xb0 +'koelg', # 0xb1 +'koelm', # 0xb2 +'koelb', # 0xb3 +'koels', # 0xb4 +'koelt', # 0xb5 +'koelp', # 0xb6 +'koelh', # 0xb7 +'koem', # 0xb8 +'koeb', # 0xb9 +'koebs', # 0xba +'koes', # 0xbb +'koess', # 0xbc +'koeng', # 0xbd +'koej', # 0xbe +'koec', # 0xbf +'koek', # 0xc0 +'koet', # 0xc1 +'koep', # 0xc2 +'koeh', # 0xc3 +'kyo', # 0xc4 +'kyog', # 0xc5 +'kyogg', # 0xc6 +'kyogs', # 0xc7 +'kyon', # 0xc8 +'kyonj', # 0xc9 +'kyonh', # 0xca +'kyod', # 0xcb +'kyol', # 0xcc +'kyolg', # 0xcd +'kyolm', # 0xce +'kyolb', # 0xcf +'kyols', # 0xd0 +'kyolt', # 0xd1 +'kyolp', # 0xd2 +'kyolh', # 0xd3 +'kyom', # 0xd4 +'kyob', # 0xd5 +'kyobs', # 0xd6 +'kyos', # 0xd7 +'kyoss', # 0xd8 +'kyong', # 0xd9 +'kyoj', # 0xda +'kyoc', # 0xdb +'kyok', # 0xdc +'kyot', # 0xdd +'kyop', # 0xde +'kyoh', # 0xdf +'ku', # 0xe0 +'kug', # 0xe1 +'kugg', # 0xe2 +'kugs', # 0xe3 +'kun', # 0xe4 +'kunj', # 0xe5 +'kunh', # 0xe6 +'kud', # 0xe7 +'kul', # 0xe8 +'kulg', # 0xe9 +'kulm', # 0xea +'kulb', # 0xeb +'kuls', # 0xec +'kult', # 0xed +'kulp', # 0xee +'kulh', # 0xef +'kum', # 0xf0 +'kub', # 0xf1 +'kubs', # 0xf2 +'kus', # 0xf3 +'kuss', # 0xf4 +'kung', # 0xf5 +'kuj', # 0xf6 +'kuc', # 0xf7 +'kuk', # 0xf8 +'kut', # 0xf9 +'kup', # 0xfa +'kuh', # 0xfb +'kweo', # 0xfc +'kweog', # 0xfd +'kweogg', # 0xfe +'kweogs', # 0xff +) diff --git a/nstock/modules/unidecode/x0d0.py b/nstock/modules/unidecode/x0d0.py new file mode 100644 index 0000000..d6b3829 --- /dev/null +++ b/nstock/modules/unidecode/x0d0.py @@ -0,0 +1,258 @@ +data = ( +'kweon', # 0x00 +'kweonj', # 0x01 +'kweonh', # 0x02 +'kweod', # 0x03 +'kweol', # 0x04 +'kweolg', # 0x05 +'kweolm', # 0x06 +'kweolb', # 0x07 +'kweols', # 0x08 +'kweolt', # 0x09 +'kweolp', # 0x0a +'kweolh', # 0x0b +'kweom', # 0x0c +'kweob', # 0x0d +'kweobs', # 0x0e +'kweos', # 0x0f +'kweoss', # 0x10 +'kweong', # 0x11 +'kweoj', # 0x12 +'kweoc', # 0x13 +'kweok', # 0x14 +'kweot', # 0x15 +'kweop', # 0x16 +'kweoh', # 0x17 +'kwe', # 0x18 +'kweg', # 0x19 +'kwegg', # 0x1a +'kwegs', # 0x1b +'kwen', # 0x1c +'kwenj', # 0x1d +'kwenh', # 0x1e +'kwed', # 0x1f +'kwel', # 0x20 +'kwelg', # 0x21 +'kwelm', # 0x22 +'kwelb', # 0x23 +'kwels', # 0x24 +'kwelt', # 0x25 +'kwelp', # 0x26 +'kwelh', # 0x27 +'kwem', # 0x28 +'kweb', # 0x29 +'kwebs', # 0x2a +'kwes', # 0x2b +'kwess', # 0x2c +'kweng', # 0x2d +'kwej', # 0x2e +'kwec', # 0x2f +'kwek', # 0x30 +'kwet', # 0x31 +'kwep', # 0x32 +'kweh', # 0x33 +'kwi', # 0x34 +'kwig', # 0x35 +'kwigg', # 0x36 +'kwigs', # 0x37 +'kwin', # 0x38 +'kwinj', # 0x39 +'kwinh', # 0x3a +'kwid', # 0x3b +'kwil', # 0x3c +'kwilg', # 0x3d +'kwilm', # 0x3e +'kwilb', # 0x3f +'kwils', # 0x40 +'kwilt', # 0x41 +'kwilp', # 0x42 +'kwilh', # 0x43 +'kwim', # 0x44 +'kwib', # 0x45 +'kwibs', # 0x46 +'kwis', # 0x47 +'kwiss', # 0x48 +'kwing', # 0x49 +'kwij', # 0x4a +'kwic', # 0x4b +'kwik', # 0x4c +'kwit', # 0x4d +'kwip', # 0x4e +'kwih', # 0x4f +'kyu', # 0x50 +'kyug', # 0x51 +'kyugg', # 0x52 +'kyugs', # 0x53 +'kyun', # 0x54 +'kyunj', # 0x55 +'kyunh', # 0x56 +'kyud', # 0x57 +'kyul', # 0x58 +'kyulg', # 0x59 +'kyulm', # 0x5a +'kyulb', # 0x5b +'kyuls', # 0x5c +'kyult', # 0x5d +'kyulp', # 0x5e +'kyulh', # 0x5f +'kyum', # 0x60 +'kyub', # 0x61 +'kyubs', # 0x62 +'kyus', # 0x63 +'kyuss', # 0x64 +'kyung', # 0x65 +'kyuj', # 0x66 +'kyuc', # 0x67 +'kyuk', # 0x68 +'kyut', # 0x69 +'kyup', # 0x6a +'kyuh', # 0x6b +'keu', # 0x6c +'keug', # 0x6d +'keugg', # 0x6e +'keugs', # 0x6f +'keun', # 0x70 +'keunj', # 0x71 +'keunh', # 0x72 +'keud', # 0x73 +'keul', # 0x74 +'keulg', # 0x75 +'keulm', # 0x76 +'keulb', # 0x77 +'keuls', # 0x78 +'keult', # 0x79 +'keulp', # 0x7a +'keulh', # 0x7b +'keum', # 0x7c +'keub', # 0x7d +'keubs', # 0x7e +'keus', # 0x7f +'keuss', # 0x80 +'keung', # 0x81 +'keuj', # 0x82 +'keuc', # 0x83 +'keuk', # 0x84 +'keut', # 0x85 +'keup', # 0x86 +'keuh', # 0x87 +'kyi', # 0x88 +'kyig', # 0x89 +'kyigg', # 0x8a +'kyigs', # 0x8b +'kyin', # 0x8c +'kyinj', # 0x8d +'kyinh', # 0x8e +'kyid', # 0x8f +'kyil', # 0x90 +'kyilg', # 0x91 +'kyilm', # 0x92 +'kyilb', # 0x93 +'kyils', # 0x94 +'kyilt', # 0x95 +'kyilp', # 0x96 +'kyilh', # 0x97 +'kyim', # 0x98 +'kyib', # 0x99 +'kyibs', # 0x9a +'kyis', # 0x9b +'kyiss', # 0x9c +'kying', # 0x9d +'kyij', # 0x9e +'kyic', # 0x9f +'kyik', # 0xa0 +'kyit', # 0xa1 +'kyip', # 0xa2 +'kyih', # 0xa3 +'ki', # 0xa4 +'kig', # 0xa5 +'kigg', # 0xa6 +'kigs', # 0xa7 +'kin', # 0xa8 +'kinj', # 0xa9 +'kinh', # 0xaa +'kid', # 0xab +'kil', # 0xac +'kilg', # 0xad +'kilm', # 0xae +'kilb', # 0xaf +'kils', # 0xb0 +'kilt', # 0xb1 +'kilp', # 0xb2 +'kilh', # 0xb3 +'kim', # 0xb4 +'kib', # 0xb5 +'kibs', # 0xb6 +'kis', # 0xb7 +'kiss', # 0xb8 +'king', # 0xb9 +'kij', # 0xba +'kic', # 0xbb +'kik', # 0xbc +'kit', # 0xbd +'kip', # 0xbe +'kih', # 0xbf +'ta', # 0xc0 +'tag', # 0xc1 +'tagg', # 0xc2 +'tags', # 0xc3 +'tan', # 0xc4 +'tanj', # 0xc5 +'tanh', # 0xc6 +'tad', # 0xc7 +'tal', # 0xc8 +'talg', # 0xc9 +'talm', # 0xca +'talb', # 0xcb +'tals', # 0xcc +'talt', # 0xcd +'talp', # 0xce +'talh', # 0xcf +'tam', # 0xd0 +'tab', # 0xd1 +'tabs', # 0xd2 +'tas', # 0xd3 +'tass', # 0xd4 +'tang', # 0xd5 +'taj', # 0xd6 +'tac', # 0xd7 +'tak', # 0xd8 +'tat', # 0xd9 +'tap', # 0xda +'tah', # 0xdb +'tae', # 0xdc +'taeg', # 0xdd +'taegg', # 0xde +'taegs', # 0xdf +'taen', # 0xe0 +'taenj', # 0xe1 +'taenh', # 0xe2 +'taed', # 0xe3 +'tael', # 0xe4 +'taelg', # 0xe5 +'taelm', # 0xe6 +'taelb', # 0xe7 +'taels', # 0xe8 +'taelt', # 0xe9 +'taelp', # 0xea +'taelh', # 0xeb +'taem', # 0xec +'taeb', # 0xed +'taebs', # 0xee +'taes', # 0xef +'taess', # 0xf0 +'taeng', # 0xf1 +'taej', # 0xf2 +'taec', # 0xf3 +'taek', # 0xf4 +'taet', # 0xf5 +'taep', # 0xf6 +'taeh', # 0xf7 +'tya', # 0xf8 +'tyag', # 0xf9 +'tyagg', # 0xfa +'tyags', # 0xfb +'tyan', # 0xfc +'tyanj', # 0xfd +'tyanh', # 0xfe +'tyad', # 0xff +) diff --git a/nstock/modules/unidecode/x0d1.py b/nstock/modules/unidecode/x0d1.py new file mode 100644 index 0000000..c2bbd16 --- /dev/null +++ b/nstock/modules/unidecode/x0d1.py @@ -0,0 +1,258 @@ +data = ( +'tyal', # 0x00 +'tyalg', # 0x01 +'tyalm', # 0x02 +'tyalb', # 0x03 +'tyals', # 0x04 +'tyalt', # 0x05 +'tyalp', # 0x06 +'tyalh', # 0x07 +'tyam', # 0x08 +'tyab', # 0x09 +'tyabs', # 0x0a +'tyas', # 0x0b +'tyass', # 0x0c +'tyang', # 0x0d +'tyaj', # 0x0e +'tyac', # 0x0f +'tyak', # 0x10 +'tyat', # 0x11 +'tyap', # 0x12 +'tyah', # 0x13 +'tyae', # 0x14 +'tyaeg', # 0x15 +'tyaegg', # 0x16 +'tyaegs', # 0x17 +'tyaen', # 0x18 +'tyaenj', # 0x19 +'tyaenh', # 0x1a +'tyaed', # 0x1b +'tyael', # 0x1c +'tyaelg', # 0x1d +'tyaelm', # 0x1e +'tyaelb', # 0x1f +'tyaels', # 0x20 +'tyaelt', # 0x21 +'tyaelp', # 0x22 +'tyaelh', # 0x23 +'tyaem', # 0x24 +'tyaeb', # 0x25 +'tyaebs', # 0x26 +'tyaes', # 0x27 +'tyaess', # 0x28 +'tyaeng', # 0x29 +'tyaej', # 0x2a +'tyaec', # 0x2b +'tyaek', # 0x2c +'tyaet', # 0x2d +'tyaep', # 0x2e +'tyaeh', # 0x2f +'teo', # 0x30 +'teog', # 0x31 +'teogg', # 0x32 +'teogs', # 0x33 +'teon', # 0x34 +'teonj', # 0x35 +'teonh', # 0x36 +'teod', # 0x37 +'teol', # 0x38 +'teolg', # 0x39 +'teolm', # 0x3a +'teolb', # 0x3b +'teols', # 0x3c +'teolt', # 0x3d +'teolp', # 0x3e +'teolh', # 0x3f +'teom', # 0x40 +'teob', # 0x41 +'teobs', # 0x42 +'teos', # 0x43 +'teoss', # 0x44 +'teong', # 0x45 +'teoj', # 0x46 +'teoc', # 0x47 +'teok', # 0x48 +'teot', # 0x49 +'teop', # 0x4a +'teoh', # 0x4b +'te', # 0x4c +'teg', # 0x4d +'tegg', # 0x4e +'tegs', # 0x4f +'ten', # 0x50 +'tenj', # 0x51 +'tenh', # 0x52 +'ted', # 0x53 +'tel', # 0x54 +'telg', # 0x55 +'telm', # 0x56 +'telb', # 0x57 +'tels', # 0x58 +'telt', # 0x59 +'telp', # 0x5a +'telh', # 0x5b +'tem', # 0x5c +'teb', # 0x5d +'tebs', # 0x5e +'tes', # 0x5f +'tess', # 0x60 +'teng', # 0x61 +'tej', # 0x62 +'tec', # 0x63 +'tek', # 0x64 +'tet', # 0x65 +'tep', # 0x66 +'teh', # 0x67 +'tyeo', # 0x68 +'tyeog', # 0x69 +'tyeogg', # 0x6a +'tyeogs', # 0x6b +'tyeon', # 0x6c +'tyeonj', # 0x6d +'tyeonh', # 0x6e +'tyeod', # 0x6f +'tyeol', # 0x70 +'tyeolg', # 0x71 +'tyeolm', # 0x72 +'tyeolb', # 0x73 +'tyeols', # 0x74 +'tyeolt', # 0x75 +'tyeolp', # 0x76 +'tyeolh', # 0x77 +'tyeom', # 0x78 +'tyeob', # 0x79 +'tyeobs', # 0x7a +'tyeos', # 0x7b +'tyeoss', # 0x7c +'tyeong', # 0x7d +'tyeoj', # 0x7e +'tyeoc', # 0x7f +'tyeok', # 0x80 +'tyeot', # 0x81 +'tyeop', # 0x82 +'tyeoh', # 0x83 +'tye', # 0x84 +'tyeg', # 0x85 +'tyegg', # 0x86 +'tyegs', # 0x87 +'tyen', # 0x88 +'tyenj', # 0x89 +'tyenh', # 0x8a +'tyed', # 0x8b +'tyel', # 0x8c +'tyelg', # 0x8d +'tyelm', # 0x8e +'tyelb', # 0x8f +'tyels', # 0x90 +'tyelt', # 0x91 +'tyelp', # 0x92 +'tyelh', # 0x93 +'tyem', # 0x94 +'tyeb', # 0x95 +'tyebs', # 0x96 +'tyes', # 0x97 +'tyess', # 0x98 +'tyeng', # 0x99 +'tyej', # 0x9a +'tyec', # 0x9b +'tyek', # 0x9c +'tyet', # 0x9d +'tyep', # 0x9e +'tyeh', # 0x9f +'to', # 0xa0 +'tog', # 0xa1 +'togg', # 0xa2 +'togs', # 0xa3 +'ton', # 0xa4 +'tonj', # 0xa5 +'tonh', # 0xa6 +'tod', # 0xa7 +'tol', # 0xa8 +'tolg', # 0xa9 +'tolm', # 0xaa +'tolb', # 0xab +'tols', # 0xac +'tolt', # 0xad +'tolp', # 0xae +'tolh', # 0xaf +'tom', # 0xb0 +'tob', # 0xb1 +'tobs', # 0xb2 +'tos', # 0xb3 +'toss', # 0xb4 +'tong', # 0xb5 +'toj', # 0xb6 +'toc', # 0xb7 +'tok', # 0xb8 +'tot', # 0xb9 +'top', # 0xba +'toh', # 0xbb +'twa', # 0xbc +'twag', # 0xbd +'twagg', # 0xbe +'twags', # 0xbf +'twan', # 0xc0 +'twanj', # 0xc1 +'twanh', # 0xc2 +'twad', # 0xc3 +'twal', # 0xc4 +'twalg', # 0xc5 +'twalm', # 0xc6 +'twalb', # 0xc7 +'twals', # 0xc8 +'twalt', # 0xc9 +'twalp', # 0xca +'twalh', # 0xcb +'twam', # 0xcc +'twab', # 0xcd +'twabs', # 0xce +'twas', # 0xcf +'twass', # 0xd0 +'twang', # 0xd1 +'twaj', # 0xd2 +'twac', # 0xd3 +'twak', # 0xd4 +'twat', # 0xd5 +'twap', # 0xd6 +'twah', # 0xd7 +'twae', # 0xd8 +'twaeg', # 0xd9 +'twaegg', # 0xda +'twaegs', # 0xdb +'twaen', # 0xdc +'twaenj', # 0xdd +'twaenh', # 0xde +'twaed', # 0xdf +'twael', # 0xe0 +'twaelg', # 0xe1 +'twaelm', # 0xe2 +'twaelb', # 0xe3 +'twaels', # 0xe4 +'twaelt', # 0xe5 +'twaelp', # 0xe6 +'twaelh', # 0xe7 +'twaem', # 0xe8 +'twaeb', # 0xe9 +'twaebs', # 0xea +'twaes', # 0xeb +'twaess', # 0xec +'twaeng', # 0xed +'twaej', # 0xee +'twaec', # 0xef +'twaek', # 0xf0 +'twaet', # 0xf1 +'twaep', # 0xf2 +'twaeh', # 0xf3 +'toe', # 0xf4 +'toeg', # 0xf5 +'toegg', # 0xf6 +'toegs', # 0xf7 +'toen', # 0xf8 +'toenj', # 0xf9 +'toenh', # 0xfa +'toed', # 0xfb +'toel', # 0xfc +'toelg', # 0xfd +'toelm', # 0xfe +'toelb', # 0xff +) diff --git a/nstock/modules/unidecode/x0d2.py b/nstock/modules/unidecode/x0d2.py new file mode 100644 index 0000000..052d462 --- /dev/null +++ b/nstock/modules/unidecode/x0d2.py @@ -0,0 +1,258 @@ +data = ( +'toels', # 0x00 +'toelt', # 0x01 +'toelp', # 0x02 +'toelh', # 0x03 +'toem', # 0x04 +'toeb', # 0x05 +'toebs', # 0x06 +'toes', # 0x07 +'toess', # 0x08 +'toeng', # 0x09 +'toej', # 0x0a +'toec', # 0x0b +'toek', # 0x0c +'toet', # 0x0d +'toep', # 0x0e +'toeh', # 0x0f +'tyo', # 0x10 +'tyog', # 0x11 +'tyogg', # 0x12 +'tyogs', # 0x13 +'tyon', # 0x14 +'tyonj', # 0x15 +'tyonh', # 0x16 +'tyod', # 0x17 +'tyol', # 0x18 +'tyolg', # 0x19 +'tyolm', # 0x1a +'tyolb', # 0x1b +'tyols', # 0x1c +'tyolt', # 0x1d +'tyolp', # 0x1e +'tyolh', # 0x1f +'tyom', # 0x20 +'tyob', # 0x21 +'tyobs', # 0x22 +'tyos', # 0x23 +'tyoss', # 0x24 +'tyong', # 0x25 +'tyoj', # 0x26 +'tyoc', # 0x27 +'tyok', # 0x28 +'tyot', # 0x29 +'tyop', # 0x2a +'tyoh', # 0x2b +'tu', # 0x2c +'tug', # 0x2d +'tugg', # 0x2e +'tugs', # 0x2f +'tun', # 0x30 +'tunj', # 0x31 +'tunh', # 0x32 +'tud', # 0x33 +'tul', # 0x34 +'tulg', # 0x35 +'tulm', # 0x36 +'tulb', # 0x37 +'tuls', # 0x38 +'tult', # 0x39 +'tulp', # 0x3a +'tulh', # 0x3b +'tum', # 0x3c +'tub', # 0x3d +'tubs', # 0x3e +'tus', # 0x3f +'tuss', # 0x40 +'tung', # 0x41 +'tuj', # 0x42 +'tuc', # 0x43 +'tuk', # 0x44 +'tut', # 0x45 +'tup', # 0x46 +'tuh', # 0x47 +'tweo', # 0x48 +'tweog', # 0x49 +'tweogg', # 0x4a +'tweogs', # 0x4b +'tweon', # 0x4c +'tweonj', # 0x4d +'tweonh', # 0x4e +'tweod', # 0x4f +'tweol', # 0x50 +'tweolg', # 0x51 +'tweolm', # 0x52 +'tweolb', # 0x53 +'tweols', # 0x54 +'tweolt', # 0x55 +'tweolp', # 0x56 +'tweolh', # 0x57 +'tweom', # 0x58 +'tweob', # 0x59 +'tweobs', # 0x5a +'tweos', # 0x5b +'tweoss', # 0x5c +'tweong', # 0x5d +'tweoj', # 0x5e +'tweoc', # 0x5f +'tweok', # 0x60 +'tweot', # 0x61 +'tweop', # 0x62 +'tweoh', # 0x63 +'twe', # 0x64 +'tweg', # 0x65 +'twegg', # 0x66 +'twegs', # 0x67 +'twen', # 0x68 +'twenj', # 0x69 +'twenh', # 0x6a +'twed', # 0x6b +'twel', # 0x6c +'twelg', # 0x6d +'twelm', # 0x6e +'twelb', # 0x6f +'twels', # 0x70 +'twelt', # 0x71 +'twelp', # 0x72 +'twelh', # 0x73 +'twem', # 0x74 +'tweb', # 0x75 +'twebs', # 0x76 +'twes', # 0x77 +'twess', # 0x78 +'tweng', # 0x79 +'twej', # 0x7a +'twec', # 0x7b +'twek', # 0x7c +'twet', # 0x7d +'twep', # 0x7e +'tweh', # 0x7f +'twi', # 0x80 +'twig', # 0x81 +'twigg', # 0x82 +'twigs', # 0x83 +'twin', # 0x84 +'twinj', # 0x85 +'twinh', # 0x86 +'twid', # 0x87 +'twil', # 0x88 +'twilg', # 0x89 +'twilm', # 0x8a +'twilb', # 0x8b +'twils', # 0x8c +'twilt', # 0x8d +'twilp', # 0x8e +'twilh', # 0x8f +'twim', # 0x90 +'twib', # 0x91 +'twibs', # 0x92 +'twis', # 0x93 +'twiss', # 0x94 +'twing', # 0x95 +'twij', # 0x96 +'twic', # 0x97 +'twik', # 0x98 +'twit', # 0x99 +'twip', # 0x9a +'twih', # 0x9b +'tyu', # 0x9c +'tyug', # 0x9d +'tyugg', # 0x9e +'tyugs', # 0x9f +'tyun', # 0xa0 +'tyunj', # 0xa1 +'tyunh', # 0xa2 +'tyud', # 0xa3 +'tyul', # 0xa4 +'tyulg', # 0xa5 +'tyulm', # 0xa6 +'tyulb', # 0xa7 +'tyuls', # 0xa8 +'tyult', # 0xa9 +'tyulp', # 0xaa +'tyulh', # 0xab +'tyum', # 0xac +'tyub', # 0xad +'tyubs', # 0xae +'tyus', # 0xaf +'tyuss', # 0xb0 +'tyung', # 0xb1 +'tyuj', # 0xb2 +'tyuc', # 0xb3 +'tyuk', # 0xb4 +'tyut', # 0xb5 +'tyup', # 0xb6 +'tyuh', # 0xb7 +'teu', # 0xb8 +'teug', # 0xb9 +'teugg', # 0xba +'teugs', # 0xbb +'teun', # 0xbc +'teunj', # 0xbd +'teunh', # 0xbe +'teud', # 0xbf +'teul', # 0xc0 +'teulg', # 0xc1 +'teulm', # 0xc2 +'teulb', # 0xc3 +'teuls', # 0xc4 +'teult', # 0xc5 +'teulp', # 0xc6 +'teulh', # 0xc7 +'teum', # 0xc8 +'teub', # 0xc9 +'teubs', # 0xca +'teus', # 0xcb +'teuss', # 0xcc +'teung', # 0xcd +'teuj', # 0xce +'teuc', # 0xcf +'teuk', # 0xd0 +'teut', # 0xd1 +'teup', # 0xd2 +'teuh', # 0xd3 +'tyi', # 0xd4 +'tyig', # 0xd5 +'tyigg', # 0xd6 +'tyigs', # 0xd7 +'tyin', # 0xd8 +'tyinj', # 0xd9 +'tyinh', # 0xda +'tyid', # 0xdb +'tyil', # 0xdc +'tyilg', # 0xdd +'tyilm', # 0xde +'tyilb', # 0xdf +'tyils', # 0xe0 +'tyilt', # 0xe1 +'tyilp', # 0xe2 +'tyilh', # 0xe3 +'tyim', # 0xe4 +'tyib', # 0xe5 +'tyibs', # 0xe6 +'tyis', # 0xe7 +'tyiss', # 0xe8 +'tying', # 0xe9 +'tyij', # 0xea +'tyic', # 0xeb +'tyik', # 0xec +'tyit', # 0xed +'tyip', # 0xee +'tyih', # 0xef +'ti', # 0xf0 +'tig', # 0xf1 +'tigg', # 0xf2 +'tigs', # 0xf3 +'tin', # 0xf4 +'tinj', # 0xf5 +'tinh', # 0xf6 +'tid', # 0xf7 +'til', # 0xf8 +'tilg', # 0xf9 +'tilm', # 0xfa +'tilb', # 0xfb +'tils', # 0xfc +'tilt', # 0xfd +'tilp', # 0xfe +'tilh', # 0xff +) diff --git a/nstock/modules/unidecode/x0d3.py b/nstock/modules/unidecode/x0d3.py new file mode 100644 index 0000000..70a4701 --- /dev/null +++ b/nstock/modules/unidecode/x0d3.py @@ -0,0 +1,258 @@ +data = ( +'tim', # 0x00 +'tib', # 0x01 +'tibs', # 0x02 +'tis', # 0x03 +'tiss', # 0x04 +'ting', # 0x05 +'tij', # 0x06 +'tic', # 0x07 +'tik', # 0x08 +'tit', # 0x09 +'tip', # 0x0a +'tih', # 0x0b +'pa', # 0x0c +'pag', # 0x0d +'pagg', # 0x0e +'pags', # 0x0f +'pan', # 0x10 +'panj', # 0x11 +'panh', # 0x12 +'pad', # 0x13 +'pal', # 0x14 +'palg', # 0x15 +'palm', # 0x16 +'palb', # 0x17 +'pals', # 0x18 +'palt', # 0x19 +'palp', # 0x1a +'palh', # 0x1b +'pam', # 0x1c +'pab', # 0x1d +'pabs', # 0x1e +'pas', # 0x1f +'pass', # 0x20 +'pang', # 0x21 +'paj', # 0x22 +'pac', # 0x23 +'pak', # 0x24 +'pat', # 0x25 +'pap', # 0x26 +'pah', # 0x27 +'pae', # 0x28 +'paeg', # 0x29 +'paegg', # 0x2a +'paegs', # 0x2b +'paen', # 0x2c +'paenj', # 0x2d +'paenh', # 0x2e +'paed', # 0x2f +'pael', # 0x30 +'paelg', # 0x31 +'paelm', # 0x32 +'paelb', # 0x33 +'paels', # 0x34 +'paelt', # 0x35 +'paelp', # 0x36 +'paelh', # 0x37 +'paem', # 0x38 +'paeb', # 0x39 +'paebs', # 0x3a +'paes', # 0x3b +'paess', # 0x3c +'paeng', # 0x3d +'paej', # 0x3e +'paec', # 0x3f +'paek', # 0x40 +'paet', # 0x41 +'paep', # 0x42 +'paeh', # 0x43 +'pya', # 0x44 +'pyag', # 0x45 +'pyagg', # 0x46 +'pyags', # 0x47 +'pyan', # 0x48 +'pyanj', # 0x49 +'pyanh', # 0x4a +'pyad', # 0x4b +'pyal', # 0x4c +'pyalg', # 0x4d +'pyalm', # 0x4e +'pyalb', # 0x4f +'pyals', # 0x50 +'pyalt', # 0x51 +'pyalp', # 0x52 +'pyalh', # 0x53 +'pyam', # 0x54 +'pyab', # 0x55 +'pyabs', # 0x56 +'pyas', # 0x57 +'pyass', # 0x58 +'pyang', # 0x59 +'pyaj', # 0x5a +'pyac', # 0x5b +'pyak', # 0x5c +'pyat', # 0x5d +'pyap', # 0x5e +'pyah', # 0x5f +'pyae', # 0x60 +'pyaeg', # 0x61 +'pyaegg', # 0x62 +'pyaegs', # 0x63 +'pyaen', # 0x64 +'pyaenj', # 0x65 +'pyaenh', # 0x66 +'pyaed', # 0x67 +'pyael', # 0x68 +'pyaelg', # 0x69 +'pyaelm', # 0x6a +'pyaelb', # 0x6b +'pyaels', # 0x6c +'pyaelt', # 0x6d +'pyaelp', # 0x6e +'pyaelh', # 0x6f +'pyaem', # 0x70 +'pyaeb', # 0x71 +'pyaebs', # 0x72 +'pyaes', # 0x73 +'pyaess', # 0x74 +'pyaeng', # 0x75 +'pyaej', # 0x76 +'pyaec', # 0x77 +'pyaek', # 0x78 +'pyaet', # 0x79 +'pyaep', # 0x7a +'pyaeh', # 0x7b +'peo', # 0x7c +'peog', # 0x7d +'peogg', # 0x7e +'peogs', # 0x7f +'peon', # 0x80 +'peonj', # 0x81 +'peonh', # 0x82 +'peod', # 0x83 +'peol', # 0x84 +'peolg', # 0x85 +'peolm', # 0x86 +'peolb', # 0x87 +'peols', # 0x88 +'peolt', # 0x89 +'peolp', # 0x8a +'peolh', # 0x8b +'peom', # 0x8c +'peob', # 0x8d +'peobs', # 0x8e +'peos', # 0x8f +'peoss', # 0x90 +'peong', # 0x91 +'peoj', # 0x92 +'peoc', # 0x93 +'peok', # 0x94 +'peot', # 0x95 +'peop', # 0x96 +'peoh', # 0x97 +'pe', # 0x98 +'peg', # 0x99 +'pegg', # 0x9a +'pegs', # 0x9b +'pen', # 0x9c +'penj', # 0x9d +'penh', # 0x9e +'ped', # 0x9f +'pel', # 0xa0 +'pelg', # 0xa1 +'pelm', # 0xa2 +'pelb', # 0xa3 +'pels', # 0xa4 +'pelt', # 0xa5 +'pelp', # 0xa6 +'pelh', # 0xa7 +'pem', # 0xa8 +'peb', # 0xa9 +'pebs', # 0xaa +'pes', # 0xab +'pess', # 0xac +'peng', # 0xad +'pej', # 0xae +'pec', # 0xaf +'pek', # 0xb0 +'pet', # 0xb1 +'pep', # 0xb2 +'peh', # 0xb3 +'pyeo', # 0xb4 +'pyeog', # 0xb5 +'pyeogg', # 0xb6 +'pyeogs', # 0xb7 +'pyeon', # 0xb8 +'pyeonj', # 0xb9 +'pyeonh', # 0xba +'pyeod', # 0xbb +'pyeol', # 0xbc +'pyeolg', # 0xbd +'pyeolm', # 0xbe +'pyeolb', # 0xbf +'pyeols', # 0xc0 +'pyeolt', # 0xc1 +'pyeolp', # 0xc2 +'pyeolh', # 0xc3 +'pyeom', # 0xc4 +'pyeob', # 0xc5 +'pyeobs', # 0xc6 +'pyeos', # 0xc7 +'pyeoss', # 0xc8 +'pyeong', # 0xc9 +'pyeoj', # 0xca +'pyeoc', # 0xcb +'pyeok', # 0xcc +'pyeot', # 0xcd +'pyeop', # 0xce +'pyeoh', # 0xcf +'pye', # 0xd0 +'pyeg', # 0xd1 +'pyegg', # 0xd2 +'pyegs', # 0xd3 +'pyen', # 0xd4 +'pyenj', # 0xd5 +'pyenh', # 0xd6 +'pyed', # 0xd7 +'pyel', # 0xd8 +'pyelg', # 0xd9 +'pyelm', # 0xda +'pyelb', # 0xdb +'pyels', # 0xdc +'pyelt', # 0xdd +'pyelp', # 0xde +'pyelh', # 0xdf +'pyem', # 0xe0 +'pyeb', # 0xe1 +'pyebs', # 0xe2 +'pyes', # 0xe3 +'pyess', # 0xe4 +'pyeng', # 0xe5 +'pyej', # 0xe6 +'pyec', # 0xe7 +'pyek', # 0xe8 +'pyet', # 0xe9 +'pyep', # 0xea +'pyeh', # 0xeb +'po', # 0xec +'pog', # 0xed +'pogg', # 0xee +'pogs', # 0xef +'pon', # 0xf0 +'ponj', # 0xf1 +'ponh', # 0xf2 +'pod', # 0xf3 +'pol', # 0xf4 +'polg', # 0xf5 +'polm', # 0xf6 +'polb', # 0xf7 +'pols', # 0xf8 +'polt', # 0xf9 +'polp', # 0xfa +'polh', # 0xfb +'pom', # 0xfc +'pob', # 0xfd +'pobs', # 0xfe +'pos', # 0xff +) diff --git a/nstock/modules/unidecode/x0d4.py b/nstock/modules/unidecode/x0d4.py new file mode 100644 index 0000000..87caad4 --- /dev/null +++ b/nstock/modules/unidecode/x0d4.py @@ -0,0 +1,258 @@ +data = ( +'poss', # 0x00 +'pong', # 0x01 +'poj', # 0x02 +'poc', # 0x03 +'pok', # 0x04 +'pot', # 0x05 +'pop', # 0x06 +'poh', # 0x07 +'pwa', # 0x08 +'pwag', # 0x09 +'pwagg', # 0x0a +'pwags', # 0x0b +'pwan', # 0x0c +'pwanj', # 0x0d +'pwanh', # 0x0e +'pwad', # 0x0f +'pwal', # 0x10 +'pwalg', # 0x11 +'pwalm', # 0x12 +'pwalb', # 0x13 +'pwals', # 0x14 +'pwalt', # 0x15 +'pwalp', # 0x16 +'pwalh', # 0x17 +'pwam', # 0x18 +'pwab', # 0x19 +'pwabs', # 0x1a +'pwas', # 0x1b +'pwass', # 0x1c +'pwang', # 0x1d +'pwaj', # 0x1e +'pwac', # 0x1f +'pwak', # 0x20 +'pwat', # 0x21 +'pwap', # 0x22 +'pwah', # 0x23 +'pwae', # 0x24 +'pwaeg', # 0x25 +'pwaegg', # 0x26 +'pwaegs', # 0x27 +'pwaen', # 0x28 +'pwaenj', # 0x29 +'pwaenh', # 0x2a +'pwaed', # 0x2b +'pwael', # 0x2c +'pwaelg', # 0x2d +'pwaelm', # 0x2e +'pwaelb', # 0x2f +'pwaels', # 0x30 +'pwaelt', # 0x31 +'pwaelp', # 0x32 +'pwaelh', # 0x33 +'pwaem', # 0x34 +'pwaeb', # 0x35 +'pwaebs', # 0x36 +'pwaes', # 0x37 +'pwaess', # 0x38 +'pwaeng', # 0x39 +'pwaej', # 0x3a +'pwaec', # 0x3b +'pwaek', # 0x3c +'pwaet', # 0x3d +'pwaep', # 0x3e +'pwaeh', # 0x3f +'poe', # 0x40 +'poeg', # 0x41 +'poegg', # 0x42 +'poegs', # 0x43 +'poen', # 0x44 +'poenj', # 0x45 +'poenh', # 0x46 +'poed', # 0x47 +'poel', # 0x48 +'poelg', # 0x49 +'poelm', # 0x4a +'poelb', # 0x4b +'poels', # 0x4c +'poelt', # 0x4d +'poelp', # 0x4e +'poelh', # 0x4f +'poem', # 0x50 +'poeb', # 0x51 +'poebs', # 0x52 +'poes', # 0x53 +'poess', # 0x54 +'poeng', # 0x55 +'poej', # 0x56 +'poec', # 0x57 +'poek', # 0x58 +'poet', # 0x59 +'poep', # 0x5a +'poeh', # 0x5b +'pyo', # 0x5c +'pyog', # 0x5d +'pyogg', # 0x5e +'pyogs', # 0x5f +'pyon', # 0x60 +'pyonj', # 0x61 +'pyonh', # 0x62 +'pyod', # 0x63 +'pyol', # 0x64 +'pyolg', # 0x65 +'pyolm', # 0x66 +'pyolb', # 0x67 +'pyols', # 0x68 +'pyolt', # 0x69 +'pyolp', # 0x6a +'pyolh', # 0x6b +'pyom', # 0x6c +'pyob', # 0x6d +'pyobs', # 0x6e +'pyos', # 0x6f +'pyoss', # 0x70 +'pyong', # 0x71 +'pyoj', # 0x72 +'pyoc', # 0x73 +'pyok', # 0x74 +'pyot', # 0x75 +'pyop', # 0x76 +'pyoh', # 0x77 +'pu', # 0x78 +'pug', # 0x79 +'pugg', # 0x7a +'pugs', # 0x7b +'pun', # 0x7c +'punj', # 0x7d +'punh', # 0x7e +'pud', # 0x7f +'pul', # 0x80 +'pulg', # 0x81 +'pulm', # 0x82 +'pulb', # 0x83 +'puls', # 0x84 +'pult', # 0x85 +'pulp', # 0x86 +'pulh', # 0x87 +'pum', # 0x88 +'pub', # 0x89 +'pubs', # 0x8a +'pus', # 0x8b +'puss', # 0x8c +'pung', # 0x8d +'puj', # 0x8e +'puc', # 0x8f +'puk', # 0x90 +'put', # 0x91 +'pup', # 0x92 +'puh', # 0x93 +'pweo', # 0x94 +'pweog', # 0x95 +'pweogg', # 0x96 +'pweogs', # 0x97 +'pweon', # 0x98 +'pweonj', # 0x99 +'pweonh', # 0x9a +'pweod', # 0x9b +'pweol', # 0x9c +'pweolg', # 0x9d +'pweolm', # 0x9e +'pweolb', # 0x9f +'pweols', # 0xa0 +'pweolt', # 0xa1 +'pweolp', # 0xa2 +'pweolh', # 0xa3 +'pweom', # 0xa4 +'pweob', # 0xa5 +'pweobs', # 0xa6 +'pweos', # 0xa7 +'pweoss', # 0xa8 +'pweong', # 0xa9 +'pweoj', # 0xaa +'pweoc', # 0xab +'pweok', # 0xac +'pweot', # 0xad +'pweop', # 0xae +'pweoh', # 0xaf +'pwe', # 0xb0 +'pweg', # 0xb1 +'pwegg', # 0xb2 +'pwegs', # 0xb3 +'pwen', # 0xb4 +'pwenj', # 0xb5 +'pwenh', # 0xb6 +'pwed', # 0xb7 +'pwel', # 0xb8 +'pwelg', # 0xb9 +'pwelm', # 0xba +'pwelb', # 0xbb +'pwels', # 0xbc +'pwelt', # 0xbd +'pwelp', # 0xbe +'pwelh', # 0xbf +'pwem', # 0xc0 +'pweb', # 0xc1 +'pwebs', # 0xc2 +'pwes', # 0xc3 +'pwess', # 0xc4 +'pweng', # 0xc5 +'pwej', # 0xc6 +'pwec', # 0xc7 +'pwek', # 0xc8 +'pwet', # 0xc9 +'pwep', # 0xca +'pweh', # 0xcb +'pwi', # 0xcc +'pwig', # 0xcd +'pwigg', # 0xce +'pwigs', # 0xcf +'pwin', # 0xd0 +'pwinj', # 0xd1 +'pwinh', # 0xd2 +'pwid', # 0xd3 +'pwil', # 0xd4 +'pwilg', # 0xd5 +'pwilm', # 0xd6 +'pwilb', # 0xd7 +'pwils', # 0xd8 +'pwilt', # 0xd9 +'pwilp', # 0xda +'pwilh', # 0xdb +'pwim', # 0xdc +'pwib', # 0xdd +'pwibs', # 0xde +'pwis', # 0xdf +'pwiss', # 0xe0 +'pwing', # 0xe1 +'pwij', # 0xe2 +'pwic', # 0xe3 +'pwik', # 0xe4 +'pwit', # 0xe5 +'pwip', # 0xe6 +'pwih', # 0xe7 +'pyu', # 0xe8 +'pyug', # 0xe9 +'pyugg', # 0xea +'pyugs', # 0xeb +'pyun', # 0xec +'pyunj', # 0xed +'pyunh', # 0xee +'pyud', # 0xef +'pyul', # 0xf0 +'pyulg', # 0xf1 +'pyulm', # 0xf2 +'pyulb', # 0xf3 +'pyuls', # 0xf4 +'pyult', # 0xf5 +'pyulp', # 0xf6 +'pyulh', # 0xf7 +'pyum', # 0xf8 +'pyub', # 0xf9 +'pyubs', # 0xfa +'pyus', # 0xfb +'pyuss', # 0xfc +'pyung', # 0xfd +'pyuj', # 0xfe +'pyuc', # 0xff +) diff --git a/nstock/modules/unidecode/x0d5.py b/nstock/modules/unidecode/x0d5.py new file mode 100644 index 0000000..4dc55f8 --- /dev/null +++ b/nstock/modules/unidecode/x0d5.py @@ -0,0 +1,258 @@ +data = ( +'pyuk', # 0x00 +'pyut', # 0x01 +'pyup', # 0x02 +'pyuh', # 0x03 +'peu', # 0x04 +'peug', # 0x05 +'peugg', # 0x06 +'peugs', # 0x07 +'peun', # 0x08 +'peunj', # 0x09 +'peunh', # 0x0a +'peud', # 0x0b +'peul', # 0x0c +'peulg', # 0x0d +'peulm', # 0x0e +'peulb', # 0x0f +'peuls', # 0x10 +'peult', # 0x11 +'peulp', # 0x12 +'peulh', # 0x13 +'peum', # 0x14 +'peub', # 0x15 +'peubs', # 0x16 +'peus', # 0x17 +'peuss', # 0x18 +'peung', # 0x19 +'peuj', # 0x1a +'peuc', # 0x1b +'peuk', # 0x1c +'peut', # 0x1d +'peup', # 0x1e +'peuh', # 0x1f +'pyi', # 0x20 +'pyig', # 0x21 +'pyigg', # 0x22 +'pyigs', # 0x23 +'pyin', # 0x24 +'pyinj', # 0x25 +'pyinh', # 0x26 +'pyid', # 0x27 +'pyil', # 0x28 +'pyilg', # 0x29 +'pyilm', # 0x2a +'pyilb', # 0x2b +'pyils', # 0x2c +'pyilt', # 0x2d +'pyilp', # 0x2e +'pyilh', # 0x2f +'pyim', # 0x30 +'pyib', # 0x31 +'pyibs', # 0x32 +'pyis', # 0x33 +'pyiss', # 0x34 +'pying', # 0x35 +'pyij', # 0x36 +'pyic', # 0x37 +'pyik', # 0x38 +'pyit', # 0x39 +'pyip', # 0x3a +'pyih', # 0x3b +'pi', # 0x3c +'pig', # 0x3d +'pigg', # 0x3e +'pigs', # 0x3f +'pin', # 0x40 +'pinj', # 0x41 +'pinh', # 0x42 +'pid', # 0x43 +'pil', # 0x44 +'pilg', # 0x45 +'pilm', # 0x46 +'pilb', # 0x47 +'pils', # 0x48 +'pilt', # 0x49 +'pilp', # 0x4a +'pilh', # 0x4b +'pim', # 0x4c +'pib', # 0x4d +'pibs', # 0x4e +'pis', # 0x4f +'piss', # 0x50 +'ping', # 0x51 +'pij', # 0x52 +'pic', # 0x53 +'pik', # 0x54 +'pit', # 0x55 +'pip', # 0x56 +'pih', # 0x57 +'ha', # 0x58 +'hag', # 0x59 +'hagg', # 0x5a +'hags', # 0x5b +'han', # 0x5c +'hanj', # 0x5d +'hanh', # 0x5e +'had', # 0x5f +'hal', # 0x60 +'halg', # 0x61 +'halm', # 0x62 +'halb', # 0x63 +'hals', # 0x64 +'halt', # 0x65 +'halp', # 0x66 +'halh', # 0x67 +'ham', # 0x68 +'hab', # 0x69 +'habs', # 0x6a +'has', # 0x6b +'hass', # 0x6c +'hang', # 0x6d +'haj', # 0x6e +'hac', # 0x6f +'hak', # 0x70 +'hat', # 0x71 +'hap', # 0x72 +'hah', # 0x73 +'hae', # 0x74 +'haeg', # 0x75 +'haegg', # 0x76 +'haegs', # 0x77 +'haen', # 0x78 +'haenj', # 0x79 +'haenh', # 0x7a +'haed', # 0x7b +'hael', # 0x7c +'haelg', # 0x7d +'haelm', # 0x7e +'haelb', # 0x7f +'haels', # 0x80 +'haelt', # 0x81 +'haelp', # 0x82 +'haelh', # 0x83 +'haem', # 0x84 +'haeb', # 0x85 +'haebs', # 0x86 +'haes', # 0x87 +'haess', # 0x88 +'haeng', # 0x89 +'haej', # 0x8a +'haec', # 0x8b +'haek', # 0x8c +'haet', # 0x8d +'haep', # 0x8e +'haeh', # 0x8f +'hya', # 0x90 +'hyag', # 0x91 +'hyagg', # 0x92 +'hyags', # 0x93 +'hyan', # 0x94 +'hyanj', # 0x95 +'hyanh', # 0x96 +'hyad', # 0x97 +'hyal', # 0x98 +'hyalg', # 0x99 +'hyalm', # 0x9a +'hyalb', # 0x9b +'hyals', # 0x9c +'hyalt', # 0x9d +'hyalp', # 0x9e +'hyalh', # 0x9f +'hyam', # 0xa0 +'hyab', # 0xa1 +'hyabs', # 0xa2 +'hyas', # 0xa3 +'hyass', # 0xa4 +'hyang', # 0xa5 +'hyaj', # 0xa6 +'hyac', # 0xa7 +'hyak', # 0xa8 +'hyat', # 0xa9 +'hyap', # 0xaa +'hyah', # 0xab +'hyae', # 0xac +'hyaeg', # 0xad +'hyaegg', # 0xae +'hyaegs', # 0xaf +'hyaen', # 0xb0 +'hyaenj', # 0xb1 +'hyaenh', # 0xb2 +'hyaed', # 0xb3 +'hyael', # 0xb4 +'hyaelg', # 0xb5 +'hyaelm', # 0xb6 +'hyaelb', # 0xb7 +'hyaels', # 0xb8 +'hyaelt', # 0xb9 +'hyaelp', # 0xba +'hyaelh', # 0xbb +'hyaem', # 0xbc +'hyaeb', # 0xbd +'hyaebs', # 0xbe +'hyaes', # 0xbf +'hyaess', # 0xc0 +'hyaeng', # 0xc1 +'hyaej', # 0xc2 +'hyaec', # 0xc3 +'hyaek', # 0xc4 +'hyaet', # 0xc5 +'hyaep', # 0xc6 +'hyaeh', # 0xc7 +'heo', # 0xc8 +'heog', # 0xc9 +'heogg', # 0xca +'heogs', # 0xcb +'heon', # 0xcc +'heonj', # 0xcd +'heonh', # 0xce +'heod', # 0xcf +'heol', # 0xd0 +'heolg', # 0xd1 +'heolm', # 0xd2 +'heolb', # 0xd3 +'heols', # 0xd4 +'heolt', # 0xd5 +'heolp', # 0xd6 +'heolh', # 0xd7 +'heom', # 0xd8 +'heob', # 0xd9 +'heobs', # 0xda +'heos', # 0xdb +'heoss', # 0xdc +'heong', # 0xdd +'heoj', # 0xde +'heoc', # 0xdf +'heok', # 0xe0 +'heot', # 0xe1 +'heop', # 0xe2 +'heoh', # 0xe3 +'he', # 0xe4 +'heg', # 0xe5 +'hegg', # 0xe6 +'hegs', # 0xe7 +'hen', # 0xe8 +'henj', # 0xe9 +'henh', # 0xea +'hed', # 0xeb +'hel', # 0xec +'helg', # 0xed +'helm', # 0xee +'helb', # 0xef +'hels', # 0xf0 +'helt', # 0xf1 +'help', # 0xf2 +'helh', # 0xf3 +'hem', # 0xf4 +'heb', # 0xf5 +'hebs', # 0xf6 +'hes', # 0xf7 +'hess', # 0xf8 +'heng', # 0xf9 +'hej', # 0xfa +'hec', # 0xfb +'hek', # 0xfc +'het', # 0xfd +'hep', # 0xfe +'heh', # 0xff +) diff --git a/nstock/modules/unidecode/x0d6.py b/nstock/modules/unidecode/x0d6.py new file mode 100644 index 0000000..042ce2b --- /dev/null +++ b/nstock/modules/unidecode/x0d6.py @@ -0,0 +1,258 @@ +data = ( +'hyeo', # 0x00 +'hyeog', # 0x01 +'hyeogg', # 0x02 +'hyeogs', # 0x03 +'hyeon', # 0x04 +'hyeonj', # 0x05 +'hyeonh', # 0x06 +'hyeod', # 0x07 +'hyeol', # 0x08 +'hyeolg', # 0x09 +'hyeolm', # 0x0a +'hyeolb', # 0x0b +'hyeols', # 0x0c +'hyeolt', # 0x0d +'hyeolp', # 0x0e +'hyeolh', # 0x0f +'hyeom', # 0x10 +'hyeob', # 0x11 +'hyeobs', # 0x12 +'hyeos', # 0x13 +'hyeoss', # 0x14 +'hyeong', # 0x15 +'hyeoj', # 0x16 +'hyeoc', # 0x17 +'hyeok', # 0x18 +'hyeot', # 0x19 +'hyeop', # 0x1a +'hyeoh', # 0x1b +'hye', # 0x1c +'hyeg', # 0x1d +'hyegg', # 0x1e +'hyegs', # 0x1f +'hyen', # 0x20 +'hyenj', # 0x21 +'hyenh', # 0x22 +'hyed', # 0x23 +'hyel', # 0x24 +'hyelg', # 0x25 +'hyelm', # 0x26 +'hyelb', # 0x27 +'hyels', # 0x28 +'hyelt', # 0x29 +'hyelp', # 0x2a +'hyelh', # 0x2b +'hyem', # 0x2c +'hyeb', # 0x2d +'hyebs', # 0x2e +'hyes', # 0x2f +'hyess', # 0x30 +'hyeng', # 0x31 +'hyej', # 0x32 +'hyec', # 0x33 +'hyek', # 0x34 +'hyet', # 0x35 +'hyep', # 0x36 +'hyeh', # 0x37 +'ho', # 0x38 +'hog', # 0x39 +'hogg', # 0x3a +'hogs', # 0x3b +'hon', # 0x3c +'honj', # 0x3d +'honh', # 0x3e +'hod', # 0x3f +'hol', # 0x40 +'holg', # 0x41 +'holm', # 0x42 +'holb', # 0x43 +'hols', # 0x44 +'holt', # 0x45 +'holp', # 0x46 +'holh', # 0x47 +'hom', # 0x48 +'hob', # 0x49 +'hobs', # 0x4a +'hos', # 0x4b +'hoss', # 0x4c +'hong', # 0x4d +'hoj', # 0x4e +'hoc', # 0x4f +'hok', # 0x50 +'hot', # 0x51 +'hop', # 0x52 +'hoh', # 0x53 +'hwa', # 0x54 +'hwag', # 0x55 +'hwagg', # 0x56 +'hwags', # 0x57 +'hwan', # 0x58 +'hwanj', # 0x59 +'hwanh', # 0x5a +'hwad', # 0x5b +'hwal', # 0x5c +'hwalg', # 0x5d +'hwalm', # 0x5e +'hwalb', # 0x5f +'hwals', # 0x60 +'hwalt', # 0x61 +'hwalp', # 0x62 +'hwalh', # 0x63 +'hwam', # 0x64 +'hwab', # 0x65 +'hwabs', # 0x66 +'hwas', # 0x67 +'hwass', # 0x68 +'hwang', # 0x69 +'hwaj', # 0x6a +'hwac', # 0x6b +'hwak', # 0x6c +'hwat', # 0x6d +'hwap', # 0x6e +'hwah', # 0x6f +'hwae', # 0x70 +'hwaeg', # 0x71 +'hwaegg', # 0x72 +'hwaegs', # 0x73 +'hwaen', # 0x74 +'hwaenj', # 0x75 +'hwaenh', # 0x76 +'hwaed', # 0x77 +'hwael', # 0x78 +'hwaelg', # 0x79 +'hwaelm', # 0x7a +'hwaelb', # 0x7b +'hwaels', # 0x7c +'hwaelt', # 0x7d +'hwaelp', # 0x7e +'hwaelh', # 0x7f +'hwaem', # 0x80 +'hwaeb', # 0x81 +'hwaebs', # 0x82 +'hwaes', # 0x83 +'hwaess', # 0x84 +'hwaeng', # 0x85 +'hwaej', # 0x86 +'hwaec', # 0x87 +'hwaek', # 0x88 +'hwaet', # 0x89 +'hwaep', # 0x8a +'hwaeh', # 0x8b +'hoe', # 0x8c +'hoeg', # 0x8d +'hoegg', # 0x8e +'hoegs', # 0x8f +'hoen', # 0x90 +'hoenj', # 0x91 +'hoenh', # 0x92 +'hoed', # 0x93 +'hoel', # 0x94 +'hoelg', # 0x95 +'hoelm', # 0x96 +'hoelb', # 0x97 +'hoels', # 0x98 +'hoelt', # 0x99 +'hoelp', # 0x9a +'hoelh', # 0x9b +'hoem', # 0x9c +'hoeb', # 0x9d +'hoebs', # 0x9e +'hoes', # 0x9f +'hoess', # 0xa0 +'hoeng', # 0xa1 +'hoej', # 0xa2 +'hoec', # 0xa3 +'hoek', # 0xa4 +'hoet', # 0xa5 +'hoep', # 0xa6 +'hoeh', # 0xa7 +'hyo', # 0xa8 +'hyog', # 0xa9 +'hyogg', # 0xaa +'hyogs', # 0xab +'hyon', # 0xac +'hyonj', # 0xad +'hyonh', # 0xae +'hyod', # 0xaf +'hyol', # 0xb0 +'hyolg', # 0xb1 +'hyolm', # 0xb2 +'hyolb', # 0xb3 +'hyols', # 0xb4 +'hyolt', # 0xb5 +'hyolp', # 0xb6 +'hyolh', # 0xb7 +'hyom', # 0xb8 +'hyob', # 0xb9 +'hyobs', # 0xba +'hyos', # 0xbb +'hyoss', # 0xbc +'hyong', # 0xbd +'hyoj', # 0xbe +'hyoc', # 0xbf +'hyok', # 0xc0 +'hyot', # 0xc1 +'hyop', # 0xc2 +'hyoh', # 0xc3 +'hu', # 0xc4 +'hug', # 0xc5 +'hugg', # 0xc6 +'hugs', # 0xc7 +'hun', # 0xc8 +'hunj', # 0xc9 +'hunh', # 0xca +'hud', # 0xcb +'hul', # 0xcc +'hulg', # 0xcd +'hulm', # 0xce +'hulb', # 0xcf +'huls', # 0xd0 +'hult', # 0xd1 +'hulp', # 0xd2 +'hulh', # 0xd3 +'hum', # 0xd4 +'hub', # 0xd5 +'hubs', # 0xd6 +'hus', # 0xd7 +'huss', # 0xd8 +'hung', # 0xd9 +'huj', # 0xda +'huc', # 0xdb +'huk', # 0xdc +'hut', # 0xdd +'hup', # 0xde +'huh', # 0xdf +'hweo', # 0xe0 +'hweog', # 0xe1 +'hweogg', # 0xe2 +'hweogs', # 0xe3 +'hweon', # 0xe4 +'hweonj', # 0xe5 +'hweonh', # 0xe6 +'hweod', # 0xe7 +'hweol', # 0xe8 +'hweolg', # 0xe9 +'hweolm', # 0xea +'hweolb', # 0xeb +'hweols', # 0xec +'hweolt', # 0xed +'hweolp', # 0xee +'hweolh', # 0xef +'hweom', # 0xf0 +'hweob', # 0xf1 +'hweobs', # 0xf2 +'hweos', # 0xf3 +'hweoss', # 0xf4 +'hweong', # 0xf5 +'hweoj', # 0xf6 +'hweoc', # 0xf7 +'hweok', # 0xf8 +'hweot', # 0xf9 +'hweop', # 0xfa +'hweoh', # 0xfb +'hwe', # 0xfc +'hweg', # 0xfd +'hwegg', # 0xfe +'hwegs', # 0xff +) diff --git a/nstock/modules/unidecode/x0d7.py b/nstock/modules/unidecode/x0d7.py new file mode 100644 index 0000000..1dfb729 --- /dev/null +++ b/nstock/modules/unidecode/x0d7.py @@ -0,0 +1,257 @@ +data = ( +'hwen', # 0x00 +'hwenj', # 0x01 +'hwenh', # 0x02 +'hwed', # 0x03 +'hwel', # 0x04 +'hwelg', # 0x05 +'hwelm', # 0x06 +'hwelb', # 0x07 +'hwels', # 0x08 +'hwelt', # 0x09 +'hwelp', # 0x0a +'hwelh', # 0x0b +'hwem', # 0x0c +'hweb', # 0x0d +'hwebs', # 0x0e +'hwes', # 0x0f +'hwess', # 0x10 +'hweng', # 0x11 +'hwej', # 0x12 +'hwec', # 0x13 +'hwek', # 0x14 +'hwet', # 0x15 +'hwep', # 0x16 +'hweh', # 0x17 +'hwi', # 0x18 +'hwig', # 0x19 +'hwigg', # 0x1a +'hwigs', # 0x1b +'hwin', # 0x1c +'hwinj', # 0x1d +'hwinh', # 0x1e +'hwid', # 0x1f +'hwil', # 0x20 +'hwilg', # 0x21 +'hwilm', # 0x22 +'hwilb', # 0x23 +'hwils', # 0x24 +'hwilt', # 0x25 +'hwilp', # 0x26 +'hwilh', # 0x27 +'hwim', # 0x28 +'hwib', # 0x29 +'hwibs', # 0x2a +'hwis', # 0x2b +'hwiss', # 0x2c +'hwing', # 0x2d +'hwij', # 0x2e +'hwic', # 0x2f +'hwik', # 0x30 +'hwit', # 0x31 +'hwip', # 0x32 +'hwih', # 0x33 +'hyu', # 0x34 +'hyug', # 0x35 +'hyugg', # 0x36 +'hyugs', # 0x37 +'hyun', # 0x38 +'hyunj', # 0x39 +'hyunh', # 0x3a +'hyud', # 0x3b +'hyul', # 0x3c +'hyulg', # 0x3d +'hyulm', # 0x3e +'hyulb', # 0x3f +'hyuls', # 0x40 +'hyult', # 0x41 +'hyulp', # 0x42 +'hyulh', # 0x43 +'hyum', # 0x44 +'hyub', # 0x45 +'hyubs', # 0x46 +'hyus', # 0x47 +'hyuss', # 0x48 +'hyung', # 0x49 +'hyuj', # 0x4a +'hyuc', # 0x4b +'hyuk', # 0x4c +'hyut', # 0x4d +'hyup', # 0x4e +'hyuh', # 0x4f +'heu', # 0x50 +'heug', # 0x51 +'heugg', # 0x52 +'heugs', # 0x53 +'heun', # 0x54 +'heunj', # 0x55 +'heunh', # 0x56 +'heud', # 0x57 +'heul', # 0x58 +'heulg', # 0x59 +'heulm', # 0x5a +'heulb', # 0x5b +'heuls', # 0x5c +'heult', # 0x5d +'heulp', # 0x5e +'heulh', # 0x5f +'heum', # 0x60 +'heub', # 0x61 +'heubs', # 0x62 +'heus', # 0x63 +'heuss', # 0x64 +'heung', # 0x65 +'heuj', # 0x66 +'heuc', # 0x67 +'heuk', # 0x68 +'heut', # 0x69 +'heup', # 0x6a +'heuh', # 0x6b +'hyi', # 0x6c +'hyig', # 0x6d +'hyigg', # 0x6e +'hyigs', # 0x6f +'hyin', # 0x70 +'hyinj', # 0x71 +'hyinh', # 0x72 +'hyid', # 0x73 +'hyil', # 0x74 +'hyilg', # 0x75 +'hyilm', # 0x76 +'hyilb', # 0x77 +'hyils', # 0x78 +'hyilt', # 0x79 +'hyilp', # 0x7a +'hyilh', # 0x7b +'hyim', # 0x7c +'hyib', # 0x7d +'hyibs', # 0x7e +'hyis', # 0x7f +'hyiss', # 0x80 +'hying', # 0x81 +'hyij', # 0x82 +'hyic', # 0x83 +'hyik', # 0x84 +'hyit', # 0x85 +'hyip', # 0x86 +'hyih', # 0x87 +'hi', # 0x88 +'hig', # 0x89 +'higg', # 0x8a +'higs', # 0x8b +'hin', # 0x8c +'hinj', # 0x8d +'hinh', # 0x8e +'hid', # 0x8f +'hil', # 0x90 +'hilg', # 0x91 +'hilm', # 0x92 +'hilb', # 0x93 +'hils', # 0x94 +'hilt', # 0x95 +'hilp', # 0x96 +'hilh', # 0x97 +'him', # 0x98 +'hib', # 0x99 +'hibs', # 0x9a +'his', # 0x9b +'hiss', # 0x9c +'hing', # 0x9d +'hij', # 0x9e +'hic', # 0x9f +'hik', # 0xa0 +'hit', # 0xa1 +'hip', # 0xa2 +'hih', # 0xa3 +'[?]', # 0xa4 +'[?]', # 0xa5 +'[?]', # 0xa6 +'[?]', # 0xa7 +'[?]', # 0xa8 +'[?]', # 0xa9 +'[?]', # 0xaa +'[?]', # 0xab +'[?]', # 0xac +'[?]', # 0xad +'[?]', # 0xae +'[?]', # 0xaf +'[?]', # 0xb0 +'[?]', # 0xb1 +'[?]', # 0xb2 +'[?]', # 0xb3 +'[?]', # 0xb4 +'[?]', # 0xb5 +'[?]', # 0xb6 +'[?]', # 0xb7 +'[?]', # 0xb8 +'[?]', # 0xb9 +'[?]', # 0xba +'[?]', # 0xbb +'[?]', # 0xbc +'[?]', # 0xbd +'[?]', # 0xbe +'[?]', # 0xbf +'[?]', # 0xc0 +'[?]', # 0xc1 +'[?]', # 0xc2 +'[?]', # 0xc3 +'[?]', # 0xc4 +'[?]', # 0xc5 +'[?]', # 0xc6 +'[?]', # 0xc7 +'[?]', # 0xc8 +'[?]', # 0xc9 +'[?]', # 0xca +'[?]', # 0xcb +'[?]', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'[?]', # 0xd0 +'[?]', # 0xd1 +'[?]', # 0xd2 +'[?]', # 0xd3 +'[?]', # 0xd4 +'[?]', # 0xd5 +'[?]', # 0xd6 +'[?]', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'[?]', # 0xdc +'[?]', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'[?]', # 0xe0 +'[?]', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'[?]', # 0xe6 +'[?]', # 0xe7 +'[?]', # 0xe8 +'[?]', # 0xe9 +'[?]', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x0f9.py b/nstock/modules/unidecode/x0f9.py new file mode 100644 index 0000000..6cc9e4c --- /dev/null +++ b/nstock/modules/unidecode/x0f9.py @@ -0,0 +1,258 @@ +data = ( +'Kay ', # 0x00 +'Kayng ', # 0x01 +'Ke ', # 0x02 +'Ko ', # 0x03 +'Kol ', # 0x04 +'Koc ', # 0x05 +'Kwi ', # 0x06 +'Kwi ', # 0x07 +'Kyun ', # 0x08 +'Kul ', # 0x09 +'Kum ', # 0x0a +'Na ', # 0x0b +'Na ', # 0x0c +'Na ', # 0x0d +'La ', # 0x0e +'Na ', # 0x0f +'Na ', # 0x10 +'Na ', # 0x11 +'Na ', # 0x12 +'Na ', # 0x13 +'Nak ', # 0x14 +'Nak ', # 0x15 +'Nak ', # 0x16 +'Nak ', # 0x17 +'Nak ', # 0x18 +'Nak ', # 0x19 +'Nak ', # 0x1a +'Nan ', # 0x1b +'Nan ', # 0x1c +'Nan ', # 0x1d +'Nan ', # 0x1e +'Nan ', # 0x1f +'Nan ', # 0x20 +'Nam ', # 0x21 +'Nam ', # 0x22 +'Nam ', # 0x23 +'Nam ', # 0x24 +'Nap ', # 0x25 +'Nap ', # 0x26 +'Nap ', # 0x27 +'Nang ', # 0x28 +'Nang ', # 0x29 +'Nang ', # 0x2a +'Nang ', # 0x2b +'Nang ', # 0x2c +'Nay ', # 0x2d +'Nayng ', # 0x2e +'No ', # 0x2f +'No ', # 0x30 +'No ', # 0x31 +'No ', # 0x32 +'No ', # 0x33 +'No ', # 0x34 +'No ', # 0x35 +'No ', # 0x36 +'No ', # 0x37 +'No ', # 0x38 +'No ', # 0x39 +'No ', # 0x3a +'Nok ', # 0x3b +'Nok ', # 0x3c +'Nok ', # 0x3d +'Nok ', # 0x3e +'Nok ', # 0x3f +'Nok ', # 0x40 +'Non ', # 0x41 +'Nong ', # 0x42 +'Nong ', # 0x43 +'Nong ', # 0x44 +'Nong ', # 0x45 +'Noy ', # 0x46 +'Noy ', # 0x47 +'Noy ', # 0x48 +'Noy ', # 0x49 +'Nwu ', # 0x4a +'Nwu ', # 0x4b +'Nwu ', # 0x4c +'Nwu ', # 0x4d +'Nwu ', # 0x4e +'Nwu ', # 0x4f +'Nwu ', # 0x50 +'Nwu ', # 0x51 +'Nuk ', # 0x52 +'Nuk ', # 0x53 +'Num ', # 0x54 +'Nung ', # 0x55 +'Nung ', # 0x56 +'Nung ', # 0x57 +'Nung ', # 0x58 +'Nung ', # 0x59 +'Twu ', # 0x5a +'La ', # 0x5b +'Lak ', # 0x5c +'Lak ', # 0x5d +'Lan ', # 0x5e +'Lyeng ', # 0x5f +'Lo ', # 0x60 +'Lyul ', # 0x61 +'Li ', # 0x62 +'Pey ', # 0x63 +'Pen ', # 0x64 +'Pyen ', # 0x65 +'Pwu ', # 0x66 +'Pwul ', # 0x67 +'Pi ', # 0x68 +'Sak ', # 0x69 +'Sak ', # 0x6a +'Sam ', # 0x6b +'Sayk ', # 0x6c +'Sayng ', # 0x6d +'Sep ', # 0x6e +'Sey ', # 0x6f +'Sway ', # 0x70 +'Sin ', # 0x71 +'Sim ', # 0x72 +'Sip ', # 0x73 +'Ya ', # 0x74 +'Yak ', # 0x75 +'Yak ', # 0x76 +'Yang ', # 0x77 +'Yang ', # 0x78 +'Yang ', # 0x79 +'Yang ', # 0x7a +'Yang ', # 0x7b +'Yang ', # 0x7c +'Yang ', # 0x7d +'Yang ', # 0x7e +'Ye ', # 0x7f +'Ye ', # 0x80 +'Ye ', # 0x81 +'Ye ', # 0x82 +'Ye ', # 0x83 +'Ye ', # 0x84 +'Ye ', # 0x85 +'Ye ', # 0x86 +'Ye ', # 0x87 +'Ye ', # 0x88 +'Ye ', # 0x89 +'Yek ', # 0x8a +'Yek ', # 0x8b +'Yek ', # 0x8c +'Yek ', # 0x8d +'Yen ', # 0x8e +'Yen ', # 0x8f +'Yen ', # 0x90 +'Yen ', # 0x91 +'Yen ', # 0x92 +'Yen ', # 0x93 +'Yen ', # 0x94 +'Yen ', # 0x95 +'Yen ', # 0x96 +'Yen ', # 0x97 +'Yen ', # 0x98 +'Yen ', # 0x99 +'Yen ', # 0x9a +'Yen ', # 0x9b +'Yel ', # 0x9c +'Yel ', # 0x9d +'Yel ', # 0x9e +'Yel ', # 0x9f +'Yel ', # 0xa0 +'Yel ', # 0xa1 +'Yem ', # 0xa2 +'Yem ', # 0xa3 +'Yem ', # 0xa4 +'Yem ', # 0xa5 +'Yem ', # 0xa6 +'Yep ', # 0xa7 +'Yeng ', # 0xa8 +'Yeng ', # 0xa9 +'Yeng ', # 0xaa +'Yeng ', # 0xab +'Yeng ', # 0xac +'Yeng ', # 0xad +'Yeng ', # 0xae +'Yeng ', # 0xaf +'Yeng ', # 0xb0 +'Yeng ', # 0xb1 +'Yeng ', # 0xb2 +'Yeng ', # 0xb3 +'Yeng ', # 0xb4 +'Yey ', # 0xb5 +'Yey ', # 0xb6 +'Yey ', # 0xb7 +'Yey ', # 0xb8 +'O ', # 0xb9 +'Yo ', # 0xba +'Yo ', # 0xbb +'Yo ', # 0xbc +'Yo ', # 0xbd +'Yo ', # 0xbe +'Yo ', # 0xbf +'Yo ', # 0xc0 +'Yo ', # 0xc1 +'Yo ', # 0xc2 +'Yo ', # 0xc3 +'Yong ', # 0xc4 +'Wun ', # 0xc5 +'Wen ', # 0xc6 +'Yu ', # 0xc7 +'Yu ', # 0xc8 +'Yu ', # 0xc9 +'Yu ', # 0xca +'Yu ', # 0xcb +'Yu ', # 0xcc +'Yu ', # 0xcd +'Yu ', # 0xce +'Yu ', # 0xcf +'Yu ', # 0xd0 +'Yuk ', # 0xd1 +'Yuk ', # 0xd2 +'Yuk ', # 0xd3 +'Yun ', # 0xd4 +'Yun ', # 0xd5 +'Yun ', # 0xd6 +'Yun ', # 0xd7 +'Yul ', # 0xd8 +'Yul ', # 0xd9 +'Yul ', # 0xda +'Yul ', # 0xdb +'Yung ', # 0xdc +'I ', # 0xdd +'I ', # 0xde +'I ', # 0xdf +'I ', # 0xe0 +'I ', # 0xe1 +'I ', # 0xe2 +'I ', # 0xe3 +'I ', # 0xe4 +'I ', # 0xe5 +'I ', # 0xe6 +'I ', # 0xe7 +'I ', # 0xe8 +'I ', # 0xe9 +'I ', # 0xea +'Ik ', # 0xeb +'Ik ', # 0xec +'In ', # 0xed +'In ', # 0xee +'In ', # 0xef +'In ', # 0xf0 +'In ', # 0xf1 +'In ', # 0xf2 +'In ', # 0xf3 +'Im ', # 0xf4 +'Im ', # 0xf5 +'Im ', # 0xf6 +'Ip ', # 0xf7 +'Ip ', # 0xf8 +'Ip ', # 0xf9 +'Cang ', # 0xfa +'Cek ', # 0xfb +'Ci ', # 0xfc +'Cip ', # 0xfd +'Cha ', # 0xfe +'Chek ', # 0xff +) diff --git a/nstock/modules/unidecode/x0fa.py b/nstock/modules/unidecode/x0fa.py new file mode 100644 index 0000000..3d4e705 --- /dev/null +++ b/nstock/modules/unidecode/x0fa.py @@ -0,0 +1,257 @@ +data = ( +'Chey ', # 0x00 +'Thak ', # 0x01 +'Thak ', # 0x02 +'Thang ', # 0x03 +'Thayk ', # 0x04 +'Thong ', # 0x05 +'Pho ', # 0x06 +'Phok ', # 0x07 +'Hang ', # 0x08 +'Hang ', # 0x09 +'Hyen ', # 0x0a +'Hwak ', # 0x0b +'Wu ', # 0x0c +'Huo ', # 0x0d +'[?] ', # 0x0e +'[?] ', # 0x0f +'Zhong ', # 0x10 +'[?] ', # 0x11 +'Qing ', # 0x12 +'[?] ', # 0x13 +'[?] ', # 0x14 +'Xi ', # 0x15 +'Zhu ', # 0x16 +'Yi ', # 0x17 +'Li ', # 0x18 +'Shen ', # 0x19 +'Xiang ', # 0x1a +'Fu ', # 0x1b +'Jing ', # 0x1c +'Jing ', # 0x1d +'Yu ', # 0x1e +'[?] ', # 0x1f +'Hagi ', # 0x20 +'[?] ', # 0x21 +'Zhu ', # 0x22 +'[?] ', # 0x23 +'[?] ', # 0x24 +'Yi ', # 0x25 +'Du ', # 0x26 +'[?] ', # 0x27 +'[?] ', # 0x28 +'[?] ', # 0x29 +'Fan ', # 0x2a +'Si ', # 0x2b +'Guan ', # 0x2c +'[?]', # 0x2d +'[?]', # 0x2e +'[?]', # 0x2f +'[?]', # 0x30 +'[?]', # 0x31 +'[?]', # 0x32 +'[?]', # 0x33 +'[?]', # 0x34 +'[?]', # 0x35 +'[?]', # 0x36 +'[?]', # 0x37 +'[?]', # 0x38 +'[?]', # 0x39 +'[?]', # 0x3a +'[?]', # 0x3b +'[?]', # 0x3c +'[?]', # 0x3d +'[?]', # 0x3e +'[?]', # 0x3f +'[?]', # 0x40 +'[?]', # 0x41 +'[?]', # 0x42 +'[?]', # 0x43 +'[?]', # 0x44 +'[?]', # 0x45 +'[?]', # 0x46 +'[?]', # 0x47 +'[?]', # 0x48 +'[?]', # 0x49 +'[?]', # 0x4a +'[?]', # 0x4b +'[?]', # 0x4c +'[?]', # 0x4d +'[?]', # 0x4e +'[?]', # 0x4f +'[?]', # 0x50 +'[?]', # 0x51 +'[?]', # 0x52 +'[?]', # 0x53 +'[?]', # 0x54 +'[?]', # 0x55 +'[?]', # 0x56 +'[?]', # 0x57 +'[?]', # 0x58 +'[?]', # 0x59 +'[?]', # 0x5a +'[?]', # 0x5b +'[?]', # 0x5c +'[?]', # 0x5d +'[?]', # 0x5e +'[?]', # 0x5f +'[?]', # 0x60 +'[?]', # 0x61 +'[?]', # 0x62 +'[?]', # 0x63 +'[?]', # 0x64 +'[?]', # 0x65 +'[?]', # 0x66 +'[?]', # 0x67 +'[?]', # 0x68 +'[?]', # 0x69 +'[?]', # 0x6a +'[?]', # 0x6b +'[?]', # 0x6c +'[?]', # 0x6d +'[?]', # 0x6e +'[?]', # 0x6f +'[?]', # 0x70 +'[?]', # 0x71 +'[?]', # 0x72 +'[?]', # 0x73 +'[?]', # 0x74 +'[?]', # 0x75 +'[?]', # 0x76 +'[?]', # 0x77 +'[?]', # 0x78 +'[?]', # 0x79 +'[?]', # 0x7a +'[?]', # 0x7b +'[?]', # 0x7c +'[?]', # 0x7d +'[?]', # 0x7e +'[?]', # 0x7f +'[?]', # 0x80 +'[?]', # 0x81 +'[?]', # 0x82 +'[?]', # 0x83 +'[?]', # 0x84 +'[?]', # 0x85 +'[?]', # 0x86 +'[?]', # 0x87 +'[?]', # 0x88 +'[?]', # 0x89 +'[?]', # 0x8a +'[?]', # 0x8b +'[?]', # 0x8c +'[?]', # 0x8d +'[?]', # 0x8e +'[?]', # 0x8f +'[?]', # 0x90 +'[?]', # 0x91 +'[?]', # 0x92 +'[?]', # 0x93 +'[?]', # 0x94 +'[?]', # 0x95 +'[?]', # 0x96 +'[?]', # 0x97 +'[?]', # 0x98 +'[?]', # 0x99 +'[?]', # 0x9a +'[?]', # 0x9b +'[?]', # 0x9c +'[?]', # 0x9d +'[?]', # 0x9e +'[?]', # 0x9f +'[?]', # 0xa0 +'[?]', # 0xa1 +'[?]', # 0xa2 +'[?]', # 0xa3 +'[?]', # 0xa4 +'[?]', # 0xa5 +'[?]', # 0xa6 +'[?]', # 0xa7 +'[?]', # 0xa8 +'[?]', # 0xa9 +'[?]', # 0xaa +'[?]', # 0xab +'[?]', # 0xac +'[?]', # 0xad +'[?]', # 0xae +'[?]', # 0xaf +'[?]', # 0xb0 +'[?]', # 0xb1 +'[?]', # 0xb2 +'[?]', # 0xb3 +'[?]', # 0xb4 +'[?]', # 0xb5 +'[?]', # 0xb6 +'[?]', # 0xb7 +'[?]', # 0xb8 +'[?]', # 0xb9 +'[?]', # 0xba +'[?]', # 0xbb +'[?]', # 0xbc +'[?]', # 0xbd +'[?]', # 0xbe +'[?]', # 0xbf +'[?]', # 0xc0 +'[?]', # 0xc1 +'[?]', # 0xc2 +'[?]', # 0xc3 +'[?]', # 0xc4 +'[?]', # 0xc5 +'[?]', # 0xc6 +'[?]', # 0xc7 +'[?]', # 0xc8 +'[?]', # 0xc9 +'[?]', # 0xca +'[?]', # 0xcb +'[?]', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'[?]', # 0xd0 +'[?]', # 0xd1 +'[?]', # 0xd2 +'[?]', # 0xd3 +'[?]', # 0xd4 +'[?]', # 0xd5 +'[?]', # 0xd6 +'[?]', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'[?]', # 0xdc +'[?]', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'[?]', # 0xe0 +'[?]', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'[?]', # 0xe6 +'[?]', # 0xe7 +'[?]', # 0xe8 +'[?]', # 0xe9 +'[?]', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'[?]', # 0xf9 +'[?]', # 0xfa +'[?]', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x0fb.py b/nstock/modules/unidecode/x0fb.py new file mode 100644 index 0000000..bf69dbb --- /dev/null +++ b/nstock/modules/unidecode/x0fb.py @@ -0,0 +1,258 @@ +data = ( +'ff', # 0x00 +'fi', # 0x01 +'fl', # 0x02 +'ffi', # 0x03 +'ffl', # 0x04 +'st', # 0x05 +'st', # 0x06 +'[?]', # 0x07 +'[?]', # 0x08 +'[?]', # 0x09 +'[?]', # 0x0a +'[?]', # 0x0b +'[?]', # 0x0c +'[?]', # 0x0d +'[?]', # 0x0e +'[?]', # 0x0f +'[?]', # 0x10 +'[?]', # 0x11 +'[?]', # 0x12 +'mn', # 0x13 +'me', # 0x14 +'mi', # 0x15 +'vn', # 0x16 +'mkh', # 0x17 +'[?]', # 0x18 +'[?]', # 0x19 +'[?]', # 0x1a +'[?]', # 0x1b +'[?]', # 0x1c +'yi', # 0x1d +'', # 0x1e +'ay', # 0x1f +'`', # 0x20 +'', # 0x21 +'d', # 0x22 +'h', # 0x23 +'k', # 0x24 +'l', # 0x25 +'m', # 0x26 +'m', # 0x27 +'t', # 0x28 +'+', # 0x29 +'sh', # 0x2a +'s', # 0x2b +'sh', # 0x2c +'s', # 0x2d +'a', # 0x2e +'a', # 0x2f +'', # 0x30 +'b', # 0x31 +'g', # 0x32 +'d', # 0x33 +'h', # 0x34 +'v', # 0x35 +'z', # 0x36 +'[?]', # 0x37 +'t', # 0x38 +'y', # 0x39 +'k', # 0x3a +'k', # 0x3b +'l', # 0x3c +'[?]', # 0x3d +'l', # 0x3e +'[?]', # 0x3f +'n', # 0x40 +'n', # 0x41 +'[?]', # 0x42 +'p', # 0x43 +'p', # 0x44 +'[?]', # 0x45 +'ts', # 0x46 +'ts', # 0x47 +'r', # 0x48 +'sh', # 0x49 +'t', # 0x4a +'vo', # 0x4b +'b', # 0x4c +'k', # 0x4d +'p', # 0x4e +'l', # 0x4f +'', # 0x50 +'', # 0x51 +'', # 0x52 +'', # 0x53 +'', # 0x54 +'', # 0x55 +'', # 0x56 +'', # 0x57 +'', # 0x58 +'', # 0x59 +'', # 0x5a +'', # 0x5b +'', # 0x5c +'', # 0x5d +'', # 0x5e +'', # 0x5f +'', # 0x60 +'', # 0x61 +'', # 0x62 +'', # 0x63 +'', # 0x64 +'', # 0x65 +'', # 0x66 +'', # 0x67 +'', # 0x68 +'', # 0x69 +'', # 0x6a +'', # 0x6b +'', # 0x6c +'', # 0x6d +'', # 0x6e +'', # 0x6f +'', # 0x70 +'', # 0x71 +'', # 0x72 +'', # 0x73 +'', # 0x74 +'', # 0x75 +'', # 0x76 +'', # 0x77 +'', # 0x78 +'', # 0x79 +'', # 0x7a +'', # 0x7b +'', # 0x7c +'', # 0x7d +'', # 0x7e +'', # 0x7f +'', # 0x80 +'', # 0x81 +'', # 0x82 +'', # 0x83 +'', # 0x84 +'', # 0x85 +'', # 0x86 +'', # 0x87 +'', # 0x88 +'', # 0x89 +'', # 0x8a +'', # 0x8b +'', # 0x8c +'', # 0x8d +'', # 0x8e +'', # 0x8f +'', # 0x90 +'', # 0x91 +'', # 0x92 +'', # 0x93 +'', # 0x94 +'', # 0x95 +'', # 0x96 +'', # 0x97 +'', # 0x98 +'', # 0x99 +'', # 0x9a +'', # 0x9b +'', # 0x9c +'', # 0x9d +'', # 0x9e +'', # 0x9f +'', # 0xa0 +'', # 0xa1 +'', # 0xa2 +'', # 0xa3 +'', # 0xa4 +'', # 0xa5 +'', # 0xa6 +'', # 0xa7 +'', # 0xa8 +'', # 0xa9 +'', # 0xaa +'', # 0xab +'', # 0xac +'', # 0xad +'', # 0xae +'', # 0xaf +'', # 0xb0 +'', # 0xb1 +'[?]', # 0xb2 +'[?]', # 0xb3 +'[?]', # 0xb4 +'[?]', # 0xb5 +'[?]', # 0xb6 +'[?]', # 0xb7 +'[?]', # 0xb8 +'[?]', # 0xb9 +'[?]', # 0xba +'[?]', # 0xbb +'[?]', # 0xbc +'[?]', # 0xbd +'[?]', # 0xbe +'[?]', # 0xbf +'[?]', # 0xc0 +'[?]', # 0xc1 +'[?]', # 0xc2 +'[?]', # 0xc3 +'[?]', # 0xc4 +'[?]', # 0xc5 +'[?]', # 0xc6 +'[?]', # 0xc7 +'[?]', # 0xc8 +'[?]', # 0xc9 +'[?]', # 0xca +'[?]', # 0xcb +'[?]', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'[?]', # 0xd0 +'[?]', # 0xd1 +'[?]', # 0xd2 +'', # 0xd3 +'', # 0xd4 +'', # 0xd5 +'', # 0xd6 +'', # 0xd7 +'', # 0xd8 +'', # 0xd9 +'', # 0xda +'', # 0xdb +'', # 0xdc +'', # 0xdd +'', # 0xde +'', # 0xdf +'', # 0xe0 +'', # 0xe1 +'', # 0xe2 +'', # 0xe3 +'', # 0xe4 +'', # 0xe5 +'', # 0xe6 +'', # 0xe7 +'', # 0xe8 +'', # 0xe9 +'', # 0xea +'', # 0xeb +'', # 0xec +'', # 0xed +'', # 0xee +'', # 0xef +'', # 0xf0 +'', # 0xf1 +'', # 0xf2 +'', # 0xf3 +'', # 0xf4 +'', # 0xf5 +'', # 0xf6 +'', # 0xf7 +'', # 0xf8 +'', # 0xf9 +'', # 0xfa +'', # 0xfb +'', # 0xfc +'', # 0xfd +'', # 0xfe +'', # 0xff +) diff --git a/nstock/modules/unidecode/x0fc.py b/nstock/modules/unidecode/x0fc.py new file mode 100644 index 0000000..298b1dc --- /dev/null +++ b/nstock/modules/unidecode/x0fc.py @@ -0,0 +1,258 @@ +data = ( +'', # 0x00 +'', # 0x01 +'', # 0x02 +'', # 0x03 +'', # 0x04 +'', # 0x05 +'', # 0x06 +'', # 0x07 +'', # 0x08 +'', # 0x09 +'', # 0x0a +'', # 0x0b +'', # 0x0c +'', # 0x0d +'', # 0x0e +'', # 0x0f +'', # 0x10 +'', # 0x11 +'', # 0x12 +'', # 0x13 +'', # 0x14 +'', # 0x15 +'', # 0x16 +'', # 0x17 +'', # 0x18 +'', # 0x19 +'', # 0x1a +'', # 0x1b +'', # 0x1c +'', # 0x1d +'', # 0x1e +'', # 0x1f +'', # 0x20 +'', # 0x21 +'', # 0x22 +'', # 0x23 +'', # 0x24 +'', # 0x25 +'', # 0x26 +'', # 0x27 +'', # 0x28 +'', # 0x29 +'', # 0x2a +'', # 0x2b +'', # 0x2c +'', # 0x2d +'', # 0x2e +'', # 0x2f +'', # 0x30 +'', # 0x31 +'', # 0x32 +'', # 0x33 +'', # 0x34 +'', # 0x35 +'', # 0x36 +'', # 0x37 +'', # 0x38 +'', # 0x39 +'', # 0x3a +'', # 0x3b +'', # 0x3c +'', # 0x3d +'', # 0x3e +'', # 0x3f +'', # 0x40 +'', # 0x41 +'', # 0x42 +'', # 0x43 +'', # 0x44 +'', # 0x45 +'', # 0x46 +'', # 0x47 +'', # 0x48 +'', # 0x49 +'', # 0x4a +'', # 0x4b +'', # 0x4c +'', # 0x4d +'', # 0x4e +'', # 0x4f +'', # 0x50 +'', # 0x51 +'', # 0x52 +'', # 0x53 +'', # 0x54 +'', # 0x55 +'', # 0x56 +'', # 0x57 +'', # 0x58 +'', # 0x59 +'', # 0x5a +'', # 0x5b +'', # 0x5c +'', # 0x5d +'', # 0x5e +'', # 0x5f +'', # 0x60 +'', # 0x61 +'', # 0x62 +'', # 0x63 +'', # 0x64 +'', # 0x65 +'', # 0x66 +'', # 0x67 +'', # 0x68 +'', # 0x69 +'', # 0x6a +'', # 0x6b +'', # 0x6c +'', # 0x6d +'', # 0x6e +'', # 0x6f +'', # 0x70 +'', # 0x71 +'', # 0x72 +'', # 0x73 +'', # 0x74 +'', # 0x75 +'', # 0x76 +'', # 0x77 +'', # 0x78 +'', # 0x79 +'', # 0x7a +'', # 0x7b +'', # 0x7c +'', # 0x7d +'', # 0x7e +'', # 0x7f +'', # 0x80 +'', # 0x81 +'', # 0x82 +'', # 0x83 +'', # 0x84 +'', # 0x85 +'', # 0x86 +'', # 0x87 +'', # 0x88 +'', # 0x89 +'', # 0x8a +'', # 0x8b +'', # 0x8c +'', # 0x8d +'', # 0x8e +'', # 0x8f +'', # 0x90 +'', # 0x91 +'', # 0x92 +'', # 0x93 +'', # 0x94 +'', # 0x95 +'', # 0x96 +'', # 0x97 +'', # 0x98 +'', # 0x99 +'', # 0x9a +'', # 0x9b +'', # 0x9c +'', # 0x9d +'', # 0x9e +'', # 0x9f +'', # 0xa0 +'', # 0xa1 +'', # 0xa2 +'', # 0xa3 +'', # 0xa4 +'', # 0xa5 +'', # 0xa6 +'', # 0xa7 +'', # 0xa8 +'', # 0xa9 +'', # 0xaa +'', # 0xab +'', # 0xac +'', # 0xad +'', # 0xae +'', # 0xaf +'', # 0xb0 +'', # 0xb1 +'', # 0xb2 +'', # 0xb3 +'', # 0xb4 +'', # 0xb5 +'', # 0xb6 +'', # 0xb7 +'', # 0xb8 +'', # 0xb9 +'', # 0xba +'', # 0xbb +'', # 0xbc +'', # 0xbd +'', # 0xbe +'', # 0xbf +'', # 0xc0 +'', # 0xc1 +'', # 0xc2 +'', # 0xc3 +'', # 0xc4 +'', # 0xc5 +'', # 0xc6 +'', # 0xc7 +'', # 0xc8 +'', # 0xc9 +'', # 0xca +'', # 0xcb +'', # 0xcc +'', # 0xcd +'', # 0xce +'', # 0xcf +'', # 0xd0 +'', # 0xd1 +'', # 0xd2 +'', # 0xd3 +'', # 0xd4 +'', # 0xd5 +'', # 0xd6 +'', # 0xd7 +'', # 0xd8 +'', # 0xd9 +'', # 0xda +'', # 0xdb +'', # 0xdc +'', # 0xdd +'', # 0xde +'', # 0xdf +'', # 0xe0 +'', # 0xe1 +'', # 0xe2 +'', # 0xe3 +'', # 0xe4 +'', # 0xe5 +'', # 0xe6 +'', # 0xe7 +'', # 0xe8 +'', # 0xe9 +'', # 0xea +'', # 0xeb +'', # 0xec +'', # 0xed +'', # 0xee +'', # 0xef +'', # 0xf0 +'', # 0xf1 +'', # 0xf2 +'', # 0xf3 +'', # 0xf4 +'', # 0xf5 +'', # 0xf6 +'', # 0xf7 +'', # 0xf8 +'', # 0xf9 +'', # 0xfa +'', # 0xfb +'', # 0xfc +'', # 0xfd +'', # 0xfe +'', # 0xff +) diff --git a/nstock/modules/unidecode/x0fd.py b/nstock/modules/unidecode/x0fd.py new file mode 100644 index 0000000..892bcb0 --- /dev/null +++ b/nstock/modules/unidecode/x0fd.py @@ -0,0 +1,257 @@ +data = ( +'', # 0x00 +'', # 0x01 +'', # 0x02 +'', # 0x03 +'', # 0x04 +'', # 0x05 +'', # 0x06 +'', # 0x07 +'', # 0x08 +'', # 0x09 +'', # 0x0a +'', # 0x0b +'', # 0x0c +'', # 0x0d +'', # 0x0e +'', # 0x0f +'', # 0x10 +'', # 0x11 +'', # 0x12 +'', # 0x13 +'', # 0x14 +'', # 0x15 +'', # 0x16 +'', # 0x17 +'', # 0x18 +'', # 0x19 +'', # 0x1a +'', # 0x1b +'', # 0x1c +'', # 0x1d +'', # 0x1e +'', # 0x1f +'', # 0x20 +'', # 0x21 +'', # 0x22 +'', # 0x23 +'', # 0x24 +'', # 0x25 +'', # 0x26 +'', # 0x27 +'', # 0x28 +'', # 0x29 +'', # 0x2a +'', # 0x2b +'', # 0x2c +'', # 0x2d +'', # 0x2e +'', # 0x2f +'', # 0x30 +'', # 0x31 +'', # 0x32 +'', # 0x33 +'', # 0x34 +'', # 0x35 +'', # 0x36 +'', # 0x37 +'', # 0x38 +'', # 0x39 +'', # 0x3a +'', # 0x3b +'', # 0x3c +'', # 0x3d +'', # 0x3e +'', # 0x3f +'[?]', # 0x40 +'[?]', # 0x41 +'[?]', # 0x42 +'[?]', # 0x43 +'[?]', # 0x44 +'[?]', # 0x45 +'[?]', # 0x46 +'[?]', # 0x47 +'[?]', # 0x48 +'[?]', # 0x49 +'[?]', # 0x4a +'[?]', # 0x4b +'[?]', # 0x4c +'[?]', # 0x4d +'[?]', # 0x4e +'[?]', # 0x4f +'', # 0x50 +'', # 0x51 +'', # 0x52 +'', # 0x53 +'', # 0x54 +'', # 0x55 +'', # 0x56 +'', # 0x57 +'', # 0x58 +'', # 0x59 +'', # 0x5a +'', # 0x5b +'', # 0x5c +'', # 0x5d +'', # 0x5e +'', # 0x5f +'', # 0x60 +'', # 0x61 +'', # 0x62 +'', # 0x63 +'', # 0x64 +'', # 0x65 +'', # 0x66 +'', # 0x67 +'', # 0x68 +'', # 0x69 +'', # 0x6a +'', # 0x6b +'', # 0x6c +'', # 0x6d +'', # 0x6e +'', # 0x6f +'', # 0x70 +'', # 0x71 +'', # 0x72 +'', # 0x73 +'', # 0x74 +'', # 0x75 +'', # 0x76 +'', # 0x77 +'', # 0x78 +'', # 0x79 +'', # 0x7a +'', # 0x7b +'', # 0x7c +'', # 0x7d +'', # 0x7e +'', # 0x7f +'', # 0x80 +'', # 0x81 +'', # 0x82 +'', # 0x83 +'', # 0x84 +'', # 0x85 +'', # 0x86 +'', # 0x87 +'', # 0x88 +'', # 0x89 +'', # 0x8a +'', # 0x8b +'', # 0x8c +'', # 0x8d +'', # 0x8e +'', # 0x8f +'[?]', # 0x90 +'[?]', # 0x91 +'', # 0x92 +'', # 0x93 +'', # 0x94 +'', # 0x95 +'', # 0x96 +'', # 0x97 +'', # 0x98 +'', # 0x99 +'', # 0x9a +'', # 0x9b +'', # 0x9c +'', # 0x9d +'', # 0x9e +'', # 0x9f +'', # 0xa0 +'', # 0xa1 +'', # 0xa2 +'', # 0xa3 +'', # 0xa4 +'', # 0xa5 +'', # 0xa6 +'', # 0xa7 +'', # 0xa8 +'', # 0xa9 +'', # 0xaa +'', # 0xab +'', # 0xac +'', # 0xad +'', # 0xae +'', # 0xaf +'', # 0xb0 +'', # 0xb1 +'', # 0xb2 +'', # 0xb3 +'', # 0xb4 +'', # 0xb5 +'', # 0xb6 +'', # 0xb7 +'', # 0xb8 +'', # 0xb9 +'', # 0xba +'', # 0xbb +'', # 0xbc +'', # 0xbd +'', # 0xbe +'', # 0xbf +'', # 0xc0 +'', # 0xc1 +'', # 0xc2 +'', # 0xc3 +'', # 0xc4 +'', # 0xc5 +'', # 0xc6 +'', # 0xc7 +'[?]', # 0xc8 +'[?]', # 0xc9 +'[?]', # 0xca +'[?]', # 0xcb +'[?]', # 0xcc +'[?]', # 0xcd +'[?]', # 0xce +'[?]', # 0xcf +'[?]', # 0xd0 +'[?]', # 0xd1 +'[?]', # 0xd2 +'[?]', # 0xd3 +'[?]', # 0xd4 +'[?]', # 0xd5 +'[?]', # 0xd6 +'[?]', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'[?]', # 0xda +'[?]', # 0xdb +'[?]', # 0xdc +'[?]', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'[?]', # 0xe0 +'[?]', # 0xe1 +'[?]', # 0xe2 +'[?]', # 0xe3 +'[?]', # 0xe4 +'[?]', # 0xe5 +'[?]', # 0xe6 +'[?]', # 0xe7 +'[?]', # 0xe8 +'[?]', # 0xe9 +'[?]', # 0xea +'[?]', # 0xeb +'[?]', # 0xec +'[?]', # 0xed +'[?]', # 0xee +'[?]', # 0xef +'', # 0xf0 +'', # 0xf1 +'', # 0xf2 +'', # 0xf3 +'', # 0xf4 +'', # 0xf5 +'', # 0xf6 +'', # 0xf7 +'', # 0xf8 +'', # 0xf9 +'', # 0xfa +'', # 0xfb +'[?]', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +) diff --git a/nstock/modules/unidecode/x0fe.py b/nstock/modules/unidecode/x0fe.py new file mode 100644 index 0000000..60e8617 --- /dev/null +++ b/nstock/modules/unidecode/x0fe.py @@ -0,0 +1,258 @@ +data = ( +'[?]', # 0x00 +'[?]', # 0x01 +'[?]', # 0x02 +'[?]', # 0x03 +'[?]', # 0x04 +'[?]', # 0x05 +'[?]', # 0x06 +'[?]', # 0x07 +'[?]', # 0x08 +'[?]', # 0x09 +'[?]', # 0x0a +'[?]', # 0x0b +'[?]', # 0x0c +'[?]', # 0x0d +'[?]', # 0x0e +'[?]', # 0x0f +'[?]', # 0x10 +'[?]', # 0x11 +'[?]', # 0x12 +'[?]', # 0x13 +'[?]', # 0x14 +'[?]', # 0x15 +'[?]', # 0x16 +'[?]', # 0x17 +'[?]', # 0x18 +'[?]', # 0x19 +'[?]', # 0x1a +'[?]', # 0x1b +'[?]', # 0x1c +'[?]', # 0x1d +'[?]', # 0x1e +'[?]', # 0x1f +'', # 0x20 +'', # 0x21 +'', # 0x22 +'~', # 0x23 +'[?]', # 0x24 +'[?]', # 0x25 +'[?]', # 0x26 +'[?]', # 0x27 +'[?]', # 0x28 +'[?]', # 0x29 +'[?]', # 0x2a +'[?]', # 0x2b +'[?]', # 0x2c +'[?]', # 0x2d +'[?]', # 0x2e +'[?]', # 0x2f +'..', # 0x30 +'--', # 0x31 +'-', # 0x32 +'_', # 0x33 +'_', # 0x34 +'(', # 0x35 +') ', # 0x36 +'{', # 0x37 +'} ', # 0x38 +'[', # 0x39 +'] ', # 0x3a +'[(', # 0x3b +')] ', # 0x3c +'<<', # 0x3d +'>> ', # 0x3e +'<', # 0x3f +'> ', # 0x40 +'[', # 0x41 +'] ', # 0x42 +'{', # 0x43 +'}', # 0x44 +'[?]', # 0x45 +'[?]', # 0x46 +'[?]', # 0x47 +'[?]', # 0x48 +'', # 0x49 +'', # 0x4a +'', # 0x4b +'', # 0x4c +'', # 0x4d +'', # 0x4e +'', # 0x4f +',', # 0x50 +',', # 0x51 +'.', # 0x52 +'', # 0x53 +';', # 0x54 +':', # 0x55 +'?', # 0x56 +'!', # 0x57 +'-', # 0x58 +'(', # 0x59 +')', # 0x5a +'{', # 0x5b +'}', # 0x5c +'{', # 0x5d +'}', # 0x5e +'#', # 0x5f +'&', # 0x60 +'*', # 0x61 +'+', # 0x62 +'-', # 0x63 +'<', # 0x64 +'>', # 0x65 +'=', # 0x66 +'', # 0x67 +'\\', # 0x68 +'$', # 0x69 +'%', # 0x6a +'@', # 0x6b +'[?]', # 0x6c +'[?]', # 0x6d +'[?]', # 0x6e +'[?]', # 0x6f +'', # 0x70 +'', # 0x71 +'', # 0x72 +'[?]', # 0x73 +'', # 0x74 +'[?]', # 0x75 +'', # 0x76 +'', # 0x77 +'', # 0x78 +'', # 0x79 +'', # 0x7a +'', # 0x7b +'', # 0x7c +'', # 0x7d +'', # 0x7e +'', # 0x7f +'', # 0x80 +'', # 0x81 +'', # 0x82 +'', # 0x83 +'', # 0x84 +'', # 0x85 +'', # 0x86 +'', # 0x87 +'', # 0x88 +'', # 0x89 +'', # 0x8a +'', # 0x8b +'', # 0x8c +'', # 0x8d +'', # 0x8e +'', # 0x8f +'', # 0x90 +'', # 0x91 +'', # 0x92 +'', # 0x93 +'', # 0x94 +'', # 0x95 +'', # 0x96 +'', # 0x97 +'', # 0x98 +'', # 0x99 +'', # 0x9a +'', # 0x9b +'', # 0x9c +'', # 0x9d +'', # 0x9e +'', # 0x9f +'', # 0xa0 +'', # 0xa1 +'', # 0xa2 +'', # 0xa3 +'', # 0xa4 +'', # 0xa5 +'', # 0xa6 +'', # 0xa7 +'', # 0xa8 +'', # 0xa9 +'', # 0xaa +'', # 0xab +'', # 0xac +'', # 0xad +'', # 0xae +'', # 0xaf +'', # 0xb0 +'', # 0xb1 +'', # 0xb2 +'', # 0xb3 +'', # 0xb4 +'', # 0xb5 +'', # 0xb6 +'', # 0xb7 +'', # 0xb8 +'', # 0xb9 +'', # 0xba +'', # 0xbb +'', # 0xbc +'', # 0xbd +'', # 0xbe +'', # 0xbf +'', # 0xc0 +'', # 0xc1 +'', # 0xc2 +'', # 0xc3 +'', # 0xc4 +'', # 0xc5 +'', # 0xc6 +'', # 0xc7 +'', # 0xc8 +'', # 0xc9 +'', # 0xca +'', # 0xcb +'', # 0xcc +'', # 0xcd +'', # 0xce +'', # 0xcf +'', # 0xd0 +'', # 0xd1 +'', # 0xd2 +'', # 0xd3 +'', # 0xd4 +'', # 0xd5 +'', # 0xd6 +'', # 0xd7 +'', # 0xd8 +'', # 0xd9 +'', # 0xda +'', # 0xdb +'', # 0xdc +'', # 0xdd +'', # 0xde +'', # 0xdf +'', # 0xe0 +'', # 0xe1 +'', # 0xe2 +'', # 0xe3 +'', # 0xe4 +'', # 0xe5 +'', # 0xe6 +'', # 0xe7 +'', # 0xe8 +'', # 0xe9 +'', # 0xea +'', # 0xeb +'', # 0xec +'', # 0xed +'', # 0xee +'', # 0xef +'', # 0xf0 +'', # 0xf1 +'', # 0xf2 +'', # 0xf3 +'', # 0xf4 +'', # 0xf5 +'', # 0xf6 +'', # 0xf7 +'', # 0xf8 +'', # 0xf9 +'', # 0xfa +'', # 0xfb +'', # 0xfc +'[?]', # 0xfd +'[?]', # 0xfe +'', # 0xff +) diff --git a/nstock/modules/unidecode/x0ff.py b/nstock/modules/unidecode/x0ff.py new file mode 100644 index 0000000..0441015 --- /dev/null +++ b/nstock/modules/unidecode/x0ff.py @@ -0,0 +1,258 @@ +data = ( +'[?]', # 0x00 +'!', # 0x01 +'"', # 0x02 +'#', # 0x03 +'$', # 0x04 +'%', # 0x05 +'&', # 0x06 +'\'', # 0x07 +'(', # 0x08 +')', # 0x09 +'*', # 0x0a +'+', # 0x0b +',', # 0x0c +'-', # 0x0d +'.', # 0x0e +'/', # 0x0f +'0', # 0x10 +'1', # 0x11 +'2', # 0x12 +'3', # 0x13 +'4', # 0x14 +'5', # 0x15 +'6', # 0x16 +'7', # 0x17 +'8', # 0x18 +'9', # 0x19 +':', # 0x1a +';', # 0x1b +'<', # 0x1c +'=', # 0x1d +'>', # 0x1e +'?', # 0x1f +'@', # 0x20 +'A', # 0x21 +'B', # 0x22 +'C', # 0x23 +'D', # 0x24 +'E', # 0x25 +'F', # 0x26 +'G', # 0x27 +'H', # 0x28 +'I', # 0x29 +'J', # 0x2a +'K', # 0x2b +'L', # 0x2c +'M', # 0x2d +'N', # 0x2e +'O', # 0x2f +'P', # 0x30 +'Q', # 0x31 +'R', # 0x32 +'S', # 0x33 +'T', # 0x34 +'U', # 0x35 +'V', # 0x36 +'W', # 0x37 +'X', # 0x38 +'Y', # 0x39 +'Z', # 0x3a +'[', # 0x3b +'\\', # 0x3c +']', # 0x3d +'^', # 0x3e +'_', # 0x3f +'`', # 0x40 +'a', # 0x41 +'b', # 0x42 +'c', # 0x43 +'d', # 0x44 +'e', # 0x45 +'f', # 0x46 +'g', # 0x47 +'h', # 0x48 +'i', # 0x49 +'j', # 0x4a +'k', # 0x4b +'l', # 0x4c +'m', # 0x4d +'n', # 0x4e +'o', # 0x4f +'p', # 0x50 +'q', # 0x51 +'r', # 0x52 +'s', # 0x53 +'t', # 0x54 +'u', # 0x55 +'v', # 0x56 +'w', # 0x57 +'x', # 0x58 +'y', # 0x59 +'z', # 0x5a +'{', # 0x5b +'|', # 0x5c +'}', # 0x5d +'~', # 0x5e +'[?]', # 0x5f +'[?]', # 0x60 +'.', # 0x61 +'[', # 0x62 +']', # 0x63 +',', # 0x64 +'*', # 0x65 +'wo', # 0x66 +'a', # 0x67 +'i', # 0x68 +'u', # 0x69 +'e', # 0x6a +'o', # 0x6b +'ya', # 0x6c +'yu', # 0x6d +'yo', # 0x6e +'tu', # 0x6f +'+', # 0x70 +'a', # 0x71 +'i', # 0x72 +'u', # 0x73 +'e', # 0x74 +'o', # 0x75 +'ka', # 0x76 +'ki', # 0x77 +'ku', # 0x78 +'ke', # 0x79 +'ko', # 0x7a +'sa', # 0x7b +'si', # 0x7c +'su', # 0x7d +'se', # 0x7e +'so', # 0x7f +'ta', # 0x80 +'ti', # 0x81 +'tu', # 0x82 +'te', # 0x83 +'to', # 0x84 +'na', # 0x85 +'ni', # 0x86 +'nu', # 0x87 +'ne', # 0x88 +'no', # 0x89 +'ha', # 0x8a +'hi', # 0x8b +'hu', # 0x8c +'he', # 0x8d +'ho', # 0x8e +'ma', # 0x8f +'mi', # 0x90 +'mu', # 0x91 +'me', # 0x92 +'mo', # 0x93 +'ya', # 0x94 +'yu', # 0x95 +'yo', # 0x96 +'ra', # 0x97 +'ri', # 0x98 +'ru', # 0x99 +'re', # 0x9a +'ro', # 0x9b +'wa', # 0x9c +'n', # 0x9d +':', # 0x9e +';', # 0x9f +'', # 0xa0 +'g', # 0xa1 +'gg', # 0xa2 +'gs', # 0xa3 +'n', # 0xa4 +'nj', # 0xa5 +'nh', # 0xa6 +'d', # 0xa7 +'dd', # 0xa8 +'r', # 0xa9 +'lg', # 0xaa +'lm', # 0xab +'lb', # 0xac +'ls', # 0xad +'lt', # 0xae +'lp', # 0xaf +'rh', # 0xb0 +'m', # 0xb1 +'b', # 0xb2 +'bb', # 0xb3 +'bs', # 0xb4 +'s', # 0xb5 +'ss', # 0xb6 +'', # 0xb7 +'j', # 0xb8 +'jj', # 0xb9 +'c', # 0xba +'k', # 0xbb +'t', # 0xbc +'p', # 0xbd +'h', # 0xbe +'[?]', # 0xbf +'[?]', # 0xc0 +'[?]', # 0xc1 +'a', # 0xc2 +'ae', # 0xc3 +'ya', # 0xc4 +'yae', # 0xc5 +'eo', # 0xc6 +'e', # 0xc7 +'[?]', # 0xc8 +'[?]', # 0xc9 +'yeo', # 0xca +'ye', # 0xcb +'o', # 0xcc +'wa', # 0xcd +'wae', # 0xce +'oe', # 0xcf +'[?]', # 0xd0 +'[?]', # 0xd1 +'yo', # 0xd2 +'u', # 0xd3 +'weo', # 0xd4 +'we', # 0xd5 +'wi', # 0xd6 +'yu', # 0xd7 +'[?]', # 0xd8 +'[?]', # 0xd9 +'eu', # 0xda +'yi', # 0xdb +'i', # 0xdc +'[?]', # 0xdd +'[?]', # 0xde +'[?]', # 0xdf +'/C', # 0xe0 +'PS', # 0xe1 +'!', # 0xe2 +'-', # 0xe3 +'|', # 0xe4 +'Y=', # 0xe5 +'W=', # 0xe6 +'[?]', # 0xe7 +'|', # 0xe8 +'-', # 0xe9 +'|', # 0xea +'-', # 0xeb +'|', # 0xec +'#', # 0xed +'O', # 0xee +'[?]', # 0xef +'[?]', # 0xf0 +'[?]', # 0xf1 +'[?]', # 0xf2 +'[?]', # 0xf3 +'[?]', # 0xf4 +'[?]', # 0xf5 +'[?]', # 0xf6 +'[?]', # 0xf7 +'[?]', # 0xf8 +'{', # 0xf9 +'|', # 0xfa +'}', # 0xfb +'', # 0xfc +'', # 0xfd +'', # 0xfe +'', # 0xff +) diff --git a/nstock/modules/unidecode/x1d4.py b/nstock/modules/unidecode/x1d4.py new file mode 100644 index 0000000..5379593 --- /dev/null +++ b/nstock/modules/unidecode/x1d4.py @@ -0,0 +1,258 @@ +data = ( +'A', # 0x00 +'B', # 0x01 +'C', # 0x02 +'D', # 0x03 +'E', # 0x04 +'F', # 0x05 +'G', # 0x06 +'H', # 0x07 +'I', # 0x08 +'J', # 0x09 +'K', # 0x0a +'L', # 0x0b +'M', # 0x0c +'N', # 0x0d +'O', # 0x0e +'P', # 0x0f +'Q', # 0x10 +'R', # 0x11 +'S', # 0x12 +'T', # 0x13 +'U', # 0x14 +'V', # 0x15 +'W', # 0x16 +'X', # 0x17 +'Y', # 0x18 +'Z', # 0x19 +'a', # 0x1a +'b', # 0x1b +'c', # 0x1c +'d', # 0x1d +'e', # 0x1e +'f', # 0x1f +'g', # 0x20 +'h', # 0x21 +'i', # 0x22 +'j', # 0x23 +'k', # 0x24 +'l', # 0x25 +'m', # 0x26 +'n', # 0x27 +'o', # 0x28 +'p', # 0x29 +'q', # 0x2a +'r', # 0x2b +'s', # 0x2c +'t', # 0x2d +'u', # 0x2e +'v', # 0x2f +'w', # 0x30 +'x', # 0x31 +'y', # 0x32 +'z', # 0x33 +'A', # 0x34 +'B', # 0x35 +'C', # 0x36 +'D', # 0x37 +'E', # 0x38 +'F', # 0x39 +'G', # 0x3a +'H', # 0x3b +'I', # 0x3c +'J', # 0x3d +'K', # 0x3e +'L', # 0x3f +'M', # 0x40 +'N', # 0x41 +'O', # 0x42 +'P', # 0x43 +'Q', # 0x44 +'R', # 0x45 +'S', # 0x46 +'T', # 0x47 +'U', # 0x48 +'V', # 0x49 +'W', # 0x4a +'X', # 0x4b +'Y', # 0x4c +'Z', # 0x4d +'a', # 0x4e +'b', # 0x4f +'c', # 0x50 +'d', # 0x51 +'e', # 0x52 +'f', # 0x53 +'g', # 0x54 +'', # 0x55 +'i', # 0x56 +'j', # 0x57 +'k', # 0x58 +'l', # 0x59 +'m', # 0x5a +'n', # 0x5b +'o', # 0x5c +'p', # 0x5d +'q', # 0x5e +'r', # 0x5f +'s', # 0x60 +'t', # 0x61 +'u', # 0x62 +'v', # 0x63 +'w', # 0x64 +'x', # 0x65 +'y', # 0x66 +'z', # 0x67 +'A', # 0x68 +'B', # 0x69 +'C', # 0x6a +'D', # 0x6b +'E', # 0x6c +'F', # 0x6d +'G', # 0x6e +'H', # 0x6f +'I', # 0x70 +'J', # 0x71 +'K', # 0x72 +'L', # 0x73 +'M', # 0x74 +'N', # 0x75 +'O', # 0x76 +'P', # 0x77 +'Q', # 0x78 +'R', # 0x79 +'S', # 0x7a +'T', # 0x7b +'U', # 0x7c +'V', # 0x7d +'W', # 0x7e +'X', # 0x7f +'Y', # 0x80 +'Z', # 0x81 +'a', # 0x82 +'b', # 0x83 +'c', # 0x84 +'d', # 0x85 +'e', # 0x86 +'f', # 0x87 +'g', # 0x88 +'h', # 0x89 +'i', # 0x8a +'j', # 0x8b +'k', # 0x8c +'l', # 0x8d +'m', # 0x8e +'n', # 0x8f +'o', # 0x90 +'p', # 0x91 +'q', # 0x92 +'r', # 0x93 +'s', # 0x94 +'t', # 0x95 +'u', # 0x96 +'v', # 0x97 +'w', # 0x98 +'x', # 0x99 +'y', # 0x9a +'z', # 0x9b +'A', # 0x9c +'', # 0x9d +'C', # 0x9e +'D', # 0x9f +'', # 0xa0 +'', # 0xa1 +'G', # 0xa2 +'', # 0xa3 +'', # 0xa4 +'J', # 0xa5 +'K', # 0xa6 +'', # 0xa7 +'', # 0xa8 +'N', # 0xa9 +'O', # 0xaa +'P', # 0xab +'Q', # 0xac +'', # 0xad +'S', # 0xae +'T', # 0xaf +'U', # 0xb0 +'V', # 0xb1 +'W', # 0xb2 +'X', # 0xb3 +'Y', # 0xb4 +'Z', # 0xb5 +'a', # 0xb6 +'b', # 0xb7 +'c', # 0xb8 +'d', # 0xb9 +'', # 0xba +'f', # 0xbb +'', # 0xbc +'h', # 0xbd +'i', # 0xbe +'j', # 0xbf +'k', # 0xc0 +'l', # 0xc1 +'m', # 0xc2 +'n', # 0xc3 +'', # 0xc4 +'p', # 0xc5 +'q', # 0xc6 +'r', # 0xc7 +'s', # 0xc8 +'t', # 0xc9 +'u', # 0xca +'v', # 0xcb +'w', # 0xcc +'x', # 0xcd +'y', # 0xce +'z', # 0xcf +'A', # 0xd0 +'B', # 0xd1 +'C', # 0xd2 +'D', # 0xd3 +'E', # 0xd4 +'F', # 0xd5 +'G', # 0xd6 +'H', # 0xd7 +'I', # 0xd8 +'J', # 0xd9 +'K', # 0xda +'L', # 0xdb +'M', # 0xdc +'N', # 0xdd +'O', # 0xde +'P', # 0xdf +'Q', # 0xe0 +'R', # 0xe1 +'S', # 0xe2 +'T', # 0xe3 +'U', # 0xe4 +'V', # 0xe5 +'W', # 0xe6 +'X', # 0xe7 +'Y', # 0xe8 +'Z', # 0xe9 +'a', # 0xea +'b', # 0xeb +'c', # 0xec +'d', # 0xed +'e', # 0xee +'f', # 0xef +'g', # 0xf0 +'h', # 0xf1 +'i', # 0xf2 +'j', # 0xf3 +'k', # 0xf4 +'l', # 0xf5 +'m', # 0xf6 +'n', # 0xf7 +'o', # 0xf8 +'p', # 0xf9 +'q', # 0xfa +'r', # 0xfb +'s', # 0xfc +'t', # 0xfd +'u', # 0xfe +'v', # 0xff +) diff --git a/nstock/modules/unidecode/x1d5.py b/nstock/modules/unidecode/x1d5.py new file mode 100644 index 0000000..6ec605b --- /dev/null +++ b/nstock/modules/unidecode/x1d5.py @@ -0,0 +1,258 @@ +data = ( +'w', # 0x00 +'x', # 0x01 +'y', # 0x02 +'z', # 0x03 +'A', # 0x04 +'B', # 0x05 +'', # 0x06 +'D', # 0x07 +'E', # 0x08 +'F', # 0x09 +'G', # 0x0a +'', # 0x0b +'', # 0x0c +'J', # 0x0d +'K', # 0x0e +'L', # 0x0f +'M', # 0x10 +'N', # 0x11 +'O', # 0x12 +'P', # 0x13 +'Q', # 0x14 +'', # 0x15 +'S', # 0x16 +'T', # 0x17 +'U', # 0x18 +'V', # 0x19 +'W', # 0x1a +'X', # 0x1b +'Y', # 0x1c +'', # 0x1d +'a', # 0x1e +'b', # 0x1f +'c', # 0x20 +'d', # 0x21 +'e', # 0x22 +'f', # 0x23 +'g', # 0x24 +'h', # 0x25 +'i', # 0x26 +'j', # 0x27 +'k', # 0x28 +'l', # 0x29 +'m', # 0x2a +'n', # 0x2b +'o', # 0x2c +'p', # 0x2d +'q', # 0x2e +'r', # 0x2f +'s', # 0x30 +'t', # 0x31 +'u', # 0x32 +'v', # 0x33 +'w', # 0x34 +'x', # 0x35 +'y', # 0x36 +'z', # 0x37 +'A', # 0x38 +'B', # 0x39 +'', # 0x3a +'D', # 0x3b +'E', # 0x3c +'F', # 0x3d +'G', # 0x3e +'', # 0x3f +'I', # 0x40 +'J', # 0x41 +'K', # 0x42 +'L', # 0x43 +'M', # 0x44 +'', # 0x45 +'O', # 0x46 +'', # 0x47 +'', # 0x48 +'', # 0x49 +'S', # 0x4a +'T', # 0x4b +'U', # 0x4c +'V', # 0x4d +'W', # 0x4e +'X', # 0x4f +'Y', # 0x50 +'', # 0x51 +'a', # 0x52 +'b', # 0x53 +'c', # 0x54 +'d', # 0x55 +'e', # 0x56 +'f', # 0x57 +'g', # 0x58 +'h', # 0x59 +'i', # 0x5a +'j', # 0x5b +'k', # 0x5c +'l', # 0x5d +'m', # 0x5e +'n', # 0x5f +'o', # 0x60 +'p', # 0x61 +'q', # 0x62 +'r', # 0x63 +'s', # 0x64 +'t', # 0x65 +'u', # 0x66 +'v', # 0x67 +'w', # 0x68 +'x', # 0x69 +'y', # 0x6a +'z', # 0x6b +'A', # 0x6c +'B', # 0x6d +'C', # 0x6e +'D', # 0x6f +'E', # 0x70 +'F', # 0x71 +'G', # 0x72 +'H', # 0x73 +'I', # 0x74 +'J', # 0x75 +'K', # 0x76 +'L', # 0x77 +'M', # 0x78 +'N', # 0x79 +'O', # 0x7a +'P', # 0x7b +'Q', # 0x7c +'R', # 0x7d +'S', # 0x7e +'T', # 0x7f +'U', # 0x80 +'V', # 0x81 +'W', # 0x82 +'X', # 0x83 +'Y', # 0x84 +'Z', # 0x85 +'a', # 0x86 +'b', # 0x87 +'c', # 0x88 +'d', # 0x89 +'e', # 0x8a +'f', # 0x8b +'g', # 0x8c +'h', # 0x8d +'i', # 0x8e +'j', # 0x8f +'k', # 0x90 +'l', # 0x91 +'m', # 0x92 +'n', # 0x93 +'o', # 0x94 +'p', # 0x95 +'q', # 0x96 +'r', # 0x97 +'s', # 0x98 +'t', # 0x99 +'u', # 0x9a +'v', # 0x9b +'w', # 0x9c +'x', # 0x9d +'y', # 0x9e +'z', # 0x9f +'A', # 0xa0 +'B', # 0xa1 +'C', # 0xa2 +'D', # 0xa3 +'E', # 0xa4 +'F', # 0xa5 +'G', # 0xa6 +'H', # 0xa7 +'I', # 0xa8 +'J', # 0xa9 +'K', # 0xaa +'L', # 0xab +'M', # 0xac +'N', # 0xad +'O', # 0xae +'P', # 0xaf +'Q', # 0xb0 +'R', # 0xb1 +'S', # 0xb2 +'T', # 0xb3 +'U', # 0xb4 +'V', # 0xb5 +'W', # 0xb6 +'X', # 0xb7 +'Y', # 0xb8 +'Z', # 0xb9 +'a', # 0xba +'b', # 0xbb +'c', # 0xbc +'d', # 0xbd +'e', # 0xbe +'f', # 0xbf +'g', # 0xc0 +'h', # 0xc1 +'i', # 0xc2 +'j', # 0xc3 +'k', # 0xc4 +'l', # 0xc5 +'m', # 0xc6 +'n', # 0xc7 +'o', # 0xc8 +'p', # 0xc9 +'q', # 0xca +'r', # 0xcb +'s', # 0xcc +'t', # 0xcd +'u', # 0xce +'v', # 0xcf +'w', # 0xd0 +'x', # 0xd1 +'y', # 0xd2 +'z', # 0xd3 +'A', # 0xd4 +'B', # 0xd5 +'C', # 0xd6 +'D', # 0xd7 +'E', # 0xd8 +'F', # 0xd9 +'G', # 0xda +'H', # 0xdb +'I', # 0xdc +'J', # 0xdd +'K', # 0xde +'L', # 0xdf +'M', # 0xe0 +'N', # 0xe1 +'O', # 0xe2 +'P', # 0xe3 +'Q', # 0xe4 +'R', # 0xe5 +'S', # 0xe6 +'T', # 0xe7 +'U', # 0xe8 +'V', # 0xe9 +'W', # 0xea +'X', # 0xeb +'Y', # 0xec +'Z', # 0xed +'a', # 0xee +'b', # 0xef +'c', # 0xf0 +'d', # 0xf1 +'e', # 0xf2 +'f', # 0xf3 +'g', # 0xf4 +'h', # 0xf5 +'i', # 0xf6 +'j', # 0xf7 +'k', # 0xf8 +'l', # 0xf9 +'m', # 0xfa +'n', # 0xfb +'o', # 0xfc +'p', # 0xfd +'q', # 0xfe +'r', # 0xff +) diff --git a/nstock/modules/unidecode/x1d6.py b/nstock/modules/unidecode/x1d6.py new file mode 100644 index 0000000..c06a855 --- /dev/null +++ b/nstock/modules/unidecode/x1d6.py @@ -0,0 +1,258 @@ +data = ( +'s', # 0x00 +'t', # 0x01 +'u', # 0x02 +'v', # 0x03 +'w', # 0x04 +'x', # 0x05 +'y', # 0x06 +'z', # 0x07 +'A', # 0x08 +'B', # 0x09 +'C', # 0x0a +'D', # 0x0b +'E', # 0x0c +'F', # 0x0d +'G', # 0x0e +'H', # 0x0f +'I', # 0x10 +'J', # 0x11 +'K', # 0x12 +'L', # 0x13 +'M', # 0x14 +'N', # 0x15 +'O', # 0x16 +'P', # 0x17 +'Q', # 0x18 +'R', # 0x19 +'S', # 0x1a +'T', # 0x1b +'U', # 0x1c +'V', # 0x1d +'W', # 0x1e +'X', # 0x1f +'Y', # 0x20 +'Z', # 0x21 +'a', # 0x22 +'b', # 0x23 +'c', # 0x24 +'d', # 0x25 +'e', # 0x26 +'f', # 0x27 +'g', # 0x28 +'h', # 0x29 +'i', # 0x2a +'j', # 0x2b +'k', # 0x2c +'l', # 0x2d +'m', # 0x2e +'n', # 0x2f +'o', # 0x30 +'p', # 0x31 +'q', # 0x32 +'r', # 0x33 +'s', # 0x34 +'t', # 0x35 +'u', # 0x36 +'v', # 0x37 +'w', # 0x38 +'x', # 0x39 +'y', # 0x3a +'z', # 0x3b +'A', # 0x3c +'B', # 0x3d +'C', # 0x3e +'D', # 0x3f +'E', # 0x40 +'F', # 0x41 +'G', # 0x42 +'H', # 0x43 +'I', # 0x44 +'J', # 0x45 +'K', # 0x46 +'L', # 0x47 +'M', # 0x48 +'N', # 0x49 +'O', # 0x4a +'P', # 0x4b +'Q', # 0x4c +'R', # 0x4d +'S', # 0x4e +'T', # 0x4f +'U', # 0x50 +'V', # 0x51 +'W', # 0x52 +'X', # 0x53 +'Y', # 0x54 +'Z', # 0x55 +'a', # 0x56 +'b', # 0x57 +'c', # 0x58 +'d', # 0x59 +'e', # 0x5a +'f', # 0x5b +'g', # 0x5c +'h', # 0x5d +'i', # 0x5e +'j', # 0x5f +'k', # 0x60 +'l', # 0x61 +'m', # 0x62 +'n', # 0x63 +'o', # 0x64 +'p', # 0x65 +'q', # 0x66 +'r', # 0x67 +'s', # 0x68 +'t', # 0x69 +'u', # 0x6a +'v', # 0x6b +'w', # 0x6c +'x', # 0x6d +'y', # 0x6e +'z', # 0x6f +'A', # 0x70 +'B', # 0x71 +'C', # 0x72 +'D', # 0x73 +'E', # 0x74 +'F', # 0x75 +'G', # 0x76 +'H', # 0x77 +'I', # 0x78 +'J', # 0x79 +'K', # 0x7a +'L', # 0x7b +'M', # 0x7c +'N', # 0x7d +'O', # 0x7e +'P', # 0x7f +'Q', # 0x80 +'R', # 0x81 +'S', # 0x82 +'T', # 0x83 +'U', # 0x84 +'V', # 0x85 +'W', # 0x86 +'X', # 0x87 +'Y', # 0x88 +'Z', # 0x89 +'a', # 0x8a +'b', # 0x8b +'c', # 0x8c +'d', # 0x8d +'e', # 0x8e +'f', # 0x8f +'g', # 0x90 +'h', # 0x91 +'i', # 0x92 +'j', # 0x93 +'k', # 0x94 +'l', # 0x95 +'m', # 0x96 +'n', # 0x97 +'o', # 0x98 +'p', # 0x99 +'q', # 0x9a +'r', # 0x9b +'s', # 0x9c +'t', # 0x9d +'u', # 0x9e +'v', # 0x9f +'w', # 0xa0 +'x', # 0xa1 +'y', # 0xa2 +'z', # 0xa3 +'i', # 0xa4 +'j', # 0xa5 +'', # 0xa6 +'', # 0xa7 +'Alpha', # 0xa8 +'Beta', # 0xa9 +'Gamma', # 0xaa +'Delta', # 0xab +'Epsilon', # 0xac +'Zeta', # 0xad +'Eta', # 0xae +'Theta', # 0xaf +'Iota', # 0xb0 +'Kappa', # 0xb1 +'Lamda', # 0xb2 +'Mu', # 0xb3 +'Nu', # 0xb4 +'Xi', # 0xb5 +'Omicron', # 0xb6 +'Pi', # 0xb7 +'Rho', # 0xb8 +'Theta', # 0xb9 +'Sigma', # 0xba +'Tau', # 0xbb +'Upsilon', # 0xbc +'Phi', # 0xbd +'Chi', # 0xbe +'Psi', # 0xbf +'Omega', # 0xc0 +'nabla', # 0xc1 +'alpha', # 0xc2 +'beta', # 0xc3 +'gamma', # 0xc4 +'delta', # 0xc5 +'epsilon', # 0xc6 +'zeta', # 0xc7 +'eta', # 0xc8 +'theta', # 0xc9 +'iota', # 0xca +'kappa', # 0xcb +'lamda', # 0xcc +'mu', # 0xcd +'nu', # 0xce +'xi', # 0xcf +'omicron', # 0xd0 +'pi', # 0xd1 +'rho', # 0xd2 +'sigma', # 0xd3 +'sigma', # 0xd4 +'tai', # 0xd5 +'upsilon', # 0xd6 +'phi', # 0xd7 +'chi', # 0xd8 +'psi', # 0xd9 +'omega', # 0xda +'', # 0xdb +'', # 0xdc +'', # 0xdd +'', # 0xde +'', # 0xdf +'', # 0xe0 +'', # 0xe1 +'', # 0xe2 +'', # 0xe3 +'', # 0xe4 +'', # 0xe5 +'', # 0xe6 +'', # 0xe7 +'', # 0xe8 +'', # 0xe9 +'', # 0xea +'', # 0xeb +'', # 0xec +'', # 0xed +'', # 0xee +'', # 0xef +'', # 0xf0 +'', # 0xf1 +'', # 0xf2 +'', # 0xf3 +'', # 0xf4 +'', # 0xf5 +'', # 0xf6 +'', # 0xf7 +'', # 0xf8 +'', # 0xf9 +'', # 0xfa +'', # 0xfb +'', # 0xfc +'', # 0xfd +'', # 0xfe +'', # 0xff +) diff --git a/nstock/modules/unidecode/x1d7.py b/nstock/modules/unidecode/x1d7.py new file mode 100644 index 0000000..6943bf4 --- /dev/null +++ b/nstock/modules/unidecode/x1d7.py @@ -0,0 +1,258 @@ +data = ( +'', # 0x00 +'', # 0x01 +'', # 0x02 +'', # 0x03 +'', # 0x04 +'', # 0x05 +'', # 0x06 +'', # 0x07 +'', # 0x08 +'', # 0x09 +'', # 0x0a +'', # 0x0b +'', # 0x0c +'', # 0x0d +'', # 0x0e +'', # 0x0f +'', # 0x10 +'', # 0x11 +'', # 0x12 +'', # 0x13 +'', # 0x14 +'', # 0x15 +'', # 0x16 +'', # 0x17 +'', # 0x18 +'', # 0x19 +'', # 0x1a +'', # 0x1b +'', # 0x1c +'', # 0x1d +'', # 0x1e +'', # 0x1f +'', # 0x20 +'', # 0x21 +'', # 0x22 +'', # 0x23 +'', # 0x24 +'', # 0x25 +'', # 0x26 +'', # 0x27 +'', # 0x28 +'', # 0x29 +'', # 0x2a +'', # 0x2b +'', # 0x2c +'', # 0x2d +'', # 0x2e +'', # 0x2f +'', # 0x30 +'', # 0x31 +'', # 0x32 +'', # 0x33 +'', # 0x34 +'', # 0x35 +'', # 0x36 +'', # 0x37 +'', # 0x38 +'', # 0x39 +'', # 0x3a +'', # 0x3b +'', # 0x3c +'', # 0x3d +'', # 0x3e +'', # 0x3f +'', # 0x40 +'', # 0x41 +'', # 0x42 +'', # 0x43 +'', # 0x44 +'', # 0x45 +'', # 0x46 +'', # 0x47 +'', # 0x48 +'', # 0x49 +'', # 0x4a +'', # 0x4b +'', # 0x4c +'', # 0x4d +'', # 0x4e +'', # 0x4f +'', # 0x50 +'', # 0x51 +'', # 0x52 +'', # 0x53 +'', # 0x54 +'', # 0x55 +'', # 0x56 +'', # 0x57 +'', # 0x58 +'', # 0x59 +'', # 0x5a +'', # 0x5b +'', # 0x5c +'', # 0x5d +'', # 0x5e +'', # 0x5f +'', # 0x60 +'', # 0x61 +'', # 0x62 +'', # 0x63 +'', # 0x64 +'', # 0x65 +'', # 0x66 +'', # 0x67 +'', # 0x68 +'', # 0x69 +'', # 0x6a +'', # 0x6b +'', # 0x6c +'', # 0x6d +'', # 0x6e +'', # 0x6f +'', # 0x70 +'', # 0x71 +'', # 0x72 +'', # 0x73 +'', # 0x74 +'', # 0x75 +'', # 0x76 +'', # 0x77 +'', # 0x78 +'', # 0x79 +'', # 0x7a +'', # 0x7b +'', # 0x7c +'', # 0x7d +'', # 0x7e +'', # 0x7f +'', # 0x80 +'', # 0x81 +'', # 0x82 +'', # 0x83 +'', # 0x84 +'', # 0x85 +'', # 0x86 +'', # 0x87 +'', # 0x88 +'', # 0x89 +'', # 0x8a +'', # 0x8b +'', # 0x8c +'', # 0x8d +'', # 0x8e +'', # 0x8f +'', # 0x90 +'', # 0x91 +'', # 0x92 +'', # 0x93 +'', # 0x94 +'', # 0x95 +'', # 0x96 +'', # 0x97 +'', # 0x98 +'', # 0x99 +'', # 0x9a +'', # 0x9b +'', # 0x9c +'', # 0x9d +'', # 0x9e +'', # 0x9f +'', # 0xa0 +'', # 0xa1 +'', # 0xa2 +'', # 0xa3 +'', # 0xa4 +'', # 0xa5 +'', # 0xa6 +'', # 0xa7 +'', # 0xa8 +'', # 0xa9 +'', # 0xaa +'', # 0xab +'', # 0xac +'', # 0xad +'', # 0xae +'', # 0xaf +'', # 0xb0 +'', # 0xb1 +'', # 0xb2 +'', # 0xb3 +'', # 0xb4 +'', # 0xb5 +'', # 0xb6 +'', # 0xb7 +'', # 0xb8 +'', # 0xb9 +'', # 0xba +'', # 0xbb +'', # 0xbc +'', # 0xbd +'', # 0xbe +'', # 0xbf +'', # 0xc0 +'', # 0xc1 +'', # 0xc2 +'', # 0xc3 +'', # 0xc4 +'', # 0xc5 +'', # 0xc6 +'', # 0xc7 +'', # 0xc8 +'', # 0xc9 +'', # 0xca +'', # 0xcb +'', # 0xcc +'', # 0xcd +'0', # 0xce +'1', # 0xcf +'2', # 0xd0 +'3', # 0xd1 +'4', # 0xd2 +'5', # 0xd3 +'6', # 0xd4 +'7', # 0xd5 +'8', # 0xd6 +'9', # 0xd7 +'0', # 0xd8 +'1', # 0xd9 +'2', # 0xda +'3', # 0xdb +'4', # 0xdc +'5', # 0xdd +'6', # 0xde +'7', # 0xdf +'8', # 0xe0 +'9', # 0xe1 +'0', # 0xe2 +'1', # 0xe3 +'2', # 0xe4 +'3', # 0xe5 +'4', # 0xe6 +'5', # 0xe7 +'6', # 0xe8 +'7', # 0xe9 +'8', # 0xea +'9', # 0xeb +'0', # 0xec +'1', # 0xed +'2', # 0xee +'3', # 0xef +'4', # 0xf0 +'5', # 0xf1 +'6', # 0xf2 +'7', # 0xf3 +'8', # 0xf4 +'9', # 0xf5 +'0', # 0xf6 +'1', # 0xf7 +'2', # 0xf8 +'3', # 0xf9 +'4', # 0xfa +'5', # 0xfb +'6', # 0xfc +'7', # 0xfd +'8', # 0xfe +'9', # 0xff +) diff --git a/nstock/modules/whoosh/__init__.py b/nstock/modules/whoosh/__init__.py new file mode 100644 index 0000000..4e78ab3 --- /dev/null +++ b/nstock/modules/whoosh/__init__.py @@ -0,0 +1,49 @@ +# Copyright 2008 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +__version__ = (2, 7, 4) + + +def versionstring(build=True, extra=True): + """Returns the version number of Whoosh as a string. + + :param build: Whether to include the build number in the string. + :param extra: Whether to include alpha/beta/rc etc. tags. Only + checked if build is True. + :rtype: str + """ + + if build: + first = 3 + else: + first = 2 + + s = ".".join(str(n) for n in __version__[:first]) + if build and extra: + s += "".join(str(n) for n in __version__[3:]) + + return s diff --git a/nstock/modules/whoosh/analysis/__init__.py b/nstock/modules/whoosh/analysis/__init__.py new file mode 100644 index 0000000..66293bc --- /dev/null +++ b/nstock/modules/whoosh/analysis/__init__.py @@ -0,0 +1,69 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +"""Classes and functions for turning a piece of text into an indexable stream +of "tokens" (usually equivalent to words). There are three general classes +involved in analysis: + +* Tokenizers are always at the start of the text processing pipeline. They take + a string and yield Token objects (actually, the same token object over and + over, for performance reasons) corresponding to the tokens (words) in the + text. + + Every tokenizer is a callable that takes a string and returns an iterator of + tokens. + +* Filters take the tokens from the tokenizer and perform various + transformations on them. For example, the LowercaseFilter converts all tokens + to lowercase, which is usually necessary when indexing regular English text. + + Every filter is a callable that takes a token generator and returns a token + generator. + +* Analyzers are convenience functions/classes that "package up" a tokenizer and + zero or more filters into a single unit. For example, the StandardAnalyzer + combines a RegexTokenizer, LowercaseFilter, and StopFilter. + + Every analyzer is a callable that takes a string and returns a token + iterator. (So Tokenizers can be used as Analyzers if you don't need any + filtering). + +You can compose tokenizers and filters together using the ``|`` character:: + + my_analyzer = RegexTokenizer() | LowercaseFilter() | StopFilter() + +The first item must be a tokenizer and the rest must be filters (you can't put +a filter first or a tokenizer after the first item). +""" + +from whoosh.analysis.acore import * +from whoosh.analysis.tokenizers import * +from whoosh.analysis.filters import * +from whoosh.analysis.morph import * +from whoosh.analysis.intraword import * +from whoosh.analysis.ngrams import * +from whoosh.analysis.analyzers import * diff --git a/nstock/modules/whoosh/analysis/acore.py b/nstock/modules/whoosh/analysis/acore.py new file mode 100644 index 0000000..adb53b7 --- /dev/null +++ b/nstock/modules/whoosh/analysis/acore.py @@ -0,0 +1,156 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from whoosh.compat import iteritems + + +# Exceptions + +class CompositionError(Exception): + pass + + +# Utility functions + +def unstopped(tokenstream): + """Removes tokens from a token stream where token.stopped = True. + """ + return (t for t in tokenstream if not t.stopped) + + +def entoken(textstream, positions=False, chars=False, start_pos=0, + start_char=0, **kwargs): + """Takes a sequence of unicode strings and yields a series of Token objects + (actually the same Token object over and over, for performance reasons), + with the attributes filled in with reasonable values (for example, if + ``positions`` or ``chars`` is True, the function assumes each token was + separated by one space). + """ + + pos = start_pos + char = start_char + t = Token(positions=positions, chars=chars, **kwargs) + + for text in textstream: + t.text = text + + if positions: + t.pos = pos + pos += 1 + + if chars: + t.startchar = char + char = char + len(text) + t.endchar = char + + yield t + + +# Token object + +class Token(object): + """ + Represents a "token" (usually a word) extracted from the source text being + indexed. + + See "Advanced analysis" in the user guide for more information. + + Because object instantiation in Python is slow, tokenizers should create + ONE SINGLE Token object and YIELD IT OVER AND OVER, changing the attributes + each time. + + This trick means that consumers of tokens (i.e. filters) must never try to + hold onto the token object between loop iterations, or convert the token + generator into a list. Instead, save the attributes between iterations, + not the object:: + + def RemoveDuplicatesFilter(self, stream): + # Removes duplicate words. + lasttext = None + for token in stream: + # Only yield the token if its text doesn't + # match the previous token. + if lasttext != token.text: + yield token + lasttext = token.text + + ...or, call token.copy() to get a copy of the token object. + """ + + def __init__(self, positions=False, chars=False, removestops=True, mode='', + **kwargs): + """ + :param positions: Whether tokens should have the token position in the + 'pos' attribute. + :param chars: Whether tokens should have character offsets in the + 'startchar' and 'endchar' attributes. + :param removestops: whether to remove stop words from the stream (if + the tokens pass through a stop filter). + :param mode: contains a string describing the purpose for which the + analyzer is being called, i.e. 'index' or 'query'. + """ + + self.positions = positions + self.chars = chars + self.stopped = False + self.boost = 1.0 + self.removestops = removestops + self.mode = mode + self.__dict__.update(kwargs) + + def __repr__(self): + parms = ", ".join("%s=%r" % (name, value) + for name, value in iteritems(self.__dict__)) + return "%s(%s)" % (self.__class__.__name__, parms) + + def copy(self): + # This is faster than using the copy module + return Token(**self.__dict__) + + +# Composition support + +class Composable(object): + is_morph = False + + def __or__(self, other): + from whoosh.analysis.analyzers import CompositeAnalyzer + + if not isinstance(other, Composable): + raise TypeError("%r is not composable with %r" % (self, other)) + return CompositeAnalyzer(self, other) + + def __repr__(self): + attrs = "" + if self.__dict__: + attrs = ", ".join("%s=%r" % (key, value) + for key, value + in iteritems(self.__dict__)) + return self.__class__.__name__ + "(%s)" % attrs + + def has_morph(self): + return self.is_morph diff --git a/nstock/modules/whoosh/analysis/analyzers.py b/nstock/modules/whoosh/analysis/analyzers.py new file mode 100644 index 0000000..f7d6e3c --- /dev/null +++ b/nstock/modules/whoosh/analysis/analyzers.py @@ -0,0 +1,296 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from whoosh.analysis.acore import Composable, CompositionError +from whoosh.analysis.tokenizers import Tokenizer +from whoosh.analysis.filters import LowercaseFilter +from whoosh.analysis.filters import StopFilter, STOP_WORDS +from whoosh.analysis.morph import StemFilter +from whoosh.analysis.intraword import IntraWordFilter +from whoosh.analysis.tokenizers import default_pattern +from whoosh.analysis.tokenizers import CommaSeparatedTokenizer +from whoosh.analysis.tokenizers import IDTokenizer +from whoosh.analysis.tokenizers import RegexTokenizer +from whoosh.analysis.tokenizers import SpaceSeparatedTokenizer +from whoosh.lang.porter import stem + + +# Analyzers + +class Analyzer(Composable): + """ Abstract base class for analyzers. + """ + + def __repr__(self): + return "%s()" % self.__class__.__name__ + + def __eq__(self, other): + return (other + and self.__class__ is other.__class__ + and self.__dict__ == other.__dict__) + + def __call__(self, value, **kwargs): + raise NotImplementedError + + def clean(self): + pass + + +class CompositeAnalyzer(Analyzer): + def __init__(self, *composables): + self.items = [] + + for comp in composables: + if isinstance(comp, CompositeAnalyzer): + self.items.extend(comp.items) + else: + self.items.append(comp) + + # Tokenizers must start a chain, and then only filters after that + # (because analyzers take a string and return a generator of tokens, + # and filters take and return generators of tokens) + for item in self.items[1:]: + if isinstance(item, Tokenizer): + raise CompositionError("Only one tokenizer allowed at the start" + " of the analyzer: %r" % self.items) + + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, + ", ".join(repr(item) for item in self.items)) + + def __call__(self, value, no_morph=False, **kwargs): + items = self.items + # Start with tokenizer + gen = items[0](value, **kwargs) + # Run filters + for item in items[1:]: + if not (no_morph and hasattr(item, "is_morph") and item.is_morph): + gen = item(gen) + return gen + + def __getitem__(self, item): + return self.items.__getitem__(item) + + def __len__(self): + return len(self.items) + + def __eq__(self, other): + return (other + and self.__class__ is other.__class__ + and self.items == other.items) + + def clean(self): + for item in self.items: + if hasattr(item, "clean"): + item.clean() + + def has_morph(self): + return any(item.is_morph for item in self.items) + + +# Functions that return composed analyzers + +def IDAnalyzer(lowercase=False): + """Deprecated, just use an IDTokenizer directly, with a LowercaseFilter if + desired. + """ + + tokenizer = IDTokenizer() + if lowercase: + tokenizer = tokenizer | LowercaseFilter() + return tokenizer + + +def KeywordAnalyzer(lowercase=False, commas=False): + """Parses whitespace- or comma-separated tokens. + + >>> ana = KeywordAnalyzer() + >>> [token.text for token in ana("Hello there, this is a TEST")] + ["Hello", "there,", "this", "is", "a", "TEST"] + + :param lowercase: whether to lowercase the tokens. + :param commas: if True, items are separated by commas rather than + whitespace. + """ + + if commas: + tokenizer = CommaSeparatedTokenizer() + else: + tokenizer = SpaceSeparatedTokenizer() + if lowercase: + tokenizer = tokenizer | LowercaseFilter() + return tokenizer + + +def RegexAnalyzer(expression=r"\w+(\.?\w+)*", gaps=False): + """Deprecated, just use a RegexTokenizer directly. + """ + + return RegexTokenizer(expression=expression, gaps=gaps) + + +def SimpleAnalyzer(expression=default_pattern, gaps=False): + """Composes a RegexTokenizer with a LowercaseFilter. + + >>> ana = SimpleAnalyzer() + >>> [token.text for token in ana("Hello there, this is a TEST")] + ["hello", "there", "this", "is", "a", "test"] + + :param expression: The regular expression pattern to use to extract tokens. + :param gaps: If True, the tokenizer *splits* on the expression, rather + than matching on the expression. + """ + + return RegexTokenizer(expression=expression, gaps=gaps) | LowercaseFilter() + + +def StandardAnalyzer(expression=default_pattern, stoplist=STOP_WORDS, + minsize=2, maxsize=None, gaps=False): + """Composes a RegexTokenizer with a LowercaseFilter and optional + StopFilter. + + >>> ana = StandardAnalyzer() + >>> [token.text for token in ana("Testing is testing and testing")] + ["testing", "testing", "testing"] + + :param expression: The regular expression pattern to use to extract tokens. + :param stoplist: A list of stop words. Set this to None to disable + the stop word filter. + :param minsize: Words smaller than this are removed from the stream. + :param maxsize: Words longer that this are removed from the stream. + :param gaps: If True, the tokenizer *splits* on the expression, rather + than matching on the expression. + """ + + ret = RegexTokenizer(expression=expression, gaps=gaps) + chain = ret | LowercaseFilter() + if stoplist is not None: + chain = chain | StopFilter(stoplist=stoplist, minsize=minsize, + maxsize=maxsize) + return chain + + +def StemmingAnalyzer(expression=default_pattern, stoplist=STOP_WORDS, + minsize=2, maxsize=None, gaps=False, stemfn=stem, + ignore=None, cachesize=50000): + """Composes a RegexTokenizer with a lower case filter, an optional stop + filter, and a stemming filter. + + >>> ana = StemmingAnalyzer() + >>> [token.text for token in ana("Testing is testing and testing")] + ["test", "test", "test"] + + :param expression: The regular expression pattern to use to extract tokens. + :param stoplist: A list of stop words. Set this to None to disable + the stop word filter. + :param minsize: Words smaller than this are removed from the stream. + :param maxsize: Words longer that this are removed from the stream. + :param gaps: If True, the tokenizer *splits* on the expression, rather + than matching on the expression. + :param ignore: a set of words to not stem. + :param cachesize: the maximum number of stemmed words to cache. The larger + this number, the faster stemming will be but the more memory it will + use. Use None for no cache, or -1 for an unbounded cache. + """ + + ret = RegexTokenizer(expression=expression, gaps=gaps) + chain = ret | LowercaseFilter() + if stoplist is not None: + chain = chain | StopFilter(stoplist=stoplist, minsize=minsize, + maxsize=maxsize) + return chain | StemFilter(stemfn=stemfn, ignore=ignore, + cachesize=cachesize) + + +def FancyAnalyzer(expression=r"\s+", stoplist=STOP_WORDS, minsize=2, + maxsize=None, gaps=True, splitwords=True, splitnums=True, + mergewords=False, mergenums=False): + """Composes a RegexTokenizer with an IntraWordFilter, LowercaseFilter, and + StopFilter. + + >>> ana = FancyAnalyzer() + >>> [token.text for token in ana("Should I call getInt or get_real?")] + ["should", "call", "getInt", "get", "int", "get_real", "get", "real"] + + :param expression: The regular expression pattern to use to extract tokens. + :param stoplist: A list of stop words. Set this to None to disable + the stop word filter. + :param minsize: Words smaller than this are removed from the stream. + :param maxsize: Words longer that this are removed from the stream. + :param gaps: If True, the tokenizer *splits* on the expression, rather + than matching on the expression. + """ + + return (RegexTokenizer(expression=expression, gaps=gaps) + | IntraWordFilter(splitwords=splitwords, splitnums=splitnums, + mergewords=mergewords, mergenums=mergenums) + | LowercaseFilter() + | StopFilter(stoplist=stoplist, minsize=minsize) + ) + + +def LanguageAnalyzer(lang, expression=default_pattern, gaps=False, + cachesize=50000): + """Configures a simple analyzer for the given language, with a + LowercaseFilter, StopFilter, and StemFilter. + + >>> ana = LanguageAnalyzer("es") + >>> [token.text for token in ana("Por el mar corren las liebres")] + ['mar', 'corr', 'liebr'] + + The list of available languages is in `whoosh.lang.languages`. + You can use :func:`whoosh.lang.has_stemmer` and + :func:`whoosh.lang.has_stopwords` to check if a given language has a + stemming function and/or stop word list available. + + :param expression: The regular expression pattern to use to extract tokens. + :param gaps: If True, the tokenizer *splits* on the expression, rather + than matching on the expression. + :param cachesize: the maximum number of stemmed words to cache. The larger + this number, the faster stemming will be but the more memory it will + use. + """ + + from whoosh.lang import NoStemmer, NoStopWords + + # Make the start of the chain + chain = (RegexTokenizer(expression=expression, gaps=gaps) + | LowercaseFilter()) + + # Add a stop word filter + try: + chain = chain | StopFilter(lang=lang) + except NoStopWords: + pass + + # Add a stemming filter + try: + chain = chain | StemFilter(lang=lang, cachesize=cachesize) + except NoStemmer: + pass + + return chain diff --git a/nstock/modules/whoosh/analysis/filters.py b/nstock/modules/whoosh/analysis/filters.py new file mode 100644 index 0000000..add9c98 --- /dev/null +++ b/nstock/modules/whoosh/analysis/filters.py @@ -0,0 +1,479 @@ +# coding=utf-8 + +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from itertools import chain + +from whoosh.compat import next, xrange +from whoosh.analysis.acore import Composable +from whoosh.util.text import rcompile + + +# Default list of stop words (words so common it's usually wasteful to index +# them). This list is used by the StopFilter class, which allows you to supply +# an optional list to override this one. + +STOP_WORDS = frozenset(('a', 'an', 'and', 'are', 'as', 'at', 'be', 'by', 'can', + 'for', 'from', 'have', 'if', 'in', 'is', 'it', 'may', + 'not', 'of', 'on', 'or', 'tbd', 'that', 'the', 'this', + 'to', 'us', 'we', 'when', 'will', 'with', 'yet', + 'you', 'your')) + + +# Simple pattern for filtering URLs, may be useful + +url_pattern = rcompile(""" +( + [A-Za-z+]+:// # URL protocol + \\S+? # URL body + (?=\\s|[.]\\s|$|[.]$) # Stop at space/end, or a dot followed by space/end +) | ( # or... + \w+([:.]?\w+)* # word characters, with opt. internal colons/dots +) +""", verbose=True) + + +# Filters + +class Filter(Composable): + """Base class for Filter objects. A Filter subclass must implement a + filter() method that takes a single argument, which is an iterator of Token + objects, and yield a series of Token objects in return. + + Filters that do morphological transformation of tokens (e.g. stemming) + should set their ``is_morph`` attribute to True. + """ + + def __eq__(self, other): + return (other + and self.__class__ is other.__class__ + and self.__dict__ == other.__dict__) + + def __ne__(self, other): + return not self == other + + def __call__(self, tokens): + raise NotImplementedError + + +class PassFilter(Filter): + """An identity filter: passes the tokens through untouched. + """ + + def __call__(self, tokens): + return tokens + + +class LoggingFilter(Filter): + """Prints the contents of every filter that passes through as a debug + log entry. + """ + + def __init__(self, logger=None): + """ + :param target: the logger to use. If omitted, the "whoosh.analysis" + logger is used. + """ + + if logger is None: + import logging + logger = logging.getLogger("whoosh.analysis") + self.logger = logger + + def __call__(self, tokens): + logger = self.logger + for t in tokens: + logger.debug(repr(t)) + yield t + + +class MultiFilter(Filter): + """Chooses one of two or more sub-filters based on the 'mode' attribute + of the token stream. + """ + + default_filter = PassFilter() + + def __init__(self, **kwargs): + """Use keyword arguments to associate mode attribute values with + instantiated filters. + + >>> iwf_for_index = IntraWordFilter(mergewords=True, mergenums=False) + >>> iwf_for_query = IntraWordFilter(mergewords=False, mergenums=False) + >>> mf = MultiFilter(index=iwf_for_index, query=iwf_for_query) + + This class expects that the value of the mode attribute is consistent + among all tokens in a token stream. + """ + self.filters = kwargs + + def __eq__(self, other): + return (other + and self.__class__ is other.__class__ + and self.filters == other.filters) + + def __call__(self, tokens): + # Only selects on the first token + t = next(tokens) + filter = self.filters.get(t.mode, self.default_filter) + return filter(chain([t], tokens)) + + +class TeeFilter(Filter): + """Interleaves the results of two or more filters (or filter chains). + + NOTE: because it needs to create copies of each token for each sub-filter, + this filter is quite slow. + + >>> target = "ALFA BRAVO CHARLIE" + >>> # In one branch, we'll lower-case the tokens + >>> f1 = LowercaseFilter() + >>> # In the other branch, we'll reverse the tokens + >>> f2 = ReverseTextFilter() + >>> ana = RegexTokenizer(r"\S+") | TeeFilter(f1, f2) + >>> [token.text for token in ana(target)] + ["alfa", "AFLA", "bravo", "OVARB", "charlie", "EILRAHC"] + + To combine the incoming token stream with the output of a filter chain, use + ``TeeFilter`` and make one of the filters a :class:`PassFilter`. + + >>> f1 = PassFilter() + >>> f2 = BiWordFilter() + >>> ana = RegexTokenizer(r"\S+") | TeeFilter(f1, f2) | LowercaseFilter() + >>> [token.text for token in ana(target)] + ["alfa", "alfa-bravo", "bravo", "bravo-charlie", "charlie"] + """ + + def __init__(self, *filters): + if len(filters) < 2: + raise Exception("TeeFilter requires two or more filters") + self.filters = filters + + def __eq__(self, other): + return (self.__class__ is other.__class__ + and self.filters == other.fitlers) + + def __call__(self, tokens): + from itertools import tee + + count = len(self.filters) + # Tee the token iterator and wrap each teed iterator with the + # corresponding filter + gens = [filter(t.copy() for t in gen) for filter, gen + in zip(self.filters, tee(tokens, count))] + # Keep a count of the number of running iterators + running = count + while running: + for i, gen in enumerate(gens): + if gen is not None: + try: + yield next(gen) + except StopIteration: + gens[i] = None + running -= 1 + + +class ReverseTextFilter(Filter): + """Reverses the text of each token. + + >>> ana = RegexTokenizer() | ReverseTextFilter() + >>> [token.text for token in ana("hello there")] + ["olleh", "ereht"] + """ + + def __call__(self, tokens): + for t in tokens: + t.text = t.text[::-1] + yield t + + +class LowercaseFilter(Filter): + """Uses unicode.lower() to lowercase token text. + + >>> rext = RegexTokenizer() + >>> stream = rext("This is a TEST") + >>> [token.text for token in LowercaseFilter(stream)] + ["this", "is", "a", "test"] + """ + + def __call__(self, tokens): + for t in tokens: + t.text = t.text.lower() + yield t + + +class StripFilter(Filter): + """Calls unicode.strip() on the token text. + """ + + def __call__(self, tokens): + for t in tokens: + t.text = t.text.strip() + yield t + + +class StopFilter(Filter): + """Marks "stop" words (words too common to index) in the stream (and by + default removes them). + + Make sure you precede this filter with a :class:`LowercaseFilter`. + + >>> stopper = RegexTokenizer() | StopFilter() + >>> [token.text for token in stopper(u"this is a test")] + ["test"] + >>> es_stopper = RegexTokenizer() | StopFilter(lang="es") + >>> [token.text for token in es_stopper(u"el lapiz es en la mesa")] + ["lapiz", "mesa"] + + The list of available languages is in `whoosh.lang.languages`. + You can use :func:`whoosh.lang.has_stopwords` to check if a given language + has a stop word list available. + """ + + def __init__(self, stoplist=STOP_WORDS, minsize=2, maxsize=None, + renumber=True, lang=None): + """ + :param stoplist: A collection of words to remove from the stream. + This is converted to a frozenset. The default is a list of + common English stop words. + :param minsize: The minimum length of token texts. Tokens with + text smaller than this will be stopped. The default is 2. + :param maxsize: The maximum length of token texts. Tokens with text + larger than this will be stopped. Use None to allow any length. + :param renumber: Change the 'pos' attribute of unstopped tokens + to reflect their position with the stopped words removed. + :param lang: Automatically get a list of stop words for the given + language + """ + + stops = set() + if stoplist: + stops.update(stoplist) + if lang: + from whoosh.lang import stopwords_for_language + + stops.update(stopwords_for_language(lang)) + + self.stops = frozenset(stops) + self.min = minsize + self.max = maxsize + self.renumber = renumber + + def __eq__(self, other): + return (other + and self.__class__ is other.__class__ + and self.stops == other.stops + and self.min == other.min + and self.renumber == other.renumber) + + def __call__(self, tokens): + stoplist = self.stops + minsize = self.min + maxsize = self.max + renumber = self.renumber + + pos = None + for t in tokens: + text = t.text + if (len(text) >= minsize + and (maxsize is None or len(text) <= maxsize) + and text not in stoplist): + # This is not a stop word + if renumber and t.positions: + if pos is None: + pos = t.pos + else: + pos += 1 + t.pos = pos + t.stopped = False + yield t + else: + # This is a stop word + if not t.removestops: + # This IS a stop word, but we're not removing them + t.stopped = True + yield t + + +class CharsetFilter(Filter): + """Translates the text of tokens by calling unicode.translate() using the + supplied character mapping object. This is useful for case and accent + folding. + + The ``whoosh.support.charset`` module has a useful map for accent folding. + + >>> from whoosh.support.charset import accent_map + >>> retokenizer = RegexTokenizer() + >>> chfilter = CharsetFilter(accent_map) + >>> [t.text for t in chfilter(retokenizer(u'café'))] + [u'cafe'] + + Another way to get a character mapping object is to convert a Sphinx + charset table file using + :func:`whoosh.support.charset.charset_table_to_dict`. + + >>> from whoosh.support.charset import charset_table_to_dict + >>> from whoosh.support.charset import default_charset + >>> retokenizer = RegexTokenizer() + >>> charmap = charset_table_to_dict(default_charset) + >>> chfilter = CharsetFilter(charmap) + >>> [t.text for t in chfilter(retokenizer(u'Stra\\xdfe'))] + [u'strase'] + + The Sphinx charset table format is described at + http://www.sphinxsearch.com/docs/current.html#conf-charset-table. + """ + + __inittypes__ = dict(charmap=dict) + + def __init__(self, charmap): + """ + :param charmap: a dictionary mapping from integer character numbers to + unicode characters, as required by the unicode.translate() method. + """ + + self.charmap = charmap + + def __eq__(self, other): + return (other + and self.__class__ is other.__class__ + and self.charmap == other.charmap) + + def __call__(self, tokens): + assert hasattr(tokens, "__iter__") + charmap = self.charmap + for t in tokens: + t.text = t.text.translate(charmap) + yield t + + +class DelimitedAttributeFilter(Filter): + """Looks for delimiter characters in the text of each token and stores the + data after the delimiter in a named attribute on the token. + + The defaults are set up to use the ``^`` character as a delimiter and store + the value after the ``^`` as the boost for the token. + + >>> daf = DelimitedAttributeFilter(delimiter="^", attribute="boost") + >>> ana = RegexTokenizer("\\\\S+") | DelimitedAttributeFilter() + >>> for t in ana(u("image render^2 file^0.5")) + ... print("%r %f" % (t.text, t.boost)) + 'image' 1.0 + 'render' 2.0 + 'file' 0.5 + + Note that you need to make sure your tokenizer includes the delimiter and + data as part of the token! + """ + + def __init__(self, delimiter="^", attribute="boost", default=1.0, + type=float): + """ + :param delimiter: a string that, when present in a token's text, + separates the actual text from the "data" payload. + :param attribute: the name of the attribute in which to store the + data on the token. + :param default: the value to use for the attribute for tokens that + don't have delimited data. + :param type: the type of the data, for example ``str`` or ``float``. + This is used to convert the string value of the data before + storing it in the attribute. + """ + + self.delim = delimiter + self.attr = attribute + self.default = default + self.type = type + + def __eq__(self, other): + return (other and self.__class__ is other.__class__ + and self.delim == other.delim + and self.attr == other.attr + and self.default == other.default) + + def __call__(self, tokens): + delim = self.delim + attr = self.attr + default = self.default + type_ = self.type + + for t in tokens: + text = t.text + pos = text.find(delim) + if pos > -1: + setattr(t, attr, type_(text[pos + 1:])) + if t.chars: + t.endchar -= len(t.text) - pos + t.text = text[:pos] + else: + setattr(t, attr, default) + + yield t + + +class SubstitutionFilter(Filter): + """Performs a regular expression substitution on the token text. + + This is especially useful for removing text from tokens, for example + hyphens:: + + ana = RegexTokenizer(r"\\S+") | SubstitutionFilter("-", "") + + Because it has the full power of the re.sub() method behind it, this filter + can perform some fairly complex transformations. For example, to take + tokens like ``'a=b', 'c=d', 'e=f'`` and change them to ``'b=a', 'd=c', + 'f=e'``:: + + # Analyzer that swaps the text on either side of an equal sign + rt = RegexTokenizer(r"\\S+") + sf = SubstitutionFilter("([^/]*)/(./*)", r"\\2/\\1") + ana = rt | sf + """ + + def __init__(self, pattern, replacement): + """ + :param pattern: a pattern string or compiled regular expression object + describing the text to replace. + :param replacement: the substitution text. + """ + + self.pattern = rcompile(pattern) + self.replacement = replacement + + def __eq__(self, other): + return (other and self.__class__ is other.__class__ + and self.pattern == other.pattern + and self.replacement == other.replacement) + + def __call__(self, tokens): + pattern = self.pattern + replacement = self.replacement + + for t in tokens: + t.text = pattern.sub(replacement, t.text) + yield t diff --git a/nstock/modules/whoosh/analysis/intraword.py b/nstock/modules/whoosh/analysis/intraword.py new file mode 100644 index 0000000..601423e --- /dev/null +++ b/nstock/modules/whoosh/analysis/intraword.py @@ -0,0 +1,494 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +import re +from collections import deque + +from whoosh.compat import u, text_type +from whoosh.compat import xrange +from whoosh.analysis.filters import Filter + + +class CompoundWordFilter(Filter): + """Given a set of words (or any object with a ``__contains__`` method), + break any tokens in the stream that are composites of words in the word set + into their individual parts. + + Given the correct set of words, this filter can break apart run-together + words and trademarks (e.g. "turbosquid", "applescript"). It can also be + useful for agglutinative languages such as German. + + The ``keep_compound`` argument lets you decide whether to keep the + compound word in the token stream along with the word segments. + + >>> cwf = CompoundWordFilter(wordset, keep_compound=True) + >>> analyzer = RegexTokenizer(r"\S+") | cwf + >>> [t.text for t in analyzer("I do not like greeneggs and ham") + ["I", "do", "not", "like", "greeneggs", "green", "eggs", "and", "ham"] + >>> cwf.keep_compound = False + >>> [t.text for t in analyzer("I do not like greeneggs and ham") + ["I", "do", "not", "like", "green", "eggs", "and", "ham"] + """ + + def __init__(self, wordset, keep_compound=True): + """ + :param wordset: an object with a ``__contains__`` method, such as a + set, containing strings to look for inside the tokens. + :param keep_compound: if True (the default), the original compound + token will be retained in the stream before the subwords. + """ + + self.wordset = wordset + self.keep_compound = keep_compound + + def subwords(self, s, memo): + if s in self.wordset: + return [s] + if s in memo: + return memo[s] + + for i in xrange(1, len(s)): + prefix = s[:i] + if prefix in self.wordset: + suffix = s[i:] + suffix_subs = self.subwords(suffix, memo) + if suffix_subs: + result = [prefix] + suffix_subs + memo[s] = result + return result + + return None + + def __call__(self, tokens): + keep_compound = self.keep_compound + memo = {} + subwords = self.subwords + for t in tokens: + subs = subwords(t.text, memo) + if subs: + if len(subs) > 1 and keep_compound: + yield t + for subword in subs: + t.text = subword + yield t + else: + yield t + + +class BiWordFilter(Filter): + """Merges adjacent tokens into "bi-word" tokens, so that for example:: + + "the", "sign", "of", "four" + + becomes:: + + "the-sign", "sign-of", "of-four" + + This can be used to create fields for pseudo-phrase searching, where if + all the terms match the document probably contains the phrase, but the + searching is faster than actually doing a phrase search on individual word + terms. + + The ``BiWordFilter`` is much faster than using the otherwise equivalent + ``ShingleFilter(2)``. + """ + + def __init__(self, sep="-"): + self.sep = sep + + def __call__(self, tokens): + sep = self.sep + prev_text = None + prev_startchar = None + prev_pos = None + atleastone = False + + for token in tokens: + # Save the original text of this token + text = token.text + + # Save the original position + positions = token.positions + if positions: + ps = token.pos + + # Save the original start char + chars = token.chars + if chars: + sc = token.startchar + + if prev_text is not None: + # Use the pos and startchar from the previous token + if positions: + token.pos = prev_pos + if chars: + token.startchar = prev_startchar + + # Join the previous token text and the current token text to + # form the biword token + token.text = "".join((prev_text, sep, text)) + yield token + atleastone = True + + # Save the originals and the new "previous" values + prev_text = text + if chars: + prev_startchar = sc + if positions: + prev_pos = ps + + # If no bi-words were emitted, that is, the token stream only had + # a single token, then emit that single token. + if not atleastone: + yield token + + +class ShingleFilter(Filter): + """Merges a certain number of adjacent tokens into multi-word tokens, so + that for example:: + + "better", "a", "witty", "fool", "than", "a", "foolish", "wit" + + with ``ShingleFilter(3, ' ')`` becomes:: + + 'better a witty', 'a witty fool', 'witty fool than', 'fool than a', + 'than a foolish', 'a foolish wit' + + This can be used to create fields for pseudo-phrase searching, where if + all the terms match the document probably contains the phrase, but the + searching is faster than actually doing a phrase search on individual word + terms. + + If you're using two-word shingles, you should use the functionally + equivalent ``BiWordFilter`` instead because it's faster than + ``ShingleFilter``. + """ + + def __init__(self, size=2, sep="-"): + self.size = size + self.sep = sep + + def __call__(self, tokens): + size = self.size + sep = self.sep + buf = deque() + atleastone = False + + def make_token(): + tk = buf[0] + tk.text = sep.join([t.text for t in buf]) + if tk.chars: + tk.endchar = buf[-1].endchar + return tk + + for token in tokens: + if not token.stopped: + buf.append(token.copy()) + if len(buf) == size: + atleastone = True + yield make_token() + buf.popleft() + + # If no shingles were emitted, that is, the token stream had fewer than + # 'size' tokens, then emit a single token with whatever tokens there + # were + if not atleastone and buf: + yield make_token() + + +class IntraWordFilter(Filter): + """Splits words into subwords and performs optional transformations on + subword groups. This filter is funtionally based on yonik's + WordDelimiterFilter in Solr, but shares no code with it. + + * Split on intra-word delimiters, e.g. `Wi-Fi` -> `Wi`, `Fi`. + * When splitwords=True, split on case transitions, + e.g. `PowerShot` -> `Power`, `Shot`. + * When splitnums=True, split on letter-number transitions, + e.g. `SD500` -> `SD`, `500`. + * Leading and trailing delimiter characters are ignored. + * Trailing possesive "'s" removed from subwords, + e.g. `O'Neil's` -> `O`, `Neil`. + + The mergewords and mergenums arguments turn on merging of subwords. + + When the merge arguments are false, subwords are not merged. + + * `PowerShot` -> `0`:`Power`, `1`:`Shot` (where `0` and `1` are token + positions). + + When one or both of the merge arguments are true, consecutive runs of + alphabetic and/or numeric subwords are merged into an additional token with + the same position as the last sub-word. + + * `PowerShot` -> `0`:`Power`, `1`:`Shot`, `1`:`PowerShot` + * `A's+B's&C's` -> `0`:`A`, `1`:`B`, `2`:`C`, `2`:`ABC` + * `Super-Duper-XL500-42-AutoCoder!` -> `0`:`Super`, `1`:`Duper`, `2`:`XL`, + `2`:`SuperDuperXL`, + `3`:`500`, `4`:`42`, `4`:`50042`, `5`:`Auto`, `6`:`Coder`, + `6`:`AutoCoder` + + When using this filter you should use a tokenizer that only splits on + whitespace, so the tokenizer does not remove intra-word delimiters before + this filter can see them, and put this filter before any use of + LowercaseFilter. + + >>> rt = RegexTokenizer(r"\\S+") + >>> iwf = IntraWordFilter() + >>> lcf = LowercaseFilter() + >>> analyzer = rt | iwf | lcf + + One use for this filter is to help match different written representations + of a concept. For example, if the source text contained `wi-fi`, you + probably want `wifi`, `WiFi`, `wi-fi`, etc. to match. One way of doing this + is to specify mergewords=True and/or mergenums=True in the analyzer used + for indexing, and mergewords=False / mergenums=False in the analyzer used + for querying. + + >>> iwf_i = IntraWordFilter(mergewords=True, mergenums=True) + >>> iwf_q = IntraWordFilter(mergewords=False, mergenums=False) + >>> iwf = MultiFilter(index=iwf_i, query=iwf_q) + >>> analyzer = RegexTokenizer(r"\S+") | iwf | LowercaseFilter() + + (See :class:`MultiFilter`.) + """ + + is_morph = True + + __inittypes__ = dict(delims=text_type, splitwords=bool, splitnums=bool, + mergewords=bool, mergenums=bool) + + def __init__(self, delims=u("-_'\"()!@#$%^&*[]{}<>\|;:,./?`~=+"), + splitwords=True, splitnums=True, + mergewords=False, mergenums=False): + """ + :param delims: a string of delimiter characters. + :param splitwords: if True, split at case transitions, + e.g. `PowerShot` -> `Power`, `Shot` + :param splitnums: if True, split at letter-number transitions, + e.g. `SD500` -> `SD`, `500` + :param mergewords: merge consecutive runs of alphabetic subwords into + an additional token with the same position as the last subword. + :param mergenums: merge consecutive runs of numeric subwords into an + additional token with the same position as the last subword. + """ + + from whoosh.support.unicode import digits, lowercase, uppercase + + self.delims = re.escape(delims) + + # Expression for text between delimiter characters + self.between = re.compile(u("[^%s]+") % (self.delims,), re.UNICODE) + # Expression for removing "'s" from the end of sub-words + dispat = u("(?<=[%s%s])'[Ss](?=$|[%s])") % (lowercase, uppercase, + self.delims) + self.possessive = re.compile(dispat, re.UNICODE) + + # Expression for finding case and letter-number transitions + lower2upper = u("[%s][%s]") % (lowercase, uppercase) + letter2digit = u("[%s%s][%s]") % (lowercase, uppercase, digits) + digit2letter = u("[%s][%s%s]") % (digits, lowercase, uppercase) + if splitwords and splitnums: + splitpat = u("(%s|%s|%s)") % (lower2upper, letter2digit, + digit2letter) + self.boundary = re.compile(splitpat, re.UNICODE) + elif splitwords: + self.boundary = re.compile(text_type(lower2upper), re.UNICODE) + elif splitnums: + numpat = u("(%s|%s)") % (letter2digit, digit2letter) + self.boundary = re.compile(numpat, re.UNICODE) + + self.splitting = splitwords or splitnums + self.mergewords = mergewords + self.mergenums = mergenums + + def __eq__(self, other): + return other and self.__class__ is other.__class__\ + and self.__dict__ == other.__dict__ + + def _split(self, string): + bound = self.boundary + + # Yields (startchar, endchar) pairs for each indexable substring in + # the given string, e.g. "WikiWord" -> (0, 4), (4, 8) + + # Whether we're splitting on transitions (case changes, letter -> num, + # num -> letter, etc.) + splitting = self.splitting + + # Make a list (dispos, for "dispossessed") of (startchar, endchar) + # pairs for runs of text between "'s" + if "'" in string: + # Split on possessive 's + dispos = [] + prev = 0 + for match in self.possessive.finditer(string): + dispos.append((prev, match.start())) + prev = match.end() + if prev < len(string): + dispos.append((prev, len(string))) + else: + # Shortcut if there's no apostrophe in the string + dispos = ((0, len(string)),) + + # For each run between 's + for sc, ec in dispos: + # Split on boundary characters + for part_match in self.between.finditer(string, sc, ec): + part_start = part_match.start() + part_end = part_match.end() + + if splitting: + # The point to start splitting at + prev = part_start + # Find transitions (e.g. "iW" or "a0") + for bmatch in bound.finditer(string, part_start, part_end): + # The point in the middle of the transition + pivot = bmatch.start() + 1 + # Yield from the previous match to the transition + yield (prev, pivot) + # Make the transition the new starting point + prev = pivot + + # If there's leftover text at the end, yield it too + if prev < part_end: + yield (prev, part_end) + else: + # Not splitting on transitions, just yield the part + yield (part_start, part_end) + + def _merge(self, parts): + mergewords = self.mergewords + mergenums = self.mergenums + + # Current type (1=alpah, 2=digit) + last = 0 + # Where to insert a merged term in the original list + insertat = 0 + # Buffer for parts to merge + buf = [] + # Iterate on a copy of the parts list so we can modify the original as + # we go + + def insert_item(buf, at, newpos): + newtext = "".join(item[0] for item in buf) + newsc = buf[0][2] # start char of first item in buffer + newec = buf[-1][3] # end char of last item in buffer + parts.insert(insertat, (newtext, newpos, newsc, newec)) + + for item in list(parts): + # item = (text, pos, startchar, endchar) + text = item[0] + pos = item[1] + + # Set the type of this part + if text.isalpha(): + this = 1 + elif text.isdigit(): + this = 2 + else: + this = None + + # Is this the same type as the previous part? + if (buf and (this == last == 1 and mergewords) + or (this == last == 2 and mergenums)): + # This part is the same type as the previous. Add it to the + # buffer of parts to merge. + buf.append(item) + else: + # This part is different than the previous. + if len(buf) > 1: + # If the buffer has at least two parts in it, merge them + # and add them to the original list of parts. + insert_item(buf, insertat, pos - 1) + insertat += 1 + # Reset the buffer + buf = [item] + last = this + insertat += 1 + + # If there are parts left in the buffer at the end, merge them and add + # them to the original list. + if len(buf) > 1: + insert_item(buf, len(parts), pos) + + def __call__(self, tokens): + mergewords = self.mergewords + mergenums = self.mergenums + + # This filter renumbers tokens as it expands them. New position + # counter. + newpos = None + for t in tokens: + text = t.text + + # If this is the first token we've seen, use it to set the new + # position counter + if newpos is None: + if t.positions: + newpos = t.pos + else: + # Token doesn't have positions, just use 0 + newpos = 0 + + if ((text.isalpha() and (text.islower() or text.isupper())) + or text.isdigit()): + # Short-circuit the common cases of no delimiters, no case + # transitions, only digits, etc. + t.pos = newpos + yield t + newpos += 1 + else: + # Split the token text on delimiters, word and/or number + # boundaries into a list of (text, pos, startchar, endchar) + # tuples + ranges = self._split(text) + parts = [(text[sc:ec], i + newpos, sc, ec) + for i, (sc, ec) in enumerate(ranges)] + + # Did the split yield more than one part? + if len(parts) > 1: + # If the options are set, merge consecutive runs of all- + # letters and/or all-numbers. + if mergewords or mergenums: + self._merge(parts) + + # Yield tokens for the parts + chars = t.chars + if chars: + base = t.startchar + for text, pos, startchar, endchar in parts: + t.text = text + t.pos = pos + if t.chars: + t.startchar = base + startchar + t.endchar = base + endchar + yield t + + if parts: + # Set the new position counter based on the last part + newpos = parts[-1][1] + 1 diff --git a/nstock/modules/whoosh/analysis/morph.py b/nstock/modules/whoosh/analysis/morph.py new file mode 100644 index 0000000..b7d644f --- /dev/null +++ b/nstock/modules/whoosh/analysis/morph.py @@ -0,0 +1,267 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from whoosh.analysis.filters import Filter +from whoosh.compat import integer_types +from whoosh.lang.dmetaphone import double_metaphone +from whoosh.lang.porter import stem +from whoosh.util.cache import lfu_cache, unbound_cache + + +class StemFilter(Filter): + """Stems (removes suffixes from) the text of tokens using the Porter + stemming algorithm. Stemming attempts to reduce multiple forms of the same + root word (for example, "rendering", "renders", "rendered", etc.) to a + single word in the index. + + >>> stemmer = RegexTokenizer() | StemFilter() + >>> [token.text for token in stemmer("fundamentally willows")] + ["fundament", "willow"] + + You can pass your own stemming function to the StemFilter. The default + is the Porter stemming algorithm for English. + + >>> stemfilter = StemFilter(stem_function) + + You can also use one of the Snowball stemming functions by passing the + `lang` keyword argument. + + >>> stemfilter = StemFilter(lang="ru") + + The list of available languages is in `whoosh.lang.languages`. + You can use :func:`whoosh.lang.has_stemmer` to check if a given language has + a stemming function available. + + By default, this class wraps an LRU cache around the stemming function. The + ``cachesize`` keyword argument sets the size of the cache. To make the + cache unbounded (the class caches every input), use ``cachesize=-1``. To + disable caching, use ``cachesize=None``. + + If you compile and install the py-stemmer library, the + :class:`PyStemmerFilter` provides slightly easier access to the language + stemmers in that library. + """ + + __inittypes__ = dict(stemfn=object, ignore=list) + + is_morph = True + + def __init__(self, stemfn=stem, lang=None, ignore=None, cachesize=50000): + """ + :param stemfn: the function to use for stemming. + :param lang: if not None, overrides the stemfn with a language stemmer + from the ``whoosh.lang.snowball`` package. + :param ignore: a set/list of words that should not be stemmed. This is + converted into a frozenset. If you omit this argument, all tokens + are stemmed. + :param cachesize: the maximum number of words to cache. Use ``-1`` for + an unbounded cache, or ``None`` for no caching. + """ + + self.stemfn = stemfn + self.lang = lang + self.ignore = frozenset() if ignore is None else frozenset(ignore) + self.cachesize = cachesize + # clear() sets the _stem attr to a cached wrapper around self.stemfn + self.clear() + + def __getstate__(self): + # Can't pickle a dynamic function, so we have to remove the _stem + # attribute from the state + return dict([(k, self.__dict__[k]) for k in self.__dict__ + if k != "_stem"]) + + def __setstate__(self, state): + # Check for old instances of StemFilter class, which didn't have a + # cachesize attribute and pickled the cache attribute + if "cachesize" not in state: + self.cachesize = 50000 + if "ignores" in state: + self.ignore = state["ignores"] + elif "ignore" not in state: + self.ignore = frozenset() + if "lang" not in state: + self.lang = None + if "cache" in state: + del state["cache"] + + self.__dict__.update(state) + # Set the _stem attribute + self.clear() + + def clear(self): + if self.lang: + from whoosh.lang import stemmer_for_language + stemfn = stemmer_for_language(self.lang) + else: + stemfn = self.stemfn + + if isinstance(self.cachesize, integer_types) and self.cachesize != 0: + if self.cachesize < 0: + self._stem = unbound_cache(stemfn) + elif self.cachesize > 1: + self._stem = lfu_cache(self.cachesize)(stemfn) + else: + self._stem = stemfn + + def cache_info(self): + if self.cachesize <= 1: + return None + return self._stem.cache_info() + + def __eq__(self, other): + return (other and self.__class__ is other.__class__ + and self.stemfn == other.stemfn) + + def __call__(self, tokens): + stemfn = self._stem + ignore = self.ignore + + for t in tokens: + if not t.stopped: + text = t.text + if text not in ignore: + t.text = stemfn(text) + yield t + + +class PyStemmerFilter(StemFilter): + """This is a simple subclass of StemFilter that works with the py-stemmer + third-party library. You must have the py-stemmer library installed to use + this filter. + + >>> PyStemmerFilter("spanish") + """ + + def __init__(self, lang="english", ignore=None, cachesize=10000): + """ + :param lang: a string identifying the stemming algorithm to use. You + can get a list of available algorithms by with the + :meth:`PyStemmerFilter.algorithms` method. The identification + strings are directly from the py-stemmer library. + :param ignore: a set/list of words that should not be stemmed. This is + converted into a frozenset. If you omit this argument, all tokens + are stemmed. + :param cachesize: the maximum number of words to cache. + """ + + self.lang = lang + self.ignore = frozenset() if ignore is None else frozenset(ignore) + self.cachesize = cachesize + self._stem = self._get_stemmer_fn() + + def algorithms(self): + """Returns a list of stemming algorithms provided by the py-stemmer + library. + """ + + import Stemmer # @UnresolvedImport + + return Stemmer.algorithms() + + def cache_info(self): + return None + + def _get_stemmer_fn(self): + import Stemmer # @UnresolvedImport + + stemmer = Stemmer.Stemmer(self.lang) + stemmer.maxCacheSize = self.cachesize + return stemmer.stemWord + + def __getstate__(self): + # Can't pickle a dynamic function, so we have to remove the _stem + # attribute from the state + return dict([(k, self.__dict__[k]) for k in self.__dict__ + if k != "_stem"]) + + def __setstate__(self, state): + # Check for old instances of StemFilter class, which didn't have a + # cachesize attribute and pickled the cache attribute + if "cachesize" not in state: + self.cachesize = 10000 + if "ignores" in state: + self.ignore = state["ignores"] + elif "ignore" not in state: + self.ignore = frozenset() + if "cache" in state: + del state["cache"] + + self.__dict__.update(state) + # Set the _stem attribute + self._stem = self._get_stemmer_fn() + + +class DoubleMetaphoneFilter(Filter): + """Transforms the text of the tokens using Lawrence Philips's Double + Metaphone algorithm. This algorithm attempts to encode words in such a way + that similar-sounding words reduce to the same code. This may be useful for + fields containing the names of people and places, and other uses where + tolerance of spelling differences is desireable. + """ + + is_morph = True + + def __init__(self, primary_boost=1.0, secondary_boost=0.5, combine=False): + """ + :param primary_boost: the boost to apply to the token containing the + primary code. + :param secondary_boost: the boost to apply to the token containing the + secondary code, if any. + :param combine: if True, the original unencoded tokens are kept in the + stream, preceding the encoded tokens. + """ + + self.primary_boost = primary_boost + self.secondary_boost = secondary_boost + self.combine = combine + + def __eq__(self, other): + return (other + and self.__class__ is other.__class__ + and self.primary_boost == other.primary_boost) + + def __call__(self, tokens): + primary_boost = self.primary_boost + secondary_boost = self.secondary_boost + combine = self.combine + + for t in tokens: + if combine: + yield t + + primary, secondary = double_metaphone(t.text) + b = t.boost + # Overwrite the token's text and boost and yield it + if primary: + t.text = primary + t.boost = b * primary_boost + yield t + if secondary: + t.text = secondary + t.boost = b * secondary_boost + yield t diff --git a/nstock/modules/whoosh/analysis/ngrams.py b/nstock/modules/whoosh/analysis/ngrams.py new file mode 100644 index 0000000..a57fcde --- /dev/null +++ b/nstock/modules/whoosh/analysis/ngrams.py @@ -0,0 +1,237 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from whoosh.compat import text_type +from whoosh.compat import xrange +from whoosh.analysis.acore import Token +from whoosh.analysis.filters import Filter, LowercaseFilter +from whoosh.analysis.tokenizers import Tokenizer, RegexTokenizer + + +# Tokenizer + +class NgramTokenizer(Tokenizer): + """Splits input text into N-grams instead of words. + + >>> ngt = NgramTokenizer(4) + >>> [token.text for token in ngt("hi there")] + ["hi t", "i th", " the", "ther", "here"] + + Note that this tokenizer does NOT use a regular expression to extract + words, so the grams emitted by it will contain whitespace, punctuation, + etc. You may want to massage the input or add a custom filter to this + tokenizer's output. + + Alternatively, if you only want sub-word grams without whitespace, you + could combine a RegexTokenizer with NgramFilter instead. + """ + + __inittypes__ = dict(minsize=int, maxsize=int) + + def __init__(self, minsize, maxsize=None): + """ + :param minsize: The minimum size of the N-grams. + :param maxsize: The maximum size of the N-grams. If you omit + this parameter, maxsize == minsize. + """ + + self.min = minsize + self.max = maxsize or minsize + + def __eq__(self, other): + if self.__class__ is other.__class__: + if self.min == other.min and self.max == other.max: + return True + return False + + def __call__(self, value, positions=False, chars=False, keeporiginal=False, + removestops=True, start_pos=0, start_char=0, mode='', + **kwargs): + assert isinstance(value, text_type), "%r is not unicode" % value + + inlen = len(value) + t = Token(positions, chars, removestops=removestops, mode=mode) + pos = start_pos + + if mode == "query": + size = min(self.max, inlen) + for start in xrange(0, inlen - size + 1): + end = start + size + if end > inlen: + continue + t.text = value[start:end] + if keeporiginal: + t.original = t.text + t.stopped = False + if positions: + t.pos = pos + if chars: + t.startchar = start_char + start + t.endchar = start_char + end + yield t + pos += 1 + else: + for start in xrange(0, inlen - self.min + 1): + for size in xrange(self.min, self.max + 1): + end = start + size + if end > inlen: + continue + t.text = value[start:end] + if keeporiginal: + t.original = t.text + t.stopped = False + if positions: + t.pos = pos + if chars: + t.startchar = start_char + start + t.endchar = start_char + end + + yield t + pos += 1 + + +# Filter + +class NgramFilter(Filter): + """Splits token text into N-grams. + + >>> rext = RegexTokenizer() + >>> stream = rext("hello there") + >>> ngf = NgramFilter(4) + >>> [token.text for token in ngf(stream)] + ["hell", "ello", "ther", "here"] + """ + + __inittypes__ = dict(minsize=int, maxsize=int) + + def __init__(self, minsize, maxsize=None, at=None): + """ + :param minsize: The minimum size of the N-grams. + :param maxsize: The maximum size of the N-grams. If you omit this + parameter, maxsize == minsize. + :param at: If 'start', only take N-grams from the start of each word. + if 'end', only take N-grams from the end of each word. Otherwise, + take all N-grams from the word (the default). + """ + + self.min = minsize + self.max = maxsize or minsize + self.at = 0 + if at == "start": + self.at = -1 + elif at == "end": + self.at = 1 + + def __eq__(self, other): + return other and self.__class__ is other.__class__\ + and self.min == other.min and self.max == other.max + + def __call__(self, tokens): + assert hasattr(tokens, "__iter__") + at = self.at + for t in tokens: + text = t.text + if len(text) < self.min: + continue + + chars = t.chars + if chars: + startchar = t.startchar + # Token positions don't mean much for N-grams, + # so we'll leave the token's original position + # untouched. + + if t.mode == "query": + size = min(self.max, len(t.text)) + if at == -1: + t.text = text[:size] + if chars: + t.endchar = startchar + size + yield t + elif at == 1: + t.text = text[0 - size:] + if chars: + t.startchar = t.endchar - size + yield t + else: + for start in xrange(0, len(text) - size + 1): + t.text = text[start:start + size] + if chars: + t.startchar = startchar + start + t.endchar = startchar + start + size + yield t + else: + if at == -1: + limit = min(self.max, len(text)) + for size in xrange(self.min, limit + 1): + t.text = text[:size] + if chars: + t.endchar = startchar + size + yield t + + elif at == 1: + if chars: + original_startchar = t.startchar + start = max(0, len(text) - self.max) + for i in xrange(start, len(text) - self.min + 1): + t.text = text[i:] + if chars: + t.startchar = original_startchar + i + yield t + else: + for start in xrange(0, len(text) - self.min + 1): + for size in xrange(self.min, self.max + 1): + end = start + size + if end > len(text): + continue + + t.text = text[start:end] + + if chars: + t.startchar = startchar + start + t.endchar = startchar + end + + yield t + + +# Analyzers + +def NgramAnalyzer(minsize, maxsize=None): + """Composes an NgramTokenizer and a LowercaseFilter. + + >>> ana = NgramAnalyzer(4) + >>> [token.text for token in ana("hi there")] + ["hi t", "i th", " the", "ther", "here"] + """ + + return NgramTokenizer(minsize, maxsize=maxsize) | LowercaseFilter() + + +def NgramWordAnalyzer(minsize, maxsize=None, tokenizer=None, at=None): + if not tokenizer: + tokenizer = RegexTokenizer() + return tokenizer | LowercaseFilter() | NgramFilter(minsize, maxsize, at=at) diff --git a/nstock/modules/whoosh/analysis/tokenizers.py b/nstock/modules/whoosh/analysis/tokenizers.py new file mode 100644 index 0000000..630ad46 --- /dev/null +++ b/nstock/modules/whoosh/analysis/tokenizers.py @@ -0,0 +1,338 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from whoosh.compat import u, text_type +from whoosh.analysis.acore import Composable, Token +from whoosh.util.text import rcompile + + +default_pattern = rcompile(r"\w+(\.?\w+)*") + + +# Tokenizers + + +class Tokenizer(Composable): + """Base class for Tokenizers. + """ + + def __eq__(self, other): + return other and self.__class__ is other.__class__ + + +class IDTokenizer(Tokenizer): + """Yields the entire input string as a single token. For use in indexed but + untokenized fields, such as a document's path. + + >>> idt = IDTokenizer() + >>> [token.text for token in idt("/a/b 123 alpha")] + ["/a/b 123 alpha"] + """ + + def __call__(self, value, positions=False, chars=False, + keeporiginal=False, removestops=True, + start_pos=0, start_char=0, mode='', **kwargs): + assert isinstance(value, text_type), "%r is not unicode" % value + t = Token(positions, chars, removestops=removestops, mode=mode, + **kwargs) + t.text = value + t.boost = 1.0 + if keeporiginal: + t.original = value + if positions: + t.pos = start_pos + 1 + if chars: + t.startchar = start_char + t.endchar = start_char + len(value) + yield t + + +class RegexTokenizer(Tokenizer): + """ + Uses a regular expression to extract tokens from text. + + >>> rex = RegexTokenizer() + >>> [token.text for token in rex(u("hi there 3.141 big-time under_score"))] + ["hi", "there", "3.141", "big", "time", "under_score"] + """ + + def __init__(self, expression=default_pattern, gaps=False): + """ + :param expression: A regular expression object or string. Each match + of the expression equals a token. Group 0 (the entire matched text) + is used as the text of the token. If you require more complicated + handling of the expression match, simply write your own tokenizer. + :param gaps: If True, the tokenizer *splits* on the expression, rather + than matching on the expression. + """ + + self.expression = rcompile(expression) + self.gaps = gaps + + def __eq__(self, other): + if self.__class__ is other.__class__: + if self.expression.pattern == other.expression.pattern: + return True + return False + + def __call__(self, value, positions=False, chars=False, keeporiginal=False, + removestops=True, start_pos=0, start_char=0, tokenize=True, + mode='', **kwargs): + """ + :param value: The unicode string to tokenize. + :param positions: Whether to record token positions in the token. + :param chars: Whether to record character offsets in the token. + :param start_pos: The position number of the first token. For example, + if you set start_pos=2, the tokens will be numbered 2,3,4,... + instead of 0,1,2,... + :param start_char: The offset of the first character of the first + token. For example, if you set start_char=2, the text "aaa bbb" + will have chars (2,5),(6,9) instead (0,3),(4,7). + :param tokenize: if True, the text should be tokenized. + """ + + assert isinstance(value, text_type), "%s is not unicode" % repr(value) + + t = Token(positions, chars, removestops=removestops, mode=mode, + **kwargs) + if not tokenize: + t.original = t.text = value + t.boost = 1.0 + if positions: + t.pos = start_pos + if chars: + t.startchar = start_char + t.endchar = start_char + len(value) + yield t + elif not self.gaps: + # The default: expression matches are used as tokens + for pos, match in enumerate(self.expression.finditer(value)): + t.text = match.group(0) + t.boost = 1.0 + if keeporiginal: + t.original = t.text + t.stopped = False + if positions: + t.pos = start_pos + pos + if chars: + t.startchar = start_char + match.start() + t.endchar = start_char + match.end() + yield t + else: + # When gaps=True, iterate through the matches and + # yield the text between them. + prevend = 0 + pos = start_pos + for match in self.expression.finditer(value): + start = prevend + end = match.start() + text = value[start:end] + if text: + t.text = text + t.boost = 1.0 + if keeporiginal: + t.original = t.text + t.stopped = False + if positions: + t.pos = pos + pos += 1 + if chars: + t.startchar = start_char + start + t.endchar = start_char + end + + yield t + + prevend = match.end() + + # If the last "gap" was before the end of the text, + # yield the last bit of text as a final token. + if prevend < len(value): + t.text = value[prevend:] + t.boost = 1.0 + if keeporiginal: + t.original = t.text + t.stopped = False + if positions: + t.pos = pos + if chars: + t.startchar = prevend + t.endchar = len(value) + yield t + + +class CharsetTokenizer(Tokenizer): + """Tokenizes and translates text according to a character mapping object. + Characters that map to None are considered token break characters. For all + other characters the map is used to translate the character. This is useful + for case and accent folding. + + This tokenizer loops character-by-character and so will likely be much + slower than :class:`RegexTokenizer`. + + One way to get a character mapping object is to convert a Sphinx charset + table file using :func:`whoosh.support.charset.charset_table_to_dict`. + + >>> from whoosh.support.charset import charset_table_to_dict + >>> from whoosh.support.charset import default_charset + >>> charmap = charset_table_to_dict(default_charset) + >>> chtokenizer = CharsetTokenizer(charmap) + >>> [t.text for t in chtokenizer(u'Stra\\xdfe ABC')] + [u'strase', u'abc'] + + The Sphinx charset table format is described at + http://www.sphinxsearch.com/docs/current.html#conf-charset-table. + """ + + __inittype__ = dict(charmap=str) + + def __init__(self, charmap): + """ + :param charmap: a mapping from integer character numbers to unicode + characters, as used by the unicode.translate() method. + """ + self.charmap = charmap + + def __eq__(self, other): + return (other + and self.__class__ is other.__class__ + and self.charmap == other.charmap) + + def __call__(self, value, positions=False, chars=False, keeporiginal=False, + removestops=True, start_pos=0, start_char=0, tokenize=True, + mode='', **kwargs): + """ + :param value: The unicode string to tokenize. + :param positions: Whether to record token positions in the token. + :param chars: Whether to record character offsets in the token. + :param start_pos: The position number of the first token. For example, + if you set start_pos=2, the tokens will be numbered 2,3,4,... + instead of 0,1,2,... + :param start_char: The offset of the first character of the first + token. For example, if you set start_char=2, the text "aaa bbb" + will have chars (2,5),(6,9) instead (0,3),(4,7). + :param tokenize: if True, the text should be tokenized. + """ + + assert isinstance(value, text_type), "%r is not unicode" % value + + t = Token(positions, chars, removestops=removestops, mode=mode, + **kwargs) + if not tokenize: + t.original = t.text = value + t.boost = 1.0 + if positions: + t.pos = start_pos + if chars: + t.startchar = start_char + t.endchar = start_char + len(value) + yield t + else: + text = u("") + charmap = self.charmap + pos = start_pos + startchar = currentchar = start_char + for char in value: + tchar = charmap[ord(char)] + if tchar: + text += tchar + else: + if currentchar > startchar: + t.text = text + t.boost = 1.0 + if keeporiginal: + t.original = t.text + if positions: + t.pos = pos + pos += 1 + if chars: + t.startchar = startchar + t.endchar = currentchar + yield t + startchar = currentchar + 1 + text = u("") + + currentchar += 1 + + if currentchar > startchar: + t.text = value[startchar:currentchar] + t.boost = 1.0 + if keeporiginal: + t.original = t.text + if positions: + t.pos = pos + if chars: + t.startchar = startchar + t.endchar = currentchar + yield t + + +def SpaceSeparatedTokenizer(): + """Returns a RegexTokenizer that splits tokens by whitespace. + + >>> sst = SpaceSeparatedTokenizer() + >>> [token.text for token in sst("hi there big-time, what's up")] + ["hi", "there", "big-time,", "what's", "up"] + """ + + return RegexTokenizer(r"[^ \t\r\n]+") + + +def CommaSeparatedTokenizer(): + """Splits tokens by commas. + + Note that the tokenizer calls unicode.strip() on each match of the regular + expression. + + >>> cst = CommaSeparatedTokenizer() + >>> [token.text for token in cst("hi there, what's , up")] + ["hi there", "what's", "up"] + """ + + from whoosh.analysis.filters import StripFilter + + return RegexTokenizer(r"[^,]+") | StripFilter() + + +class PathTokenizer(Tokenizer): + """A simple tokenizer that given a string ``"/a/b/c"`` yields tokens + ``["/a", "/a/b", "/a/b/c"]``. + """ + + def __init__(self, expression="[^/]+"): + self.expr = rcompile(expression) + + def __call__(self, value, positions=False, start_pos=0, **kwargs): + assert isinstance(value, text_type), "%r is not unicode" % value + token = Token(positions, **kwargs) + pos = start_pos + for match in self.expr.finditer(value): + token.text = value[:match.end()] + if positions: + token.pos = pos + pos += 1 + yield token + diff --git a/nstock/modules/whoosh/automata/__init__.py b/nstock/modules/whoosh/automata/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/nstock/modules/whoosh/automata/fsa.py b/nstock/modules/whoosh/automata/fsa.py new file mode 100644 index 0000000..280ddb5 --- /dev/null +++ b/nstock/modules/whoosh/automata/fsa.py @@ -0,0 +1,715 @@ +from __future__ import print_function + +import itertools +import operator +import sys +from bisect import bisect_left +from collections import defaultdict + +from whoosh.compat import iteritems, next, text_type, unichr, xrange + + +unull = unichr(0) + + +# Marker constants + +class Marker(object): + def __init__(self, name): + self.name = name + + def __repr__(self): + return "<%s>" % self.name + + +EPSILON = Marker("EPSILON") +ANY = Marker("ANY") + + +# Base class + +class FSA(object): + def __init__(self, initial): + self.initial = initial + self.transitions = {} + self.final_states = set() + + def __len__(self): + return len(self.all_states()) + + def __eq__(self, other): + if self.initial != other.initial: + return False + if self.final_states != other.final_states: + return False + st = self.transitions + ot = other.transitions + if list(st) != list(ot): + return False + for key in st: + if st[key] != ot[key]: + return False + return True + + def all_states(self): + stateset = set(self.transitions) + for src, trans in iteritems(self.transitions): + stateset.update(trans.values()) + return stateset + + def all_labels(self): + labels = set() + for src, trans in iteritems(self.transitions): + labels.update(trans) + return labels + + def get_labels(self, src): + return iter(self.transitions.get(src, [])) + + def generate_all(self, state=None, sofar=""): + state = self.start() if state is None else state + if self.is_final(state): + yield sofar + for label in sorted(self.get_labels(state)): + newstate = self.next_state(state, label) + for string in self.generate_all(newstate, sofar + label): + yield string + + def start(self): + return self.initial + + def next_state(self, state, label): + raise NotImplementedError + + def is_final(self, state): + raise NotImplementedError + + def add_transition(self, src, label, dest): + raise NotImplementedError + + def add_final_state(self, state): + raise NotImplementedError + + def to_dfa(self): + raise NotImplementedError + + def accept(self, string, debug=False): + state = self.start() + + for label in string: + if debug: + print(" ", state, "->", label, "->") + + state = self.next_state(state, label) + if not state: + break + + return self.is_final(state) + + def append(self, fsa): + self.transitions.update(fsa.transitions) + for state in self.final_states: + self.add_transition(state, EPSILON, fsa.initial) + self.final_states = fsa.final_states + + +# Implementations + +class NFA(FSA): + def __init__(self, initial): + self.transitions = {} + self.final_states = set() + self.initial = initial + + def dump(self, stream=sys.stdout): + starts = self.start() + for src in self.transitions: + beg = "@" if src in starts else " " + print(beg, src, file=stream) + xs = self.transitions[src] + for label in xs: + dests = xs[label] + end = "||" if self.is_final(dests) else "" + + def start(self): + return frozenset(self._expand(set([self.initial]))) + + def add_transition(self, src, label, dest): + self.transitions.setdefault(src, {}).setdefault(label, set()).add(dest) + + def add_final_state(self, state): + self.final_states.add(state) + + def triples(self): + for src, trans in iteritems(self.transitions): + for label, dests in iteritems(trans): + for dest in dests: + yield src, label, dest + + def is_final(self, states): + return bool(self.final_states.intersection(states)) + + def _expand(self, states): + transitions = self.transitions + frontier = set(states) + while frontier: + state = frontier.pop() + if state in transitions and EPSILON in transitions[state]: + new_states = transitions[state][EPSILON].difference(states) + frontier.update(new_states) + states.update(new_states) + return states + + def next_state(self, states, label): + transitions = self.transitions + dest_states = set() + for state in states: + if state in transitions: + xs = transitions[state] + if label in xs: + dest_states.update(xs[label]) + if ANY in xs: + dest_states.update(xs[ANY]) + return frozenset(self._expand(dest_states)) + + def get_labels(self, states): + transitions = self.transitions + labels = set() + for state in states: + if state in transitions: + labels.update(transitions[state]) + return labels + + def embed(self, other): + # Copy all transitions from the other NFA into this one + for s, othertrans in iteritems(other.transitions): + trans = self.transitions.setdefault(s, {}) + for label, otherdests in iteritems(othertrans): + dests = trans.setdefault(label, set()) + dests.update(otherdests) + + def insert(self, src, other, dest): + self.embed(other) + + # Connect src to the other NFA's initial state, and the other + # NFA's final states to dest + self.add_transition(src, EPSILON, other.initial) + for finalstate in other.final_states: + self.add_transition(finalstate, EPSILON, dest) + + def to_dfa(self): + dfa = DFA(self.start()) + frontier = [self.start()] + seen = set() + while frontier: + current = frontier.pop() + if self.is_final(current): + dfa.add_final_state(current) + labels = self.get_labels(current) + for label in labels: + if label is EPSILON: + continue + new_state = self.next_state(current, label) + if new_state not in seen: + frontier.append(new_state) + seen.add(new_state) + if self.is_final(new_state): + dfa.add_final_state(new_state) + if label is ANY: + dfa.set_default_transition(current, new_state) + else: + dfa.add_transition(current, label, new_state) + return dfa + + +class DFA(FSA): + def __init__(self, initial): + self.initial = initial + self.transitions = {} + self.defaults = {} + self.final_states = set() + self.outlabels = {} + + def dump(self, stream=sys.stdout): + for src in sorted(self.transitions): + beg = "@" if src == self.initial else " " + print(beg, src, file=stream) + xs = self.transitions[src] + for label in sorted(xs): + dest = xs[label] + end = "||" if self.is_final(dest) else "" + + def start(self): + return self.initial + + def add_transition(self, src, label, dest): + self.transitions.setdefault(src, {})[label] = dest + + def set_default_transition(self, src, dest): + self.defaults[src] = dest + + def add_final_state(self, state): + self.final_states.add(state) + + def is_final(self, state): + return state in self.final_states + + def next_state(self, src, label): + trans = self.transitions.get(src, {}) + return trans.get(label, self.defaults.get(src, None)) + + def next_valid_string(self, string, asbytes=False): + state = self.start() + stack = [] + + # Follow the DFA as far as possible + i = 0 + for i, label in enumerate(string): + stack.append((string[:i], state, label)) + state = self.next_state(state, label) + if not state: + break + else: + stack.append((string[:i + 1], state, None)) + + if self.is_final(state): + # Word is already valid + return string + + # Perform a 'wall following' search for the lexicographically smallest + # accepting state. + while stack: + path, state, label = stack.pop() + label = self.find_next_edge(state, label, asbytes=asbytes) + if label: + path += label + state = self.next_state(state, label) + if self.is_final(state): + return path + stack.append((path, state, None)) + return None + + def find_next_edge(self, s, label, asbytes): + if label is None: + label = b"\x00" if asbytes else u'\0' + else: + label = (label + 1) if asbytes else unichr(ord(label) + 1) + trans = self.transitions.get(s, {}) + if label in trans or s in self.defaults: + return label + + try: + labels = self.outlabels[s] + except KeyError: + self.outlabels[s] = labels = sorted(trans) + + pos = bisect_left(labels, label) + if pos < len(labels): + return labels[pos] + return None + + def reachable_from(self, src, inclusive=True): + transitions = self.transitions + + reached = set() + if inclusive: + reached.add(src) + + stack = [src] + seen = set() + while stack: + src = stack.pop() + seen.add(src) + for _, dest in iteritems(transitions[src]): + reached.add(dest) + if dest not in seen: + stack.append(dest) + return reached + + def minimize(self): + transitions = self.transitions + initial = self.initial + + # Step 1: Delete unreachable states + reachable = self.reachable_from(initial) + for src in list(transitions): + if src not in reachable: + del transitions[src] + final_states = self.final_states.intersection(reachable) + labels = self.all_labels() + + # Step 2: Partition the states into equivalence sets + changed = True + parts = [final_states, reachable - final_states] + while changed: + changed = False + for i in xrange(len(parts)): + part = parts[i] + changed_part = False + for label in labels: + next_part = None + new_part = set() + for state in part: + dest = transitions[state].get(label) + if dest is not None: + if next_part is None: + for p in parts: + if dest in p: + next_part = p + elif dest not in next_part: + new_part.add(state) + changed = True + changed_part = True + if changed_part: + old_part = part - new_part + parts.pop(i) + parts.append(old_part) + parts.append(new_part) + break + + # Choose one state from each equivalence set and map all equivalent + # states to it + new_trans = {} + + # Create mapping + mapping = {} + new_initial = None + for part in parts: + representative = part.pop() + if representative is initial: + new_initial = representative + mapping[representative] = representative + new_trans[representative] = {} + for state in part: + if state is initial: + new_initial = representative + mapping[state] = representative + assert new_initial is not None + + # Apply mapping to existing transitions + new_finals = set(mapping[s] for s in final_states) + for state, d in iteritems(new_trans): + trans = transitions[state] + for label, dest in iteritems(trans): + d[label] = mapping[dest] + + # Remove dead states - non-final states with no outgoing arcs except + # to themselves + non_final_srcs = [src for src in new_trans if src not in new_finals] + removing = set() + for src in non_final_srcs: + dests = set(new_trans[src].values()) + dests.discard(src) + if not dests: + removing.add(src) + del new_trans[src] + # Delete transitions to removed dead states + for t in new_trans.values(): + for label in list(t): + if t[label] in removing: + del t[label] + + self.transitions = new_trans + self.initial = new_initial + self.final_states = new_finals + + def to_dfa(self): + return self + + +# Useful functions + +def renumber_dfa(dfa, base=0): + c = itertools.count(base) + mapping = {} + + def remap(state): + if state in mapping: + newnum = mapping[state] + else: + newnum = next(c) + mapping[state] = newnum + return newnum + + newdfa = DFA(remap(dfa.initial)) + for src, trans in iteritems(dfa.transitions): + for label, dest in iteritems(trans): + newdfa.add_transition(remap(src), label, remap(dest)) + for finalstate in dfa.final_states: + newdfa.add_final_state(remap(finalstate)) + for src, dest in iteritems(dfa.defaults): + newdfa.set_default_transition(remap(src), remap(dest)) + return newdfa + + +def u_to_utf8(dfa, base=0): + c = itertools.count(base) + transitions = dfa.transitions + + for src, trans in iteritems(transitions): + trans = transitions[src] + for label, dest in list(iteritems(trans)): + if label is EPSILON: + continue + elif label is ANY: + raise Exception + else: + assert isinstance(label, text_type) + label8 = label.encode("utf8") + for i, byte in enumerate(label8): + if i < len(label8) - 1: + st = next(c) + dfa.add_transition(src, byte, st) + src = st + else: + dfa.add_transition(src, byte, dest) + del trans[label] + + +def find_all_matches(dfa, lookup_func, first=unull): + """ + Uses lookup_func to find all words within levenshtein distance k of word. + + Args: + word: The word to look up + k: Maximum edit distance + lookup_func: A single argument function that returns the first word in the + database that is greater than or equal to the input argument. + Yields: + Every matching word within levenshtein distance k from the database. + """ + + match = dfa.next_valid_string(first) + while match: + key = lookup_func(match) + if key is None: + return + if match == key: + yield match + key += unull + match = dfa.next_valid_string(key) + + +# Construction functions + +def reverse_nfa(n): + s = object() + nfa = NFA(s) + for src, trans in iteritems(n.transitions): + for label, destset in iteritems(trans): + for dest in destset: + nfa.add_transition(dest, label, src) + for finalstate in n.final_states: + nfa.add_transition(s, EPSILON, finalstate) + nfa.add_final_state(n.initial) + return nfa + + +def product(dfa1, op, dfa2): + dfa1 = dfa1.to_dfa() + dfa2 = dfa2.to_dfa() + start = (dfa1.start(), dfa2.start()) + dfa = DFA(start) + stack = [start] + while stack: + src = stack.pop() + state1, state2 = src + trans1 = set(dfa1.transitions[state1]) + trans2 = set(dfa2.transitions[state2]) + for label in trans1.intersection(trans2): + state1 = dfa1.next_state(state1, label) + state2 = dfa2.next_state(state2, label) + if op(state1 is not None, state2 is not None): + dest = (state1, state2) + dfa.add_transition(src, label, dest) + stack.append(dest) + if op(dfa1.is_final(state1), dfa2.is_final(state2)): + dfa.add_final_state(dest) + return dfa + + +def intersection(dfa1, dfa2): + return product(dfa1, operator.and_, dfa2) + + +def union(dfa1, dfa2): + return product(dfa1, operator.or_, dfa2) + + +def epsilon_nfa(): + return basic_nfa(EPSILON) + + +def dot_nfa(): + return basic_nfa(ANY) + + +def basic_nfa(label): + s = object() + e = object() + nfa = NFA(s) + nfa.add_transition(s, label, e) + nfa.add_final_state(e) + return nfa + + +def charset_nfa(labels): + s = object() + e = object() + nfa = NFA(s) + for label in labels: + nfa.add_transition(s, label, e) + nfa.add_final_state(e) + return nfa + + +def string_nfa(string): + s = object() + e = object() + nfa = NFA(s) + for label in string: + e = object() + nfa.add_transition(s, label, e) + s = e + nfa.add_final_state(e) + return nfa + + +def choice_nfa(n1, n2): + s = object() + e = object() + nfa = NFA(s) + # -> nfa1 - + # / \ + # s e + # \ / + # -> nfa2 - + nfa.insert(s, n1, e) + nfa.insert(s, n2, e) + nfa.add_final_state(e) + return nfa + + +def concat_nfa(n1, n2): + s = object() + m = object() + e = object() + nfa = NFA(s) + nfa.insert(s, n1, m) + nfa.insert(m, n2, e) + nfa.add_final_state(e) + return nfa + + +def star_nfa(n): + s = object() + e = object() + nfa = NFA(s) + # -----<----- + # / \ + # s ---> n ---> e + # \ / + # ----->----- + + nfa.insert(s, n, e) + nfa.add_transition(s, EPSILON, e) + for finalstate in n.final_states: + nfa.add_transition(finalstate, EPSILON, s) + nfa.add_final_state(e) + return nfa + + +def plus_nfa(n): + return concat_nfa(n, star_nfa(n)) + + +def optional_nfa(n): + return choice_nfa(n, epsilon_nfa()) + + +# Daciuk Mihov DFA construction algorithm + +class DMNode(object): + def __init__(self, n): + self.n = n + self.arcs = {} + self.final = False + + def __repr__(self): + return "<%s, %r>" % (self.n, self.tuple()) + + def __hash__(self): + return hash(self.tuple()) + + def tuple(self): + arcs = tuple(sorted(iteritems(self.arcs))) + return arcs, self.final + + +def strings_dfa(strings): + dfa = DFA(0) + c = itertools.count(1) + + last = "" + seen = {} + nodes = [DMNode(0)] + + for string in strings: + if string <= last: + raise Exception("Strings must be in order") + if not string: + raise Exception("Can't add empty string") + + # Find the common prefix with the previous string + i = 0 + while i < len(last) and i < len(string) and last[i] == string[i]: + i += 1 + prefixlen = i + + # Freeze the transitions after the prefix, since they're not shared + add_suffix(dfa, nodes, last, prefixlen + 1, seen) + + # Create new nodes for the substring after the prefix + for label in string[prefixlen:]: + node = DMNode(next(c)) + # Create an arc from the previous node to this node + nodes[-1].arcs[label] = node.n + nodes.append(node) + # Mark the last node as an accept state + nodes[-1].final = True + + last = string + + if len(nodes) > 1: + add_suffix(dfa, nodes, last, 0, seen) + return dfa + + +def add_suffix(dfa, nodes, last, downto, seen): + while len(nodes) > downto: + node = nodes.pop() + tup = node.tuple() + + # If a node just like this one (final/nonfinal, same arcs to same + # destinations) is already seen, replace with it + try: + this = seen[tup] + except KeyError: + this = node.n + if node.final: + dfa.add_final_state(this) + seen[tup] = this + else: + # If we replaced the node with an already seen one, fix the parent + # node's pointer to this + parent = nodes[-1] + inlabel = last[len(nodes) - 1] + parent.arcs[inlabel] = this + + # Add the node's transitions to the DFA + for label, dest in iteritems(node.arcs): + dfa.add_transition(this, label, dest) + + + + diff --git a/nstock/modules/whoosh/automata/glob.py b/nstock/modules/whoosh/automata/glob.py new file mode 100644 index 0000000..b8fbc87 --- /dev/null +++ b/nstock/modules/whoosh/automata/glob.py @@ -0,0 +1,90 @@ +# Copyright 2012 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from whoosh.automata.fsa import ANY, EPSILON, NFA + + +# Constants for glob +_LIT = 0 +_STAR = 1 +_PLUS = 2 +_QUEST = 3 +_RANGE = 4 + + +def parse_glob(pattern, _glob_multi="*", _glob_single="?", + _glob_range1="[", _glob_range2="]"): + pos = 0 + last = None + while pos < len(pattern): + char = pattern[pos] + pos += 1 + if char == _glob_multi: # * + # (Ignore more than one star in a row) + if last is not _STAR: + yield _STAR, None + last = _STAR + elif char == _glob_single: # ? + # (Ignore ? after a star) + if last is not _STAR: + yield _QUEST, None + last = _QUEST + elif char == _glob_range1: # [ + chars = set() + negate = False + # Take the char range specification until the ] + while pos < len(pattern): + char = pattern[pos] + pos += 1 + if char == _glob_range2: + break + chars.add(char) + if chars: + yield _RANGE, (chars, negate) + last = _RANGE + else: + yield _LIT, char + last = _LIT + + +def glob_automaton(pattern): + nfa = NFA(0) + i = -1 + for i, (op, arg) in enumerate(parse_glob(pattern)): + if op is _LIT: + nfa.add_transition(i, arg, i + 1) + elif op is _STAR: + nfa.add_transition(i, ANY, i + 1) + nfa.add_transition(i, EPSILON, i + 1) + nfa.add_transition(i + 1, EPSILON, i) + elif op is _QUEST: + nfa.add_transition(i, ANY, i + 1) + elif op is _RANGE: + for char in arg[0]: + nfa.add_transition(i, char, i + 1) + nfa.add_final_state(i + 1) + return nfa diff --git a/nstock/modules/whoosh/automata/lev.py b/nstock/modules/whoosh/automata/lev.py new file mode 100644 index 0000000..7067c64 --- /dev/null +++ b/nstock/modules/whoosh/automata/lev.py @@ -0,0 +1,30 @@ +from __future__ import print_function + +from whoosh.compat import unichr, xrange +from whoosh.automata.fsa import ANY, EPSILON, NFA, unull + + +def levenshtein_automaton(term, k, prefix=0): + nfa = NFA((0, 0)) + if prefix: + for i in xrange(prefix): + c = term[i] + nfa.add_transition((i, 0), c, (i + 1, 0)) + + for i in xrange(prefix, len(term)): + c = term[i] + for e in xrange(k + 1): + # Correct character + nfa.add_transition((i, e), c, (i + 1, e)) + if e < k: + # Deletion + nfa.add_transition((i, e), ANY, (i, e + 1)) + # Insertion + nfa.add_transition((i, e), EPSILON, (i + 1, e + 1)) + # Substitution + nfa.add_transition((i, e), ANY, (i + 1, e + 1)) + for e in xrange(k + 1): + if e < k: + nfa.add_transition((len(term), e), ANY, (len(term), e + 1)) + nfa.add_final_state((len(term), e)) + return nfa diff --git a/nstock/modules/whoosh/automata/nfa.py b/nstock/modules/whoosh/automata/nfa.py new file mode 100644 index 0000000..6ea72be --- /dev/null +++ b/nstock/modules/whoosh/automata/nfa.py @@ -0,0 +1,388 @@ +# Copyright 2012 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from whoosh.automata.fst import Arc + + +class Instruction(object): + def __repr__(self): + return "%s()" % (self.__class__.__name__, ) + + +class Char(Instruction): + """ + Matches a literal character. + """ + + def __init__(self, c): + self.c = c + + def __repr__(self): + return "Char(%r)" % self.c + +class Lit(Instruction): + """ + Matches a literal string. + """ + + def __init__(self, c): + self.c = c + + def __repr__(self): + return "Lit(%r)" % self.c + + +class Any(Instruction): + """ + Matches any character. + """ + + +class Match(Instruction): + """ + Stop this thread: the string matched. + """ + + def __repr__(self): + return "Match()" + + +class Jmp(Instruction): + """ + Jump to a specified instruction. + """ + + def __init__(self, x): + self.x = x + + def __repr__(self): + return "Jmp(%s)" % self.x + + +class Split(Instruction): + """ + Split execution: continue at two separate specified instructions. + """ + + def __init__(self, x, y): + self.x = x + self.y = y + + def __repr__(self): + return "Split(%s, %s)" % (self.x, self.y) + + +class Label(Instruction): + """ + Placeholder to act as a target for JMP instructions + """ + + def __hash__(self): + return id(self) + + def __repr__(self): + return "L(%s)" % hex(id(self)) + + +def concat(e1, e2): + return e1 + e2 + + +def alt(e1, e2): + L1, L2, L3 = Label(), Label(), Label() + return [L1] + e1 + [Jmp(L3), L2] + e2 + [L3] + + +def zero_or_one(e): + L1, L2 = Label(), Label() + return [Split(L1, L2), L1] + e + [L2] + + +def zero_or_more(e): + L1, L2, L3 = Label(), Label(), Label() + return [L1, Split(L2, L3), L2] + e + [Jmp(L1), L3] + + +def one_or_more(e): + L1, L2 = Label(), Label() + return [L1] + e + [Split(L1, L2), L2] + + +def fixup(program): + refs = {} + i = 0 + while i < len(program): + op = program[i] + if isinstance(op, Label): + refs[op] = i + program.pop(i) + else: + i += 1 + + if refs: + for op in program: + if isinstance(op, (Jmp, Split)): + op.x = refs[op.x] + if isinstance(op, Split): + op.y = refs[op.y] + + return program + [Match] + + +class ThreadList(object): + def __init__(self, program, max=1000): + self.program = program + self.max = max + self.threads = [] + + def __nonzero__(self): + return bool(self.threads) + + def current(self): + return self.threads.pop() + + def add(self, thread): + op = self.program[thread.pc] + optype = type(op) + if optype is Jmp: + self.add(thread.at(op.x)) + elif optype is Split: + self.add(thread.copy_at(op.x)) + self.add(thread.at(op.y)) + else: + self.threads.append(thread) + + +class Thread(object): + def __init__(self, pc, address, sofar='', accept=False): + self.pc = pc + self.address = address + self.sofar = sofar + self.accept = accept + + def at(self, pc): + self.pc = pc + return self + + def copy_at(self, pc): + return Thread(pc, self.address, self.sofar, self.accept) + + def __repr__(self): + d = self.__dict__ + return "Thread(%s)" % ",".join("%s=%r" % (k, v) for k, v in d.items()) + + +def advance(thread, arc, c): + thread.pc += 1 + thread.address = arc.target + thread.sofar += c + thread.accept = arc.accept + + +def run(graph, program, address): + threads = ThreadList(program) + threads.add(Thread(0, address)) + arc = Arc() + while threads: + thread = threads.current() + address = thread.address + op = program[thread.pc] + optype = type(op) + + if optype is Char: + if address: + arc = graph.find_arc(address, op.c, arc) + if arc: + advance(thread, arc) + threads.add(thread) + elif optype is Lit: + if address: + c = op.c + arc = graph.find_path(c, arc, address) + if arc: + advance(thread, arc, c) + threads.add(thread) + elif optype is Any: + if address: + sofar = thread.sofar + pc = thread.pc + 1 + for arc in graph.iter_arcs(address, arc): + t = Thread(pc, arc.target, sofar + arc.label, arc.accept) + threads.add(t) + elif op is Match: + if thread.accept: + yield thread.sofar + else: + raise Exception("Don't know what to do with %r" % op) + + +LO = 0 +HI = 1 + + +def regex_limit(graph, mode, program, address): + low = mode == LO + output = [] + threads = ThreadList(program) + threads.add(Thread(0, address)) + arc = Arc() + while threads: + thread = threads.current() + address = thread.address + op = program[thread.pc] + optype = type(op) + + if optype is Char: + if address: + arc = graph.find_arc(address, op.c, arc) + if arc: + if low and arc.accept: + return thread.sofar + thread.label + advance(thread, arc) + threads.add(thread) + elif optype is Lit: + if address: + labels = op.c + for label in labels: + arc = graph.find_arc(address, label) + if arc is None: + return thread.sofar + elif thread.accept: + return thread.sofar + elif optype is Any: + if address: + if low: + arc = graph.arc_at(address, arc) + else: + for arc in graph.iter_arcs(address): + pass + advance(thread, arc, arc.label) + threads.add(thread) + elif thread.accept: + return thread.sofar + elif op is Match: + return thread.sofar + else: + raise Exception("Don't know what to do with %r" % op) + + +# if __name__ == "__main__": +# from whoosh import index, query +# from whoosh.filedb.filestore import RamStorage +# from whoosh.automata import fst +# from whoosh.util.testing import timing +# +# st = RamStorage() +# gw = fst.GraphWriter(st.create_file("test")) +# gw.start_field("test") +# for key in ["aaaa", "aaab", "aabb", "abbb", "babb", "bbab", "bbba"]: +# gw.insert(key) +# gw.close() +# gr = fst.GraphReader(st.open_file("test")) +# +# program = one_or_more([Lit("a")]) +# print program +# program = fixup(program) +# print program +# print list(run(gr, program, gr.root("test"))) +# +# ix = index.open_dir("e:/dev/src/houdini/help/index") +# r = ix.reader() +# gr = r._get_graph() +# +# # program = fixup([Any(), Any(), Any(), Any(), Any()]) +# # program = fixup(concat(zero_or_more([Any()]), [Char("/")])) +# # with timing(): +# # x = list(run(gr, program, gr.root("path"))) +# # print len(x) +# +# q = query.Regex("path", "^.[abc].*/$") +# with timing(): +# y = list(q._btexts(r)) +# print len(y) +# print y[0], y[-1] +# +# pr = [Any()] + alt([Lit("c")], alt([Lit("b")], [Lit("a")])) + zero_or_more([Any()]) + [Lit("/")] +# program = fixup(pr) +# # with timing(): +# # x = list(run(gr, program, gr.root("path"))) +# # print len(x), x +# +# with timing(): +# print "lo=", regex_limit(gr, LO, program, gr.root("path")) +# print "hi=", regex_limit(gr, HI, program, gr.root("path")) +# +# +# +# #int +# #backtrackingvm(Inst *prog, char *input) +# #{ +# # enum { MAXTHREAD = 1000 }; +# # Thread ready[MAXTHREAD]; +# # int nready; +# # Inst *pc; +# # char *sp; +# # +# # /* queue initial thread */ +# # ready[0] = thread(prog, input); +# # nready = 1; +# # +# # /* run threads in stack order */ +# # while(nready > 0){ +# # --nready; /* pop state for next thread to run */ +# # pc = ready[nready].pc; +# # sp = ready[nready].sp; +# # for(;;){ +# # switch(pc->opcode){ +# # case Char: +# # if(*sp != pc->c) +# # goto Dead; +# # pc++; +# # sp++; +# # continue; +# # case Match: +# # return 1; +# # case Jmp: +# # pc = pc->x; +# # continue; +# # case Split: +# # if(nready >= MAXTHREAD){ +# # fprintf(stderr, "regexp overflow"); +# # return -1; +# # } +# # /* queue new thread */ +# # ready[nready++] = thread(pc->y, sp); +# # pc = pc->x; /* continue current thread */ +# # continue; +# # } +# # } +# # Dead:; +# # } +# # return 0; +# #} +# +# diff --git a/nstock/modules/whoosh/automata/reg.py b/nstock/modules/whoosh/automata/reg.py new file mode 100644 index 0000000..578071e --- /dev/null +++ b/nstock/modules/whoosh/automata/reg.py @@ -0,0 +1,135 @@ +# Copyright 2014 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +import re +from whoosh.automata.fsa import ANY, EPSILON, NFA + + +# Operator precedence +CHOICE = ("|", ) +ops = () + + +def parse(pattern): + stack = [] + ops = [] + + + + +class RegexBuilder(object): + def __init__(self): + self.statenum = 1 + + def new_state(self): + self.statenum += 1 + return self.statenum + + def epsilon(self): + s = self.new_state() + e = self.new_state() + nfa = NFA(s) + nfa.add_transition(s, EPSILON, e) + nfa.add_final_state(e) + return nfa + + def char(self, label): + s = self.new_state() + e = self.new_state() + nfa = NFA(s) + nfa.add_transition(s, label, e) + nfa.add_final_state(e) + return nfa + + def charset(self, chars): + s = self.new_state() + e = self.new_state() + nfa = NFA(s) + for char in chars: + nfa.add_transition(s, char, e) + nfa.add_final_state(e) + return e + + def dot(self): + s = self.new_state() + e = self.new_state() + nfa = NFA(s) + nfa.add_transition(s, ANY, e) + nfa.add_final_state(e) + return nfa + + def choice(self, n1, n2): + s = self.new_state() + s1 = self.new_state() + s2 = self.new_state() + e1 = self.new_state() + e2 = self.new_state() + e = self.new_state() + nfa = NFA(s) + nfa.add_transition(s, EPSILON, s1) + nfa.add_transition(s, EPSILON, s2) + nfa.insert(s1, n1, e1) + nfa.insert(s2, n2, e2) + nfa.add_transition(e1, EPSILON, e) + nfa.add_transition(e2, EPSILON, e) + nfa.add_final_state(e) + return nfa + + def concat(self, n1, n2): + s = self.new_state() + m = self.new_state() + e = self.new_state() + nfa = NFA(s) + nfa.insert(s, n1, m) + nfa.insert(m, n2, e) + nfa.add_final_state(e) + return nfa + + def star(self, n): + s = self.new_state() + m1 = self.new_state() + m2 = self.new_state() + e = self.new_state() + nfa = NFA(s) + nfa.add_transition(s, EPSILON, m1) + nfa.add_transition(s, EPSILON, e) + nfa.insert(m1, n, m2) + nfa.add_transition(m2, EPSILON, m1) + nfa.add_transition(m2, EPSILON, e) + nfa.add_final_state(e) + return nfa + + def plus(self, n): + return self.concat(n, self.star(n)) + + def question(self, n): + return self.choice(n, self.epsilon()) + + + + + diff --git a/nstock/modules/whoosh/classify.py b/nstock/modules/whoosh/classify.py new file mode 100755 index 0000000..628edf5 --- /dev/null +++ b/nstock/modules/whoosh/classify.py @@ -0,0 +1,377 @@ +# Copyright 2008 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +"""Classes and functions for classifying and extracting information from +documents. +""" + +from __future__ import division +import random +from collections import defaultdict +from math import log + +from whoosh.compat import xrange, iteritems + + +# Expansion models + +class ExpansionModel(object): + def __init__(self, doc_count, field_length): + self.N = doc_count + self.collection_total = field_length + + if self.N: + self.mean_length = self.collection_total / self.N + else: + self.mean_length = 0 + + def normalizer(self, maxweight, top_total): + raise NotImplementedError + + def score(self, weight_in_top, weight_in_collection, top_total): + raise NotImplementedError + + +class Bo1Model(ExpansionModel): + def normalizer(self, maxweight, top_total): + f = maxweight / self.N + return (maxweight * log((1.0 + f) / f) + log(1.0 + f)) / log(2.0) + + def score(self, weight_in_top, weight_in_collection, top_total): + f = weight_in_collection / self.N + return weight_in_top * log((1.0 + f) / f, 2) + log(1.0 + f, 2) + + +class Bo2Model(ExpansionModel): + def normalizer(self, maxweight, top_total): + f = maxweight * self.N / self.collection_total + return maxweight * log((1.0 + f) / f, 2) + log(1.0 + f, 2) + + def score(self, weight_in_top, weight_in_collection, top_total): + f = weight_in_top * top_total / self.collection_total + return weight_in_top * log((1.0 + f) / f, 2) + log(1.0 + f, 2) + + +class KLModel(ExpansionModel): + def normalizer(self, maxweight, top_total): + return (maxweight * log(self.collection_total / top_total) / log(2.0) + * top_total) + + def score(self, weight_in_top, weight_in_collection, top_total): + wit_over_tt = weight_in_top / top_total + wic_over_ct = weight_in_collection / self.collection_total + + if wit_over_tt < wic_over_ct: + return 0 + else: + return wit_over_tt * log(wit_over_tt + / (weight_in_top / self.collection_total), + 2) + + +class Expander(object): + """Uses an ExpansionModel to expand the set of query terms based on the top + N result documents. + """ + + def __init__(self, ixreader, fieldname, model=Bo1Model): + """ + :param reader: A :class:whoosh.reading.IndexReader object. + :param fieldname: The name of the field in which to search. + :param model: (classify.ExpansionModel) The model to use for expanding + the query terms. If you omit this parameter, the expander uses + :class:`Bo1Model` by default. + """ + + self.ixreader = ixreader + self.fieldname = fieldname + doccount = self.ixreader.doc_count_all() + fieldlen = self.ixreader.field_length(fieldname) + + if type(model) is type: + model = model(doccount, fieldlen) + self.model = model + + # Maps words to their weight in the top N documents. + self.topN_weight = defaultdict(float) + + # Total weight of all terms in the top N documents. + self.top_total = 0 + + def add(self, vector): + """Adds forward-index information about one of the "top N" documents. + + :param vector: A series of (text, weight) tuples, such as is + returned by Reader.vector_as("weight", docnum, fieldname). + """ + + total_weight = 0 + topN_weight = self.topN_weight + + for word, weight in vector: + total_weight += weight + topN_weight[word] += weight + + self.top_total += total_weight + + def add_document(self, docnum): + ixreader = self.ixreader + if self.ixreader.has_vector(docnum, self.fieldname): + self.add(ixreader.vector_as("weight", docnum, self.fieldname)) + elif self.ixreader.schema[self.fieldname].stored: + self.add_text(ixreader.stored_fields(docnum).get(self.fieldname)) + else: + raise Exception("Field %r in document %s is not vectored or stored" + % (self.fieldname, docnum)) + + def add_text(self, string): + # Unfortunately since field.index() yields bytes texts, and we want + # unicode, we end up encoding and decoding unnecessarily. + # + # TODO: Find a way around this + + field = self.ixreader.schema[self.fieldname] + from_bytes = field.from_bytes + self.add((from_bytes(text), weight) for text, _, weight, _ + in field.index(string)) + + def expanded_terms(self, number, normalize=True): + """Returns the N most important terms in the vectors added so far. + + :param number: The number of terms to return. + :param normalize: Whether to normalize the weights. + :returns: A list of ("term", weight) tuples. + """ + + model = self.model + fieldname = self.fieldname + ixreader = self.ixreader + field = ixreader.schema[fieldname] + tlist = [] + maxweight = 0 + + # If no terms have been added, return an empty list + if not self.topN_weight: + return [] + + for word, weight in iteritems(self.topN_weight): + btext = field.to_bytes(word) + if (fieldname, btext) in ixreader: + cf = ixreader.frequency(fieldname, btext) + score = model.score(weight, cf, self.top_total) + if score > maxweight: + maxweight = score + tlist.append((score, word)) + + if normalize: + norm = model.normalizer(maxweight, self.top_total) + else: + norm = maxweight + tlist = [(weight / norm, t) for weight, t in tlist] + tlist.sort(key=lambda x: (0 - x[0], x[1])) + + return [(t, weight) for weight, t in tlist[:number]] + + +# Similarity functions + +def shingles(input, size=2): + d = defaultdict(int) + for shingle in (input[i:i + size] + for i in xrange(len(input) - (size - 1))): + d[shingle] += 1 + return iteritems(d) + + +def simhash(features, hashbits=32): + if hashbits == 32: + hashfn = hash + else: + hashfn = lambda s: _hash(s, hashbits) + + vs = [0] * hashbits + for feature, weight in features: + h = hashfn(feature) + for i in xrange(hashbits): + if h & (1 << i): + vs[i] += weight + else: + vs[i] -= weight + + out = 0 + for i, v in enumerate(vs): + if v > 0: + out |= 1 << i + return out + + +def _hash(s, hashbits): + # A variable-length version of Python's builtin hash + if s == "": + return 0 + else: + x = ord(s[0]) << 7 + m = 1000003 + mask = 2 ** hashbits - 1 + for c in s: + x = ((x * m) ^ ord(c)) & mask + x ^= len(s) + if x == -1: + x = -2 + return x + + +def hamming_distance(first_hash, other_hash, hashbits=32): + x = (first_hash ^ other_hash) & ((1 << hashbits) - 1) + tot = 0 + while x: + tot += 1 + x &= x - 1 + return tot + + +# Clustering + +def kmeans(data, k, t=0.0001, distfun=None, maxiter=50, centers=None): + """ + One-dimensional K-means clustering function. + + :param data: list of data points. + :param k: number of clusters. + :param t: tolerance; stop if changes between iterations are smaller than + this value. + :param distfun: a distance function. + :param centers: a list of centroids to start with. + :param maxiter: maximum number of iterations to run. + """ + + # Adapted from a C version by Roger Zhang, + # http://cs.smu.ca/~r_zhang/code/kmeans.c + + DOUBLE_MAX = 1.797693e308 + n = len(data) + + error = DOUBLE_MAX # sum of squared euclidean distance + + counts = [0] * k # size of each cluster + labels = [0] * n # output cluster label for each data point + + # c1 is an array of len k of the temp centroids + c1 = [0] * k + + # choose k initial centroids + if centers: + c = centers + else: + c = random.sample(data, k) + + niter = 0 + # main loop + while True: + # save error from last step + old_error = error + error = 0 + + # clear old counts and temp centroids + for i in xrange(k): + counts[i] = 0 + c1[i] = 0 + + for h in xrange(n): + # identify the closest cluster + min_distance = DOUBLE_MAX + for i in xrange(k): + distance = (data[h] - c[i]) ** 2 + if distance < min_distance: + labels[h] = i + min_distance = distance + + # update size and temp centroid of the destination cluster + c1[labels[h]] += data[h] + counts[labels[h]] += 1 + # update standard error + error += min_distance + + for i in xrange(k): # update all centroids + c[i] = c1[i] / counts[i] if counts[i] else c1[i] + + niter += 1 + if (abs(error - old_error) < t) or (niter > maxiter): + break + + return labels, c + + +# Sliding window clusters + +def two_pass_variance(data): + n = 0 + sum1 = 0 + sum2 = 0 + + for x in data: + n += 1 + sum1 = sum1 + x + + mean = sum1 / n + + for x in data: + sum2 += (x - mean) * (x - mean) + + variance = sum2 / (n - 1) + return variance + + +def weighted_incremental_variance(data_weight_pairs): + mean = 0 + S = 0 + sumweight = 0 + for x, weight in data_weight_pairs: + temp = weight + sumweight + Q = x - mean + R = Q * weight / temp + S += sumweight * Q * R + mean += R + sumweight = temp + Variance = S / (sumweight - 1) # if sample is the population, omit -1 + return Variance + + +def swin(data, size): + clusters = [] + for i, left in enumerate(data): + j = i + right = data[j] + while j < len(data) - 1 and right - left < size: + j += 1 + right = data[j] + v = 99999 + if j - i > 1: + v = two_pass_variance(data[i:j + 1]) + clusters.append((left, right, j - i, v)) + clusters.sort(key=lambda x: (0 - x[2], x[3])) + return clusters diff --git a/nstock/modules/whoosh/codec/__init__.py b/nstock/modules/whoosh/codec/__init__.py new file mode 100644 index 0000000..7044563 --- /dev/null +++ b/nstock/modules/whoosh/codec/__init__.py @@ -0,0 +1,32 @@ +# Copyright 2012 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + + +def default_codec(*args, **kwargs): + from whoosh.codec.whoosh3 import W3Codec + + return W3Codec(*args, **kwargs) diff --git a/nstock/modules/whoosh/codec/base.py b/nstock/modules/whoosh/codec/base.py new file mode 100644 index 0000000..159a978 --- /dev/null +++ b/nstock/modules/whoosh/codec/base.py @@ -0,0 +1,843 @@ +# Copyright 2011 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +""" +This module contains base classes/interfaces for "codec" objects. +""" + +from bisect import bisect_right + +from whoosh import columns +from whoosh.automata import lev +from whoosh.compat import abstractmethod, izip, unichr, xrange +from whoosh.filedb.compound import CompoundStorage +from whoosh.system import emptybytes +from whoosh.util import random_name + + +# Exceptions + +class OutOfOrderError(Exception): + pass + + +# Base classes + +class Codec(object): + length_stats = True + + # Per document value writer + + @abstractmethod + def per_document_writer(self, storage, segment): + raise NotImplementedError + + # Inverted index writer + + @abstractmethod + def field_writer(self, storage, segment): + raise NotImplementedError + + # Postings + + @abstractmethod + def postings_writer(self, dbfile, byteids=False): + raise NotImplementedError + + @abstractmethod + def postings_reader(self, dbfile, terminfo, format_, term=None, scorer=None): + raise NotImplementedError + + # Index readers + + def automata(self, storage, segment): + return Automata() + + @abstractmethod + def terms_reader(self, storage, segment): + raise NotImplementedError + + @abstractmethod + def per_document_reader(self, storage, segment): + raise NotImplementedError + + # Segments and generations + + @abstractmethod + def new_segment(self, storage, indexname): + raise NotImplementedError + + +class WrappingCodec(Codec): + def __init__(self, child): + self._child = child + + def per_document_writer(self, storage, segment): + return self._child.per_document_writer(storage, segment) + + def field_writer(self, storage, segment): + return self._child.field_writer(storage, segment) + + def postings_writer(self, dbfile, byteids=False): + return self._child.postings_writer(dbfile, byteids=byteids) + + def postings_reader(self, dbfile, terminfo, format_, term=None, scorer=None): + return self._child.postings_reader(dbfile, terminfo, format_, term=term, + scorer=scorer) + + def automata(self, storage, segment): + return self._child.automata(storage, segment) + + def terms_reader(self, storage, segment): + return self._child.terms_reader(storage, segment) + + def per_document_reader(self, storage, segment): + return self._child.per_document_reader(storage, segment) + + def new_segment(self, storage, indexname): + return self._child.new_segment(storage, indexname) + + +# Writer classes + +class PerDocumentWriter(object): + @abstractmethod + def start_doc(self, docnum): + raise NotImplementedError + + @abstractmethod + def add_field(self, fieldname, fieldobj, value, length): + raise NotImplementedError + + @abstractmethod + def add_column_value(self, fieldname, columnobj, value): + raise NotImplementedError("Codec does not implement writing columns") + + @abstractmethod + def add_vector_items(self, fieldname, fieldobj, items): + raise NotImplementedError + + def add_vector_matcher(self, fieldname, fieldobj, vmatcher): + def readitems(): + while vmatcher.is_active(): + text = vmatcher.id() + weight = vmatcher.weight() + valuestring = vmatcher.value() + yield (text, weight, valuestring) + vmatcher.next() + self.add_vector_items(fieldname, fieldobj, readitems()) + + def finish_doc(self): + pass + + def close(self): + pass + + +class FieldWriter(object): + def add_postings(self, schema, lengths, items): + # This method translates a generator of (fieldname, btext, docnum, w, v) + # postings into calls to start_field(), start_term(), add(), + # finish_term(), finish_field(), etc. + + start_field = self.start_field + start_term = self.start_term + add = self.add + finish_term = self.finish_term + finish_field = self.finish_field + + if lengths: + dfl = lengths.doc_field_length + else: + dfl = lambda docnum, fieldname: 0 + + # The fieldname of the previous posting + lastfn = None + # The bytes text of the previous posting + lasttext = None + # The (fieldname, btext) of the previous spelling posting + lastspell = None + # The field object for the current field + fieldobj = None + for fieldname, btext, docnum, weight, value in items: + # Check for out-of-order postings. This is convoluted because Python + # 3 removed the ability to compare a string to None + if lastfn is not None and fieldname < lastfn: + raise OutOfOrderError("Field %r .. %r" % (lastfn, fieldname)) + if fieldname == lastfn and lasttext and btext < lasttext: + raise OutOfOrderError("Term %s:%r .. %s:%r" + % (lastfn, lasttext, fieldname, btext)) + + # If the fieldname of this posting is different from the last one, + # tell the writer we're starting a new field + if fieldname != lastfn: + if lasttext is not None: + finish_term() + if lastfn is not None and fieldname != lastfn: + finish_field() + fieldobj = schema[fieldname] + start_field(fieldname, fieldobj) + lastfn = fieldname + lasttext = None + + # HACK: items where docnum == -1 indicate words that should be added + # to the spelling graph, not the postings + if docnum == -1: + # spellterm = (fieldname, btext) + # # There can be duplicates of spelling terms, so only add a spell + # # term if it's greater than the last one + # if lastspell is None or spellterm > lastspell: + # spellword = fieldobj.from_bytes(btext) + # self.add_spell_word(fieldname, spellword) + # lastspell = spellterm + continue + + # If this term is different from the term in the previous posting, + # tell the writer to start a new term + if btext != lasttext: + if lasttext is not None: + finish_term() + start_term(btext) + lasttext = btext + + # Add this posting + length = dfl(docnum, fieldname) + if value is None: + value = emptybytes + add(docnum, weight, value, length) + + if lasttext is not None: + finish_term() + if lastfn is not None: + finish_field() + + @abstractmethod + def start_field(self, fieldname, fieldobj): + raise NotImplementedError + + @abstractmethod + def start_term(self, text): + raise NotImplementedError + + @abstractmethod + def add(self, docnum, weight, vbytes, length): + raise NotImplementedError + + def add_spell_word(self, fieldname, text): + raise NotImplementedError + + @abstractmethod + def finish_term(self): + raise NotImplementedError + + def finish_field(self): + pass + + def close(self): + pass + + +# Postings + +class PostingsWriter(object): + @abstractmethod + def start_postings(self, format_, terminfo): + raise NotImplementedError + + @abstractmethod + def add_posting(self, id_, weight, vbytes, length=None): + raise NotImplementedError + + def finish_postings(self): + pass + + @abstractmethod + def written(self): + """Returns True if this object has already written to disk. + """ + + raise NotImplementedError + + +# Reader classes + +class FieldCursor(object): + def first(self): + raise NotImplementedError + + def find(self, string): + raise NotImplementedError + + def next(self): + raise NotImplementedError + + def term(self): + raise NotImplementedError + + +class TermsReader(object): + @abstractmethod + def __contains__(self, term): + raise NotImplementedError + + @abstractmethod + def cursor(self, fieldname, fieldobj): + raise NotImplementedError + + @abstractmethod + def terms(self): + raise NotImplementedError + + @abstractmethod + def terms_from(self, fieldname, prefix): + raise NotImplementedError + + @abstractmethod + def items(self): + raise NotImplementedError + + @abstractmethod + def items_from(self, fieldname, prefix): + raise NotImplementedError + + @abstractmethod + def term_info(self, fieldname, text): + raise NotImplementedError + + @abstractmethod + def frequency(self, fieldname, text): + return self.term_info(fieldname, text).weight() + + @abstractmethod + def doc_frequency(self, fieldname, text): + return self.term_info(fieldname, text).doc_frequency() + + @abstractmethod + def matcher(self, fieldname, text, format_, scorer=None): + raise NotImplementedError + + @abstractmethod + def indexed_field_names(self): + raise NotImplementedError + + def close(self): + pass + + +class Automata(object): + @staticmethod + def levenshtein_dfa(uterm, maxdist, prefix=0): + return lev.levenshtein_automaton(uterm, maxdist, prefix).to_dfa() + + @staticmethod + def find_matches(dfa, cur): + unull = unichr(0) + + term = cur.text() + if term is None: + return + + match = dfa.next_valid_string(term) + while match: + cur.find(match) + term = cur.text() + if term is None: + return + if match == term: + yield match + term += unull + match = dfa.next_valid_string(term) + + def terms_within(self, fieldcur, uterm, maxdist, prefix=0): + dfa = self.levenshtein_dfa(uterm, maxdist, prefix) + return self.find_matches(dfa, fieldcur) + + +# Per-doc value reader + +class PerDocumentReader(object): + def close(self): + pass + + @abstractmethod + def doc_count(self): + raise NotImplementedError + + @abstractmethod + def doc_count_all(self): + raise NotImplementedError + + # Deletions + + @abstractmethod + def has_deletions(self): + raise NotImplementedError + + @abstractmethod + def is_deleted(self, docnum): + raise NotImplementedError + + @abstractmethod + def deleted_docs(self): + raise NotImplementedError + + def all_doc_ids(self): + """ + Returns an iterator of all (undeleted) document IDs in the reader. + """ + + is_deleted = self.is_deleted + return (docnum for docnum in xrange(self.doc_count_all()) + if not is_deleted(docnum)) + + def iter_docs(self): + for docnum in self.all_doc_ids(): + yield docnum, self.stored_fields(docnum) + + # Columns + + def supports_columns(self): + return False + + def has_column(self, fieldname): + return False + + def list_columns(self): + raise NotImplementedError + + # Don't need to override this if supports_columns() returns False + def column_reader(self, fieldname, column): + raise NotImplementedError + + # Bitmaps + + def field_docs(self, fieldname): + return None + + # Lengths + + @abstractmethod + def doc_field_length(self, docnum, fieldname, default=0): + raise NotImplementedError + + @abstractmethod + def field_length(self, fieldname): + raise NotImplementedError + + @abstractmethod + def min_field_length(self, fieldname): + raise NotImplementedError + + @abstractmethod + def max_field_length(self, fieldname): + raise NotImplementedError + + # Vectors + + def has_vector(self, docnum, fieldname): + return False + + # Don't need to override this if has_vector() always returns False + def vector(self, docnum, fieldname, format_): + raise NotImplementedError + + # Stored + + @abstractmethod + def stored_fields(self, docnum): + raise NotImplementedError + + def all_stored_fields(self): + for docnum in self.all_doc_ids(): + yield self.stored_fields(docnum) + + +# Segment base class + +class Segment(object): + """Do not instantiate this object directly. It is used by the Index object + to hold information about a segment. A list of objects of this class are + pickled as part of the TOC file. + + The TOC file stores a minimal amount of information -- mostly a list of + Segment objects. Segments are the real reverse indexes. Having multiple + segments allows quick incremental indexing: just create a new segment for + the new documents, and have the index overlay the new segment over previous + ones for purposes of reading/search. "Optimizing" the index combines the + contents of existing segments into one (removing any deleted documents + along the way). + """ + + # Extension for compound segment files + COMPOUND_EXT = ".seg" + + # self.indexname + # self.segid + + def __init__(self, indexname): + self.indexname = indexname + self.segid = self._random_id() + self.compound = False + + @classmethod + def _random_id(cls, size=16): + return random_name(size=size) + + def __repr__(self): + return "<%s %s>" % (self.__class__.__name__, self.segment_id()) + + def codec(self): + raise NotImplementedError + + def index_name(self): + return self.indexname + + def segment_id(self): + if hasattr(self, "name"): + # Old segment class + return self.name + else: + return "%s_%s" % (self.index_name(), self.segid) + + def is_compound(self): + if not hasattr(self, "compound"): + return False + return self.compound + + # File convenience methods + + def make_filename(self, ext): + return "%s%s" % (self.segment_id(), ext) + + def list_files(self, storage): + prefix = "%s." % self.segment_id() + return [name for name in storage.list() if name.startswith(prefix)] + + def create_file(self, storage, ext, **kwargs): + """Convenience method to create a new file in the given storage named + with this segment's ID and the given extension. Any keyword arguments + are passed to the storage's create_file method. + """ + + fname = self.make_filename(ext) + return storage.create_file(fname, **kwargs) + + def open_file(self, storage, ext, **kwargs): + """Convenience method to open a file in the given storage named with + this segment's ID and the given extension. Any keyword arguments are + passed to the storage's open_file method. + """ + + fname = self.make_filename(ext) + return storage.open_file(fname, **kwargs) + + def create_compound_file(self, storage): + segfiles = self.list_files(storage) + assert not any(name.endswith(self.COMPOUND_EXT) for name in segfiles) + cfile = self.create_file(storage, self.COMPOUND_EXT) + CompoundStorage.assemble(cfile, storage, segfiles) + for name in segfiles: + storage.delete_file(name) + self.compound = True + + def open_compound_file(self, storage): + name = self.make_filename(self.COMPOUND_EXT) + dbfile = storage.open_file(name) + return CompoundStorage(dbfile, use_mmap=storage.supports_mmap) + + # Abstract methods + + @abstractmethod + def doc_count_all(self): + """ + Returns the total number of documents, DELETED OR UNDELETED, in this + segment. + """ + + raise NotImplementedError + + def doc_count(self): + """ + Returns the number of (undeleted) documents in this segment. + """ + + return self.doc_count_all() - self.deleted_count() + + def set_doc_count(self, doccount): + raise NotImplementedError + + def has_deletions(self): + """ + Returns True if any documents in this segment are deleted. + """ + + return self.deleted_count() > 0 + + @abstractmethod + def deleted_count(self): + """ + Returns the total number of deleted documents in this segment. + """ + + raise NotImplementedError + + @abstractmethod + def deleted_docs(self): + raise NotImplementedError + + @abstractmethod + def delete_document(self, docnum, delete=True): + """Deletes the given document number. The document is not actually + removed from the index until it is optimized. + + :param docnum: The document number to delete. + :param delete: If False, this undeletes a deleted document. + """ + + raise NotImplementedError + + @abstractmethod + def is_deleted(self, docnum): + """ + Returns True if the given document number is deleted. + """ + + raise NotImplementedError + + def should_assemble(self): + return True + + +# Wrapping Segment + +class WrappingSegment(Segment): + def __init__(self, child): + self._child = child + + def codec(self): + return self._child.codec() + + def index_name(self): + return self._child.index_name() + + def segment_id(self): + return self._child.segment_id() + + def is_compound(self): + return self._child.is_compound() + + def should_assemble(self): + return self._child.should_assemble() + + def make_filename(self, ext): + return self._child.make_filename(ext) + + def list_files(self, storage): + return self._child.list_files(storage) + + def create_file(self, storage, ext, **kwargs): + return self._child.create_file(storage, ext, **kwargs) + + def open_file(self, storage, ext, **kwargs): + return self._child.open_file(storage, ext, **kwargs) + + def create_compound_file(self, storage): + return self._child.create_compound_file(storage) + + def open_compound_file(self, storage): + return self._child.open_compound_file(storage) + + def delete_document(self, docnum, delete=True): + return self._child.delete_document(docnum, delete=delete) + + def has_deletions(self): + return self._child.has_deletions() + + def deleted_count(self): + return self._child.deleted_count() + + def deleted_docs(self): + return self._child.deleted_docs() + + def is_deleted(self, docnum): + return self._child.is_deleted(docnum) + + def set_doc_count(self, doccount): + self._child.set_doc_count(doccount) + + def doc_count(self): + return self._child.doc_count() + + def doc_count_all(self): + return self._child.doc_count_all() + + +# Multi per doc reader + +class MultiPerDocumentReader(PerDocumentReader): + def __init__(self, readers, offset=0): + self._readers = readers + + self._doc_offsets = [] + self._doccount = 0 + for pdr in readers: + self._doc_offsets.append(self._doccount) + self._doccount += pdr.doc_count_all() + + self.is_closed = False + + def close(self): + for r in self._readers: + r.close() + self.is_closed = True + + def doc_count_all(self): + return self._doccount + + def doc_count(self): + total = 0 + for r in self._readers: + total += r.doc_count() + return total + + def _document_reader(self, docnum): + return max(0, bisect_right(self._doc_offsets, docnum) - 1) + + def _reader_and_docnum(self, docnum): + rnum = self._document_reader(docnum) + offset = self._doc_offsets[rnum] + return rnum, docnum - offset + + # Deletions + + def has_deletions(self): + return any(r.has_deletions() for r in self._readers) + + def is_deleted(self, docnum): + x, y = self._reader_and_docnum(docnum) + return self._readers[x].is_deleted(y) + + def deleted_docs(self): + for r, offset in izip(self._readers, self._doc_offsets): + for docnum in r.deleted_docs(): + yield docnum + offset + + def all_doc_ids(self): + for r, offset in izip(self._readers, self._doc_offsets): + for docnum in r.all_doc_ids(): + yield docnum + offset + + # Columns + + def has_column(self, fieldname): + return any(r.has_column(fieldname) for r in self._readers) + + def column_reader(self, fieldname, column): + if not self.has_column(fieldname): + raise ValueError("No column %r" % (fieldname,)) + + default = column.default_value() + colreaders = [] + for r in self._readers: + if r.has_column(fieldname): + cr = r.column_reader(fieldname, column) + else: + cr = columns.EmptyColumnReader(default, r.doc_count_all()) + colreaders.append(cr) + + if len(colreaders) == 1: + return colreaders[0] + else: + return columns.MultiColumnReader(colreaders) + + # Lengths + + def doc_field_length(self, docnum, fieldname, default=0): + x, y = self._reader_and_docnum(docnum) + return self._readers[x].doc_field_length(y, fieldname, default) + + def field_length(self, fieldname): + total = 0 + for r in self._readers: + total += r.field_length(fieldname) + return total + + def min_field_length(self): + return min(r.min_field_length() for r in self._readers) + + def max_field_length(self): + return max(r.max_field_length() for r in self._readers) + + +# Extended base classes + +class PerDocWriterWithColumns(PerDocumentWriter): + def __init__(self): + PerDocumentWriter.__init__(self) + # Implementations need to set these attributes + self._storage = None + self._segment = None + self._docnum = None + + @abstractmethod + def _has_column(self, fieldname): + raise NotImplementedError + + @abstractmethod + def _create_column(self, fieldname, column): + raise NotImplementedError + + @abstractmethod + def _get_column(self, fieldname): + raise NotImplementedError + + def add_column_value(self, fieldname, column, value): + if not self._has_column(fieldname): + self._create_column(fieldname, column) + self._get_column(fieldname).add(self._docnum, value) + + +# FieldCursor implementations + +class EmptyCursor(FieldCursor): + def first(self): + return None + + def find(self, term): + return None + + def next(self): + return None + + def text(self): + return None + + def term_info(self): + return None + + def is_valid(self): + return False diff --git a/nstock/modules/whoosh/codec/memory.py b/nstock/modules/whoosh/codec/memory.py new file mode 100644 index 0000000..5a5babe --- /dev/null +++ b/nstock/modules/whoosh/codec/memory.py @@ -0,0 +1,334 @@ +# Copyright 2012 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from __future__ import with_statement +from bisect import bisect_left +from threading import Lock, RLock + +from whoosh.compat import xrange +from whoosh.codec import base +from whoosh.matching import ListMatcher +from whoosh.reading import SegmentReader, TermInfo, TermNotFound +from whoosh.writing import SegmentWriter + + +class MemWriter(SegmentWriter): + def commit(self): + self._finalize_segment() + + +class MemoryCodec(base.Codec): + def __init__(self): + from whoosh.filedb.filestore import RamStorage + + self.storage = RamStorage() + self.segment = MemSegment(self, "blah") + + def writer(self, schema): + ix = self.storage.create_index(schema) + return MemWriter(ix, _lk=False, codec=self, + docbase=self.segment._doccount) + + def reader(self, schema): + return SegmentReader(self.storage, schema, self.segment, codec=self) + + def per_document_writer(self, storage, segment): + return MemPerDocWriter(self.storage, self.segment) + + def field_writer(self, storage, segment): + return MemFieldWriter(self.storage, self.segment) + + def per_document_reader(self, storage, segment): + return MemPerDocReader(self.storage, self.segment) + + def terms_reader(self, storage, segment): + return MemTermsReader(self.storage, self.segment) + + def new_segment(self, storage, indexname): + return self.segment + + +class MemPerDocWriter(base.PerDocWriterWithColumns): + def __init__(self, storage, segment): + self._storage = storage + self._segment = segment + self.is_closed = False + self._colwriters = {} + self._doccount = 0 + + def _has_column(self, fieldname): + return fieldname in self._colwriters + + def _create_column(self, fieldname, column): + colfile = self._storage.create_file("%s.c" % fieldname) + self._colwriters[fieldname] = (colfile, column.writer(colfile)) + + def _get_column(self, fieldname): + return self._colwriters[fieldname][1] + + def start_doc(self, docnum): + self._doccount += 1 + self._docnum = docnum + self._stored = {} + self._lengths = {} + self._vectors = {} + + def add_field(self, fieldname, fieldobj, value, length): + if value is not None: + self._stored[fieldname] = value + if length is not None: + self._lengths[fieldname] = length + + def add_vector_items(self, fieldname, fieldobj, items): + self._vectors[fieldname] = tuple(items) + + def finish_doc(self): + with self._segment._lock: + docnum = self._docnum + self._segment._stored[docnum] = self._stored + self._segment._lengths[docnum] = self._lengths + self._segment._vectors[docnum] = self._vectors + + def close(self): + colwriters = self._colwriters + for fieldname in colwriters: + colfile, colwriter = colwriters[fieldname] + colwriter.finish(self._doccount) + colfile.close() + self.is_closed = True + + +class MemPerDocReader(base.PerDocumentReader): + def __init__(self, storage, segment): + self._storage = storage + self._segment = segment + + def doc_count(self): + return self._segment.doc_count() + + def doc_count_all(self): + return self._segment.doc_count_all() + + def has_deletions(self): + return self._segment.has_deletions() + + def is_deleted(self, docnum): + return self._segment.is_deleted(docnum) + + def deleted_docs(self): + return self._segment.deleted_docs() + + def supports_columns(self): + return True + + def has_column(self, fieldname): + filename = "%s.c" % fieldname + return self._storage.file_exists(filename) + + def column_reader(self, fieldname, column): + filename = "%s.c" % fieldname + colfile = self._storage.open_file(filename) + length = self._storage.file_length(filename) + return column.reader(colfile, 0, length, self._segment.doc_count_all()) + + def doc_field_length(self, docnum, fieldname, default=0): + return self._segment._lengths[docnum].get(fieldname, default) + + def field_length(self, fieldname): + return sum(lens.get(fieldname, 0) for lens + in self._segment._lengths.values()) + + def min_field_length(self, fieldname): + return min(lens[fieldname] for lens in self._segment._lengths.values() + if fieldname in lens) + + def max_field_length(self, fieldname): + return max(lens[fieldname] for lens in self._segment._lengths.values() + if fieldname in lens) + + def has_vector(self, docnum, fieldname): + return (docnum in self._segment._vectors + and fieldname in self._segment._vectors[docnum]) + + def vector(self, docnum, fieldname, format_): + items = self._segment._vectors[docnum][fieldname] + ids, weights, values = zip(*items) + return ListMatcher(ids, weights, values, format_) + + def stored_fields(self, docnum): + return self._segment._stored[docnum] + + def close(self): + pass + + +class MemFieldWriter(base.FieldWriter): + def __init__(self, storage, segment): + self._storage = storage + self._segment = segment + self._fieldname = None + self._btext = None + self.is_closed = False + + def start_field(self, fieldname, fieldobj): + if self._fieldname is not None: + raise Exception("Called start_field in a field") + + with self._segment._lock: + invindex = self._segment._invindex + if fieldname not in invindex: + invindex[fieldname] = {} + + self._fieldname = fieldname + self._fieldobj = fieldobj + + def start_term(self, btext): + if self._btext is not None: + raise Exception("Called start_term in a term") + fieldname = self._fieldname + + fielddict = self._segment._invindex[fieldname] + terminfos = self._segment._terminfos + with self._segment._lock: + if btext not in fielddict: + fielddict[btext] = [] + + if (fieldname, btext) not in terminfos: + terminfos[fieldname, btext] = TermInfo() + + self._postings = fielddict[btext] + self._terminfo = terminfos[fieldname, btext] + self._btext = btext + + def add(self, docnum, weight, vbytes, length): + self._postings.append((docnum, weight, vbytes)) + self._terminfo.add_posting(docnum, weight, length) + + def finish_term(self): + if self._btext is None: + raise Exception("Called finish_term outside a term") + + self._postings = None + self._btext = None + self._terminfo = None + + def finish_field(self): + if self._fieldname is None: + raise Exception("Called finish_field outside a field") + self._fieldname = None + self._fieldobj = None + + def close(self): + self.is_closed = True + + +class MemTermsReader(base.TermsReader): + def __init__(self, storage, segment): + self._storage = storage + self._segment = segment + self._invindex = segment._invindex + + def __contains__(self, term): + return term in self._segment._terminfos + + def terms(self): + for fieldname in self._invindex: + for btext in self._invindex[fieldname]: + yield (fieldname, btext) + + def terms_from(self, fieldname, prefix): + if fieldname not in self._invindex: + raise TermNotFound("Unknown field %r" % (fieldname,)) + terms = sorted(self._invindex[fieldname]) + if not terms: + return + start = bisect_left(terms, prefix) + for i in xrange(start, len(terms)): + yield (fieldname, terms[i]) + + def term_info(self, fieldname, text): + return self._segment._terminfos[fieldname, text] + + def matcher(self, fieldname, btext, format_, scorer=None): + items = self._invindex[fieldname][btext] + ids, weights, values = zip(*items) + return ListMatcher(ids, weights, values, format_, scorer=scorer) + + def indexed_field_names(self): + return self._invindex.keys() + + def close(self): + pass + + +class MemSegment(base.Segment): + def __init__(self, codec, indexname): + base.Segment.__init__(self, indexname) + self._codec = codec + self._doccount = 0 + self._stored = {} + self._lengths = {} + self._vectors = {} + self._invindex = {} + self._terminfos = {} + self._lock = Lock() + + def codec(self): + return self._codec + + def set_doc_count(self, doccount): + self._doccount = doccount + + def doc_count(self): + return len(self._stored) + + def doc_count_all(self): + return self._doccount + + def delete_document(self, docnum, delete=True): + if not delete: + raise Exception("MemoryCodec can't undelete") + with self._lock: + del self._stored[docnum] + del self._lengths[docnum] + del self._vectors[docnum] + + def has_deletions(self): + with self._lock: + return self._doccount - len(self._stored) + + def is_deleted(self, docnum): + return docnum not in self._stored + + def deleted_docs(self): + stored = self._stored + for docnum in xrange(self.doc_count_all()): + if docnum not in stored: + yield docnum + + def should_assemble(self): + return False diff --git a/nstock/modules/whoosh/codec/plaintext.py b/nstock/modules/whoosh/codec/plaintext.py new file mode 100644 index 0000000..e042eb6 --- /dev/null +++ b/nstock/modules/whoosh/codec/plaintext.py @@ -0,0 +1,452 @@ +# Copyright 2012 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from ast import literal_eval + +from whoosh.compat import b, bytes_type, text_type, integer_types, PY3 +from whoosh.compat import iteritems, dumps, loads, xrange +from whoosh.codec import base +from whoosh.matching import ListMatcher +from whoosh.reading import TermInfo, TermNotFound + +if not PY3: + class memoryview: + pass + +_reprable = (bytes_type, text_type, integer_types, float) + + +# Mixin classes for producing and consuming the simple text format + +class LineWriter(object): + def _print_line(self, indent, command, **kwargs): + self._dbfile.write(b(" ") * indent) + self._dbfile.write(command.encode("latin1")) + for k, v in iteritems(kwargs): + if isinstance(v, memoryview): + v = bytes(v) + if v is not None and not isinstance(v, _reprable): + raise TypeError(type(v)) + self._dbfile.write(("\t%s=%r" % (k, v)).encode("latin1")) + self._dbfile.write(b("\n")) + + +class LineReader(object): + def __init__(self, dbfile): + self._dbfile = dbfile + + def _reset(self): + self._dbfile.seek(0) + + def _find_line(self, indent, command, **kwargs): + for largs in self._find_lines(indent, command, **kwargs): + return largs + + def _find_lines(self, indent, command, **kwargs): + while True: + line = self._dbfile.readline() + if not line: + return + + c = self._parse_line(line) + if c is None: + return + + lindent, lcommand, largs = c + if lindent == indent and lcommand == command: + matched = True + if kwargs: + for k in kwargs: + if kwargs[k] != largs.get(k): + matched = False + break + + if matched: + yield largs + elif lindent < indent: + return + + def _parse_line(self, line): + line = line.decode("latin1") + line = line.rstrip() + l = len(line) + line = line.lstrip() + if not line or line.startswith("#"): + return None + + indent = (l - len(line)) // 2 + + parts = line.split("\t") + command = parts[0] + args = {} + for i in xrange(1, len(parts)): + n, v = parts[i].split("=") + args[n] = literal_eval(v) + return (indent, command, args) + + def _find_root(self, command): + self._reset() + c = self._find_line(0, command) + if c is None: + raise Exception("No root section %r" % (command,)) + + +# Codec class + +class PlainTextCodec(base.Codec): + length_stats = False + + def per_document_writer(self, storage, segment): + return PlainPerDocWriter(storage, segment) + + def field_writer(self, storage, segment): + return PlainFieldWriter(storage, segment) + + def per_document_reader(self, storage, segment): + return PlainPerDocReader(storage, segment) + + def terms_reader(self, storage, segment): + return PlainTermsReader(storage, segment) + + def new_segment(self, storage, indexname): + return PlainSegment(indexname) + + +class PlainPerDocWriter(base.PerDocumentWriter, LineWriter): + def __init__(self, storage, segment): + self._dbfile = storage.create_file(segment.make_filename(".dcs")) + self._print_line(0, "DOCS") + self.is_closed = False + + def start_doc(self, docnum): + self._print_line(1, "DOC", dn=docnum) + + def add_field(self, fieldname, fieldobj, value, length): + if value is not None: + value = dumps(value, 2) + self._print_line(2, "DOCFIELD", fn=fieldname, v=value, len=length) + + def add_column_value(self, fieldname, columnobj, value): + self._print_line(2, "COLVAL", fn=fieldname, v=value) + + def add_vector_items(self, fieldname, fieldobj, items): + self._print_line(2, "VECTOR", fn=fieldname) + for text, weight, vbytes in items: + self._print_line(3, "VPOST", t=text, w=weight, v=vbytes) + + def finish_doc(self): + pass + + def close(self): + self._dbfile.close() + self.is_closed = True + + +class PlainPerDocReader(base.PerDocumentReader, LineReader): + def __init__(self, storage, segment): + self._dbfile = storage.open_file(segment.make_filename(".dcs")) + self._segment = segment + self.is_closed = False + + def doc_count(self): + return self._segment.doc_count() + + def doc_count_all(self): + return self._segment.doc_count() + + def has_deletions(self): + return False + + def is_deleted(self, docnum): + return False + + def deleted_docs(self): + return frozenset() + + def _find_doc(self, docnum): + self._find_root("DOCS") + c = self._find_line(1, "DOC") + while c is not None: + dn = c["dn"] + if dn == docnum: + return True + elif dn > docnum: + return False + c = self._find_line(1, "DOC") + return False + + def _iter_docs(self): + self._find_root("DOCS") + c = self._find_line(1, "DOC") + while c is not None: + yield c["dn"] + c = self._find_line(1, "DOC") + + def _iter_docfields(self, fieldname): + for _ in self._iter_docs(): + for c in self._find_lines(2, "DOCFIELD", fn=fieldname): + yield c + + def _iter_lengths(self, fieldname): + return (c.get("len", 0) for c in self._iter_docfields(fieldname)) + + def doc_field_length(self, docnum, fieldname, default=0): + for dn in self._iter_docs(): + if dn == docnum: + + c = self._find_line(2, "DOCFIELD", fn=fieldname) + if c is not None: + return c.get("len", default) + elif dn > docnum: + break + + return default + + def _column_values(self, fieldname): + for i, docnum in enumerate(self._iter_docs()): + if i != docnum: + raise Exception("Missing column value for field %r doc %d?" + % (fieldname, i)) + + c = self._find_line(2, "COLVAL", fn=fieldname) + if c is None: + raise Exception("Missing column value for field %r doc %d?" + % (fieldname, docnum)) + + yield c.get("v") + + def has_column(self, fieldname): + for _ in self._column_values(fieldname): + return True + return False + + def column_reader(self, fieldname, column): + return list(self._column_values(fieldname)) + + def field_length(self, fieldname): + return sum(self._iter_lengths(fieldname)) + + def min_field_length(self, fieldname): + return min(self._iter_lengths(fieldname)) + + def max_field_length(self, fieldname): + return max(self._iter_lengths(fieldname)) + + def has_vector(self, docnum, fieldname): + if self._find_doc(docnum): + if self._find_line(2, "VECTOR"): + return True + return False + + def vector(self, docnum, fieldname, format_): + if not self._find_doc(docnum): + raise Exception + if not self._find_line(2, "VECTOR"): + raise Exception + + ids = [] + weights = [] + values = [] + c = self._find_line(3, "VPOST") + while c is not None: + ids.append(c["t"]) + weights.append(c["w"]) + values.append(c["v"]) + c = self._find_line(3, "VPOST") + + return ListMatcher(ids, weights, values, format_,) + + def _read_stored_fields(self): + sfs = {} + c = self._find_line(2, "DOCFIELD") + while c is not None: + v = c.get("v") + if v is not None: + v = loads(v) + sfs[c["fn"]] = v + c = self._find_line(2, "DOCFIELD") + return sfs + + def stored_fields(self, docnum): + if not self._find_doc(docnum): + raise Exception + return self._read_stored_fields() + + def iter_docs(self): + return enumerate(self.all_stored_fields()) + + def all_stored_fields(self): + for _ in self._iter_docs(): + yield self._read_stored_fields() + + def close(self): + self._dbfile.close() + self.is_closed = True + + +class PlainFieldWriter(base.FieldWriter, LineWriter): + def __init__(self, storage, segment): + self._dbfile = storage.create_file(segment.make_filename(".trm")) + self._print_line(0, "TERMS") + + @property + def is_closed(self): + return self._dbfile.is_closed + + def start_field(self, fieldname, fieldobj): + self._fieldobj = fieldobj + self._print_line(1, "TERMFIELD", fn=fieldname) + + def start_term(self, btext): + self._terminfo = TermInfo() + self._print_line(2, "BTEXT", t=btext) + + def add(self, docnum, weight, vbytes, length): + self._terminfo.add_posting(docnum, weight, length) + self._print_line(3, "POST", dn=docnum, w=weight, v=vbytes) + + def finish_term(self): + ti = self._terminfo + self._print_line(3, "TERMINFO", + df=ti.doc_frequency(), weight=ti.weight(), + minlength=ti.min_length(), maxlength=ti.max_length(), + maxweight=ti.max_weight(), + minid=ti.min_id(), maxid=ti.max_id()) + + def add_spell_word(self, fieldname, text): + self._print_line(2, "SPELL", fn=fieldname, t=text) + + def close(self): + self._dbfile.close() + + +class PlainTermsReader(base.TermsReader, LineReader): + def __init__(self, storage, segment): + self._dbfile = storage.open_file(segment.make_filename(".trm")) + self._segment = segment + self.is_closed = False + + def _find_field(self, fieldname): + self._find_root("TERMS") + if self._find_line(1, "TERMFIELD", fn=fieldname) is None: + raise TermNotFound("No field %r" % fieldname) + + def _iter_fields(self): + self._find_root() + c = self._find_line(1, "TERMFIELD") + while c is not None: + yield c["fn"] + c = self._find_line(1, "TERMFIELD") + + def _iter_btexts(self): + c = self._find_line(2, "BTEXT") + while c is not None: + yield c["t"] + c = self._find_line(2, "BTEXT") + + def _find_term(self, fieldname, btext): + self._find_field(fieldname) + for t in self._iter_btexts(): + if t == btext: + return True + elif t > btext: + break + return False + + def _find_terminfo(self): + c = self._find_line(3, "TERMINFO") + return TermInfo(**c) + + def __contains__(self, term): + fieldname, btext = term + return self._find_term(fieldname, btext) + + def indexed_field_names(self): + return self._iter_fields() + + def terms(self): + for fieldname in self._iter_fields(): + for btext in self._iter_btexts(): + yield (fieldname, btext) + + def terms_from(self, fieldname, prefix): + self._find_field(fieldname) + for btext in self._iter_btexts(): + if btext < prefix: + continue + yield (fieldname, btext) + + def items(self): + for fieldname, btext in self.terms(): + yield (fieldname, btext), self._find_terminfo() + + def items_from(self, fieldname, prefix): + for fieldname, btext in self.terms_from(fieldname, prefix): + yield (fieldname, btext), self._find_terminfo() + + def term_info(self, fieldname, btext): + if not self._find_term(fieldname, btext): + raise TermNotFound((fieldname, btext)) + return self._find_terminfo() + + def matcher(self, fieldname, btext, format_, scorer=None): + if not self._find_term(fieldname, btext): + raise TermNotFound((fieldname, btext)) + + ids = [] + weights = [] + values = [] + c = self._find_line(3, "POST") + while c is not None: + ids.append(c["dn"]) + weights.append(c["w"]) + values.append(c["v"]) + c = self._find_line(3, "POST") + + return ListMatcher(ids, weights, values, format_, scorer=scorer) + + def close(self): + self._dbfile.close() + self.is_closed = True + + +class PlainSegment(base.Segment): + def __init__(self, indexname): + base.Segment.__init__(self, indexname) + self._doccount = 0 + + def codec(self): + return PlainTextCodec() + + def set_doc_count(self, doccount): + self._doccount = doccount + + def doc_count(self): + return self._doccount + + def should_assemble(self): + return False diff --git a/nstock/modules/whoosh/codec/whoosh3.py b/nstock/modules/whoosh/codec/whoosh3.py new file mode 100644 index 0000000..a1be958 --- /dev/null +++ b/nstock/modules/whoosh/codec/whoosh3.py @@ -0,0 +1,1291 @@ +# Copyright 2012 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +""" +This module implements a "codec" for writing/reading Whoosh X indexes. +""" + +import struct +from array import array +from collections import defaultdict + +from whoosh import columns, formats +from whoosh.compat import b, bytes_type, string_type, integer_types +from whoosh.compat import dumps, loads, iteritems, xrange +from whoosh.codec import base +from whoosh.filedb import compound, filetables +from whoosh.matching import ListMatcher, ReadTooFar, LeafMatcher +from whoosh.reading import TermInfo, TermNotFound +from whoosh.system import emptybytes +from whoosh.system import _SHORT_SIZE, _INT_SIZE, _LONG_SIZE, _FLOAT_SIZE +from whoosh.system import pack_ushort, unpack_ushort +from whoosh.system import pack_int, unpack_int, pack_long, unpack_long +from whoosh.util.numlists import delta_encode, delta_decode +from whoosh.util.numeric import length_to_byte, byte_to_length + +try: + import zlib +except ImportError: + zlib = None + + +# This byte sequence is written at the start of a posting list to identify the +# codec/version +WHOOSH3_HEADER_MAGIC = b("W3Bl") + +# Column type to store field length info +LENGTHS_COLUMN = columns.NumericColumn("B", default=0) +# Column type to store pointers to vector posting lists +VECTOR_COLUMN = columns.NumericColumn("I") +# Column type to store vector posting list lengths +VECTOR_LEN_COLUMN = columns.NumericColumn("i") +# Column type to store values of stored fields +STORED_COLUMN = columns.PickleColumn(columns.CompressedBytesColumn()) + + +class W3Codec(base.Codec): + # File extensions + TERMS_EXT = ".trm" # Term index + POSTS_EXT = ".pst" # Term postings + VPOSTS_EXT = ".vps" # Vector postings + COLUMN_EXT = ".col" # Per-document value columns + + def __init__(self, blocklimit=128, compression=3, inlinelimit=1): + self._blocklimit = blocklimit + self._compression = compression + self._inlinelimit = inlinelimit + + # def automata(self): + + # Per-document value writer + def per_document_writer(self, storage, segment): + return W3PerDocWriter(self, storage, segment) + + # Inverted index writer + def field_writer(self, storage, segment): + return W3FieldWriter(self, storage, segment) + + # Postings + + def postings_writer(self, dbfile, byteids=False): + return W3PostingsWriter(dbfile, blocklimit=self._blocklimit, + byteids=byteids, compression=self._compression, + inlinelimit=self._inlinelimit) + + def postings_reader(self, dbfile, terminfo, format_, term=None, scorer=None): + if terminfo.is_inlined(): + # If the postings were inlined into the terminfo object, pull them + # out and use a ListMatcher to wrap them in a Matcher interface + ids, weights, values = terminfo.inlined_postings() + m = ListMatcher(ids, weights, values, format_, scorer=scorer, + term=term, terminfo=terminfo) + else: + offset, length = terminfo.extent() + m = W3LeafMatcher(dbfile, offset, length, format_, term=term, + scorer=scorer) + return m + + # Readers + + def per_document_reader(self, storage, segment): + return W3PerDocReader(storage, segment) + + def terms_reader(self, storage, segment): + tiname = segment.make_filename(self.TERMS_EXT) + tilen = storage.file_length(tiname) + tifile = storage.open_file(tiname) + + postfile = segment.open_file(storage, self.POSTS_EXT) + + return W3TermsReader(self, tifile, tilen, postfile) + + # Graph methods provided by CodecWithGraph + + # Columns + + def supports_columns(self): + return True + + @classmethod + def column_filename(cls, segment, fieldname): + ext = "".join((".", fieldname, cls.COLUMN_EXT)) + return segment.make_filename(ext) + + # Segments and generations + + def new_segment(self, storage, indexname): + return W3Segment(self, indexname) + + +# Common functions + +def _vecfield(fieldname): + return "_%s_vec" % fieldname + + +def _lenfield(fieldname): + return "_%s_len" % fieldname + + +# Per-doc information writer + +class W3PerDocWriter(base.PerDocWriterWithColumns): + def __init__(self, codec, storage, segment): + self._codec = codec + self._storage = storage + self._segment = segment + + tempst = storage.temp_storage("%s.tmp" % segment.indexname) + self._cols = compound.CompoundWriter(tempst) + self._colwriters = {} + self._create_column("_stored", STORED_COLUMN) + + self._fieldlengths = defaultdict(int) + self._doccount = 0 + self._docnum = None + self._storedfields = None + self._indoc = False + self.is_closed = False + + # We'll wait to create the vector file until someone actually tries + # to add a vector + self._vpostfile = None + + def _create_file(self, ext): + return self._segment.create_file(self._storage, ext) + + def _has_column(self, fieldname): + return fieldname in self._colwriters + + def _create_column(self, fieldname, column): + writers = self._colwriters + if fieldname in writers: + raise Exception("Already added column %r" % fieldname) + + f = self._cols.create_file(fieldname) + writers[fieldname] = column.writer(f) + + def _get_column(self, fieldname): + return self._colwriters[fieldname] + + def _prep_vectors(self): + self._vpostfile = self._create_file(W3Codec.VPOSTS_EXT) + # We'll use offset==0 as a marker for "no vectors", so we can't start + # postings at position 0, so just write a few header bytes :) + self._vpostfile.write(b("VPST")) + + def start_doc(self, docnum): + if self._indoc: + raise Exception("Called start_doc when already in a doc") + if docnum != self._doccount: + raise Exception("Called start_doc(%r) was expecting %r" + % (docnum, self._doccount)) + + self._docnum = docnum + self._doccount += 1 + self._storedfields = {} + self._indoc = True + + def add_field(self, fieldname, fieldobj, value, length): + if value is not None: + self._storedfields[fieldname] = value + if length: + # Add byte to length column + lenfield = _lenfield(fieldname) + lb = length_to_byte(length) + self.add_column_value(lenfield, LENGTHS_COLUMN, lb) + # Add length to total field length + self._fieldlengths[fieldname] += length + + def add_vector_items(self, fieldname, fieldobj, items): + if not items: + # Don't do anything if the list of items is empty + return + + if self._vpostfile is None: + self._prep_vectors() + + # Write vector postings + vpostwriter = self._codec.postings_writer(self._vpostfile, byteids=True) + vpostwriter.start_postings(fieldobj.vector, W3TermInfo()) + for text, weight, vbytes in items: + vpostwriter.add_posting(text, weight, vbytes) + # finish_postings() returns terminfo object + vinfo = vpostwriter.finish_postings() + + # Add row to vector lookup column + vecfield = _vecfield(fieldname) # Compute vector column name + offset, length = vinfo.extent() + assert offset != 0 + self.add_column_value(vecfield, VECTOR_COLUMN, offset) + self.add_column_value(vecfield + "L", VECTOR_LEN_COLUMN, length) + + def finish_doc(self): + sf = self._storedfields + if sf: + self.add_column_value("_stored", STORED_COLUMN, sf) + sf.clear() + self._indoc = False + + def _column_filename(self, fieldname): + return W3Codec.column_filename(self._segment, fieldname) + + def close(self): + if self._indoc is not None: + # Called close without calling finish_doc + self.finish_doc() + + self._segment._fieldlengths = self._fieldlengths + + # Finish open columns and close the columns writer + for writer in self._colwriters.values(): + writer.finish(self._doccount) + self._cols.save_as_files(self._storage, self._column_filename) + + # If vectors were written, close the vector writers + if self._vpostfile: + self._vpostfile.close() + + self.is_closed = True + + +class W3FieldWriter(base.FieldWriter): + def __init__(self, codec, storage, segment): + self._codec = codec + self._storage = storage + self._segment = segment + + self._fieldname = None + self._fieldid = None + self._btext = None + self._fieldobj = None + self._format = None + + _tifile = self._create_file(W3Codec.TERMS_EXT) + self._tindex = filetables.OrderedHashWriter(_tifile) + self._fieldmap = self._tindex.extras["fieldmap"] = {} + + self._postfile = self._create_file(W3Codec.POSTS_EXT) + + self._postwriter = None + self._infield = False + self.is_closed = False + + def _create_file(self, ext): + return self._segment.create_file(self._storage, ext) + + def start_field(self, fieldname, fieldobj): + fmap = self._fieldmap + if fieldname in fmap: + self._fieldid = fmap[fieldname] + else: + self._fieldid = len(fmap) + fmap[fieldname] = self._fieldid + + self._fieldname = fieldname + self._fieldobj = fieldobj + self._format = fieldobj.format + self._infield = True + + # Start a new postwriter for this field + self._postwriter = self._codec.postings_writer(self._postfile) + + def start_term(self, btext): + if self._postwriter is None: + raise Exception("Called start_term before start_field") + self._btext = btext + self._postwriter.start_postings(self._fieldobj.format, W3TermInfo()) + + def add(self, docnum, weight, vbytes, length): + self._postwriter.add_posting(docnum, weight, vbytes, length) + + def finish_term(self): + terminfo = self._postwriter.finish_postings() + + # Add row to term info table + keybytes = pack_ushort(self._fieldid) + self._btext + valbytes = terminfo.to_bytes() + self._tindex.add(keybytes, valbytes) + + # FieldWriterWithGraph.add_spell_word + + def finish_field(self): + if not self._infield: + raise Exception("Called finish_field before start_field") + self._infield = False + self._postwriter = None + + def close(self): + self._tindex.close() + self._postfile.close() + self.is_closed = True + + +# Reader objects + +class W3PerDocReader(base.PerDocumentReader): + def __init__(self, storage, segment): + self._storage = storage + self._segment = segment + self._doccount = segment.doc_count_all() + + self._vpostfile = None + self._colfiles = {} + self._readers = {} + self._minlengths = {} + self._maxlengths = {} + + def close(self): + for colfile, _, _ in self._colfiles.values(): + colfile.close() + if self._vpostfile: + self._vpostfile.close() + + def doc_count(self): + return self._doccount - self._segment.deleted_count() + + def doc_count_all(self): + return self._doccount + + # Deletions + + def has_deletions(self): + return self._segment.has_deletions() + + def is_deleted(self, docnum): + return self._segment.is_deleted(docnum) + + def deleted_docs(self): + return self._segment.deleted_docs() + + # Columns + + def has_column(self, fieldname): + filename = W3Codec.column_filename(self._segment, fieldname) + return self._storage.file_exists(filename) + + def _get_column_file(self, fieldname): + filename = W3Codec.column_filename(self._segment, fieldname) + length = self._storage.file_length(filename) + colfile = self._storage.open_file(filename) + return colfile, 0, length + + def column_reader(self, fieldname, column): + if fieldname not in self._colfiles: + self._colfiles[fieldname] = self._get_column_file(fieldname) + colfile, offset, length = self._colfiles[fieldname] + return column.reader(colfile, offset, length, self._doccount) + + # Lengths + + def _cached_reader(self, fieldname, column): + if fieldname in self._readers: + return self._readers[fieldname] + else: + if not self.has_column(fieldname): + return None + + reader = self.column_reader(fieldname, column) + self._readers[fieldname] = reader + return reader + + def doc_field_length(self, docnum, fieldname, default=0): + if docnum > self._doccount: + raise IndexError("Asked for docnum %r of %d" + % (docnum, self._doccount)) + + lenfield = _lenfield(fieldname) + reader = self._cached_reader(lenfield, LENGTHS_COLUMN) + if reader is None: + return default + + lbyte = reader[docnum] + if lbyte: + return byte_to_length(lbyte) + + def field_length(self, fieldname): + return self._segment._fieldlengths.get(fieldname, 0) + + def _minmax_length(self, fieldname, op, cache): + if fieldname in cache: + return cache[fieldname] + + lenfield = _lenfield(fieldname) + reader = self._cached_reader(lenfield, LENGTHS_COLUMN) + length = byte_to_length(op(reader)) + cache[fieldname] = length + return length + + def min_field_length(self, fieldname): + return self._minmax_length(fieldname, min, self._minlengths) + + def max_field_length(self, fieldname): + return self._minmax_length(fieldname, max, self._maxlengths) + + # Vectors + + def _prep_vectors(self): + f = self._segment.open_file(self._storage, W3Codec.VPOSTS_EXT) + self._vpostfile = f + + def _vector_extent(self, docnum, fieldname): + if docnum > self._doccount: + raise IndexError("Asked for document %r of %d" + % (docnum, self._doccount)) + vecfield = _vecfield(fieldname) # Compute vector column name + + # Get the offset from the vector offset column + offset = self._cached_reader(vecfield, VECTOR_COLUMN)[docnum] + + # Get the length from the length column, if it exists, otherwise return + # -1 for the length (backwards compatibility with old dev versions) + lreader = self._cached_reader(vecfield + "L", VECTOR_COLUMN) + if lreader: + length = lreader[docnum] + else: + length = -1 + + return offset, length + + def has_vector(self, docnum, fieldname): + if self.has_column(_vecfield(fieldname)): + offset, length = self._vector_extent(docnum, fieldname) + return offset != 0 + return False + + def vector(self, docnum, fieldname, format_): + if self._vpostfile is None: + self._prep_vectors() + offset, length = self._vector_extent(docnum, fieldname) + if not offset: + raise Exception("Field %r has no vector in docnum %s" % + (fieldname, docnum)) + m = W3LeafMatcher(self._vpostfile, offset, length, format_, + byteids=True) + return m + + # Stored fields + + def stored_fields(self, docnum): + reader = self._cached_reader("_stored", STORED_COLUMN) + v = reader[docnum] + if v is None: + v = {} + return v + + +class W3FieldCursor(base.FieldCursor): + def __init__(self, tindex, fieldname, keycoder, keydecoder, fieldobj): + self._tindex = tindex + self._fieldname = fieldname + self._keycoder = keycoder + self._keydecoder = keydecoder + self._fieldobj = fieldobj + + prefixbytes = keycoder(fieldname, b'') + self._startpos = self._tindex.closest_key_pos(prefixbytes) + + self._pos = self._startpos + self._text = None + self._datapos = None + self._datalen = None + self.next() + + def first(self): + self._pos = self._startpos + return self.next() + + def find(self, term): + if not isinstance(term, bytes_type): + term = self._fieldobj.to_bytes(term) + key = self._keycoder(self._fieldname, term) + self._pos = self._tindex.closest_key_pos(key) + return self.next() + + def next(self): + if self._pos is not None: + keyrng = self._tindex.key_and_range_at(self._pos) + if keyrng is not None: + keybytes, datapos, datalen = keyrng + fname, text = self._keydecoder(keybytes) + if fname == self._fieldname: + self._pos = datapos + datalen + self._text = self._fieldobj.from_bytes(text) + self._datapos = datapos + self._datalen = datalen + return self._text + + self._text = self._pos = self._datapos = self._datalen = None + return None + + def text(self): + return self._text + + def term_info(self): + if self._pos is None: + return None + + databytes = self._tindex.dbfile.get(self._datapos, self._datalen) + return W3TermInfo.from_bytes(databytes) + + def is_valid(self): + return self._pos is not None + + +class W3TermsReader(base.TermsReader): + def __init__(self, codec, dbfile, length, postfile): + self._codec = codec + self._dbfile = dbfile + self._tindex = filetables.OrderedHashReader(dbfile, length) + self._fieldmap = self._tindex.extras["fieldmap"] + self._postfile = postfile + + self._fieldunmap = [None] * len(self._fieldmap) + for fieldname, num in iteritems(self._fieldmap): + self._fieldunmap[num] = fieldname + + def _keycoder(self, fieldname, tbytes): + assert isinstance(tbytes, bytes_type), "tbytes=%r" % tbytes + fnum = self._fieldmap.get(fieldname, 65535) + return pack_ushort(fnum) + tbytes + + def _keydecoder(self, keybytes): + fieldid = unpack_ushort(keybytes[:_SHORT_SIZE])[0] + return self._fieldunmap[fieldid], keybytes[_SHORT_SIZE:] + + def _range_for_key(self, fieldname, tbytes): + return self._tindex.range_for_key(self._keycoder(fieldname, tbytes)) + + def __contains__(self, term): + return self._keycoder(*term) in self._tindex + + def indexed_field_names(self): + return self._fieldmap.keys() + + def cursor(self, fieldname, fieldobj): + tindex = self._tindex + coder = self._keycoder + decoder = self._keydecoder + return W3FieldCursor(tindex, fieldname, coder, decoder, fieldobj) + + def terms(self): + keydecoder = self._keydecoder + return (keydecoder(keybytes) for keybytes in self._tindex.keys()) + + def terms_from(self, fieldname, prefix): + prefixbytes = self._keycoder(fieldname, prefix) + keydecoder = self._keydecoder + return (keydecoder(keybytes) for keybytes + in self._tindex.keys_from(prefixbytes)) + + def items(self): + tidecoder = W3TermInfo.from_bytes + keydecoder = self._keydecoder + return ((keydecoder(keybytes), tidecoder(valbytes)) + for keybytes, valbytes in self._tindex.items()) + + def items_from(self, fieldname, prefix): + prefixbytes = self._keycoder(fieldname, prefix) + tidecoder = W3TermInfo.from_bytes + keydecoder = self._keydecoder + return ((keydecoder(keybytes), tidecoder(valbytes)) + for keybytes, valbytes in self._tindex.items_from(prefixbytes)) + + def term_info(self, fieldname, tbytes): + key = self._keycoder(fieldname, tbytes) + try: + return W3TermInfo.from_bytes(self._tindex[key]) + except KeyError: + raise TermNotFound("No term %s:%r" % (fieldname, tbytes)) + + def frequency(self, fieldname, tbytes): + datapos = self._range_for_key(fieldname, tbytes)[0] + return W3TermInfo.read_weight(self._dbfile, datapos) + + def doc_frequency(self, fieldname, tbytes): + datapos = self._range_for_key(fieldname, tbytes)[0] + return W3TermInfo.read_doc_freq(self._dbfile, datapos) + + def matcher(self, fieldname, tbytes, format_, scorer=None): + terminfo = self.term_info(fieldname, tbytes) + m = self._codec.postings_reader(self._postfile, terminfo, format_, + term=(fieldname, tbytes), scorer=scorer) + return m + + def close(self): + self._tindex.close() + self._postfile.close() + + +# Postings + +class W3PostingsWriter(base.PostingsWriter): + """This object writes posting lists to the postings file. It groups postings + into blocks and tracks block level statistics to makes it easier to skip + through the postings. + """ + + def __init__(self, postfile, blocklimit, byteids=False, compression=3, + inlinelimit=1): + self._postfile = postfile + self._blocklimit = blocklimit + self._byteids = byteids + self._compression = compression + self._inlinelimit = inlinelimit + + self._blockcount = 0 + self._format = None + self._terminfo = None + + def written(self): + return self._blockcount > 0 + + def start_postings(self, format_, terminfo): + # Start a new term + if self._terminfo: + # If self._terminfo is not None, that means we are already in a term + raise Exception("Called start in a term") + + assert isinstance(format_, formats.Format) + self._format = format_ + # Reset block count + self._blockcount = 0 + # Reset block bufferg + self._new_block() + # Remember terminfo object passed to us + self._terminfo = terminfo + # Remember where we started in the posting file + self._startoffset = self._postfile.tell() + + def add_posting(self, id_, weight, vbytes, length=None): + # Add a posting to the buffered block + + # If the number of buffered postings == the block limit, write out the + # buffered block and reset before adding this one + if len(self._ids) >= self._blocklimit: + self._write_block() + + # Check types + if self._byteids: + assert isinstance(id_, string_type), "id_=%r" % id_ + else: + assert isinstance(id_, integer_types), "id_=%r" % id_ + assert isinstance(weight, (int, float)), "weight=%r" % weight + assert isinstance(vbytes, bytes_type), "vbytes=%r" % vbytes + assert length is None or isinstance(length, integer_types) + + self._ids.append(id_) + self._weights.append(weight) + + if weight > self._maxweight: + self._maxweight = weight + if vbytes: + self._values.append(vbytes) + if length: + minlength = self._minlength + if minlength is None or length < minlength: + self._minlength = length + if length > self._maxlength: + self._maxlength = length + + def finish_postings(self): + terminfo = self._terminfo + # If we have fewer than "inlinelimit" postings in this posting list, + # "inline" the postings into the terminfo instead of writing them to + # the posting file + if not self.written() and len(self) < self._inlinelimit: + terminfo.add_block(self) + terminfo.set_inline(self._ids, self._weights, self._values) + else: + # If there are leftover items in the current block, write them out + if self._ids: + self._write_block(last=True) + startoffset = self._startoffset + length = self._postfile.tell() - startoffset + terminfo.set_extent(startoffset, length) + + # Clear self._terminfo to indicate we're between terms + self._terminfo = None + # Return the current terminfo object + return terminfo + + def _new_block(self): + # Reset block buffer + + # List of IDs (docnums for regular posting list, terms for vector PL) + self._ids = [] if self._byteids else array("I") + # List of weights + self._weights = array("f") + # List of encoded payloads + self._values = [] + # Statistics + self._minlength = None + self._maxlength = 0 + self._maxweight = 0 + + def _write_block(self, last=False): + # Write the buffered block to the postings file + + # If this is the first block, write a small header first + if not self._blockcount: + self._postfile.write(WHOOSH3_HEADER_MAGIC) + + # Add this block's statistics to the terminfo object, which tracks the + # overall statistics for all term postings + self._terminfo.add_block(self) + + # Minify the IDs, weights, and values, and put them in a tuple + data = (self._mini_ids(), self._mini_weights(), self._mini_values()) + # Pickle the tuple + databytes = dumps(data, 2) + # If the pickle is less than 20 bytes, don't bother compressing + if len(databytes) < 20: + comp = 0 + # Compress the pickle (if self._compression > 0) + comp = self._compression + if comp: + databytes = zlib.compress(databytes, comp) + + # Make a tuple of block info. The posting reader can check this info + # and decide whether to skip the block without having to decompress the + # full block data + # + # - Number of postings in block + # - Last ID in block + # - Maximum weight in block + # - Compression level + # - Minimum length byte + # - Maximum length byte + ids = self._ids + infobytes = dumps((len(ids), ids[-1], self._maxweight, comp, + length_to_byte(self._minlength), + length_to_byte(self._maxlength), + ), 2) + + # Write block length + postfile = self._postfile + blocklength = len(infobytes) + len(databytes) + if last: + # If this is the last block, use a negative number + blocklength *= -1 + postfile.write_int(blocklength) + # Write block info + postfile.write(infobytes) + # Write block data + postfile.write(databytes) + + self._blockcount += 1 + # Reset block buffer + self._new_block() + + # Methods to reduce the byte size of the various lists + + def _mini_ids(self): + # Minify IDs + + ids = self._ids + if not self._byteids: + ids = delta_encode(ids) + return tuple(ids) + + def _mini_weights(self): + # Minify weights + + weights = self._weights + + if all(w == 1.0 for w in weights): + return None + elif all(w == weights[0] for w in weights): + return weights[0] + else: + return tuple(weights) + + def _mini_values(self): + # Minify values + + fixedsize = self._format.fixed_value_size() + values = self._values + + if fixedsize is None or fixedsize < 0: + vs = tuple(values) + elif fixedsize == 0: + vs = None + else: + vs = emptybytes.join(values) + return vs + + # Block stats methods + + def __len__(self): + # Returns the number of unwritten buffered postings + return len(self._ids) + + def min_id(self): + # First ID in the buffered block + return self._ids[0] + + def max_id(self): + # Last ID in the buffered block + return self._ids[-1] + + def min_length(self): + # Shortest field length in the buffered block + return self._minlength + + def max_length(self): + # Longest field length in the buffered block + return self._maxlength + + def max_weight(self): + # Highest weight in the buffered block + return self._maxweight + + +class W3LeafMatcher(LeafMatcher): + """Reads on-disk postings from the postings file and presents the + :class:`whoosh.matching.Matcher` interface. + """ + + def __init__(self, postfile, startoffset, length, format_, term=None, + byteids=None, scorer=None): + self._postfile = postfile + self._startoffset = startoffset + self._length = length + self.format = format_ + self._term = term + self._byteids = byteids + self.scorer = scorer + + self._fixedsize = self.format.fixed_value_size() + # Read the header tag at the start of the postings + self._read_header() + # "Reset" to read the first block + self.reset() + + def _read_header(self): + # Seek to the start of the postings and check the header tag + postfile = self._postfile + + postfile.seek(self._startoffset) + magic = postfile.read(4) + if magic != WHOOSH3_HEADER_MAGIC: + raise Exception("Block tag error %r" % magic) + + # Remember the base offset (start of postings, after the header) + self._baseoffset = postfile.tell() + + def reset(self): + # Reset block stats + self._blocklength = None + self._maxid = None + self._maxweight = None + self._compression = None + self._minlength = None + self._maxlength = None + + self._lastblock = False + self._atend = False + # Consume first block + self._goto(self._baseoffset) + + def _goto(self, position): + # Read the posting block at the given position + + postfile = self._postfile + + # Reset block data -- we'll lazy load the data from the new block as + # needed + self._data = None + self._ids = None + self._weights = None + self._values = None + # Reset pointer into the block + self._i = 0 + + # Seek to the start of the block + postfile.seek(position) + # Read the block length + length = postfile.read_int() + # If the block length is negative, that means this is the last block + if length < 0: + self._lastblock = True + length *= -1 + + # Remember the offset of the next block + self._nextoffset = position + _INT_SIZE + length + # Read the pickled block info tuple + info = postfile.read_pickle() + # Remember the offset of the block's data + self._dataoffset = postfile.tell() + + # Decompose the info tuple to set the current block info + (self._blocklength, self._maxid, self._maxweight, self._compression, + mnlen, mxlen) = info + self._minlength = byte_to_length(mnlen) + self._maxlength = byte_to_length(mxlen) + + def _next_block(self): + if self._atend: + # We were already at the end, and yet somebody called _next_block() + # again, so something is wrong somewhere + raise Exception("No next block") + elif self._lastblock: + # Reached the end of the postings + self._atend = True + else: + # Go to the next block + self._goto(self._nextoffset) + + def _skip_to_block(self, skipwhile): + # Skip blocks as long as the skipwhile() function returns True + + skipped = 0 + while self.is_active() and skipwhile(): + self._next_block() + skipped += 1 + return skipped + + def is_active(self): + return not self._atend and self._i < self._blocklength + + def id(self): + # Get the current ID (docnum for regular postings, term for vector) + + # If we haven't loaded the block IDs yet, load them now + if self._ids is None: + self._read_ids() + + return self._ids[self._i] + + def weight(self): + # Get the weight for the current posting + + # If we haven't loaded the block weights yet, load them now + if self._weights is None: + self._read_weights() + + return self._weights[self._i] + + def value(self): + # Get the value for the current posting + + # If we haven't loaded the block values yet, load them now + if self._values is None: + self._read_values() + + return self._values[self._i] + + def next(self): + # Move to the next posting + + # Increment the in-block pointer + self._i += 1 + # If we reached the end of the block, move to the next block + if self._i == self._blocklength: + self._next_block() + return True + else: + return False + + def skip_to(self, targetid): + # Skip to the next ID equal to or greater than the given target ID + + if not self.is_active(): + raise ReadTooFar + + # If we're already at or past target ID, do nothing + if targetid <= self.id(): + return + + # Skip to the block that would contain the target ID + block_max_id = self.block_max_id + if targetid > block_max_id(): + self._skip_to_block(lambda: targetid > block_max_id()) + + # Iterate through the IDs in the block until we find or pass the + # target + while self.is_active() and self.id() < targetid: + self.next() + + def skip_to_quality(self, minquality): + # Skip blocks until we find one that might exceed the given minimum + # quality + + block_quality = self.block_quality + + # If the quality of this block is already higher than the minimum, + # do nothing + if block_quality() > minquality: + return 0 + + # Skip blocks as long as the block quality is not greater than the + # minimum + return self._skip_to_block(lambda: block_quality() <= minquality) + + def block_min_id(self): + if self._ids is None: + self._read_ids() + return self._ids[0] + + def block_max_id(self): + return self._maxid + + def block_min_length(self): + return self._minlength + + def block_max_length(self): + return self._maxlength + + def block_max_weight(self): + return self._maxweight + + def _read_data(self): + # Load block data tuple from disk + + datalen = self._nextoffset - self._dataoffset + b = self._postfile.get(self._dataoffset, datalen) + + # Decompress the pickled data if necessary + if self._compression: + b = zlib.decompress(b) + + # Unpickle the data tuple and save it in an attribute + self._data = loads(b) + + def _read_ids(self): + # If we haven't loaded the data from disk yet, load it now + if self._data is None: + self._read_data() + ids = self._data[0] + + # De-minify the IDs + if not self._byteids: + ids = tuple(delta_decode(ids)) + + self._ids = ids + + def _read_weights(self): + # If we haven't loaded the data from disk yet, load it now + if self._data is None: + self._read_data() + weights = self._data[1] + + # De-minify the weights + postcount = self._blocklength + if weights is None: + self._weights = array("f", (1.0 for _ in xrange(postcount))) + elif isinstance(weights, float): + self._weights = array("f", (weights for _ in xrange(postcount))) + else: + self._weights = weights + + def _read_values(self): + # If we haven't loaded the data from disk yet, load it now + if self._data is None: + self._read_data() + + # De-minify the values + fixedsize = self._fixedsize + vs = self._data[2] + if fixedsize is None or fixedsize < 0: + self._values = vs + elif fixedsize is 0: + self._values = (None,) * self._blocklength + else: + assert isinstance(vs, bytes_type) + self._values = tuple(vs[i:i + fixedsize] + for i in xrange(0, len(vs), fixedsize)) + + +# Term info implementation + +class W3TermInfo(TermInfo): + # B | Flags + # f | Total weight + # I | Total doc freq + # B | Min length (encoded as byte) + # B | Max length (encoded as byte) + # f | Max weight + # I | Minimum (first) ID + # I | Maximum (last) ID + _struct = struct.Struct("!BfIBBfII") + + def __init__(self, *args, **kwargs): + TermInfo.__init__(self, *args, **kwargs) + self._offset = None + self._length = None + self._inlined = None + + def add_block(self, block): + self._weight += sum(block._weights) + self._df += len(block) + + ml = block.min_length() + if self._minlength is None: + self._minlength = ml + else: + self._minlength = min(self._minlength, ml) + + self._maxlength = max(self._maxlength, block.max_length()) + self._maxweight = max(self._maxweight, block.max_weight()) + if self._minid is None: + self._minid = block.min_id() + self._maxid = block.max_id() + + def set_extent(self, offset, length): + self._offset = offset + self._length = length + + def extent(self): + return self._offset, self._length + + def set_inlined(self, ids, weights, values): + self._inlined = (tuple(ids), tuple(weights), tuple(values)) + + def is_inlined(self): + return self._inlined is not None + + def inlined_postings(self): + return self._inlined + + def to_bytes(self): + isinlined = self.is_inlined() + + # Encode the lengths as 0-255 values + minlength = (0 if self._minlength is None + else length_to_byte(self._minlength)) + maxlength = length_to_byte(self._maxlength) + # Convert None values to the out-of-band NO_ID constant so they can be + # stored as unsigned ints + minid = 0xffffffff if self._minid is None else self._minid + maxid = 0xffffffff if self._maxid is None else self._maxid + + # Pack the term info into bytes + st = self._struct.pack(isinlined, self._weight, self._df, + minlength, maxlength, self._maxweight, + minid, maxid) + + if isinlined: + # Postings are inlined - dump them using the pickle protocol + postbytes = dumps(self._inlined, 2) + else: + postbytes = pack_long(self._offset) + pack_int(self._length) + st += postbytes + return st + + @classmethod + def from_bytes(cls, s): + st = cls._struct + vals = st.unpack(s[:st.size]) + terminfo = cls() + + flags = vals[0] + terminfo._weight = vals[1] + terminfo._df = vals[2] + terminfo._minlength = byte_to_length(vals[3]) + terminfo._maxlength = byte_to_length(vals[4]) + terminfo._maxweight = vals[5] + terminfo._minid = None if vals[6] == 0xffffffff else vals[6] + terminfo._maxid = None if vals[7] == 0xffffffff else vals[7] + + if flags: + # Postings are stored inline + terminfo._inlined = loads(s[st.size:]) + else: + # Last bytes are pointer into posting file and length + offpos = st.size + lenpos = st.size + _LONG_SIZE + terminfo._offset = unpack_long(s[offpos:lenpos])[0] + terminfo._length = unpack_int(s[lenpos:lenpos + _INT_SIZE]) + + return terminfo + + @classmethod + def read_weight(cls, dbfile, datapos): + return dbfile.get_float(datapos + 1) + + @classmethod + def read_doc_freq(cls, dbfile, datapos): + return dbfile.get_uint(datapos + 1 + _FLOAT_SIZE) + + @classmethod + def read_min_and_max_length(cls, dbfile, datapos): + lenpos = datapos + 1 + _FLOAT_SIZE + _INT_SIZE + ml = byte_to_length(dbfile.get_byte(lenpos)) + xl = byte_to_length(dbfile.get_byte(lenpos + 1)) + return ml, xl + + @classmethod + def read_max_weight(cls, dbfile, datapos): + weightspos = datapos + 1 + _FLOAT_SIZE + _INT_SIZE + 2 + return dbfile.get_float(weightspos) + + +# Segment implementation + +class W3Segment(base.Segment): + def __init__(self, codec, indexname, doccount=0, segid=None, deleted=None): + self.indexname = indexname + self.segid = self._random_id() if segid is None else segid + + self._codec = codec + self._doccount = doccount + self._deleted = deleted + self.compound = False + + def codec(self, **kwargs): + return self._codec + + def set_doc_count(self, dc): + self._doccount = dc + + def doc_count_all(self): + return self._doccount + + def deleted_count(self): + if self._deleted is None: + return 0 + return len(self._deleted) + + def deleted_docs(self): + if self._deleted is None: + return () + else: + return iter(self._deleted) + + def delete_document(self, docnum, delete=True): + if delete: + if self._deleted is None: + self._deleted = set() + self._deleted.add(docnum) + elif self._deleted is not None and docnum in self._deleted: + self._deleted.clear(docnum) + + def is_deleted(self, docnum): + if self._deleted is None: + return False + return docnum in self._deleted diff --git a/nstock/modules/whoosh/collectors.py b/nstock/modules/whoosh/collectors.py new file mode 100644 index 0000000..5b7e9c1 --- /dev/null +++ b/nstock/modules/whoosh/collectors.py @@ -0,0 +1,1165 @@ +# Copyright 2012 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +""" +This module contains "collector" objects. Collectors provide a way to gather +"raw" results from a :class:`whoosh.matching.Matcher` object, implement +sorting, filtering, collation, etc., and produce a +:class:`whoosh.searching.Results` object. + +The basic collectors are: + +TopCollector + Returns the top N matching results sorted by score, using block-quality + optimizations to skip blocks of documents that can't contribute to the top + N. The :meth:`whoosh.searching.Searcher.search` method uses this type of + collector by default or when you specify a ``limit``. + +UnlimitedCollector + Returns all matching results sorted by score. The + :meth:`whoosh.searching.Searcher.search` method uses this type of collector + when you specify ``limit=None`` or you specify a limit equal to or greater + than the number of documents in the searcher. + +SortingCollector + Returns all matching results sorted by a :class:`whoosh.sorting.Facet` + object. The :meth:`whoosh.searching.Searcher.search` method uses this type + of collector when you use the ``sortedby`` parameter. + +Here's an example of a simple collector that instead of remembering the matched +documents just counts up the number of matches:: + + class CountingCollector(Collector): + def prepare(self, top_searcher, q, context): + # Always call super method in prepare + Collector.prepare(self, top_searcher, q, context) + + self.count = 0 + + def collect(self, sub_docnum): + self.count += 1 + + c = CountingCollector() + mysearcher.search_with_collector(myquery, c) + print(c.count) + +There are also several wrapping collectors that extend or modify the +functionality of other collectors. The meth:`whoosh.searching.Searcher.search` +method uses many of these when you specify various parameters. + +NOTE: collectors are not designed to be reentrant or thread-safe. It is +generally a good idea to create a new collector for each search. +""" + +import os +import threading +from array import array +from bisect import insort +from collections import defaultdict +from heapq import heapify, heappush, heapreplace + +from whoosh import sorting +from whoosh.compat import abstractmethod, iteritems, itervalues, xrange +from whoosh.searching import Results, TimeLimit +from whoosh.util import now + + +# Functions + +def ilen(iterator): + total = 0 + for _ in iterator: + total += 1 + return total + + +# Base class + +class Collector(object): + """Base class for collectors. + """ + + def prepare(self, top_searcher, q, context): + """This method is called before a search. + + Subclasses can override this to perform set-up work, but + they should still call the superclass's method because it sets several + necessary attributes on the collector object: + + self.top_searcher + The top-level searcher. + self.q + The query object + self.context + ``context.needs_current`` controls whether a wrapping collector + requires that this collector's matcher be in a valid state at every + call to ``collect()``. If this is ``False``, the collector is free + to use faster methods that don't necessarily keep the matcher + updated, such as ``matcher.all_ids()``. + + :param top_searcher: the top-level :class:`whoosh.searching.Searcher` + object. + :param q: the :class:`whoosh.query.Query` object being searched for. + :param context: a :class:`whoosh.searching.SearchContext` object + containing information about the search. + """ + + self.top_searcher = top_searcher + self.q = q + self.context = context + + self.starttime = now() + self.runtime = None + self.docset = set() + + def run(self): + # Collect matches for each sub-searcher + try: + for subsearcher, offset in self.top_searcher.leaf_searchers(): + self.set_subsearcher(subsearcher, offset) + self.collect_matches() + finally: + self.finish() + + def set_subsearcher(self, subsearcher, offset): + """This method is called each time the collector starts on a new + sub-searcher. + + Subclasses can override this to perform set-up work, but + they should still call the superclass's method because it sets several + necessary attributes on the collector object: + + self.subsearcher + The current sub-searcher. If the top-level searcher is atomic, this + is the same as the top-level searcher. + self.offset + The document number offset of the current searcher. You must add + this number to the document number passed to + :meth:`Collector.collect` to get the top-level document number + for use in results. + self.matcher + A :class:`whoosh.matching.Matcher` object representing the matches + for the query in the current sub-searcher. + """ + + self.subsearcher = subsearcher + self.offset = offset + self.matcher = self.q.matcher(subsearcher, self.context) + + def computes_count(self): + """Returns True if the collector naturally computes the exact number of + matching documents. Collectors that use block optimizations will return + False since they might skip blocks containing matching documents. + + Note that if this method returns False you can still call :meth:`count`, + but it means that method might have to do more work to calculate the + number of matching documents. + """ + + return True + + def all_ids(self): + """Returns a sequence of docnums matched in this collector. (Only valid + after the collector is run.) + + The default implementation is based on the docset. If a collector does + not maintain the docset, it will need to override this method. + """ + + return self.docset + + def count(self): + """Returns the total number of documents matched in this collector. + (Only valid after the collector is run.) + + The default implementation is based on the docset. If a collector does + not maintain the docset, it will need to override this method. + """ + + return len(self.docset) + + def collect_matches(self): + """This method calls :meth:`Collector.matches` and then for each + matched document calls :meth:`Collector.collect`. Sub-classes that + want to intervene between finding matches and adding them to the + collection (for example, to filter out certain documents) can override + this method. + """ + + collect = self.collect + for sub_docnum in self.matches(): + collect(sub_docnum) + + @abstractmethod + def collect(self, sub_docnum): + """This method is called for every matched document. It should do the + work of adding a matched document to the results, and it should return + an object to use as a "sorting key" for the given document (such as the + document's score, a key generated by a facet, or just None). Subclasses + must implement this method. + + If you want the score for the current document, use + ``self.matcher.score()``. + + Overriding methods should add the current document offset + (``self.offset``) to the ``sub_docnum`` to get the top-level document + number for the matching document to add to results. + + :param sub_docnum: the document number of the current match within the + current sub-searcher. You must add ``self.offset`` to this number + to get the document's top-level document number. + """ + + raise NotImplementedError + + @abstractmethod + def sort_key(self, sub_docnum): + """Returns a sorting key for the current match. This should return the + same value returned by :meth:`Collector.collect`, but without the side + effect of adding the current document to the results. + + If the collector has been prepared with ``context.needs_current=True``, + this method can use ``self.matcher`` to get information, for example + the score. Otherwise, it should only use the provided ``sub_docnum``, + since the matcher may be in an inconsistent state. + + Subclasses must implement this method. + """ + + raise NotImplementedError + + def remove(self, global_docnum): + """Removes a document from the collector. Not that this method uses the + global document number as opposed to :meth:`Collector.collect` which + takes a segment-relative docnum. + """ + + items = self.items + for i in xrange(len(items)): + if items[i][1] == global_docnum: + items.pop(i) + return + raise KeyError(global_docnum) + + def _step_through_matches(self): + matcher = self.matcher + while matcher.is_active(): + yield matcher.id() + matcher.next() + + def matches(self): + """Yields a series of relative document numbers for matches + in the current subsearcher. + """ + + # We jump through a lot of hoops to avoid stepping through the matcher + # "manually" if we can because all_ids() is MUCH faster + if self.context.needs_current: + return self._step_through_matches() + else: + return self.matcher.all_ids() + + def finish(self): + """This method is called after a search. + + Subclasses can override this to perform set-up work, but + they should still call the superclass's method because it sets several + necessary attributes on the collector object: + + self.runtime + The time (in seconds) the search took. + """ + + self.runtime = now() - self.starttime + + def _results(self, items, **kwargs): + # Fills in a Results object with the invariant information and the + # given "items" (a list of (score, docnum) tuples) + r = Results(self.top_searcher, self.q, items, **kwargs) + r.runtime = self.runtime + r.collector = self + return r + + @abstractmethod + def results(self): + """Returns a :class:`~whoosh.searching.Results` object containing the + results of the search. Subclasses must implement this method + """ + + raise NotImplementedError + + +# Scored collectors + +class ScoredCollector(Collector): + """Base class for collectors that sort the results based on document score. + """ + + def __init__(self, replace=10): + """ + :param replace: Number of matches between attempts to replace the + matcher with a more efficient version. + """ + + Collector.__init__(self) + self.replace = replace + + def prepare(self, top_searcher, q, context): + # This collector requires a valid matcher at each step + Collector.prepare(self, top_searcher, q, context) + + if top_searcher.weighting.use_final: + self.final_fn = top_searcher.weighting.final + else: + self.final_fn = None + + # Heap containing top N (score, 0-docnum) pairs + self.items = [] + # Minimum score a document must have to make it into the top N. This is + # used by the block-quality optimizations + self.minscore = 0 + # Number of times the matcher was replaced (for debugging) + self.replaced_times = 0 + # Number of blocks skipped by quality optimizations (for debugging) + self.skipped_times = 0 + + def sort_key(self, sub_docnum): + return 0 - self.matcher.score() + + def _collect(self, global_docnum, score): + # Concrete subclasses should override this method to collect matching + # documents + + raise NotImplementedError + + def _use_block_quality(self): + # Concrete subclasses should override this method to return True if the + # collector should use block quality optimizations + + return False + + def collect(self, sub_docnum): + # Do common work to calculate score and top-level document number + global_docnum = self.offset + sub_docnum + + score = self.matcher.score() + if self.final_fn: + score = self.final_fn(self.top_searcher, global_docnum, score) + + # Call specialized method on subclass + return self._collect(global_docnum, score) + + def matches(self): + minscore = self.minscore + matcher = self.matcher + usequality = self._use_block_quality() + replace = self.replace + replacecounter = 0 + + # A flag to indicate whether we should check block quality at the start + # of the next loop + checkquality = True + + while matcher.is_active(): + # If the replacement counter has reached 0, try replacing the + # matcher with a more efficient version + if replace: + if replacecounter == 0 or self.minscore != minscore: + self.matcher = matcher = matcher.replace(minscore or 0) + self.replaced_times += 1 + if not matcher.is_active(): + break + usequality = self._use_block_quality() + replacecounter = self.replace + + if self.minscore != minscore: + checkquality = True + minscore = self.minscore + + replacecounter -= 1 + + # If we're using block quality optimizations, and the checkquality + # flag is true, try to skip ahead to the next block with the + # minimum required quality + if usequality and checkquality and minscore is not None: + self.skipped_times += matcher.skip_to_quality(minscore) + # Skipping ahead might have moved the matcher to the end of the + # posting list + if not matcher.is_active(): + break + + yield matcher.id() + + # Move to the next document. This method returns True if the + # matcher has entered a new block, so we should check block quality + # again. + checkquality = matcher.next() + + +class TopCollector(ScoredCollector): + """A collector that only returns the top "N" scored results. + """ + + def __init__(self, limit=10, usequality=True, **kwargs): + """ + :param limit: the maximum number of results to return. + :param usequality: whether to use block-quality optimizations. This may + be useful for debugging. + """ + + ScoredCollector.__init__(self, **kwargs) + self.limit = limit + self.usequality = usequality + self.total = 0 + + def _use_block_quality(self): + return (self.usequality + and not self.top_searcher.weighting.use_final + and self.matcher.supports_block_quality()) + + def computes_count(self): + return not self._use_block_quality() + + def all_ids(self): + # Since this collector can skip blocks, it doesn't track the total + # number of matching documents, so if the user asks for all matched + # docs we need to re-run the search using docs_for_query + + return self.top_searcher.docs_for_query(self.q) + + def count(self): + if self.computes_count(): + return self.total + else: + return ilen(self.all_ids()) + + # ScoredCollector.collect calls this + def _collect(self, global_docnum, score): + items = self.items + self.total += 1 + + # Document numbers are negated before putting them in the heap so that + # higher document numbers have lower "priority" in the queue. Lower + # document numbers should always come before higher document numbers + # with the same score to keep the order stable. + if len(items) < self.limit: + # The heap isn't full, so add this document + heappush(items, (score, 0 - global_docnum)) + # Negate score to act as sort key so higher scores appear first + return 0 - score + elif score > items[0][0]: + # The heap is full, but if this document has a high enough + # score to make the top N, add it to the heap + heapreplace(items, (score, 0 - global_docnum)) + self.minscore = items[0][0] + # Negate score to act as sort key so higher scores appear first + return 0 - score + else: + return 0 + + def remove(self, global_docnum): + negated = 0 - global_docnum + items = self.items + + # Remove the document if it's on the list (it may not be since + # TopCollector forgets documents that don't make the top N list) + for i in xrange(len(items)): + if items[i][1] == negated: + items.pop(i) + # Restore the heap invariant + heapify(items) + self.minscore = items[0][0] if items else 0 + return + + def results(self): + # The items are stored (postive score, negative docnum) so the heap + # keeps the highest scores and lowest docnums, in order from lowest to + # highest. Since for the results we want the highest scores first, + # sort the heap in reverse order + items = self.items + items.sort(reverse=True) + # De-negate the docnums for presentation to the user + items = [(score, 0 - docnum) for score, docnum in items] + return self._results(items) + + +class UnlimitedCollector(ScoredCollector): + """A collector that returns **all** scored results. + """ + + def __init__(self, reverse=False): + ScoredCollector.__init__(self) + self.reverse = reverse + + # ScoredCollector.collect calls this + def _collect(self, global_docnum, score): + self.items.append((score, global_docnum)) + self.docset.add(global_docnum) + # Negate score to act as sort key so higher scores appear first + return 0 - score + + def results(self): + # Sort by negated scores so that higher scores go first, then by + # document number to keep the order stable when documents have the + # same score + self.items.sort(key=lambda x: (0 - x[0], x[1]), reverse=self.reverse) + return self._results(self.items, docset=self.docset) + + +# Sorting collector + +class SortingCollector(Collector): + """A collector that returns results sorted by a given + :class:`whoosh.sorting.Facet` object. See :doc:`/facets` for more + information. + """ + + def __init__(self, sortedby, limit=10, reverse=False): + """ + :param sortedby: see :doc:`/facets`. + :param reverse: If True, reverse the overall results. Note that you + can reverse individual facets in a multi-facet sort key as well. + """ + + Collector.__init__(self) + self.sortfacet = sorting.MultiFacet.from_sortedby(sortedby) + self.limit = limit + self.reverse = reverse + + def prepare(self, top_searcher, q, context): + self.categorizer = self.sortfacet.categorizer(top_searcher) + # If the categorizer requires a valid matcher, then tell the child + # collector that we need it + rm = context.needs_current or self.categorizer.needs_current + Collector.prepare(self, top_searcher, q, context.set(needs_current=rm)) + + # List of (sortkey, docnum) pairs + self.items = [] + + def set_subsearcher(self, subsearcher, offset): + Collector.set_subsearcher(self, subsearcher, offset) + self.categorizer.set_searcher(subsearcher, offset) + + def sort_key(self, sub_docnum): + return self.categorizer.key_for(self.matcher, sub_docnum) + + def collect(self, sub_docnum): + global_docnum = self.offset + sub_docnum + sortkey = self.sort_key(sub_docnum) + self.items.append((sortkey, global_docnum)) + self.docset.add(global_docnum) + return sortkey + + def results(self): + items = self.items + items.sort(reverse=self.reverse) + if self.limit: + items = items[:self.limit] + return self._results(items, docset=self.docset) + + +class UnsortedCollector(Collector): + def prepare(self, top_searcher, q, context): + Collector.prepare(self, top_searcher, q, context.set(weighting=None)) + self.items = [] + + def collect(self, sub_docnum): + global_docnum = self.offset + sub_docnum + self.items.append((None, global_docnum)) + self.docset.add(global_docnum) + + def results(self): + items = self.items + return self._results(items, docset=self.docset) + + +# Wrapping collectors + +class WrappingCollector(Collector): + """Base class for collectors that wrap other collectors. + """ + + def __init__(self, child): + self.child = child + + @property + def top_searcher(self): + return self.child.top_searcher + + @property + def context(self): + return self.child.context + + def prepare(self, top_searcher, q, context): + self.child.prepare(top_searcher, q, context) + + def set_subsearcher(self, subsearcher, offset): + self.child.set_subsearcher(subsearcher, offset) + self.subsearcher = subsearcher + self.matcher = self.child.matcher + self.offset = self.child.offset + + def all_ids(self): + return self.child.all_ids() + + def count(self): + return self.child.count() + + def collect_matches(self): + for sub_docnum in self.matches(): + self.collect(sub_docnum) + + def sort_key(self, sub_docnum): + return self.child.sort_key(sub_docnum) + + def collect(self, sub_docnum): + return self.child.collect(sub_docnum) + + def remove(self, global_docnum): + return self.child.remove(global_docnum) + + def matches(self): + return self.child.matches() + + def finish(self): + self.child.finish() + + def results(self): + return self.child.results() + + +# Allow and disallow collector + +class FilterCollector(WrappingCollector): + """A collector that lets you allow and/or restrict certain document numbers + in the results:: + + uc = collectors.UnlimitedCollector() + + ins = query.Term("chapter", "rendering") + outs = query.Term("status", "restricted") + fc = FilterCollector(uc, allow=ins, restrict=outs) + + mysearcher.search_with_collector(myquery, fc) + print(fc.results()) + + This collector discards a document if: + + * The allowed set is not None and a document number is not in the set, or + * The restrict set is not None and a document number is in the set. + + (So, if the same document number is in both sets, that document will be + discarded.) + + If you have a reference to the collector, you can use + ``FilterCollector.filtered_count`` to get the number of matching documents + filtered out of the results by the collector. + """ + + def __init__(self, child, allow=None, restrict=None): + """ + :param child: the collector to wrap. + :param allow: a query, Results object, or set-like object containing + docnument numbers that are allowed in the results, or None (meaning + everything is allowed). + :param restrict: a query, Results object, or set-like object containing + document numbers to disallow from the results, or None (meaning + nothing is disallowed). + """ + + self.child = child + self.allow = allow + self.restrict = restrict + + def prepare(self, top_searcher, q, context): + self.child.prepare(top_searcher, q, context) + + allow = self.allow + restrict = self.restrict + ftc = top_searcher._filter_to_comb + + self._allow = ftc(allow) if allow else None + self._restrict = ftc(restrict) if restrict else None + self.filtered_count = 0 + + def all_ids(self): + child = self.child + + _allow = self._allow + _restrict = self._restrict + + for global_docnum in child.all_ids(): + if ( + (_allow and global_docnum not in _allow) or + (_restrict and global_docnum in _restrict) + ): + continue + yield global_docnum + + def count(self): + child = self.child + if child.computes_count(): + return child.count() + else: + return ilen(self.all_ids()) + + def collect_matches(self): + child = self.child + _allow = self._allow + _restrict = self._restrict + + if _allow is not None or _restrict is not None: + filtered_count = self.filtered_count + for sub_docnum in child.matches(): + global_docnum = self.offset + sub_docnum + if ((_allow is not None and global_docnum not in _allow) + or (_restrict is not None and global_docnum in _restrict)): + filtered_count += 1 + continue + child.collect(sub_docnum) + self.filtered_count = filtered_count + else: + # If there was no allow or restrict set, don't do anything special, + # just forward the call to the child collector + child.collect_matches() + + def results(self): + r = self.child.results() + r.collector = self + r.filtered_count = self.filtered_count + r.allowed = self.allow + r.restricted = self.restrict + return r + + +# Facet grouping collector + +class FacetCollector(WrappingCollector): + """A collector that creates groups of documents based on + :class:`whoosh.sorting.Facet` objects. See :doc:`/facets` for more + information. + + This collector is used if you specify a ``groupedby`` parameter in the + :meth:`whoosh.searching.Searcher.search` method. You can use the + :meth:`whoosh.searching.Results.groups` method to access the facet groups. + + If you have a reference to the collector can also use + ``FacetedCollector.facetmaps`` to access the groups directly:: + + uc = collectors.UnlimitedCollector() + fc = FacetedCollector(uc, sorting.FieldFacet("category")) + mysearcher.search_with_collector(myquery, fc) + print(fc.facetmaps) + """ + + def __init__(self, child, groupedby, maptype=None): + """ + :param groupedby: see :doc:`/facets`. + :param maptype: a :class:`whoosh.sorting.FacetMap` type to use for any + facets that don't specify their own. + """ + + self.child = child + self.facets = sorting.Facets.from_groupedby(groupedby) + self.maptype = maptype + + def prepare(self, top_searcher, q, context): + facets = self.facets + + # For each facet we're grouping by: + # - Create a facetmap (to hold the groups) + # - Create a categorizer (to generate document keys) + self.facetmaps = {} + self.categorizers = {} + + # Set needs_current to True if any of the categorizers require the + # current document to work + needs_current = context.needs_current + for facetname, facet in facets.items(): + self.facetmaps[facetname] = facet.map(self.maptype) + + ctr = facet.categorizer(top_searcher) + self.categorizers[facetname] = ctr + needs_current = needs_current or ctr.needs_current + context = context.set(needs_current=needs_current) + + self.child.prepare(top_searcher, q, context) + + def set_subsearcher(self, subsearcher, offset): + WrappingCollector.set_subsearcher(self, subsearcher, offset) + + # Tell each categorizer about the new subsearcher and offset + for categorizer in itervalues(self.categorizers): + categorizer.set_searcher(self.child.subsearcher, self.child.offset) + + def collect(self, sub_docnum): + matcher = self.child.matcher + global_docnum = sub_docnum + self.child.offset + + # We want the sort key for the document so we can (by default) sort + # the facet groups + sortkey = self.child.collect(sub_docnum) + + # For each facet we're grouping by + for name, categorizer in iteritems(self.categorizers): + add = self.facetmaps[name].add + + # We have to do more work if the facet allows overlapping groups + if categorizer.allow_overlap: + for key in categorizer.keys_for(matcher, sub_docnum): + add(categorizer.key_to_name(key), global_docnum, sortkey) + else: + key = categorizer.key_for(matcher, sub_docnum) + key = categorizer.key_to_name(key) + add(key, global_docnum, sortkey) + + return sortkey + + def results(self): + r = self.child.results() + r._facetmaps = self.facetmaps + return r + + +# Collapsing collector + +class CollapseCollector(WrappingCollector): + """A collector that collapses results based on a facet. That is, it + eliminates all but the top N results that share the same facet key. + Documents with an empty key for the facet are never eliminated. + + The "top" results within each group is determined by the result ordering + (e.g. highest score in a scored search) or an optional second "ordering" + facet. + + If you have a reference to the collector you can use + ``CollapseCollector.collapsed_counts`` to access the number of documents + eliminated based on each key:: + + tc = TopCollector(limit=20) + cc = CollapseCollector(tc, "group", limit=3) + mysearcher.search_with_collector(myquery, cc) + print(cc.collapsed_counts) + + See :ref:`collapsing` for more information. + """ + + def __init__(self, child, keyfacet, limit=1, order=None): + """ + :param child: the collector to wrap. + :param keyfacet: a :class:`whoosh.sorting.Facet` to use for collapsing. + All but the top N documents that share a key will be eliminated + from the results. + :param limit: the maximum number of documents to keep for each key. + :param order: an optional :class:`whoosh.sorting.Facet` to use + to determine the "top" document(s) to keep when collapsing. The + default (``orderfaceet=None``) uses the results order (e.g. the + highest score in a scored search). + """ + + self.child = child + self.keyfacet = sorting.MultiFacet.from_sortedby(keyfacet) + + self.limit = limit + if order: + self.orderfacet = sorting.MultiFacet.from_sortedby(order) + else: + self.orderfacet = None + + def prepare(self, top_searcher, q, context): + # Categorizer for getting the collapse key of a document + self.keyer = self.keyfacet.categorizer(top_searcher) + # Categorizer for getting the collapse order of a document + self.orderer = None + if self.orderfacet: + self.orderer = self.orderfacet.categorizer(top_searcher) + + # Dictionary mapping keys to lists of (sortkey, global_docnum) pairs + # representing the best docs for that key + self.lists = defaultdict(list) + # Dictionary mapping keys to the number of documents that have been + # filtered out with that key + self.collapsed_counts = defaultdict(int) + # Total number of documents filtered out by collapsing + self.collapsed_total = 0 + + # If the keyer or orderer require a valid matcher, tell the child + # collector we need it + needs_current = (context.needs_current + or self.keyer.needs_current + or (self.orderer and self.orderer.needs_current)) + self.child.prepare(top_searcher, q, + context.set(needs_current=needs_current)) + + def set_subsearcher(self, subsearcher, offset): + WrappingCollector.set_subsearcher(self, subsearcher, offset) + + # Tell the keyer and (optional) orderer about the new subsearcher + self.keyer.set_searcher(subsearcher, offset) + if self.orderer: + self.orderer.set_searcher(subsearcher, offset) + + def all_ids(self): + child = self.child + limit = self.limit + counters = defaultdict(int) + + for subsearcher, offset in child.subsearchers(): + self.set_subsearcher(subsearcher, offset) + matcher = child.matcher + keyer = self.keyer + for sub_docnum in child.matches(): + ckey = keyer.key_for(matcher, sub_docnum) + if ckey is not None: + if ckey in counters and counters[ckey] >= limit: + continue + else: + counters[ckey] += 1 + yield offset + sub_docnum + + def count(self): + if self.child.computes_count(): + return self.child.count() - self.collapsed_total + else: + return ilen(self.all_ids()) + + def collect_matches(self): + lists = self.lists + limit = self.limit + keyer = self.keyer + orderer = self.orderer + collapsed_counts = self.collapsed_counts + + child = self.child + matcher = child.matcher + offset = child.offset + for sub_docnum in child.matches(): + # Collapsing category key + ckey = keyer.key_to_name(keyer.key_for(matcher, sub_docnum)) + if not ckey: + # If the document isn't in a collapsing category, just add it + child.collect(sub_docnum) + else: + global_docnum = offset + sub_docnum + + if orderer: + # If user specified a collapse order, use it + sortkey = orderer.key_for(child.matcher, sub_docnum) + else: + # Otherwise, use the results order + sortkey = child.sort_key(sub_docnum) + + # Current list of best docs for this collapse key + best = lists[ckey] + add = False + if len(best) < limit: + # If the heap is not full yet, just add this document + add = True + elif sortkey < best[-1][0]: + # If the heap is full but this document has a lower sort + # key than the highest key currently on the heap, replace + # the "least-best" document + # Tell the child collector to remove the document + child.remove(best.pop()[1]) + add = True + + if add: + insort(best, (sortkey, global_docnum)) + child.collect(sub_docnum) + else: + # Remember that a document was filtered + collapsed_counts[ckey] += 1 + self.collapsed_total += 1 + + def results(self): + r = self.child.results() + r.collapsed_counts = self.collapsed_counts + return r + + +# Time limit collector + +class TimeLimitCollector(WrappingCollector): + """A collector that raises a :class:`TimeLimit` exception if the search + does not complete within a certain number of seconds:: + + uc = collectors.UnlimitedCollector() + tlc = TimeLimitedCollector(uc, timelimit=5.8) + try: + mysearcher.search_with_collector(myquery, tlc) + except collectors.TimeLimit: + print("The search ran out of time!") + + # We can still get partial results from the collector + print(tlc.results()) + + IMPORTANT: On Unix systems (systems where signal.SIGALRM is defined), the + code uses signals to stop searching immediately when the time limit is + reached. On Windows, the OS does not support this functionality, so the + search only checks the time between each found document, so if a matcher + is slow the search could exceed the time limit. + """ + + def __init__(self, child, timelimit, greedy=False, use_alarm=True): + """ + :param child: the collector to wrap. + :param timelimit: the maximum amount of time (in seconds) to + allow for searching. If the search takes longer than this, it will + raise a ``TimeLimit`` exception. + :param greedy: if ``True``, the collector will finish adding the most + recent hit before raising the ``TimeLimit`` exception. + :param use_alarm: if ``True`` (the default), the collector will try to + use signal.SIGALRM (on UNIX). + """ + self.child = child + self.timelimit = timelimit + self.greedy = greedy + + if use_alarm: + import signal + self.use_alarm = use_alarm and hasattr(signal, "SIGALRM") + else: + self.use_alarm = False + + self.timer = None + self.timedout = False + + def prepare(self, top_searcher, q, context): + self.child.prepare(top_searcher, q, context) + + self.timedout = False + if self.use_alarm: + import signal + signal.signal(signal.SIGALRM, self._was_signaled) + + # Start a timer thread. If the timer fires, it will call this object's + # _timestop() method + self.timer = threading.Timer(self.timelimit, self._timestop) + self.timer.start() + + def _timestop(self): + # Called when the timer expires + self.timer = None + # Set an attribute that will be noticed in the collect_matches() loop + self.timedout = True + + if self.use_alarm: + import signal + os.kill(os.getpid(), signal.SIGALRM) + + def _was_signaled(self, signum, frame): + raise TimeLimit + + def collect_matches(self): + child = self.child + greedy = self.greedy + + for sub_docnum in child.matches(): + # If the timer fired since the last loop and we're not greedy, + # raise the exception + if self.timedout and not greedy: + raise TimeLimit + + child.collect(sub_docnum) + + # If the timer fired since we entered the loop or it fired earlier + # but we were greedy, raise now + if self.timedout: + raise TimeLimit + + def finish(self): + if self.timer: + self.timer.cancel() + self.timer = None + self.child.finish() + + +# Matched terms collector + +class TermsCollector(WrappingCollector): + """A collector that remembers which terms appeared in which terms appeared + in each matched document. + + This collector is used if you specify ``terms=True`` in the + :meth:`whoosh.searching.Searcher.search` method. + + If you have a reference to the collector can also use + ``TermsCollector.termslist`` to access the term lists directly:: + + uc = collectors.UnlimitedCollector() + tc = TermsCollector(uc) + mysearcher.search_with_collector(myquery, tc) + # tc.termdocs is a dictionary mapping (fieldname, text) tuples to + # sets of document numbers + print(tc.termdocs) + # tc.docterms is a dictionary mapping docnums to lists of + # (fieldname, text) tuples + print(tc.docterms) + """ + + def __init__(self, child, settype=set): + self.child = child + self.settype = settype + + def prepare(self, top_searcher, q, context): + # This collector requires a valid matcher at each step + self.child.prepare(top_searcher, q, context.set(needs_current=True)) + + # A dictionary mapping (fieldname, text) pairs to arrays of docnums + self.termdocs = defaultdict(lambda: array("I")) + # A dictionary mapping docnums to lists of (fieldname, text) pairs + self.docterms = defaultdict(list) + + def set_subsearcher(self, subsearcher, offset): + WrappingCollector.set_subsearcher(self, subsearcher, offset) + + # Store a list of all the term matchers in the matcher tree + self.termmatchers = list(self.child.matcher.term_matchers()) + + def collect(self, sub_docnum): + child = self.child + termdocs = self.termdocs + docterms = self.docterms + + child.collect(sub_docnum) + + global_docnum = child.offset + sub_docnum + + # For each term matcher... + for tm in self.termmatchers: + # If the term matcher is matching the current document... + if tm.is_active() and tm.id() == sub_docnum: + # Add it to the list of matching documents for the term + term = tm.term() + termdocs[term].append(global_docnum) + docterms[global_docnum].append(term) + + def results(self): + r = self.child.results() + r.termdocs = dict(self.termdocs) + r.docterms = dict(self.docterms) + return r diff --git a/nstock/modules/whoosh/columns.py b/nstock/modules/whoosh/columns.py new file mode 100644 index 0000000..2f3e6cf --- /dev/null +++ b/nstock/modules/whoosh/columns.py @@ -0,0 +1,1474 @@ +# Copyright 2012 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +""" +The API and implementation of columns may change in the next version of Whoosh! + +This module contains "Column" objects which you can use as the argument to a +Field object's ``sortable=`` keyword argument. Each field defines a default +column type for when the user specifies ``sortable=True`` (the object returned +by the field's ``default_column()`` method). + +The default column type for most fields is ``VarBytesColumn``, +although numeric and date fields use ``NumericColumn``. Expert users may use +other field types that may be faster or more storage efficient based on the +field contents. For example, if a field always contains one of a limited number +of possible values, a ``RefBytesColumn`` will save space by only storing the +values once. If a field's values are always a fixed length, the +``FixedBytesColumn`` saves space by not storing the length of each value. + +A ``Column`` object basically exists to store configuration information and +provides two important methods: ``writer()`` to return a ``ColumnWriter`` object +and ``reader()`` to return a ``ColumnReader`` object. +""" + +from __future__ import division, with_statement +import struct, warnings +from array import array +from bisect import bisect_right + +try: + import zlib +except ImportError: + zlib = None + +from whoosh.compat import b, bytes_type, BytesIO +from whoosh.compat import array_tobytes, xrange +from whoosh.compat import dumps, loads +from whoosh.filedb.structfile import StructFile +from whoosh.idsets import BitSet, OnDiskBitSet +from whoosh.system import emptybytes +from whoosh.util.cache import lru_cache +from whoosh.util.numeric import typecode_max, typecode_min +from whoosh.util.numlists import GrowableArray +from whoosh.util.varints import varint, read_varint + + +# Utility functions + +def _mintype(maxn): + if maxn < 2 ** 8: + typecode = "B" + elif maxn < 2 ** 16: + typecode = "H" + elif maxn < 2 ** 31: + typecode = "i" + else: + typecode = "I" + + return typecode + + +# Python does not support arrays of long long see Issue 1172711 +# These functions help write/read a simulated an array of q/Q using lists + +def write_qsafe_array(typecode, arry, dbfile): + if typecode == "q": + for num in arry: + dbfile.write_long(num) + elif typecode == "Q": + for num in arry: + dbfile.write_ulong(num) + else: + dbfile.write_array(arry) + + +def read_qsafe_array(typecode, size, dbfile): + if typecode == "q": + arry = [dbfile.read_long() for _ in xrange(size)] + elif typecode == "Q": + arry = [dbfile.read_ulong() for _ in xrange(size)] + else: + arry = dbfile.read_array(typecode, size) + + return arry + + +def make_array(typecode, size=0, default=None): + if typecode.lower() == "q": + # Python does not support arrays of long long see Issue 1172711 + if default is not None and size: + arry = [default] * size + else: + arry = [] + else: + if default is not None and size: + arry = array(typecode, (default for _ in xrange(size))) + else: + arry = array(typecode) + return arry + + +# Base classes + +class Column(object): + """Represents a "column" of rows mapping docnums to document values. + + The interface requires that you store the start offset of the column, the + length of the column data, and the number of documents (rows) separately, + and pass them to the reader object. + """ + + reversible = False + + def writer(self, dbfile): + """Returns a :class:`ColumnWriter` object you can use to use to create + a column of this type on disk. + + :param dbfile: the :class:`~whoosh.filedb.structfile.StructFile` to + write to. + """ + + return self.Writer(dbfile) + + def reader(self, dbfile, basepos, length, doccount): + """Returns a :class:`ColumnReader` object you can use to read a column + of this type from disk. + + :param dbfile: the :class:`~whoosh.filedb.structfile.StructFile` to + read from. + :param basepos: the offset within the file at which the column starts. + :param length: the length in bytes of the column occupies in the file. + :param doccount: the number of rows (documents) in the column. + """ + + return self.Reader(dbfile, basepos, length, doccount) + + def default_value(self, reverse=False): + """Returns the default value for this column type. + """ + + return self._default + + def stores_lists(self): + """Returns True if the column stores a list of values for each document + instead of a single value. + """ + + return False + + +class ColumnWriter(object): + def __init__(self, dbfile): + self._dbfile = dbfile + self._count = 0 + + def fill(self, docnum): + write = self._dbfile.write + default = self._defaultbytes + if docnum > self._count: + for _ in xrange(docnum - self._count): + write(default) + + def add(self, docnum, value): + raise NotImplementedError + + def finish(self, docnum): + pass + + +class ColumnReader(object): + def __init__(self, dbfile, basepos, length, doccount): + self._dbfile = dbfile + self._basepos = basepos + self._length = length + self._doccount = doccount + + def __len__(self): + return self._doccount + + def __getitem__(self, docnum): + raise NotImplementedError + + def sort_key(self, docnum): + return self[docnum] + + def __iter__(self): + for i in xrange(self._doccount): + yield self[i] + + def load(self): + return list(self) + + def set_reverse(self): + raise NotImplementedError + + +# Arbitrary bytes column + +class VarBytesColumn(Column): + """Stores variable length byte strings. See also :class:`RefBytesColumn`. + + The current implementation limits the total length of all document values + a segment to 2 GB. + + The default value (the value returned for a document that didn't have a + value assigned to it at indexing time) is an empty bytestring (``b''``). + """ + + _default = emptybytes + + def __init__(self, allow_offsets=True, write_offsets_cutoff=2**15): + """ + :param allow_offsets: Whether the column should write offsets when there + are many rows in the column (this makes opening the column much + faster). This argument is mostly for testing. + :param write_offsets_cutoff: Write offsets (for speed) when there are + more than this many rows in the column. This argument is mostly + for testing. + """ + + self.allow_offsets = allow_offsets + self.write_offsets_cutoff = write_offsets_cutoff + + def writer(self, dbfile): + return self.Writer(dbfile, self.allow_offsets, + self.write_offsets_cutoff) + + class Writer(ColumnWriter): + def __init__(self, dbfile, allow_offsets=True, cutoff=2**15): + assert isinstance(dbfile, StructFile) + self._dbfile = dbfile + self._count = 0 + self._lengths = GrowableArray(allow_longs=False) + self._offsets = GrowableArray(allow_longs=False) + self._offset_base = 0 + self.allow_offsets = allow_offsets + self.cutoff = cutoff + + def __repr__(self): + return "" + + def fill(self, docnum): + base = self._offset_base + if docnum > self._count: + self._lengths.extend(0 for _ in xrange(docnum - self._count)) + self._offsets.extend(base for _ in xrange(docnum - self._count)) + + def add(self, docnum, v): + self.fill(docnum) + self._dbfile.write(v) + self._lengths.append(len(v)) + self._offsets.append(self._offset_base) + self._offset_base += len(v) + self._count = docnum + 1 + + def finish(self, doccount): + dbfile = self._dbfile + lengths = self._lengths.array + offsets = self._offsets.array + self.fill(doccount) + + dbfile.write_array(lengths) + + # Only write the offsets if there is a large number of items in the + # column, otherwise it's fast enough to derive them from the lens + write_offsets = self.allow_offsets and doccount > self.cutoff + if write_offsets: + dbfile.write_array(offsets) + + # Backwards compatibility: previous versions only wrote the lengths, + # and the last byte of the column was the lengths type code... + dbfile.write(lengths.typecode.encode("ascii")) + # ...but if we wrote offsets, make the last byte "X" so we know + if write_offsets: + dbfile.write(offsets.typecode.encode("ascii")) + dbfile.write("X".encode("ascii")) + + class Reader(ColumnReader): + def __init__(self, dbfile, basepos, length, doccount): + self._dbfile = dbfile + self._basepos = basepos + self._length = length + self._doccount = doccount + + self.had_stored_offsets = False # for testing + self._read_offsets_and_lengths() + + def __repr__(self): + return "" + + def _read_offsets_and_lengths(self): + dbfile = self._dbfile + basepos = self._basepos + length = self._length + doccount = self._doccount + + # The end of the lengths array is the end of the data minus the + # typecode byte + lastbyte = basepos + length - 1 + # Load the length typecode from the end + lens_code = chr(dbfile.get_byte(lastbyte)) + + offsets = None + if lens_code == "X": + self.had_stored_offsets = True + # This indicates we wrote the offsets, so get the real lengths + # type code + lens_code = chr(dbfile.get_byte(lastbyte - 2)) + offsets_code = chr(dbfile.get_byte(lastbyte - 1)) + + # Read the offsets from before the last byte + itemsize = struct.calcsize(offsets_code) + offsetstart = (lastbyte - 2) - doccount * itemsize + offsets = dbfile.get_array(offsetstart, offsets_code, doccount) + lastbyte = offsetstart + + # Load the length array + itemsize = struct.calcsize(lens_code) + lenstart = lastbyte - (itemsize * doccount) + lengths = dbfile.get_array(lenstart, lens_code, doccount) + + # If we didn't write the offsets, derive them from the lengths + if offsets is None: + offsets = array("L") + base = 0 + for length in lengths: + offsets.append(base) + base += length + + self._offsets = offsets + self._lengths = lengths + + def __getitem__(self, docnum): + length = self._lengths[docnum] + if not length: + return emptybytes + offset = self._offsets[docnum] + return self._dbfile.get(self._basepos + offset, length) + + def __iter__(self): + get = self._dbfile.get + pos = self._basepos + for length in self._lengths: + yield get(pos, length) + pos += length + + +class FixedBytesColumn(Column): + """Stores fixed-length byte strings. + """ + + def __init__(self, fixedlen, default=None): + """ + :param fixedlen: the fixed length of byte strings in this column. + :param default: the default value to use for documents that don't + specify a value. If you don't specify a default, the column will + use ``b'\\x00' * fixedlen``. + """ + + self._fixedlen = fixedlen + + if default is None: + default = b("\x00") * fixedlen + elif len(default) != fixedlen: + raise ValueError + self._default = default + + def writer(self, dbfile): + return self.Writer(dbfile, self._fixedlen, self._default) + + def reader(self, dbfile, basepos, length, doccount): + return self.Reader(dbfile, basepos, length, doccount, self._fixedlen, + self._default) + + class Writer(ColumnWriter): + def __init__(self, dbfile, fixedlen, default): + self._dbfile = dbfile + self._fixedlen = fixedlen + self._default = self._defaultbytes = default + self._count = 0 + + def __repr__(self): + return "" + + def add(self, docnum, v): + if v == self._default: + return + if docnum > self._count: + self.fill(docnum) + assert len(v) == self._fixedlen + self._dbfile.write(v) + self._count = docnum + 1 + + class Reader(ColumnReader): + def __init__(self, dbfile, basepos, length, doccount, fixedlen, + default): + self._dbfile = dbfile + self._basepos = basepos + self._doccount = doccount + self._fixedlen = fixedlen + self._default = self._defaultbytes = default + self._count = length // fixedlen + + def __repr__(self): + return "" + + def __getitem__(self, docnum): + if docnum >= self._count: + return self._defaultbytes + pos = self._basepos + self._fixedlen * docnum + return self._dbfile.get(pos, self._fixedlen) + + def __iter__(self): + count = self._count + default = self._default + for i in xrange(self._doccount): + if i < count: + yield self[i] + else: + yield default + + +# Variable/fixed length reference (enum) column + +class RefBytesColumn(Column): + """Stores variable-length or fixed-length byte strings, similar to + :class:`VarBytesColumn` and :class:`FixedBytesColumn`. However, where those + columns stores a value for each document, this column keeps a list of all + the unique values in the field, and for each document stores a short + pointer into the unique list. For fields where the number of possible + values is smaller than the number of documents (for example, + "category" or "chapter"), this saves significant space. + + This column type supports a maximum of 65535 unique values across all + documents in a segment. You should generally use this column type where the + number of unique values is in no danger of approaching that number (for + example, a "tags" field). If you try to index too many unique values, the + column will convert additional unique values to the default value and issue + a warning using the ``warnings`` module (this will usually be preferable to + crashing the indexer and potentially losing indexed documents). + """ + + # NOTE that RefBytes is reversible within a single column (we could just + # negate the reference number), but it's NOT reversible ACROSS SEGMENTS + # (since different segments can have different uniques values in their + # columns), so we have to say that the column type is not reversible + reversible = False + + def __init__(self, fixedlen=0, default=None): + """ + :param fixedlen: an optional fixed length for the values. If you + specify a number other than 0, the column will require all values + to be the specified length. + :param default: a default value to use for documents that don't specify + one. If you don't specify a default, the column will use an empty + bytestring (``b''``), or if you specify a fixed length, + ``b'\\x00' * fixedlen``. + """ + + self._fixedlen = fixedlen + + if default is None: + default = b("\x00") * fixedlen if fixedlen else emptybytes + elif fixedlen and len(default) != fixedlen: + raise ValueError + self._default = default + + def writer(self, dbfile): + return self.Writer(dbfile, self._fixedlen, self._default) + + def reader(self, dbfile, basepos, length, doccount): + return self.Reader(dbfile, basepos, length, doccount, self._fixedlen) + + class Writer(ColumnWriter): + def __init__(self, dbfile, fixedlen, default): + self._dbfile = dbfile + self._fixedlen = fixedlen + self._default = default + + # At first we'll buffer refs in a byte array. If the number of + # uniques stays below 256, we can just write the byte array. As + # soon as the ref count goes above 255, we know we're going to have + # to write shorts, so we'll switch to writing directly. + self._refs = array("B") + self._uniques = {default: 0} + self._count = 0 + + def __repr__(self): + return "" + + def fill(self, docnum): + if docnum > self._count: + if self._refs is not None: + self._refs.extend(0 for _ in xrange(docnum - self._count)) + else: + dbfile = self._dbfile + for _ in xrange(docnum - self._count): + dbfile.write_ushort(0) + + def add(self, docnum, v): + dbfile = self._dbfile + refs = self._refs + self.fill(docnum) + + uniques = self._uniques + try: + ref = uniques[v] + except KeyError: + uniques[v] = ref = len(uniques) + if refs is not None and ref >= 256: + # We won't be able to use bytes, we have to switch to + # writing unbuffered ushorts + for n in refs: + dbfile.write_ushort(n) + refs = self._refs = None + + if refs is not None: + self._refs.append(ref) + else: + if ref > 65535: + warnings.warn("RefBytesColumn dropped unique value %r" % v, + UserWarning) + ref = 0 + dbfile.write_ushort(ref) + + self._count = docnum + 1 + + def _write_uniques(self, typecode): + dbfile = self._dbfile + fixedlen = self._fixedlen + uniques = self._uniques + + dbfile.write_varint(len(uniques)) + # Sort unique values by position + vs = sorted(uniques.keys(), key=lambda key: uniques[key]) + for v in vs: + if not fixedlen: + dbfile.write_varint(len(v)) + dbfile.write(v) + + def finish(self, doccount): + dbfile = self._dbfile + refs = self._refs + self.fill(doccount) + + typecode = "H" + if refs is not None: + dbfile.write_array(refs) + typecode = refs.typecode + + self._write_uniques(typecode) + dbfile.write_byte(ord(typecode)) + + class Reader(ColumnReader): + def __init__(self, dbfile, basepos, length, doccount, fixedlen): + self._dbfile = dbfile + self._basepos = basepos + self._doccount = doccount + self._fixedlen = fixedlen + + self._typecode = chr(dbfile.get_byte(basepos + length - 1)) + + st = struct.Struct("!" + self._typecode) + self._unpack = st.unpack + self._itemsize = st.size + + dbfile.seek(basepos + doccount * self._itemsize) + self._uniques = self._read_uniques() + + def __repr__(self): + return "" + + def _read_uniques(self): + dbfile = self._dbfile + fixedlen = self._fixedlen + + ucount = dbfile.read_varint() + length = fixedlen + uniques = [] + for _ in xrange(ucount): + if not fixedlen: + length = dbfile.read_varint() + uniques.append(dbfile.read(length)) + return uniques + + def __getitem__(self, docnum): + pos = self._basepos + docnum * self._itemsize + ref = self._unpack(self._dbfile.get(pos, self._itemsize))[0] + return self._uniques[ref] + + def __iter__(self): + get = self._dbfile.get + basepos = self._basepos + uniques = self._uniques + unpack = self._unpack + itemsize = self._itemsize + + for i in xrange(self._doccount): + pos = basepos + i * itemsize + ref = unpack(get(pos, itemsize))[0] + yield uniques[ref] + + +# Numeric column + +class NumericColumn(FixedBytesColumn): + """Stores numbers (integers and floats) as compact binary. + """ + + reversible = True + + def __init__(self, typecode, default=0): + """ + :param typecode: a typecode character (as used by the ``struct`` + module) specifying the number type. For example, ``"i"`` for + signed integers. + :param default: the default value to use for documents that don't + specify one. + """ + + self._typecode = typecode + self._default = default + + def writer(self, dbfile): + return self.Writer(dbfile, self._typecode, self._default) + + def reader(self, dbfile, basepos, length, doccount): + return self.Reader(dbfile, basepos, length, doccount, self._typecode, + self._default) + + def default_value(self, reverse=False): + v = self._default + if reverse: + v = 0 - v + return v + + class Writer(FixedBytesColumn.Writer): + def __init__(self, dbfile, typecode, default): + self._dbfile = dbfile + self._pack = struct.Struct("!" + typecode).pack + self._default = default + self._defaultbytes = self._pack(default) + self._fixedlen = struct.calcsize(typecode) + self._count = 0 + + def __repr__(self): + return "" + + def add(self, docnum, v): + if v == self._default: + return + if docnum > self._count: + self.fill(docnum) + self._dbfile.write(self._pack(v)) + self._count = docnum + 1 + + class Reader(FixedBytesColumn.Reader): + def __init__(self, dbfile, basepos, length, doccount, typecode, + default): + self._dbfile = dbfile + self._basepos = basepos + self._doccount = doccount + self._default = default + self._reverse = False + + self._typecode = typecode + self._unpack = struct.Struct("!" + typecode).unpack + self._defaultbytes = struct.pack("!" + typecode, default) + self._fixedlen = struct.calcsize(typecode) + self._count = length // self._fixedlen + + def __repr__(self): + return "" + + def __getitem__(self, docnum): + s = FixedBytesColumn.Reader.__getitem__(self, docnum) + return self._unpack(s)[0] + + def sort_key(self, docnum): + key = self[docnum] + if self._reverse: + key = 0 - key + return key + + def load(self): + if self._typecode in "qQ": + return list(self) + else: + return array(self._typecode, self) + + def set_reverse(self): + self._reverse = True + + +# Column of boolean values + +class BitColumn(Column): + """Stores a column of True/False values compactly. + """ + + reversible = True + _default = False + + def __init__(self, compress_at=2048): + """ + :param compress_at: columns with this number of values or fewer will + be saved compressed on disk, and loaded into RAM for reading. Set + this to 0 to disable compression. + """ + + self._compressat = compress_at + + def writer(self, dbfile): + return self.Writer(dbfile, self._compressat) + + def default_value(self, reverse=False): + return self._default ^ reverse + + class Writer(ColumnWriter): + def __init__(self, dbfile, compressat): + self._dbfile = dbfile + self._compressat = compressat + self._bitset = BitSet() + + def __repr__(self): + return "" + + def add(self, docnum, value): + if value: + self._bitset.add(docnum) + + def finish(self, doccount): + dbfile = self._dbfile + bits = self._bitset.bits + + if zlib and len(bits) <= self._compressat: + compressed = zlib.compress(array_tobytes(bits), 3) + dbfile.write(compressed) + dbfile.write_byte(1) + else: + dbfile.write_array(bits) + dbfile.write_byte(0) + + class Reader(ColumnReader): + def __init__(self, dbfile, basepos, length, doccount): + self._dbfile = dbfile + self._basepos = basepos + self._length = length + self._doccount = doccount + self._reverse = False + + compressed = dbfile.get_byte(basepos + (length - 1)) + if compressed: + bbytes = zlib.decompress(dbfile.get(basepos, length - 1)) + bitset = BitSet.from_bytes(bbytes) + else: + dbfile.seek(basepos) + bitset = OnDiskBitSet(dbfile, basepos, length - 1) + self._bitset = bitset + + def id_set(self): + return self._bitset + + def __repr__(self): + return "" + + def __getitem__(self, i): + return i in self._bitset + + def sort_key(self, docnum): + return int(self[docnum] ^ self._reverse) + + def __iter__(self): + i = 0 + for num in self._bitset: + if num > i: + for _ in xrange(num - i): + yield False + yield True + i = num + 1 + if self._doccount > i: + for _ in xrange(self._doccount - i): + yield False + + def load(self): + if isinstance(self._bitset, OnDiskBitSet): + bs = self._dbfile.get_array(self._basepos, "B", + self._length - 1) + self._bitset = BitSet.from_bytes(bs) + return self + + def set_reverse(self): + self._reverse = True + + +# Compressed variants + +class CompressedBytesColumn(Column): + """Stores variable-length byte strings compressed using deflate (by + default). + """ + + def __init__(self, level=3, module="zlib"): + """ + :param level: the compression level to use. + :param module: a string containing the name of the compression module + to use. The default is "zlib". The module should export "compress" + and "decompress" functions. + """ + + self._level = level + self._module = module + + def writer(self, dbfile): + return self.Writer(dbfile, self._level, self._module) + + def reader(self, dbfile, basepos, length, doccount): + return self.Reader(dbfile, basepos, length, doccount, self._module) + + class Writer(VarBytesColumn.Writer): + def __init__(self, dbfile, level, module): + VarBytesColumn.Writer.__init__(self, dbfile) + self._level = level + self._compress = __import__(module).compress + + def __repr__(self): + return "" + + def add(self, docnum, v): + v = self._compress(v, self._level) + VarBytesColumn.Writer.add(self, docnum, v) + + class Reader(VarBytesColumn.Reader): + def __init__(self, dbfile, basepos, length, doccount, module): + VarBytesColumn.Reader.__init__(self, dbfile, basepos, length, + doccount) + self._decompress = __import__(module).decompress + + def __repr__(self): + return "" + + def __getitem__(self, docnum): + v = VarBytesColumn.Reader.__getitem__(self, docnum) + if v: + v = self._decompress(v) + return v + + def __iter__(self): + for v in VarBytesColumn.Reader.__iter__(self): + yield self._decompress(v) + + def load(self): + return list(self) + + +class CompressedBlockColumn(Column): + """An experimental column type that compresses and decompresses blocks of + values at a time. This can lead to high compression and decent performance + for columns with lots of very short values, but random access times are + usually terrible. + """ + + def __init__(self, level=3, blocksize=32, module="zlib"): + """ + :param level: the compression level to use. + :param blocksize: the size (in KB) of each compressed block. + :param module: a string containing the name of the compression module + to use. The default is "zlib". The module should export "compress" + and "decompress" functions. + """ + + self._level = level + self._blocksize = blocksize + self._module = module + + def writer(self, dbfile): + return self.Writer(dbfile, self._level, self._blocksize, self._module) + + def reader(self, dbfile, basepos, length, doccount): + return self.Reader(dbfile, basepos, length, doccount, self._module) + + class Writer(ColumnWriter): + def __init__(self, dbfile, level, blocksize, module): + self._dbfile = dbfile + self._blocksize = blocksize * 1024 + self._level = level + self._compress = __import__(module).compress + + self._reset() + + def __repr__(self): + return "" + + def _reset(self): + self._startdoc = None + self._block = emptybytes + self._lengths = [] + + def _emit(self): + dbfile = self._dbfile + block = self._compress(self._block, self._level) + header = (self._startdoc, self._lastdoc, len(block), + tuple(self._lengths)) + dbfile.write_pickle(header) + dbfile.write(block) + + def add(self, docnum, v): + if self._startdoc is None: + self._startdoc = docnum + self._lengths.append((docnum, len(v))) + self._lastdoc = docnum + + self._block += v + if len(self._block) >= self._blocksize: + self._emit() + self._reset() + + def finish(self, doccount): + # If there's still a pending block, write it out + if self._startdoc is not None: + self._emit() + + class Reader(ColumnReader): + def __init__(self, dbfile, basepos, length, doccount, module): + ColumnReader.__init__(self, dbfile, basepos, length, doccount) + self._decompress = __import__(module).decompress + + self._blocks = [] + dbfile.seek(basepos) + pos = 0 + while pos < length: + startdoc, enddoc, blocklen, lengths = dbfile.read_pickle() + here = dbfile.tell() + self._blocks.append((startdoc, enddoc, here, blocklen, + lengths)) + dbfile.seek(blocklen, 1) + pos = here + blocklen + + def __repr__(self): + return "" + + def _find_block(self, docnum): + # TODO: use binary search instead of linear + for i, b in enumerate(self._blocks): + if docnum < b[0]: + return None + elif docnum <= b[1]: + return i + return None + + def _get_block(self, blocknum): + block = self._blocks[blocknum] + pos = block[2] + blocklen = block[3] + lengths = block[4] + + data = self._decompress(self._dbfile.get(self._basepos + pos, + blocklen)) + values = {} + base = 0 + for docnum, vlen in lengths: + values[docnum] = data[base:base + vlen] + base += vlen + return values + + def __getitem__(self, docnum): + i = self._find_block(docnum) + if i is None: + return emptybytes + return self._get_block(i)[docnum] + + def __iter__(self): + last = -1 + for i, block in enumerate(self._blocks): + startdoc = block[0] + enddoc = block[1] + if startdoc > (last + 1): + for _ in xrange(startdoc - last): + yield emptybytes + values = self._get_block(i) + for docnum in xrange(startdoc, enddoc + 1): + if docnum in values: + yield values[docnum] + else: + yield emptybytes + last = enddoc + if enddoc < self._doccount - 1: + for _ in xrange(self._doccount - enddoc): + yield emptybytes + + +class StructColumn(FixedBytesColumn): + def __init__(self, spec, default): + self._spec = spec + self._fixedlen = struct.calcsize(spec) + self._default = default + + def writer(self, dbfile): + return self.Writer(dbfile, self._spec, self._default) + + def reader(self, dbfile, basepos, length, doccount): + return self.Reader(dbfile, basepos, length, doccount, self._spec, + self._default) + + class Writer(FixedBytesColumn.Writer): + def __init__(self, dbfile, spec, default): + self._dbfile = dbfile + self._struct = struct.Struct(spec) + self._fixedlen = self._struct.size + self._default = default + self._defaultbytes = self._struct.pack(*default) + self._count = 0 + + def __repr__(self): + return "" + + def add(self, docnum, v): + b = self._struct.pack(*v) + FixedBytesColumn.Writer.add(self, docnum, b) + + class Reader(FixedBytesColumn.Reader): + def __init__(self, dbfile, basepos, length, doccount, spec, default): + self._dbfile = dbfile + self._basepos = basepos + self._doccount = doccount + self._struct = struct.Struct(spec) + self._fixedlen = self._struct.size + self._default = default + self._defaultbytes = self._struct.pack(*default) + self._count = length // self._fixedlen + + def __repr__(self): + return "" + + def __getitem__(self, docnum): + v = FixedBytesColumn.Reader.__getitem__(self, docnum) + return self._struct.unpack(v) + + +# Utility readers + +class EmptyColumnReader(ColumnReader): + """Acts like a reader for a column with no stored values. Always returns + the default. + """ + + def __init__(self, default, doccount): + """ + :param default: the value to return for all "get" requests. + :param doccount: the number of documents in the nominal column. + """ + + self._default = default + self._doccount = doccount + + def __getitem__(self, docnum): + return self._default + + def __iter__(self): + return (self._default for _ in xrange(self._doccount)) + + def load(self): + return self + + +class MultiColumnReader(ColumnReader): + """Serializes access to multiple column readers, making them appear to be + one large column. + """ + + def __init__(self, readers, offsets=None): + """ + :param readers: a sequence of column reader objects. + """ + + self._readers = readers + + self._doc_offsets = [] + self._doccount = 0 + + if offsets is None: + for r in readers: + self._doc_offsets.append(self._doccount) + self._doccount += len(r) + else: + assert len(offsets) == len(readers) + self._doc_offsets = offsets + + def _document_reader(self, docnum): + return max(0, bisect_right(self._doc_offsets, docnum) - 1) + + def _reader_and_docnum(self, docnum): + rnum = self._document_reader(docnum) + offset = self._doc_offsets[rnum] + return rnum, docnum - offset + + def __getitem__(self, docnum): + x, y = self._reader_and_docnum(docnum) + return self._readers[x][y] + + def __iter__(self): + for r in self._readers: + for v in r: + yield v + + +class TranslatingColumnReader(ColumnReader): + """Calls a function to "translate" values from an underlying column reader + object before returning them. + + ``IndexReader`` objects can wrap a column reader with this object to call + ``FieldType.from_column_value`` on the stored column value before returning + it the the user. + """ + + def __init__(self, reader, translate): + """ + :param reader: the underlying ColumnReader object to get values from. + :param translate: a function that takes a value from the underlying + reader and returns a translated value. + """ + + self._reader = reader + self._translate = translate + + def raw_column(self): + """Returns the underlying column reader. + """ + + return self._reader + + def __len__(self): + return len(self._reader) + + def __getitem__(self, docnum): + return self._translate(self._reader[docnum]) + + def sort_key(self, docnum): + return self._reader.sort_key(docnum) + + def __iter__(self): + translate = self._translate + return (translate(v) for v in self._reader) + + def set_reverse(self): + self._reader.set_reverse() + + +# Column wrappers + +class WrappedColumn(Column): + def __init__(self, child): + self._child = child + + def writer(self, *args, **kwargs): + return self.Writer(self._child.writer(*args, **kwargs)) + + def reader(self, *args, **kwargs): + return self.Reader(self._child.reader(*args, **kwargs)) + + def stores_lists(self): + return self._child.stores_lists() + + +class WrappedColumnWriter(ColumnWriter): + def __init__(self, child): + self._child = child + + def fill(self, docnum): + return self._child.fill(docnum) + + def add(self, docnum, value): + return self._child.add(docnum, value) + + def finish(self, docnum): + return self._child.finish(docnum) + + +class WrappedColumnReader(ColumnReader): + def __init__(self, child): + self._child = child + + def __len__(self): + return len(self._child) + + def __getitem__(self, docnum): + return self._child[docnum] + + def sort_key(self, docnum): + return self._child.sort_key(docnum) + + def __iter__(self): + return iter(self._child) + + def load(self): + return list(self) + + def set_reverse(self): + self._child.set_reverse() + + +class ClampedNumericColumn(WrappedColumn): + """An experimental wrapper type for NumericColumn that clamps out-of-range + values instead of raising an exception. + """ + + def reader(self, *args, **kwargs): + return self._child.reader(*args, **kwargs) + + class Writer(WrappedColumnWriter): + def __init__(self, child): + self._child = child + self._min = typecode_min[child._typecode] + self._max = typecode_max[child._typecode] + + def add(self, docnum, v): + v = min(v, self._min) + v = max(v, self._max) + self._child.add(docnum, v) + + +class PickleColumn(WrappedColumn): + """Converts arbitrary objects to pickled bytestrings and stores them using + the wrapped column (usually a :class:`VarBytesColumn` or + :class:`CompressedBytesColumn`). + + If you can express the value you want to store as a number or bytestring, + you should use the appropriate column type to avoid the time and size + overhead of pickling and unpickling. + """ + + class Writer(WrappedColumnWriter): + def __repr__(self): + return "" + + def add(self, docnum, v): + if v is None: + v = emptybytes + else: + v = dumps(v, 2) + self._child.add(docnum, v) + + class Reader(WrappedColumnReader): + def __repr__(self): + return "" + + def __getitem__(self, docnum): + v = self._child[docnum] + if not v: + return None + else: + return loads(v) + + def __iter__(self): + for v in self._child: + if not v: + yield None + else: + yield loads(v) + + +# List columns + +class ListColumn(WrappedColumn): + def stores_lists(self): + return True + + +class ListColumnReader(ColumnReader): + def sort_key(self, docnum): + return self[docnum][0] + + def __iter__(self): + for docnum in xrange(len(self)): + yield self[docnum] + + +class VarBytesListColumn(ListColumn): + def __init__(self): + self._child = VarBytesColumn() + + class Writer(WrappedColumnWriter): + def add(self, docnum, ls): + out = [varint(len(ls))] + for v in ls: + assert isinstance(v, bytes_type) + out.append(varint(len(v))) + out.append(v) + self._child.add(docnum, emptybytes.join(out)) + + class Reader(ListColumnReader, WrappedColumnReader): + def __getitem__(self, docnum): + data = self._child[docnum] + if not data: + return [] + bio = BytesIO(data) + count = read_varint(bio.read) + out = [] + for _ in xrange(count): + vlen = read_varint(bio.read) + v = bio.read(vlen) + out.append(v) + return out + + +class FixedBytesListColumn(ListColumn): + def __init__(self, fixedlen): + self._fixedlen = fixedlen + self._child = VarBytesColumn() + + def writer(self, *args, **kwargs): + return self.Writer(self._child.writer(*args, **kwargs), self._fixedlen) + + def reader(self, *args, **kwargs): + return self.Reader(self._child.reader(*args, **kwargs), self._fixedlen) + + class Writer(WrappedColumnWriter): + def __init__(self, child, fixedlen): + self._child = child + self._fixedlen = fixedlen + self._lengths = GrowableArray() + self._count = 0 + + def add(self, docnum, ls): + out = [] + for v in ls: + assert len(v) == self._fixedlen + out.append(v) + b = emptybytes.join(out) + self._child.add(docnum, b) + + class Reader(ListColumnReader, WrappedColumnReader): + def __init__(self, child, fixedlen): + self._child = child + self._fixedlen = fixedlen + + def __getitem__(self, docnum): + fixedlen = self._fixedlen + v = self._child[docnum] + if not v: + return [] + ls = [v[i:i + fixedlen] for i in xrange(0, len(v), fixedlen)] + return ls + + +#class RefListColumn(Column): +# def __init__(self, fixedlen=0): +# """ +# :param fixedlen: an optional fixed length for the values. If you +# specify a number other than 0, the column will require all values +# to be the specified length. +# :param default: a default value to use for documents that don't specify +# one. If you don't specify a default, the column will use an empty +# bytestring (``b''``), or if you specify a fixed length, +# ``b'\\x00' * fixedlen``. +# """ +# +# self._fixedlen = fixedlen +# +# def stores_lists(self): +# return True +# +# def writer(self, dbfile): +# return self.Writer(dbfile, self._fixedlen) +# +# def reader(self, dbfile, basepos, length, doccount): +# return self.Reader(dbfile, basepos, length, doccount, self._fixedlen) +# +# class Writer(ColumnWriter): +# def __init__(self, dbfile, fixedlen): +# self._dbfile = dbfile +# self._fixedlen = fixedlen +# +# self._refs = GrowableArray(allow_longs=False) +# self._lengths = GrowableArray(allow_longs=False) +# self._count = 0 +# +# def __repr__(self): +# return "" +# +# def fill(self, docnum): +# if docnum > self._count: +# self._lengths.extend(0 for _ in xrange(docnum - self._count)) +# +# def add(self, docnum, ls): +# uniques = self._uniques +# refs = self._refs +# +# self.fill(docnum) +# self._lengths.append(len(ls)) +# for v in ls: +# try: +# i = uniques[v] +# except KeyError: +# uniques[v] = i = len(uniques) +# refs.append(i) +# +# self._count = docnum + 1 +# +# def finish(self, doccount): +# dbfile = self._dbfile +# refs = self._refs.array +# lengths = self._lengths.array +# +# self.fill(doccount) +# dbfile.write_byte(ord(lengths.typecode)) +# dbfile.write_array(lengths) +# dbfile.write_byte(ord(refs.typecode)) +# self._write_uniques(refs.typecode) +# dbfile.write_array(refs) +# +# class Reader(ListColumnReader): +# def __init__(self, dbfile, basepos, length, doccount, fixedlen): +# self._dbfile = dbfile +# self._basepos = basepos +# self._doccount = doccount +# self._fixedlen = fixedlen +# +# dbfile.seek(basepos) +# lencode = chr(dbfile.read_byte()) +# self._lengths = dbfile.read_array(lencode, doccount) +# +# self._typecode = chr(dbfile.read_byte()) +# refst = struct.Struct("!" + self._typecode) +# self._unpack = refst.unpack +# self._itemsize = refst.size +# +# self._read_uniques() +# self._refbase = dbfile.tell() +# +# # Create an array of offsets into the references using the lengths +# offsets = array("i", (0,)) +# for length in self._lengths: +# offsets.append(offsets[-1] + length) +# self._offsets = offsets +# +# def __repr__(self): +# return "" +# +# def _get_ref(self, docnum): +# pos = self._basepos + 1 + docnum * self._itemsize +# return self._unpack(self._dbfile.get(pos, self._itemsize))[0] +# +# def __getitem__(self, docnum): +# offset = self._offsets[docnum] +# length = self._lengths[docnum] +# +# pos = self._refbase + offset * self._itemsize +# reflist = self._dbfile.get_array(pos, self._typecode, length) +# return [self._uniques[ref] for ref in reflist] diff --git a/nstock/modules/whoosh/compat.py b/nstock/modules/whoosh/compat.py new file mode 100644 index 0000000..5408849 --- /dev/null +++ b/nstock/modules/whoosh/compat.py @@ -0,0 +1,208 @@ +import array, sys + + +# Run time aliasing of Python2/3 differences + +def htmlescape(s, quote=True): + # this is html.escape reimplemented with cgi.escape, + # so it works for python 2.x, 3.0 and 3.1 + import cgi + s = cgi.escape(s, quote) + if quote: + # python 3.2 also replaces the single quotes: + s = s.replace("'", "'") + return s + +if sys.version_info[0] < 3: + PY3 = False + + def b(s): + return s + + import cStringIO as StringIO + StringIO = BytesIO = StringIO.StringIO + callable = callable + integer_types = (int, long) + iteritems = lambda o: o.iteritems() + itervalues = lambda o: o.itervalues() + iterkeys = lambda o: o.iterkeys() + from itertools import izip + long_type = long + next = lambda o: o.next() + import cPickle as pickle + from cPickle import dumps, loads, dump, load + string_type = basestring + text_type = unicode + bytes_type = str + unichr = unichr + from urllib import urlretrieve + import Queue as queue + + def byte(num): + return chr(num) + + def u(s): + return unicode(s, "unicode_escape") + + def with_metaclass(meta, base=object): + class _WhooshBase(base): + __metaclass__ = meta + return _WhooshBase + + xrange = xrange + zip_ = zip + + def memoryview_(source, offset=None, length=None): + if offset or length: + return buffer(source, offset, length) + else: + return buffer(source) + +else: + PY3 = True + import collections + + def b(s): + return s.encode("latin-1") + + import io + BytesIO = io.BytesIO + callable = lambda o: isinstance(o, collections.Callable) + exec_ = eval("exec") + integer_types = (int,) + iteritems = lambda o: o.items() + itervalues = lambda o: o.values() + iterkeys = lambda o: iter(o.keys()) + izip = zip + long_type = int + next = next + import pickle + from pickle import dumps, loads, dump, load + StringIO = io.StringIO + string_type = str + text_type = str + bytes_type = bytes + unichr = chr + from urllib.request import urlretrieve + import queue + + def byte(num): + return bytes((num,)) + + def u(s): + if isinstance(s, bytes): + return s.decode("ascii") + return s + + def with_metaclass(meta, base=object): + ns = dict(base=base, meta=meta) + exec_("""class _WhooshBase(base, metaclass=meta): + pass""", ns) + return ns["_WhooshBase"] + + xrange = range + zip_ = lambda * args: list(zip(*args)) + + def memoryview_(source, offset=None, length=None): + mv = memoryview(source) + if offset or length: + return mv[offset:offset + length] + else: + return mv + + try: + # for python >= 3.2, avoid DeprecationWarning for cgi.escape + from html import escape as htmlescape + except ImportError: + pass + + +if hasattr(array.array, "tobytes"): + def array_tobytes(arry): + return arry.tobytes() + + def array_frombytes(arry, bs): + return arry.frombytes(bs) +else: + def array_tobytes(arry): + return arry.tostring() + + def array_frombytes(arry, bs): + return arry.fromstring(bs) + + +# Implementations missing from older versions of Python + +try: + from itertools import permutations # @UnusedImport +except ImportError: + # Python 2.5 + def permutations(iterable, r=None): + pool = tuple(iterable) + n = len(pool) + r = n if r is None else r + if r > n: + return + indices = range(n) + cycles = range(n, n - r, -1) + yield tuple(pool[i] for i in indices[:r]) + while n: + for i in reversed(range(r)): + cycles[i] -= 1 + if cycles[i] == 0: + indices[i:] = indices[i + 1:] + indices[i:i + 1] + cycles[i] = n - i + else: + j = cycles[i] + indices[i], indices[-j] = indices[-j], indices[i] + yield tuple(pool[i] for i in indices[:r]) + break + else: + return + + +try: + # Python 2.6-2.7 + from itertools import izip_longest # @UnusedImport +except ImportError: + try: + # Python 3.0 + from itertools import zip_longest as izip_longest # @UnusedImport + except ImportError: + # Python 2.5 + from itertools import chain, izip, repeat + + def izip_longest(*args, **kwds): + fillvalue = kwds.get('fillvalue') + + def sentinel(counter=([fillvalue] * (len(args) - 1)).pop): + yield counter() + + fillers = repeat(fillvalue) + iters = [chain(it, sentinel(), fillers) for it in args] + try: + for tup in izip(*iters): + yield tup + except IndexError: + pass + + +try: + from operator import methodcaller # @UnusedImport +except ImportError: + # Python 2.5 + def methodcaller(name, *args, **kwargs): + def caller(obj): + return getattr(obj, name)(*args, **kwargs) + return caller + + +try: + from abc import abstractmethod # @UnusedImport +except ImportError: + # Python 2.5 + def abstractmethod(funcobj): + """A decorator indicating abstract methods. + """ + funcobj.__isabstractmethod__ = True + return funcobj diff --git a/nstock/modules/whoosh/externalsort.py b/nstock/modules/whoosh/externalsort.py new file mode 100644 index 0000000..846359e --- /dev/null +++ b/nstock/modules/whoosh/externalsort.py @@ -0,0 +1,240 @@ +# Copyright 2011 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +""" +This module implements a general external merge sort for Python objects. +""" + +from __future__ import with_statement + +import os, tempfile +from heapq import heapify, heappop, heapreplace + +from whoosh.compat import dump, load + + +## Python 3.2 had a bug that make marshal.load unusable +#if (hasattr(platform, "python_implementation") +# and platform.python_implementation() == "CPython" +# and platform.python_version() == "3.2.0"): +# # Use pickle instead of marshal on Python 3.2 +# from whoosh.compat import dump as dump_pickle +# from whoosh.compat import load +# +# def dump(obj, f): +# dump_pickle(obj, f, -1) +#else: +# from marshal import dump, load + + +try: + from heapq import merge + + def imerge(iterables): + return merge(*iterables) +except ImportError: + def imerge(iterables): + _hpop, _hreplace, _Stop = (heappop, heapreplace, StopIteration) + h = [] + h_append = h.append + for itnum, it in enumerate(map(iter, iterables)): + try: + nx = it.next + h_append([nx(), itnum, nx]) + except _Stop: + pass + heapify(h) + + while 1: + try: + while 1: + v, itnum, nx = s = h[0] + yield v + s[0] = nx() + _hreplace(h, s) + except _Stop: + _hpop(h) + except IndexError: + return + + +class SortingPool(object): + """This object implements a general K-way external merge sort for Python + objects. + + >>> pool = MergePool() + >>> # Add an unlimited number of items in any order + >>> for item in my_items: + ... pool.add(item) + ... + >>> # Get the items back in sorted order + >>> for item in pool.items(): + ... print(item) + + This class uses the `marshal` module to write the items to temporary files, + so you can only sort marshal-able types (generally: numbers, strings, + tuples, lists, and dicts). + """ + + def __init__(self, maxsize=1000000, tempdir=None, prefix="", + suffix=".run"): + """ + :param maxsize: the maximum number of items to keep in memory at once. + :param tempdir: the path of a directory to use for temporary file + storage. The default is to use the system's temp directory. + :param prefix: a prefix to add to temporary filenames. + :param suffix: a suffix to add to temporary filenames. + """ + + self.tempdir = tempdir + if maxsize < 1: + raise ValueError("maxsize=%s must be >= 1" % maxsize) + self.maxsize = maxsize + self.prefix = prefix + self.suffix = suffix + # Current run queue + self.current = [] + # List of run filenames + self.runs = [] + + def _new_run(self): + fd, path = tempfile.mkstemp(prefix=self.prefix, suffix=self.suffix, + dir=self.tempdir) + f = os.fdopen(fd, "wb") + return path, f + + def _open_run(self, path): + return open(path, "rb") + + def _remove_run(self, path): + os.remove(path) + + def _read_run(self, path): + f = self._open_run(path) + try: + while True: + yield load(f) + except EOFError: + return + finally: + f.close() + self._remove_run(path) + + def _merge_runs(self, paths): + iters = [self._read_run(path) for path in paths] + for item in imerge(iters): + yield item + + def add(self, item): + """Adds `item` to the pool to be sorted. + """ + + if len(self.current) >= self.maxsize: + self.save() + self.current.append(item) + + def _write_run(self, f, items): + for item in items: + dump(item, f, 2) + f.close() + + def _add_run(self, filename): + self.runs.append(filename) + + def save(self): + current = self.current + if current: + current.sort() + path, f = self._new_run() + self._write_run(f, current) + self._add_run(path) + self.current = [] + + def cleanup(self): + for path in self.runs: + try: + os.remove(path) + except OSError: + pass + + def reduce_to(self, target, k): + # Reduce the number of runs to "target" by merging "k" runs at a time + + if k < 2: + raise ValueError("k=%s must be > 2" % k) + if target < 1: + raise ValueError("target=%s must be >= 1" % target) + runs = self.runs + while len(runs) > target: + newpath, f = self._new_run() + # Take k runs off the end of the run list + tomerge = [] + while runs and len(tomerge) < k: + tomerge.append(runs.pop()) + # Merge them into a new run and add it at the start of the list + self._write_run(f, self._merge_runs(tomerge)) + runs.insert(0, newpath) + + def items(self, maxfiles=128): + """Returns a sorted list or iterator of the items in the pool. + + :param maxfiles: maximum number of files to open at once. + """ + + if maxfiles < 2: + raise ValueError("maxfiles=%s must be >= 2" % maxfiles) + + if not self.runs: + # We never wrote a run to disk, so just sort the queue in memory + # and return that + return sorted(self.current) + # Write a new run with the leftover items in the queue + self.save() + + # If we have more runs than allowed open files, merge some of the runs + if maxfiles < len(self.runs): + self.reduce_to(maxfiles, maxfiles) + + # Take all the runs off the run list and merge them + runs = self.runs + self.runs = [] # Minor detail, makes this object reusable + return self._merge_runs(runs) + + +def sort(items, maxsize=100000, tempdir=None, maxfiles=128): + """Sorts the given items using an external merge sort. + + :param tempdir: the path of a directory to use for temporary file + storage. The default is to use the system's temp directory. + :param maxsize: the maximum number of items to keep in memory at once. + :param maxfiles: maximum number of files to open at once. + """ + + p = SortingPool(maxsize=maxsize, tempdir=tempdir) + for item in items: + p.add(item) + return p.items(maxfiles=maxfiles) diff --git a/nstock/modules/whoosh/fields.py b/nstock/modules/whoosh/fields.py new file mode 100644 index 0000000..9457d34 --- /dev/null +++ b/nstock/modules/whoosh/fields.py @@ -0,0 +1,1613 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +""" + Contains functions and classes related to fields. +""" + +import datetime, fnmatch, re, struct, sys +from array import array +from decimal import Decimal + +from whoosh import analysis, columns, formats +from whoosh.compat import with_metaclass +from whoosh.compat import itervalues, xrange +from whoosh.compat import bytes_type, string_type, text_type +from whoosh.system import emptybytes +from whoosh.system import pack_byte, unpack_byte +from whoosh.util.numeric import to_sortable, from_sortable +from whoosh.util.numeric import typecode_max, NaN +from whoosh.util.text import utf8encode, utf8decode +from whoosh.util.times import datetime_to_long, long_to_datetime + + +# Exceptions + +class FieldConfigurationError(Exception): + pass + + +class UnknownFieldError(Exception): + pass + + +# Field Types + +class FieldType(object): + """ + Represents a field configuration. + + The FieldType object supports the following attributes: + + * format (formats.Format): the storage format for posting blocks. + + * analyzer (analysis.Analyzer): the analyzer to use to turn text into + terms. + + * scorable (boolean): whether searches against this field may be scored. + This controls whether the index stores per-document field lengths for + this field. + + * stored (boolean): whether the content of this field is stored for each + document. For example, in addition to indexing the title of a document, + you usually want to store the title so it can be presented as part of + the search results. + + * unique (boolean): whether this field's value is unique to each document. + For example, 'path' or 'ID'. IndexWriter.update_document() will use + fields marked as 'unique' to find the previous version of a document + being updated. + + * multitoken_query is a string indicating what kind of query to use when + a "word" in a user query parses into multiple tokens. The string is + interpreted by the query parser. The strings understood by the default + query parser are "first" (use first token only), "and" (join the tokens + with an AND query), "or" (join the tokens with OR), "phrase" (join + the tokens with a phrase query), and "default" (use the query parser's + default join type). + + * vector (formats.Format or boolean): the format to use to store term + vectors. If not a ``Format`` object, any true value means to use the + index format as the term vector format. Any flase value means don't + store term vectors for this field. + + The constructor for the base field type simply lets you supply your own + attribute values. Subclasses may configure some or all of this for you. + """ + + analyzer = format = scorable = stored = unique = vector = None + indexed = True + multitoken_query = "default" + sortable_typecode = None + column_type = None + + def __init__(self, format, analyzer, scorable=False, + stored=False, unique=False, multitoken_query="default", + sortable=False, vector=None): + self.format = format + self.analyzer = analyzer + self.scorable = scorable + self.stored = stored + self.unique = unique + self.multitoken_query = multitoken_query + self.set_sortable(sortable) + + if isinstance(vector, formats.Format): + self.vector = vector + elif vector: + self.vector = self.format + else: + self.vector = None + + def __repr__(self): + return ("%s(format=%r, scorable=%s, stored=%s, unique=%s)" + % (self.__class__.__name__, self.format, self.scorable, + self.stored, self.unique)) + + def __eq__(self, other): + return all((isinstance(other, FieldType), + (self.format == other.format), + (self.scorable == other.scorable), + (self.stored == other.stored), + (self.unique == other.unique), + (self.column_type == other.column_type))) + + def __ne__(self, other): + return not(self.__eq__(other)) + + # Text + + def index(self, value, **kwargs): + """Returns an iterator of (btext, frequency, weight, encoded_value) + tuples for each unique word in the input value. + + The default implementation uses the ``analyzer`` attribute to tokenize + the value into strings, then encodes them into bytes using UTF-8. + """ + + if not self.format: + raise Exception("%s field %r cannot index without a format" + % (self.__class__.__name__, self)) + if not isinstance(value, (text_type, list, tuple)): + raise ValueError("%r is not unicode or sequence" % value) + assert isinstance(self.format, formats.Format) + + if "mode" not in kwargs: + kwargs["mode"] = "index" + + word_values = self.format.word_values + ana = self.analyzer + for tstring, freq, wt, vbytes in word_values(value, ana, **kwargs): + yield (utf8encode(tstring)[0], freq, wt, vbytes) + + def tokenize(self, value, **kwargs): + """ + Analyzes the given string and returns an iterator of Token objects + (note: for performance reasons, actually the same token yielded over + and over with different attributes). + """ + + if not self.analyzer: + raise Exception("%s field has no analyzer" % self.__class__) + return self.analyzer(value, **kwargs) + + def process_text(self, qstring, mode='', **kwargs): + """ + Analyzes the given string and returns an iterator of token texts. + + >>> field = fields.TEXT() + >>> list(field.process_text("The ides of March")) + ["ides", "march"] + """ + + if not self.format: + raise Exception("%s field has no format" % self) + return (t.text for t in self.tokenize(qstring, mode=mode, **kwargs)) + + # Conversion + + def to_bytes(self, value): + """ + Returns a bytes representation of the given value, appropriate to be + written to disk. The default implementation assumes a unicode value and + encodes it using UTF-8. + """ + + if isinstance(value, (list, tuple)): + value = value[0] + if not isinstance(value, bytes_type): + value = utf8encode(value)[0] + return value + + def to_column_value(self, value): + """ + Returns an object suitable to be inserted into the document values + column for this field. The default implementation simply calls + ``self.to_bytes(value)``. + """ + + return self.to_bytes(value) + + def from_bytes(self, bs): + return utf8decode(bs)[0] + + def from_column_value(self, value): + return self.from_bytes(value) + + # Columns/sorting + + def set_sortable(self, sortable): + if sortable: + if isinstance(sortable, columns.Column): + self.column_type = sortable + else: + self.column_type = self.default_column() + else: + self.column_type = None + + def sortable_terms(self, ixreader, fieldname): + """ + Returns an iterator of the "sortable" tokens in the given reader and + field. These values can be used for sorting. The default implementation + simply returns all tokens in the field. + + This can be overridden by field types such as NUMERIC where some values + in a field are not useful for sorting. + """ + + return ixreader.lexicon(fieldname) + + def default_column(self): + return columns.VarBytesColumn() + + # Parsing + + def self_parsing(self): + """ + Subclasses should override this method to return True if they want + the query parser to call the field's ``parse_query()`` method instead + of running the analyzer on text in this field. This is useful where + the field needs full control over how queries are interpreted, such + as in the numeric field type. + """ + + return False + + def parse_query(self, fieldname, qstring, boost=1.0): + """ + When ``self_parsing()`` returns True, the query parser will call + this method to parse basic query text. + """ + + raise NotImplementedError(self.__class__.__name__) + + def parse_range(self, fieldname, start, end, startexcl, endexcl, + boost=1.0): + """ + When ``self_parsing()`` returns True, the query parser will call + this method to parse range query text. If this method returns None + instead of a query object, the parser will fall back to parsing the + start and end terms using process_text(). + """ + + return None + + # Spelling + + def separate_spelling(self): + """ + Returns True if the field stores unstemmed words in a separate field for + spelling suggestions. + """ + + return False + + def spelling_fieldname(self, fieldname): + """ + Returns the name of a field to use for spelling suggestions instead of + this field. + + :param fieldname: the name of this field. + """ + + return fieldname + + def spellable_words(self, value): + """Returns an iterator of each unique word (in sorted order) in the + input value, suitable for inclusion in the field's word graph. + + The default behavior is to call the field analyzer with the keyword + argument ``no_morph=True``, which should make the analyzer skip any + morphological transformation filters (e.g. stemming) to preserve the + original form of the words. Exotic field types may need to override + this behavior. + """ + + if isinstance(value, (list, tuple)): + words = value + else: + words = [token.text for token + in self.analyzer(value, no_morph=True)] + + return iter(sorted(set(words))) + + # Utility + + def subfields(self): + """ + Returns an iterator of ``(name_prefix, fieldobject)`` pairs for the + fields that need to be indexed when content is put in this field. The + default implementation simply yields ``("", self)``. + """ + + yield "", self + + def supports(self, name): + """ + Returns True if the underlying format supports the given posting + value type. + + >>> field = TEXT() + >>> field.supports("positions") + True + >>> field.supports("chars") + False + """ + + return self.format.supports(name) + + def clean(self): + """ + Clears any cached information in the field and any child objects. + """ + + if self.format and hasattr(self.format, "clean"): + self.format.clean() + + # Events + + def on_add(self, schema, fieldname): + pass + + def on_remove(self, schema, fieldname): + pass + + +# Wrapper base class + +class FieldWrapper(FieldType): + def __init__(self, subfield, prefix): + if isinstance(subfield, type): + subfield = subfield() + self.subfield = subfield + self.name_prefix = prefix + + # By default we'll copy all the subfield's attributes -- override these + # in subclass constructor for things you want to change + self.analyzer = subfield.analyzer + self.format = subfield.format + self.column_type = subfield.column_type + self.scorable = subfield.scorable + self.stored = subfield.stored + self.unique = subfield.unique + self.indexed = subfield.indexed + self.vector = subfield.vector + + def __eq__(self, other): + return self.subfield.__eq__(other) + + def __ne__(self, other): + return self.subfield.__ne__(other) + + # Text + + # def index(self, value, boost=1.0, **kwargs): + # return self.subfield.index(value, boost, **kwargs) + # + # def tokenize(self, value, **kwargs): + # return self.subfield.tokenize(value, **kwargs) + # + # def process_text(self, qstring, mode='', **kwargs): + # return self.subfield.process_text(qstring, mode, **kwargs) + + # Conversion + + def to_bytes(self, value): + return self.subfield.to_bytes(value) + + def to_column_value(self, value): + return self.subfield.to_column_value(value) + + def from_bytes(self, bs): + return self.subfield.from_bytes(bs) + + def from_column_value(self, value): + return self.subfield.from_column_value(value) + + # Sorting/columns + + def set_sortable(self, sortable): + self.subfield.set_sortable(sortable) + + def sortable_terms(self, ixreader, fieldname): + return self.subfield.sortable_terms(ixreader, fieldname) + + def default_column(self): + return self.subfield.default_column() + + # Parsing + + def self_parsing(self): + return self.subfield.self_parsing() + + def parse_query(self, fieldname, qstring, boost=1.0): + return self.subfield.parse_query(fieldname, qstring, boost) + + def parse_range(self, fieldname, start, end, startexcl, endexcl, boost=1.0): + self.subfield.parse_range(fieldname, start, end, startexcl, endexcl, + boost) + + # Utility + + def subfields(self): + # The default FieldWrapper.subfields() implementation DOES NOT split + # out the subfield here -- you need to override if that's what you want + yield "", self + + def supports(self, name): + return self.subfield.supports(name) + + def clean(self): + self.subfield.clean() + + # Events + + def on_add(self, schema, fieldname): + self.subfield.on_add(schema, fieldname) + + def on_remove(self, schema, fieldname): + self.subfield.on_remove(schema, fieldname) + + +# Pre-configured field types + +class ID(FieldType): + """ + Configured field type that indexes the entire value of the field as one + token. This is useful for data you don't want to tokenize, such as the path + of a file. + """ + + def __init__(self, stored=False, unique=False, field_boost=1.0, + sortable=False, analyzer=None): + """ + :param stored: Whether the value of this field is stored with the + document. + """ + + self.analyzer = analyzer or analysis.IDAnalyzer() + # Don't store any information other than the doc ID + self.format = formats.Existence(field_boost=field_boost) + self.stored = stored + self.unique = unique + self.set_sortable(sortable) + + +class IDLIST(FieldType): + """ + Configured field type for fields containing IDs separated by whitespace + and/or punctuation (or anything else, using the expression param). + """ + + def __init__(self, stored=False, unique=False, expression=None, + field_boost=1.0): + """ + :param stored: Whether the value of this field is stored with the + document. + :param unique: Whether the value of this field is unique per-document. + :param expression: The regular expression object to use to extract + tokens. The default expression breaks tokens on CRs, LFs, tabs, + spaces, commas, and semicolons. + """ + + expression = expression or re.compile(r"[^\r\n\t ,;]+") + self.analyzer = analysis.RegexAnalyzer(expression=expression) + # Don't store any information other than the doc ID + self.format = formats.Existence(field_boost=field_boost) + self.stored = stored + self.unique = unique + + +class NUMERIC(FieldType): + """ + Special field type that lets you index integer or floating point + numbers in relatively short fixed-width terms. The field converts numbers + to sortable bytes for you before indexing. + + You specify the numeric type of the field (``int`` or ``float``) when you + create the ``NUMERIC`` object. The default is ``int``. For ``int``, you can + specify a size in bits (``32`` or ``64``). For both ``int`` and ``float`` + you can specify a ``signed`` keyword argument (default is ``True``). + + >>> schema = Schema(path=STORED, position=NUMERIC(int, 64, signed=False)) + >>> ix = storage.create_index(schema) + >>> with ix.writer() as w: + ... w.add_document(path="/a", position=5820402204) + ... + + You can also use the NUMERIC field to store Decimal instances by specifying + a type of ``int`` or ``long`` and the ``decimal_places`` keyword argument. + This simply multiplies each number by ``(10 ** decimal_places)`` before + storing it as an integer. Of course this may throw away decimal prcesision + (by truncating, not rounding) and imposes the same maximum value limits as + ``int``/``long``, but these may be acceptable for certain applications. + + >>> from decimal import Decimal + >>> schema = Schema(path=STORED, position=NUMERIC(int, decimal_places=4)) + >>> ix = storage.create_index(schema) + >>> with ix.writer() as w: + ... w.add_document(path="/a", position=Decimal("123.45") + ... + + """ + + def __init__(self, numtype=int, bits=32, stored=False, unique=False, + field_boost=1.0, decimal_places=0, shift_step=4, signed=True, + sortable=False, default=None): + """ + :param numtype: the type of numbers that can be stored in this field, + either ``int``, ``float``. If you use ``Decimal``, + use the ``decimal_places`` argument to control how many decimal + places the field will store. + :param bits: When ``numtype`` is ``int``, the number of bits to use to + store the number: 8, 16, 32, or 64. + :param stored: Whether the value of this field is stored with the + document. + :param unique: Whether the value of this field is unique per-document. + :param decimal_places: specifies the number of decimal places to save + when storing Decimal instances. If you set this, you will always + get Decimal instances back from the field. + :param shift_steps: The number of bits of precision to shift away at + each tiered indexing level. Values should generally be 1-8. Lower + values yield faster searches but take up more space. A value + of `0` means no tiered indexing. + :param signed: Whether the numbers stored in this field may be + negative. + """ + + # Allow users to specify strings instead of Python types in case + # docstring isn't clear + if numtype == "int": + numtype = int + if numtype == "float": + numtype = float + # Raise an error if the user tries to use a type other than int or + # float + if numtype is Decimal: + numtype = int + if not decimal_places: + raise TypeError("To store Decimal instances, you must set the " + "decimal_places argument") + elif numtype not in (int, float): + raise TypeError("Can't use %r as a type, use int or float" + % numtype) + # Sanity check + if numtype is float and decimal_places: + raise Exception("A float type and decimal_places argument %r are " + "incompatible" % decimal_places) + + intsizes = [8, 16, 32, 64] + intcodes = ["B", "H", "I", "Q"] + # Set up field configuration based on type and size + if numtype is float: + bits = 64 # Floats are converted to 64 bit ints + else: + if bits not in intsizes: + raise Exception("Invalid bits %r, use 8, 16, 32, or 64" + % bits) + # Type code for the *sortable* representation + self.sortable_typecode = intcodes[intsizes.index(bits)] + self._struct = struct.Struct(">" + str(self.sortable_typecode)) + + self.numtype = numtype + self.bits = bits + self.stored = stored + self.unique = unique + self.decimal_places = decimal_places + self.shift_step = shift_step + self.signed = signed + self.analyzer = analysis.IDAnalyzer() + # Don't store any information other than the doc ID + self.format = formats.Existence(field_boost=field_boost) + self.min_value, self.max_value = self._min_max() + + # Column configuration + if default is None: + if numtype is int: + default = typecode_max[self.sortable_typecode] + else: + default = NaN + elif not self.is_valid(default): + raise Exception("The default %r is not a valid number for this " + "field" % default) + + self.default = default + self.set_sortable(sortable) + + def __getstate__(self): + d = self.__dict__.copy() + if "_struct" in d: + del d["_struct"] + return d + + def __setstate__(self, d): + self.__dict__.update(d) + self._struct = struct.Struct(">" + str(self.sortable_typecode)) + if "min_value" not in d: + d["min_value"], d["max_value"] = self._min_max() + + def _min_max(self): + numtype = self.numtype + bits = self.bits + signed = self.signed + + # Calculate the minimum and maximum possible values for error checking + min_value = from_sortable(numtype, bits, signed, 0) + max_value = from_sortable(numtype, bits, signed, 2 ** bits - 1) + + return min_value, max_value + + def default_column(self): + return columns.NumericColumn(self.sortable_typecode, + default=self.default) + + def is_valid(self, x): + try: + x = self.to_bytes(x) + except ValueError: + return False + except OverflowError: + return False + + return True + + def index(self, num, **kwargs): + # If the user gave us a list of numbers, recurse on the list + if isinstance(num, (list, tuple)): + for n in num: + for item in self.index(n): + yield item + return + + # word, freq, weight, valuestring + if self.shift_step: + for shift in xrange(0, self.bits, self.shift_step): + yield (self.to_bytes(num, shift), 1, 1.0, emptybytes) + else: + yield (self.to_bytes(num), 1, 1.0, emptybytes) + + def prepare_number(self, x): + if x == emptybytes or x is None: + return x + + dc = self.decimal_places + if dc and isinstance(x, (string_type, Decimal)): + x = Decimal(x) * (10 ** dc) + elif isinstance(x, Decimal): + raise TypeError("Can't index a Decimal object unless you specified " + "decimal_places on the field") + + try: + x = self.numtype(x) + except OverflowError: + raise ValueError("Value %r overflowed number type %r" + % (x, self.numtype)) + + if x < self.min_value or x > self.max_value: + raise ValueError("Numeric field value %s out of range [%s, %s]" + % (x, self.min_value, self.max_value)) + return x + + def unprepare_number(self, x): + dc = self.decimal_places + if dc: + s = str(x) + x = Decimal(s[:-dc] + "." + s[-dc:]) + return x + + def to_column_value(self, x): + if isinstance(x, (list, tuple, array)): + x = x[0] + x = self.prepare_number(x) + return to_sortable(self.numtype, self.bits, self.signed, x) + + def from_column_value(self, x): + x = from_sortable(self.numtype, self.bits, self.signed, x) + return self.unprepare_number(x) + + def to_bytes(self, x, shift=0): + # Try to avoid re-encoding; this sucks because on Python 2 we can't + # tell the difference between a string and encoded bytes, so we have + # to require the user use unicode when they mean string + if isinstance(x, bytes_type): + return x + + if x == emptybytes or x is None: + return self.sortable_to_bytes(0) + + x = self.prepare_number(x) + x = to_sortable(self.numtype, self.bits, self.signed, x) + return self.sortable_to_bytes(x, shift) + + def sortable_to_bytes(self, x, shift=0): + if shift: + x >>= shift + return pack_byte(shift) + self._struct.pack(x) + + def from_bytes(self, bs): + x = self._struct.unpack(bs[1:])[0] + x = from_sortable(self.numtype, self.bits, self.signed, x) + x = self.unprepare_number(x) + return x + + def process_text(self, text, **kwargs): + return (self.to_bytes(text),) + + def self_parsing(self): + return True + + def parse_query(self, fieldname, qstring, boost=1.0): + from whoosh import query + from whoosh.qparser.common import QueryParserError + + if qstring == "*": + return query.Every(fieldname, boost=boost) + + if not self.is_valid(qstring): + raise QueryParserError("%r is not a valid number" % qstring) + + token = self.to_bytes(qstring) + return query.Term(fieldname, token, boost=boost) + + def parse_range(self, fieldname, start, end, startexcl, endexcl, + boost=1.0): + from whoosh import query + from whoosh.qparser.common import QueryParserError + + if start is not None: + if not self.is_valid(start): + raise QueryParserError("Range start %r is not a valid number" + % start) + start = self.prepare_number(start) + if end is not None: + if not self.is_valid(end): + raise QueryParserError("Range end %r is not a valid number" + % end) + end = self.prepare_number(end) + return query.NumericRange(fieldname, start, end, startexcl, endexcl, + boost=boost) + + def sortable_terms(self, ixreader, fieldname): + zero = b"\x00" + for token in ixreader.lexicon(fieldname): + if token[0:1] != zero: + # Only yield the full-precision values + break + yield token + + +class DATETIME(NUMERIC): + """ + Special field type that lets you index datetime objects. The field + converts the datetime objects to sortable text for you before indexing. + + Since this field is based on Python's datetime module it shares all the + limitations of that module, such as the inability to represent dates before + year 1 in the proleptic Gregorian calendar. However, since this field + stores datetimes as an integer number of microseconds, it could easily + represent a much wider range of dates if the Python datetime implementation + ever supports them. + + >>> schema = Schema(path=STORED, date=DATETIME) + >>> ix = storage.create_index(schema) + >>> w = ix.writer() + >>> w.add_document(path="/a", date=datetime.now()) + >>> w.commit() + """ + + def __init__(self, stored=False, unique=False, sortable=False): + """ + :param stored: Whether the value of this field is stored with the + document. + :param unique: Whether the value of this field is unique per-document. + """ + + super(DATETIME, self).__init__(int, 64, stored=stored, + unique=unique, shift_step=8, + sortable=sortable) + + def prepare_datetime(self, x): + from whoosh.util.times import floor + + if isinstance(x, text_type): + # For indexing, support same strings as for query parsing -- + # convert unicode to datetime object + x = self._parse_datestring(x) + x = floor(x) # this makes most sense (unspecified = lowest) + + if isinstance(x, datetime.datetime): + return datetime_to_long(x) + elif isinstance(x, bytes_type): + return x + else: + raise Exception("%r is not a datetime" % (x,)) + + def to_column_value(self, x): + if isinstance(x, bytes_type): + raise Exception("%r is not a datetime" % (x,)) + if isinstance(x, (list, tuple)): + x = x[0] + return self.prepare_datetime(x) + + def from_column_value(self, x): + return long_to_datetime(x) + + def to_bytes(self, x, shift=0): + x = self.prepare_datetime(x) + return NUMERIC.to_bytes(self, x, shift=shift) + + def from_bytes(self, bs): + x = NUMERIC.from_bytes(self, bs) + return long_to_datetime(x) + + def _parse_datestring(self, qstring): + # This method parses a very simple datetime representation of the form + # YYYY[MM[DD[hh[mm[ss[uuuuuu]]]]]] + from whoosh.util.times import adatetime, fix, is_void + + qstring = qstring.replace(" ", "").replace("-", "").replace(".", "") + year = month = day = hour = minute = second = microsecond = None + if len(qstring) >= 4: + year = int(qstring[:4]) + if len(qstring) >= 6: + month = int(qstring[4:6]) + if len(qstring) >= 8: + day = int(qstring[6:8]) + if len(qstring) >= 10: + hour = int(qstring[8:10]) + if len(qstring) >= 12: + minute = int(qstring[10:12]) + if len(qstring) >= 14: + second = int(qstring[12:14]) + if len(qstring) == 20: + microsecond = int(qstring[14:]) + + at = fix(adatetime(year, month, day, hour, minute, second, + microsecond)) + if is_void(at): + raise Exception("%r is not a parseable date" % qstring) + return at + + def parse_query(self, fieldname, qstring, boost=1.0): + from whoosh import query + from whoosh.util.times import is_ambiguous + + try: + at = self._parse_datestring(qstring) + except: + e = sys.exc_info()[1] + return query.error_query(e) + + if is_ambiguous(at): + startnum = datetime_to_long(at.floor()) + endnum = datetime_to_long(at.ceil()) + return query.NumericRange(fieldname, startnum, endnum) + else: + return query.Term(fieldname, at, boost=boost) + + def parse_range(self, fieldname, start, end, startexcl, endexcl, + boost=1.0): + from whoosh import query + + if start is None and end is None: + return query.Every(fieldname, boost=boost) + + if start is not None: + startdt = self._parse_datestring(start).floor() + start = datetime_to_long(startdt) + + if end is not None: + enddt = self._parse_datestring(end).ceil() + end = datetime_to_long(enddt) + + return query.NumericRange(fieldname, start, end, boost=boost) + + +class BOOLEAN(FieldType): + """ + Special field type that lets you index boolean values (True and False). + The field converts the boolean values to text for you before indexing. + + >>> schema = Schema(path=STORED, done=BOOLEAN) + >>> ix = storage.create_index(schema) + >>> w = ix.writer() + >>> w.add_document(path="/a", done=False) + >>> w.commit() + """ + + bytestrings = (b"f", b"t") + trues = frozenset(u"t true yes 1".split()) + falses = frozenset(u"f false no 0".split()) + + def __init__(self, stored=False, field_boost=1.0): + """ + :param stored: Whether the value of this field is stored with the + document. + """ + + self.stored = stored + # Don't store any information other than the doc ID + self.format = formats.Existence(field_boost=field_boost) + + def _obj_to_bool(self, x): + # We special case strings such as "true", "false", "yes", "no", but + # otherwise call bool() on the query value. This lets you pass objects + # as query values and do the right thing. + + if isinstance(x, string_type) and x.lower() in self.trues: + x = True + elif isinstance(x, string_type) and x.lower() in self.falses: + x = False + else: + x = bool(x) + return x + + def to_bytes(self, x): + if isinstance(x, bytes_type): + return x + elif isinstance(x, string_type): + x = x.lower() in self.trues + else: + x = bool(x) + bs = self.bytestrings[int(x)] + return bs + + def index(self, bit, **kwargs): + if isinstance(bit, string_type): + bit = bit.lower() in self.trues + else: + bit = bool(bit) + # word, freq, weight, valuestring + return [(self.bytestrings[int(bit)], 1, 1.0, emptybytes)] + + def self_parsing(self): + return True + + def parse_query(self, fieldname, qstring, boost=1.0): + from whoosh import query + + if qstring == "*": + return query.Every(fieldname, boost=boost) + + return query.Term(fieldname, self._obj_to_bool(qstring), boost=boost) + + +class STORED(FieldType): + """ + Configured field type for fields you want to store but not index. + """ + + indexed = False + stored = True + + def __init__(self): + pass + + +class COLUMN(FieldType): + """ + Configured field type for fields you want to store as a per-document + value column but not index. + """ + + indexed = False + stored = False + + def __init__(self, columnobj=None): + if columnobj is None: + columnobj = columns.VarBytesColumn() + if not isinstance(columnobj, columns.Column): + raise TypeError("%r is not a column object" % (columnobj,)) + self.column_type = columnobj + + def to_bytes(self, v): + return v + + def from_bytes(self, b): + return b + + +class KEYWORD(FieldType): + """ + Configured field type for fields containing space-separated or + comma-separated keyword-like data (such as tags). The default is to not + store positional information (so phrase searching is not allowed in this + field) and to not make the field scorable. + """ + + def __init__(self, stored=False, lowercase=False, commas=False, + scorable=False, unique=False, field_boost=1.0, sortable=False, + vector=None, analyzer=None): + """ + :param stored: Whether to store the value of the field with the + document. + :param commas: Whether this is a comma-separated field. If this is False + (the default), it is treated as a space-separated field. + :param scorable: Whether this field is scorable. + """ + + if not analyzer: + analyzer = analysis.KeywordAnalyzer(lowercase=lowercase, + commas=commas) + self.analyzer = analyzer + + # Store field lengths and weights along with doc ID + self.format = formats.Frequency(field_boost=field_boost) + self.scorable = scorable + self.stored = stored + self.unique = unique + + if isinstance(vector, formats.Format): + self.vector = vector + elif vector: + self.vector = self.format + else: + self.vector = None + + if sortable: + self.column_type = self.default_column() + + +class TEXT(FieldType): + """ + Configured field type for text fields (for example, the body text of an + article). The default is to store positional information to allow phrase + searching. This field type is always scorable. + """ + + def __init__(self, analyzer=None, phrase=True, chars=False, stored=False, + field_boost=1.0, multitoken_query="default", spelling=False, + sortable=False, lang=None, vector=None, + spelling_prefix="spell_"): + """ + :param analyzer: The analysis.Analyzer to use to index the field + contents. See the analysis module for more information. If you omit + this argument, the field uses analysis.StandardAnalyzer. + :param phrase: Whether the store positional information to allow phrase + searching. + :param chars: Whether to store character ranges along with positions. + If this is True, "phrase" is also implied. + :param stored: Whether to store the value of this field with the + document. Since this field type generally contains a lot of text, + you should avoid storing it with the document unless you need to, + for example to allow fast excerpts in the search results. + :param spelling: if True, and if the field's analyzer changes the form + of term text (such as a stemming analyzer), this field will store + extra information in a separate field (named using the + ``spelling_prefix`` keyword argument) to allow spelling suggestions + to use the unchanged word forms as spelling suggestions. + :param sortable: If True, make this field sortable using the default + column type. If you pass a :class:`whoosh.columns.Column` instance + instead of True, the field will use the given column type. + :param lang: automaticaly configure a + :class:`whoosh.analysis.LanguageAnalyzer` for the given language. + This is ignored if you also specify an ``analyzer``. + :param vector: if this value evaluates to true, store a list of the + terms in this field in each document. If the value is an instance + of :class:`whoosh.formats.Format`, the index will use the object to + store the term vector. Any other true value (e.g. ``vector=True``) + will use the field's index format to store the term vector as well. + """ + + if analyzer: + self.analyzer = analyzer + elif lang: + self.analyzer = analysis.LanguageAnalyzer(lang) + else: + self.analyzer = analysis.StandardAnalyzer() + + if chars: + formatclass = formats.Characters + elif phrase: + formatclass = formats.Positions + else: + formatclass = formats.Frequency + self.format = formatclass(field_boost=field_boost) + + if sortable: + if isinstance(sortable, columns.Column): + self.column_type = sortable + else: + self.column_type = columns.VarBytesColumn() + else: + self.column_type = None + + self.spelling = spelling + self.spelling_prefix = spelling_prefix + self.multitoken_query = multitoken_query + self.scorable = True + self.stored = stored + + if isinstance(vector, formats.Format): + self.vector = vector + elif vector: + self.vector = self.format + else: + self.vector = None + + def subfields(self): + yield "", self + + # If the user indicated this is a spellable field, and the analyzer + # is morphic, then also index into a spelling-only field that stores + # minimal information + if self.separate_spelling(): + yield self.spelling_prefix, SpellField(self.analyzer) + + def separate_spelling(self): + return self.spelling and self.analyzer.has_morph() + + def spelling_fieldname(self, fieldname): + if self.separate_spelling(): + return self.spelling_prefix + fieldname + else: + return fieldname + + +class SpellField(FieldType): + """ + This is a utility field type meant to be returned by ``TEXT.subfields()`` + when it needs a minimal field to store the spellable words. + """ + + def __init__(self, analyzer): + self.format = formats.Frequency() + self.analyzer = analyzer + self.column_type = None + self.scorabe = False + self.stored = False + self.unique = False + self.indexed = True + self.spelling = False + + # All the text analysis methods add "nomorph" to the keywords to get + # unmorphed term texts + + def index(self, value, boost=1.0, **kwargs): + kwargs["nomorph"] = True + return FieldType.index(self, value, boost=boost, **kwargs) + + def tokenzie(self, value, **kwargs): + kwargs["nomorph"] = True + return FieldType.tokenize(self, value, **kwargs) + + def process_text(self, qstring, mode='', **kwargs): + kwargs["nomorph"] = True + return FieldType.process_text(self, qstring, mode=mode, **kwargs) + + +class NGRAM(FieldType): + """ + Configured field that indexes text as N-grams. For example, with a field + type NGRAM(3,4), the value "hello" will be indexed as tokens + "hel", "hell", "ell", "ello", "llo". This field type chops the entire text + into N-grams, including whitespace and punctuation. See :class:`NGRAMWORDS` + for a field type that breaks the text into words first before chopping the + words into N-grams. + """ + + scorable = True + + def __init__(self, minsize=2, maxsize=4, stored=False, field_boost=1.0, + queryor=False, phrase=False, sortable=False): + """ + :param minsize: The minimum length of the N-grams. + :param maxsize: The maximum length of the N-grams. + :param stored: Whether to store the value of this field with the + document. Since this field type generally contains a lot of text, + you should avoid storing it with the document unless you need to, + for example to allow fast excerpts in the search results. + :param queryor: if True, combine the N-grams with an Or query. The + default is to combine N-grams with an And query. + :param phrase: store positions on the N-grams to allow exact phrase + searching. The default is off. + """ + + formatclass = formats.Frequency + if phrase: + formatclass = formats.Positions + + self.analyzer = analysis.NgramAnalyzer(minsize, maxsize) + self.format = formatclass(field_boost=field_boost) + self.analyzer = analysis.NgramAnalyzer(minsize, maxsize) + self.stored = stored + self.queryor = queryor + self.set_sortable(sortable) + + def self_parsing(self): + return True + + def parse_query(self, fieldname, qstring, boost=1.0): + from whoosh import query + + terms = [query.Term(fieldname, g) + for g in self.process_text(qstring, mode='query')] + cls = query.Or if self.queryor else query.And + + return cls(terms, boost=boost) + + +class NGRAMWORDS(NGRAM): + """ + Configured field that chops text into words using a tokenizer, + lowercases the words, and then chops the words into N-grams. + """ + + scorable = True + + def __init__(self, minsize=2, maxsize=4, stored=False, field_boost=1.0, + tokenizer=None, at=None, queryor=False, sortable=False): + """ + :param minsize: The minimum length of the N-grams. + :param maxsize: The maximum length of the N-grams. + :param stored: Whether to store the value of this field with the + document. Since this field type generally contains a lot of text, + you should avoid storing it with the document unless you need to, + for example to allow fast excerpts in the search results. + :param tokenizer: an instance of :class:`whoosh.analysis.Tokenizer` + used to break the text into words. + :param at: if 'start', only takes N-grams from the start of the word. + If 'end', only takes N-grams from the end. Otherwise the default + is to take all N-grams from each word. + :param queryor: if True, combine the N-grams with an Or query. The + default is to combine N-grams with an And query. + """ + + self.analyzer = analysis.NgramWordAnalyzer(minsize, maxsize, tokenizer, + at=at) + self.format = formats.Frequency(field_boost=field_boost) + self.stored = stored + self.queryor = queryor + self.set_sortable(sortable) + + +# Other fields + +class ReverseField(FieldWrapper): + def __init__(self, subfield, prefix="rev_"): + FieldWrapper.__init__(self, subfield, prefix) + self.analyzer = subfield.analyzer | analysis.ReverseTextFilter() + self.format = BasicFormat(lengths=False, weights=False) + + self.scorable = False + self.set_sortable(False) + self.stored = False + self.unique = False + self.vector = False + + def subfields(self): + yield "", self.subfield + yield self.name_prefix, self + + +# Schema class + +class MetaSchema(type): + def __new__(cls, name, bases, attrs): + super_new = super(MetaSchema, cls).__new__ + if not any(b for b in bases if isinstance(b, MetaSchema)): + # If this isn't a subclass of MetaSchema, don't do anything special + return super_new(cls, name, bases, attrs) + + # Create the class + special_attrs = {} + for key in list(attrs.keys()): + if key.startswith("__"): + special_attrs[key] = attrs.pop(key) + new_class = super_new(cls, name, bases, special_attrs) + + fields = {} + for b in bases: + if hasattr(b, "_clsfields"): + fields.update(b._clsfields) + fields.update(attrs) + new_class._clsfields = fields + return new_class + + def schema(self): + return Schema(**self._clsfields) + + +class Schema(object): + """ + Represents the collection of fields in an index. Maps field names to + FieldType objects which define the behavior of each field. + + Low-level parts of the index use field numbers instead of field names for + compactness. This class has several methods for converting between the + field name, field number, and field object itself. + """ + + def __init__(self, **fields): + """ + All keyword arguments to the constructor are treated as fieldname = + fieldtype pairs. The fieldtype can be an instantiated FieldType object, + or a FieldType sub-class (in which case the Schema will instantiate it + with the default constructor before adding it). + + For example:: + + s = Schema(content = TEXT, + title = TEXT(stored = True), + tags = KEYWORD(stored = True)) + """ + + self._fields = {} + self._subfields = {} + self._dyn_fields = {} + + for name in sorted(fields.keys()): + self.add(name, fields[name]) + + def copy(self): + """ + Returns a shallow copy of the schema. The field instances are not + deep copied, so they are shared between schema copies. + """ + + return self.__class__(**self._fields) + + def __eq__(self, other): + return (other.__class__ is self.__class__ + and list(self.items()) == list(other.items())) + + def __ne__(self, other): + return not(self.__eq__(other)) + + def __repr__(self): + return "<%s: %r>" % (self.__class__.__name__, self.names()) + + def __iter__(self): + """ + Returns the field objects in this schema. + """ + + return iter(self._fields.values()) + + def __getitem__(self, name): + """ + Returns the field associated with the given field name. + """ + + # If the name is in the dictionary, just return it + if name in self._fields: + return self._fields[name] + + # Check if the name matches a dynamic field + for expr, fieldtype in itervalues(self._dyn_fields): + if expr.match(name): + return fieldtype + + raise KeyError("No field named %r" % (name,)) + + def __len__(self): + """ + Returns the number of fields in this schema. + """ + + return len(self._fields) + + def __contains__(self, fieldname): + """ + Returns True if a field by the given name is in this schema. + """ + + # Defined in terms of __getitem__ so that there's only one method to + # override to provide dynamic fields + try: + field = self[fieldname] + return field is not None + except KeyError: + return False + + def __setstate__(self, state): + if "_subfields" not in state: + state["_subfields"] = {} + self.__dict__.update(state) + + def to_bytes(self, fieldname, value): + return self[fieldname].to_bytes(value) + + def items(self): + """ + Returns a list of ("fieldname", field_object) pairs for the fields + in this schema. + """ + + return sorted(self._fields.items()) + + def names(self, check_names=None): + """ + Returns a list of the names of the fields in this schema. + + :param check_names: (optional) sequence of field names to check + whether the schema accepts them as (dynamic) field names - + acceptable names will also be in the result list. + Note: You may also have static field names in check_names, that + won't create duplicates in the result list. Unsupported names + will not be in the result list. + """ + + fieldnames = set(self._fields.keys()) + if check_names is not None: + check_names = set(check_names) - fieldnames + fieldnames.update(fieldname for fieldname in check_names + if fieldname in self) + return sorted(fieldnames) + + def clean(self): + for field in self: + field.clean() + + def add(self, name, fieldtype, glob=False): + """ + Adds a field to this schema. + + :param name: The name of the field. + :param fieldtype: An instantiated fields.FieldType object, or a + FieldType subclass. If you pass an instantiated object, the schema + will use that as the field configuration for this field. If you + pass a FieldType subclass, the schema will automatically + instantiate it with the default constructor. + """ + + # If the user passed a type rather than an instantiated field object, + # instantiate it automatically + if type(fieldtype) is type: + try: + fieldtype = fieldtype() + except: + e = sys.exc_info()[1] + raise FieldConfigurationError("Error: %s instantiating field " + "%r: %r" % (e, name, fieldtype)) + + if not isinstance(fieldtype, FieldType): + raise FieldConfigurationError("%r is not a FieldType object" + % fieldtype) + + self._subfields[name] = sublist = [] + for prefix, subfield in fieldtype.subfields(): + fname = prefix + name + sublist.append(fname) + + # Check field name + if fname.startswith("_"): + raise FieldConfigurationError("Names cannot start with _") + elif " " in fname: + raise FieldConfigurationError("Names cannot contain spaces") + elif fname in self._fields or (glob and fname in self._dyn_fields): + raise FieldConfigurationError("%r already in schema" % fname) + + # Add the field + if glob: + expr = re.compile(fnmatch.translate(name)) + self._dyn_fields[fname] = (expr, subfield) + else: + fieldtype.on_add(self, fname) + self._fields[fname] = subfield + + def remove(self, fieldname): + if fieldname in self._fields: + self._fields[fieldname].on_remove(self, fieldname) + del self._fields[fieldname] + + if fieldname in self._subfields: + for subname in self._subfields[fieldname]: + if subname in self._fields: + del self._fields[subname] + del self._subfields[fieldname] + + elif fieldname in self._dyn_fields: + del self._dyn_fields[fieldname] + + else: + raise KeyError("No field named %r" % fieldname) + + def indexable_fields(self, fieldname): + if fieldname in self._subfields: + for subname in self._subfields[fieldname]: + yield subname, self._fields[subname] + else: + # Use __getitem__ here instead of getting it directly from _fields + # because it might be a glob + yield fieldname, self[fieldname] + + def has_scorable_fields(self): + return any(ftype.scorable for ftype in self) + + def stored_names(self): + """ + Returns a list of the names of fields that are stored. + """ + + return [name for name, field in self.items() if field.stored] + + def scorable_names(self): + """ + Returns a list of the names of fields that store field + lengths. + """ + + return [name for name, field in self.items() if field.scorable] + + +class SchemaClass(with_metaclass(MetaSchema, Schema)): + """ + Allows you to define a schema using declarative syntax, similar to + Django models:: + + class MySchema(SchemaClass): + path = ID + date = DATETIME + content = TEXT + + You can use inheritance to share common fields between schemas:: + + class Parent(SchemaClass): + path = ID(stored=True) + date = DATETIME + + class Child1(Parent): + content = TEXT(positions=False) + + class Child2(Parent): + tags = KEYWORD + + This class overrides ``__new__`` so instantiating your sub-class always + results in an instance of ``Schema``. + + >>> class MySchema(SchemaClass): + ... title = TEXT(stored=True) + ... content = TEXT + ... + >>> s = MySchema() + >>> type(s) + + + """ + + def __new__(cls, *args, **kwargs): + obj = super(Schema, cls).__new__(Schema) + kw = getattr(cls, "_clsfields", {}) + kw.update(kwargs) + obj.__init__(*args, **kw) + return obj + + +def ensure_schema(schema): + if isinstance(schema, type) and issubclass(schema, Schema): + schema = schema.schema() + if not isinstance(schema, Schema): + raise FieldConfigurationError("%r is not a Schema" % schema) + return schema + + +def merge_fielddict(d1, d2): + keyset = set(d1.keys()) | set(d2.keys()) + out = {} + for name in keyset: + field1 = d1.get(name) + field2 = d2.get(name) + if field1 and field2 and field1 != field2: + raise Exception("Inconsistent field %r: %r != %r" + % (name, field1, field2)) + out[name] = field1 or field2 + return out + + +def merge_schema(s1, s2): + schema = Schema() + schema._fields = merge_fielddict(s1._fields, s2._fields) + schema._dyn_fields = merge_fielddict(s1._dyn_fields, s2._dyn_fields) + return schema + + +def merge_schemas(schemas): + schema = schemas[0] + for i in xrange(1, len(schemas)): + schema = merge_schema(schema, schemas[i]) + return schema diff --git a/nstock/modules/whoosh/filedb/__init__.py b/nstock/modules/whoosh/filedb/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/nstock/modules/whoosh/filedb/compound.py b/nstock/modules/whoosh/filedb/compound.py new file mode 100644 index 0000000..508077a --- /dev/null +++ b/nstock/modules/whoosh/filedb/compound.py @@ -0,0 +1,331 @@ +# Copyright 2011 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +import errno +import os +import sys +from threading import Lock +from shutil import copyfileobj + +try: + import mmap +except ImportError: + mmap = None + +from whoosh.compat import BytesIO, memoryview_ +from whoosh.filedb.structfile import BufferFile, StructFile +from whoosh.filedb.filestore import FileStorage, StorageError +from whoosh.system import emptybytes +from whoosh.util import random_name + + +class CompoundStorage(FileStorage): + readonly = True + + def __init__(self, dbfile, use_mmap=True, basepos=0): + self._file = dbfile + self.is_closed = False + + # Seek to the end to get total file size (to check if mmap is OK) + dbfile.seek(0, os.SEEK_END) + filesize = self._file.tell() + dbfile.seek(basepos) + + self._diroffset = self._file.read_long() + self._dirlength = self._file.read_int() + self._file.seek(self._diroffset) + self._dir = self._file.read_pickle() + self._options = self._file.read_pickle() + self._locks = {} + self._source = None + + use_mmap = ( + use_mmap + and hasattr(self._file, "fileno") # check file is a real file + and filesize < sys.maxsize # check fit on 32-bit Python + ) + if mmap and use_mmap: + # Try to open the entire segment as a memory-mapped object + try: + fileno = self._file.fileno() + self._source = mmap.mmap(fileno, 0, access=mmap.ACCESS_READ) + except (mmap.error, OSError): + e = sys.exc_info()[1] + # If we got an error because there wasn't enough memory to + # open the map, ignore it and fall through, we'll just use the + # (slower) "sub-file" implementation + if e.errno == errno.ENOMEM: + pass + else: + raise + else: + # If that worked, we can close the file handle we were given + self._file.close() + self._file = None + + def __repr__(self): + return "<%s (%s)>" % (self.__class__.__name__, self._name) + + def close(self): + if self.is_closed: + raise Exception("Already closed") + self.is_closed = True + + if self._source: + try: + self._source.close() + except BufferError: + del self._source + if self._file: + self._file.close() + + def range(self, name): + try: + fileinfo = self._dir[name] + except KeyError: + raise NameError("Unknown file %r" % (name,)) + return fileinfo["offset"], fileinfo["length"] + + def open_file(self, name, *args, **kwargs): + if self.is_closed: + raise StorageError("Storage was closed") + + offset, length = self.range(name) + if self._source: + # Create a memoryview/buffer from the mmap + buf = memoryview_(self._source, offset, length) + f = BufferFile(buf, name=name) + elif hasattr(self._file, "subset"): + f = self._file.subset(offset, length, name=name) + else: + f = StructFile(SubFile(self._file, offset, length), name=name) + return f + + def list(self): + return list(self._dir.keys()) + + def file_exists(self, name): + return name in self._dir + + def file_length(self, name): + info = self._dir[name] + return info["length"] + + def file_modified(self, name): + info = self._dir[name] + return info["modified"] + + def lock(self, name): + if name not in self._locks: + self._locks[name] = Lock() + return self._locks[name] + + @staticmethod + def assemble(dbfile, store, names, **options): + assert names, names + + directory = {} + basepos = dbfile.tell() + dbfile.write_long(0) # Directory position + dbfile.write_int(0) # Directory length + + # Copy the files into the compound file + for name in names: + if name.endswith(".toc") or name.endswith(".seg"): + raise Exception(name) + + for name in names: + offset = dbfile.tell() + length = store.file_length(name) + modified = store.file_modified(name) + directory[name] = {"offset": offset, "length": length, + "modified": modified} + f = store.open_file(name) + copyfileobj(f, dbfile) + f.close() + + CompoundStorage.write_dir(dbfile, basepos, directory, options) + + @staticmethod + def write_dir(dbfile, basepos, directory, options=None): + options = options or {} + + dirpos = dbfile.tell() # Remember the start of the directory + dbfile.write_pickle(directory) # Write the directory + dbfile.write_pickle(options) + endpos = dbfile.tell() # Remember the end of the directory + dbfile.flush() + dbfile.seek(basepos) # Seek back to the start + dbfile.write_long(dirpos) # Directory position + dbfile.write_int(endpos - dirpos) # Directory length + + dbfile.close() + + +class SubFile(object): + def __init__(self, parentfile, offset, length, name=None): + self._file = parentfile + self._offset = offset + self._length = length + self._end = offset + length + self._pos = 0 + + self.name = name + self.closed = False + + def close(self): + self.closed = True + + def subset(self, position, length, name=None): + start = self._offset + position + end = start + length + name = name or self.name + assert self._offset >= start >= self._end + assert self._offset >= end >= self._end + return SubFile(self._file, self._offset + position, length, name=name) + + def read(self, size=None): + if size is None: + size = self._length - self._pos + else: + size = min(size, self._length - self._pos) + if size < 0: + size = 0 + + if size > 0: + self._file.seek(self._offset + self._pos) + self._pos += size + return self._file.read(size) + else: + return emptybytes + + def readline(self): + maxsize = self._length - self._pos + self._file.seek(self._offset + self._pos) + data = self._file.readline() + if len(data) > maxsize: + data = data[:maxsize] + self._pos += len(data) + return data + + def seek(self, where, whence=0): + if whence == 0: # Absolute + pos = where + elif whence == 1: # Relative + pos = self._pos + where + elif whence == 2: # From end + pos = self._length - where + else: + raise ValueError + + self._pos = pos + + def tell(self): + return self._pos + + +class CompoundWriter(object): + def __init__(self, tempstorage, buffersize=32 * 1024): + assert isinstance(buffersize, int) + self._tempstorage = tempstorage + self._tempname = "%s.ctmp" % random_name() + self._temp = tempstorage.create_file(self._tempname, mode="w+b") + self._buffersize = buffersize + self._streams = {} + + def create_file(self, name): + ss = self.SubStream(self._temp, self._buffersize) + self._streams[name] = ss + return StructFile(ss) + + def _readback(self): + temp = self._temp + for name, substream in self._streams.items(): + substream.close() + + def gen(): + for f, offset, length in substream.blocks: + if f is None: + f = temp + f.seek(offset) + yield f.read(length) + + yield (name, gen) + temp.close() + self._tempstorage.delete_file(self._tempname) + + def save_as_compound(self, dbfile): + basepos = dbfile.tell() + dbfile.write_long(0) # Directory offset + dbfile.write_int(0) # Directory length + + directory = {} + for name, blocks in self._readback(): + filestart = dbfile.tell() + for block in blocks(): + dbfile.write(block) + directory[name] = {"offset": filestart, + "length": dbfile.tell() - filestart} + + CompoundStorage.write_dir(dbfile, basepos, directory) + + def save_as_files(self, storage, name_fn): + for name, blocks in self._readback(): + f = storage.create_file(name_fn(name)) + for block in blocks(): + f.write(block) + f.close() + + class SubStream(object): + def __init__(self, dbfile, buffersize): + self._dbfile = dbfile + self._buffersize = buffersize + self._buffer = BytesIO() + self.blocks = [] + + def tell(self): + return sum(b[2] for b in self.blocks) + self._buffer.tell() + + def write(self, inbytes): + bio = self._buffer + buflen = bio.tell() + length = buflen + len(inbytes) + if length >= self._buffersize: + offset = self._dbfile.tell() + self._dbfile.write(bio.getvalue()[:buflen]) + self._dbfile.write(inbytes) + + self.blocks.append((None, offset, length)) + self._buffer.seek(0) + else: + bio.write(inbytes) + + def close(self): + bio = self._buffer + length = bio.tell() + if length: + self.blocks.append((bio, 0, length)) diff --git a/nstock/modules/whoosh/filedb/filestore.py b/nstock/modules/whoosh/filedb/filestore.py new file mode 100644 index 0000000..d7e230d --- /dev/null +++ b/nstock/modules/whoosh/filedb/filestore.py @@ -0,0 +1,662 @@ +# Copyright 2009 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from __future__ import with_statement +import errno, os, sys, tempfile +from threading import Lock + +from whoosh.compat import BytesIO, memoryview_ +from whoosh.filedb.structfile import BufferFile, StructFile +from whoosh.index import _DEF_INDEX_NAME, EmptyIndexError +from whoosh.util import random_name +from whoosh.util.filelock import FileLock + + +# Exceptions + +class StorageError(Exception): + pass + + +class ReadOnlyError(StorageError): + pass + + +# Base class + +class Storage(object): + """Abstract base class for storage objects. + + A storage object is a virtual flat filesystem, allowing the creation and + retrieval of file-like objects + (:class:`~whoosh.filedb.structfile.StructFile` objects). The default + implementation (:class:`FileStorage`) uses actual files in a directory. + + All access to files in Whoosh goes through this object. This allows more + different forms of storage (for example, in RAM, in a database, in a single + file) to be used transparently. + + For example, to create a :class:`FileStorage` object:: + + # Create a storage object + st = FileStorage("indexdir") + # Create the directory if it doesn't already exist + st.create() + + The :meth:`Storage.create` method makes it slightly easier to swap storage + implementations. The ``create()`` method handles set-up of the storage + object. For example, ``FileStorage.create()`` creates the directory. A + database implementation might create tables. This is designed to let you + avoid putting implementation-specific setup code in your application. + """ + + readonly = False + supports_mmap = False + + def __iter__(self): + return iter(self.list()) + + def __enter__(self): + self.create() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.close() + + def create(self): + """Creates any required implementation-specific resources. For example, + a filesystem-based implementation might create a directory, while a + database implementation might create tables. For example:: + + from whoosh.filedb.filestore import FileStorage + # Create a storage object + st = FileStorage("indexdir") + # Create any necessary resources + st.create() + + This method returns ``self`` so you can also say:: + + st = FileStorage("indexdir").create() + + Storage implementations should be written so that calling create() a + second time on the same storage + + :return: a :class:`Storage` instance. + """ + + return self + + def destroy(self, *args, **kwargs): + """Removes any implementation-specific resources related to this storage + object. For example, a filesystem-based implementation might delete a + directory, and a database implementation might drop tables. + + The arguments are implementation-specific. + """ + + pass + + def create_index(self, schema, indexname=_DEF_INDEX_NAME, indexclass=None): + """Creates a new index in this storage. + + >>> from whoosh import fields + >>> from whoosh.filedb.filestore import FileStorage + >>> schema = fields.Schema(content=fields.TEXT) + >>> # Create the storage directory + >>> st = FileStorage.create("indexdir") + >>> # Create an index in the storage + >>> ix = st.create_index(schema) + + :param schema: the :class:`whoosh.fields.Schema` object to use for the + new index. + :param indexname: the name of the index within the storage object. You + can use this option to store multiple indexes in the same storage. + :param indexclass: an optional custom ``Index`` sub-class to use to + create the index files. The default is + :class:`whoosh.index.FileIndex`. This method will call the + ``create`` class method on the given class to create the index. + :return: a :class:`whoosh.index.Index` instance. + """ + + if self.readonly: + raise ReadOnlyError + if indexclass is None: + import whoosh.index + indexclass = whoosh.index.FileIndex + return indexclass.create(self, schema, indexname) + + def open_index(self, indexname=_DEF_INDEX_NAME, schema=None, indexclass=None): + """Opens an existing index (created using :meth:`create_index`) in this + storage. + + >>> from whoosh.filedb.filestore import FileStorage + >>> st = FileStorage("indexdir") + >>> # Open an index in the storage + >>> ix = st.open_index() + + :param indexname: the name of the index within the storage object. You + can use this option to store multiple indexes in the same storage. + :param schema: if you pass in a :class:`whoosh.fields.Schema` object + using this argument, it will override the schema that was stored + with the index. + :param indexclass: an optional custom ``Index`` sub-class to use to + open the index files. The default is + :class:`whoosh.index.FileIndex`. This method will instantiate the + class with this storage object. + :return: a :class:`whoosh.index.Index` instance. + """ + + if indexclass is None: + import whoosh.index + indexclass = whoosh.index.FileIndex + return indexclass(self, schema=schema, indexname=indexname) + + def index_exists(self, indexname=None): + """Returns True if a non-empty index exists in this storage. + + :param indexname: the name of the index within the storage object. You + can use this option to store multiple indexes in the same storage. + :rtype: bool + """ + + if indexname is None: + indexname = _DEF_INDEX_NAME + try: + ix = self.open_index(indexname) + gen = ix.latest_generation() + ix.close() + return gen > -1 + except EmptyIndexError: + pass + return False + + def create_file(self, name): + """Creates a file with the given name in this storage. + + :param name: the name for the new file. + :return: a :class:`whoosh.filedb.structfile.StructFile` instance. + """ + + raise NotImplementedError + + def open_file(self, name, *args, **kwargs): + """Opens a file with the given name in this storage. + + :param name: the name for the new file. + :return: a :class:`whoosh.filedb.structfile.StructFile` instance. + """ + + raise NotImplementedError + + def list(self): + """Returns a list of file names in this storage. + + :return: a list of strings + """ + raise NotImplementedError + + def file_exists(self, name): + """Returns True if the given file exists in this storage. + + :param name: the name to check. + :rtype: bool + """ + + raise NotImplementedError + + def file_modified(self, name): + """Returns the last-modified time of the given file in this storage (as + a "ctime" UNIX timestamp). + + :param name: the name to check. + :return: a "ctime" number. + """ + + raise NotImplementedError + + def file_length(self, name): + """Returns the size (in bytes) of the given file in this storage. + + :param name: the name to check. + :rtype: int + """ + + raise NotImplementedError + + def delete_file(self, name): + """Removes the given file from this storage. + + :param name: the name to delete. + """ + + raise NotImplementedError + + def rename_file(self, frm, to, safe=False): + """Renames a file in this storage. + + :param frm: The current name of the file. + :param to: The new name for the file. + :param safe: if True, raise an exception if a file with the new name + already exists. + """ + + raise NotImplementedError + + def lock(self, name): + """Return a named lock object (implementing ``.acquire()`` and + ``.release()`` methods). Different storage implementations may use + different lock types with different guarantees. For example, the + RamStorage object uses Python thread locks, while the FileStorage + object uses filesystem-based locks that are valid across different + processes. + + :param name: a name for the lock. + :return: a lock-like object. + """ + + raise NotImplementedError + + def close(self): + """Closes any resources opened by this storage object. For some storage + implementations this will be a no-op, but for others it is necessary + to release locks and/or prevent leaks, so it's a good idea to call it + when you're done with a storage object. + """ + + pass + + def optimize(self): + """Optimizes the storage object. The meaning and cost of "optimizing" + will vary by implementation. For example, a database implementation + might run a garbage collection procedure on the underlying database. + """ + + pass + + def temp_storage(self, name=None): + """Creates a new storage object for temporary files. You can call + :meth:`Storage.destroy` on the new storage when you're finished with + it. + + :param name: a name for the new storage. This may be optional or + required depending on the storage implementation. + :rtype: :class:`Storage` + """ + + raise NotImplementedError + + +class OverlayStorage(Storage): + """Overlays two storage objects. Reads are processed from the first if it + has the named file, otherwise the second. Writes always go to the second. + """ + + def __init__(self, a, b): + self.a = a + self.b = b + + def create_index(self, *args, **kwargs): + self.b.create_index(*args, **kwargs) + + def open_index(self, *args, **kwargs): + self.a.open_index(*args, **kwargs) + + def create_file(self, *args, **kwargs): + return self.b.create_file(*args, **kwargs) + + def open_file(self, name, *args, **kwargs): + if self.a.file_exists(name): + return self.a.open_file(name, *args, **kwargs) + else: + return self.b.open_file(name, *args, **kwargs) + + def list(self): + return list(set(self.a.list()) | set(self.b.list())) + + def file_exists(self, name): + return self.a.file_exists(name) or self.b.file_exists(name) + + def file_modified(self, name): + if self.a.file_exists(name): + return self.a.file_modified(name) + else: + return self.b.file_modified(name) + + def file_length(self, name): + if self.a.file_exists(name): + return self.a.file_length(name) + else: + return self.b.file_length(name) + + def delete_file(self, name): + return self.b.delete_file(name) + + def rename_file(self, *args, **kwargs): + raise NotImplementedError + + def lock(self, name): + return self.b.lock(name) + + def close(self): + self.a.close() + self.b.close() + + def optimize(self): + self.a.optimize() + self.b.optimize() + + def temp_storage(self, name=None): + return self.b.temp_storage(name=name) + + +class FileStorage(Storage): + """Storage object that stores the index as files in a directory on disk. + + Prior to version 3, the initializer would raise an IOError if the directory + did not exist. As of version 3, the object does not check if the + directory exists at initialization. This change is to support using the + :meth:`FileStorage.create` method. + """ + + supports_mmap = True + + def __init__(self, path, supports_mmap=True, readonly=False, debug=False): + """ + :param path: a path to a directory. + :param supports_mmap: if True (the default), use the ``mmap`` module to + open memory mapped files. You can open the storage object with + ``supports_mmap=False`` to force Whoosh to open files normally + instead of with ``mmap``. + :param readonly: If ``True``, the object will raise an exception if you + attempt to create or rename a file. + """ + + self.folder = path + self.supports_mmap = supports_mmap + self.readonly = readonly + self._debug = debug + self.locks = {} + + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self.folder) + + def create(self): + """Creates this storage object's directory path using ``os.makedirs`` if + it doesn't already exist. + + >>> from whoosh.filedb.filestore import FileStorage + >>> st = FileStorage("indexdir") + >>> st.create() + + This method returns ``self``, you can say:: + + st = FileStorage("indexdir").create() + + Note that you can simply create handle the creation of the directory + yourself and open the storage object using the initializer:: + + dirname = "indexdir" + os.mkdir(dirname) + st = FileStorage(dirname) + + However, using the ``create()`` method allows you to potentially swap in + other storage implementations more easily. + + :return: a :class:`Storage` instance. + """ + + dirpath = os.path.abspath(self.folder) + # If the given directory does not already exist, try to create it + try: + os.makedirs(dirpath) + except OSError: + # This is necessary for compatibility between Py2 and Py3 + e = sys.exc_info()[1] + # If we get an error because the path already exists, ignore it + if e.errno != errno.EEXIST: + raise + + # Raise an exception if the given path is not a directory + if not os.path.isdir(dirpath): + e = IOError("%r is not a directory" % dirpath) + e.errno = errno.ENOTDIR + raise e + + return self + + def destroy(self): + """Removes any files in this storage object and then removes the + storage object's directory. What happens if any of the files or the + directory are in use depends on the underlying platform. + """ + + # Remove all files + self.clean() + try: + # Try to remove the directory + os.rmdir(self.folder) + except IOError: + e = sys.exc_info()[1] + if e.errno == errno.ENOENT: + pass + else: + raise e + + def create_file(self, name, excl=False, mode="wb", **kwargs): + """Creates a file with the given name in this storage. + + :param name: the name for the new file. + :param excl: if True, try to open the file in "exclusive" mode. + :param mode: the mode flags with which to open the file. The default is + ``"wb"``. + :return: a :class:`whoosh.filedb.structfile.StructFile` instance. + """ + + if self.readonly: + raise ReadOnlyError + + path = self._fpath(name) + if excl: + flags = os.O_CREAT | os.O_EXCL | os.O_RDWR + if hasattr(os, "O_BINARY"): + flags |= os.O_BINARY + fd = os.open(path, flags) + fileobj = os.fdopen(fd, mode) + else: + fileobj = open(path, mode) + + f = StructFile(fileobj, name=name, **kwargs) + return f + + def open_file(self, name, **kwargs): + """Opens an existing file in this storage. + + :param name: the name of the file to open. + :param kwargs: additional keyword arguments are passed through to the + :class:`~whoosh.filedb.structfile.StructFile` initializer. + :return: a :class:`whoosh.filedb.structfile.StructFile` instance. + """ + + f = StructFile(open(self._fpath(name), "rb"), name=name, **kwargs) + return f + + def _fpath(self, fname): + return os.path.abspath(os.path.join(self.folder, fname)) + + def clean(self, ignore=False): + if self.readonly: + raise ReadOnlyError + + path = self.folder + files = self.list() + for fname in files: + try: + os.remove(os.path.join(path, fname)) + except OSError: + if not ignore: + raise + + def list(self): + try: + files = os.listdir(self.folder) + except IOError: + files = [] + + return files + + def file_exists(self, name): + return os.path.exists(self._fpath(name)) + + def file_modified(self, name): + return os.path.getmtime(self._fpath(name)) + + def file_length(self, name): + return os.path.getsize(self._fpath(name)) + + def delete_file(self, name): + if self.readonly: + raise ReadOnlyError + + os.remove(self._fpath(name)) + + def rename_file(self, oldname, newname, safe=False): + if self.readonly: + raise ReadOnlyError + + if os.path.exists(self._fpath(newname)): + if safe: + raise NameError("File %r exists" % newname) + else: + os.remove(self._fpath(newname)) + os.rename(self._fpath(oldname), self._fpath(newname)) + + def lock(self, name): + return FileLock(self._fpath(name)) + + def temp_storage(self, name=None): + name = name or "%s.tmp" % random_name() + path = os.path.join(self.folder, name) + tempstore = FileStorage(path) + return tempstore.create() + + +class RamStorage(Storage): + """Storage object that keeps the index in memory. + """ + + supports_mmap = False + + def __init__(self): + self.files = {} + self.locks = {} + self.folder = '' + + def destroy(self): + del self.files + del self.locks + + def list(self): + return list(self.files.keys()) + + def clean(self): + self.files = {} + + def total_size(self): + return sum(self.file_length(f) for f in self.list()) + + def file_exists(self, name): + return name in self.files + + def file_length(self, name): + if name not in self.files: + raise NameError(name) + return len(self.files[name]) + + def file_modified(self, name): + return -1 + + def delete_file(self, name): + if name not in self.files: + raise NameError(name) + del self.files[name] + + def rename_file(self, name, newname, safe=False): + if name not in self.files: + raise NameError(name) + if safe and newname in self.files: + raise NameError("File %r exists" % newname) + + content = self.files[name] + del self.files[name] + self.files[newname] = content + + def create_file(self, name, **kwargs): + def onclose_fn(sfile): + self.files[name] = sfile.file.getvalue() + f = StructFile(BytesIO(), name=name, onclose=onclose_fn) + return f + + def open_file(self, name, **kwargs): + if name not in self.files: + raise NameError(name) + buf = memoryview_(self.files[name]) + return BufferFile(buf, name=name, **kwargs) + + def lock(self, name): + if name not in self.locks: + self.locks[name] = Lock() + return self.locks[name] + + def temp_storage(self, name=None): + tdir = tempfile.gettempdir() + name = name or "%s.tmp" % random_name() + path = os.path.join(tdir, name) + tempstore = FileStorage(path) + return tempstore.create() + + +def copy_storage(sourcestore, deststore): + """Copies the files from the source storage object to the destination + storage object using ``shutil.copyfileobj``. + """ + from shutil import copyfileobj + + for name in sourcestore.list(): + with sourcestore.open_file(name) as source: + with deststore.create_file(name) as dest: + copyfileobj(source, dest) + + +def copy_to_ram(storage): + """Copies the given FileStorage object into a new RamStorage object. + + :rtype: :class:`RamStorage` + """ + + ram = RamStorage() + copy_storage(storage, ram) + return ram diff --git a/nstock/modules/whoosh/filedb/filetables.py b/nstock/modules/whoosh/filedb/filetables.py new file mode 100644 index 0000000..f34f409 --- /dev/null +++ b/nstock/modules/whoosh/filedb/filetables.py @@ -0,0 +1,735 @@ +# Copyright 2009 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +"""This module defines writer and reader classes for a fast, immutable +on-disk key-value database format. The current format is based heavily on +D. J. Bernstein's CDB format (http://cr.yp.to/cdb.html). +""" + +import os, struct +from binascii import crc32 +from bisect import bisect_left +from hashlib import md5 # @UnresolvedImport + +from whoosh.compat import b, bytes_type +from whoosh.compat import xrange +from whoosh.util.numlists import GrowableArray +from whoosh.system import _INT_SIZE, emptybytes + + +# Exceptions + +class FileFormatError(Exception): + pass + + +# Hash functions + +def cdb_hash(key): + h = 5381 + for c in key: + h = (h + (h << 5)) & 0xffffffff ^ ord(c) + return h + + +def md5_hash(key): + return int(md5(key).hexdigest(), 16) & 0xffffffff + + +def crc_hash(key): + return crc32(key) & 0xffffffff + + +_hash_functions = (md5_hash, crc_hash, cdb_hash) + + +# Structs + +# Two uints before the key/value pair giving the length of the key and value +_lengths = struct.Struct("!ii") +# A pointer in a hash table, giving the hash value and the key position +_pointer = struct.Struct("!Iq") +# A pointer in the hash table directory, giving the position and number of slots +_dir_entry = struct.Struct("!qi") + +_directory_size = 256 * _dir_entry.size + + +# Basic hash file + +class HashWriter(object): + """Implements a fast on-disk key-value store. This hash uses a two-level + hashing scheme, where a key is hashed, the low eight bits of the hash value + are used to index into one of 256 hash tables. This is basically the CDB + algorithm, but unlike CDB this object writes all data serially (it doesn't + seek backwards to overwrite information at the end). + + Also unlike CDB, this format uses 64-bit file pointers, so the file length + is essentially unlimited. However, each key and value must be less than + 2 GB in length. + """ + + def __init__(self, dbfile, magic=b("HSH3"), hashtype=0): + """ + :param dbfile: a :class:`~whoosh.filedb.structfile.StructFile` object + to write to. + :param magic: the format tag bytes to write at the start of the file. + :param hashtype: an integer indicating which hashing algorithm to use. + Possible values are 0 (MD5), 1 (CRC32), or 2 (CDB hash). + """ + + self.dbfile = dbfile + self.hashtype = hashtype + self.hashfn = _hash_functions[self.hashtype] + # A place for subclasses to put extra metadata + self.extras = {} + + self.startoffset = dbfile.tell() + # Write format tag + dbfile.write(magic) + # Write hash type + dbfile.write_byte(self.hashtype) + # Unused future expansion bits + dbfile.write_int(0) + dbfile.write_int(0) + + # 256 lists of hashed keys and positions + self.buckets = [[] for _ in xrange(256)] + # List to remember the positions of the hash tables + self.directory = [] + + def tell(self): + return self.dbfile.tell() + + def add(self, key, value): + """Adds a key/value pair to the file. Note that keys DO NOT need to be + unique. You can store multiple values under the same key and retrieve + them using :meth:`HashReader.all`. + """ + + assert isinstance(key, bytes_type) + assert isinstance(value, bytes_type) + + dbfile = self.dbfile + pos = dbfile.tell() + dbfile.write(_lengths.pack(len(key), len(value))) + dbfile.write(key) + dbfile.write(value) + + # Get hash value for the key + h = self.hashfn(key) + # Add hash and on-disk position to appropriate bucket + self.buckets[h & 255].append((h, pos)) + + def add_all(self, items): + """Convenience method to add a sequence of ``(key, value)`` pairs. This + is the same as calling :meth:`HashWriter.add` on each pair in the + sequence. + """ + + add = self.add + for key, value in items: + add(key, value) + + def _write_hashes(self): + # Writes 256 hash tables containing pointers to the key/value pairs + + dbfile = self.dbfile + # Represent and empty slot in the hash table using 0,0 (no key can + # start at position 0 because of the header) + null = (0, 0) + + for entries in self.buckets: + # Start position of this bucket's hash table + pos = dbfile.tell() + # Remember the start position and the number of slots + numslots = 2 * len(entries) + self.directory.append((pos, numslots)) + + # Create the empty hash table + hashtable = [null] * numslots + # For each (hash value, key position) tuple in the bucket + for hashval, position in entries: + # Bitshift and wrap to get the slot for this entry + slot = (hashval >> 8) % numslots + # If the slot is taken, keep going until we find an empty slot + while hashtable[slot] != null: + slot = (slot + 1) % numslots + # Insert the entry into the hashtable + hashtable[slot] = (hashval, position) + + # Write the hash table for this bucket to disk + for hashval, position in hashtable: + dbfile.write(_pointer.pack(hashval, position)) + + def _write_directory(self): + # Writes a directory of pointers to the 256 hash tables + + dbfile = self.dbfile + for position, numslots in self.directory: + dbfile.write(_dir_entry.pack(position, numslots)) + + def _write_extras(self): + self.dbfile.write_pickle(self.extras) + + def close(self): + dbfile = self.dbfile + + # Write hash tables + self._write_hashes() + # Write directory of pointers to hash tables + self._write_directory() + + expos = dbfile.tell() + # Write extra information + self._write_extras() + # Write length of pickle + dbfile.write_int(dbfile.tell() - expos) + + endpos = dbfile.tell() + dbfile.close() + return endpos + + +class HashReader(object): + """Reader for the fast on-disk key-value files created by + :class:`HashWriter`. + """ + + def __init__(self, dbfile, length=None, magic=b("HSH3"), startoffset=0): + """ + :param dbfile: a :class:`~whoosh.filedb.structfile.StructFile` object + to read from. + :param length: the length of the file data. This is necessary since the + hashing information is written at the end of the file. + :param magic: the format tag bytes to look for at the start of the + file. If the file's format tag does not match these bytes, the + object raises a :class:`FileFormatError` exception. + :param startoffset: the starting point of the file data. + """ + + self.dbfile = dbfile + self.startoffset = startoffset + self.is_closed = False + + if length is None: + dbfile.seek(0, os.SEEK_END) + length = dbfile.tell() - startoffset + + dbfile.seek(startoffset) + # Check format tag + filemagic = dbfile.read(4) + if filemagic != magic: + raise FileFormatError("Unknown file header %r" % filemagic) + # Read hash type + self.hashtype = dbfile.read_byte() + self.hashfn = _hash_functions[self.hashtype] + # Skip unused future expansion bits + dbfile.read_int() + dbfile.read_int() + self.startofdata = dbfile.tell() + + exptr = startoffset + length - _INT_SIZE + # Get the length of extras from the end of the file + exlen = dbfile.get_int(exptr) + # Read the extras + expos = exptr - exlen + dbfile.seek(expos) + self._read_extras() + + # Calculate the directory base from the beginning of the extras + dbfile.seek(expos - _directory_size) + # Read directory of hash tables + self.tables = [] + entrysize = _dir_entry.size + unpackentry = _dir_entry.unpack + for _ in xrange(256): + # position, numslots + self.tables.append(unpackentry(dbfile.read(entrysize))) + # The position of the first hash table is the end of the key/value pairs + self.endofdata = self.tables[0][0] + + @classmethod + def open(cls, storage, name): + """Convenience method to open a hash file given a + :class:`whoosh.filedb.filestore.Storage` object and a name. This takes + care of opening the file and passing its length to the initializer. + """ + + length = storage.file_length(name) + dbfile = storage.open_file(name) + return cls(dbfile, length) + + def file(self): + return self.dbfile + + def _read_extras(self): + try: + self.extras = self.dbfile.read_pickle() + except EOFError: + self.extras = {} + + def close(self): + if self.is_closed: + raise Exception("Tried to close %r twice" % self) + self.dbfile.close() + self.is_closed = True + + def key_at(self, pos): + # Returns the key bytes at the given position + + dbfile = self.dbfile + keylen = dbfile.get_uint(pos) + return dbfile.get(pos + _lengths.size, keylen) + + def key_and_range_at(self, pos): + # Returns a (keybytes, datapos, datalen) tuple for the key at the given + # position + dbfile = self.dbfile + lenssize = _lengths.size + + if pos >= self.endofdata: + return None + + keylen, datalen = _lengths.unpack(dbfile.get(pos, lenssize)) + keybytes = dbfile.get(pos + lenssize, keylen) + datapos = pos + lenssize + keylen + return keybytes, datapos, datalen + + def _ranges(self, pos=None, eod=None): + # Yields a series of (keypos, keylength, datapos, datalength) tuples + # for the key/value pairs in the file + dbfile = self.dbfile + pos = pos or self.startofdata + eod = eod or self.endofdata + lenssize = _lengths.size + unpacklens = _lengths.unpack + + while pos < eod: + keylen, datalen = unpacklens(dbfile.get(pos, lenssize)) + keypos = pos + lenssize + datapos = keypos + keylen + yield (keypos, keylen, datapos, datalen) + pos = datapos + datalen + + def __getitem__(self, key): + for value in self.all(key): + return value + raise KeyError(key) + + def __iter__(self): + dbfile = self.dbfile + for keypos, keylen, datapos, datalen in self._ranges(): + key = dbfile.get(keypos, keylen) + value = dbfile.get(datapos, datalen) + yield (key, value) + + def __contains__(self, key): + for _ in self.ranges_for_key(key): + return True + return False + + def keys(self): + dbfile = self.dbfile + for keypos, keylen, _, _ in self._ranges(): + yield dbfile.get(keypos, keylen) + + def values(self): + dbfile = self.dbfile + for _, _, datapos, datalen in self._ranges(): + yield dbfile.get(datapos, datalen) + + def items(self): + dbfile = self.dbfile + for keypos, keylen, datapos, datalen in self._ranges(): + yield (dbfile.get(keypos, keylen), dbfile.get(datapos, datalen)) + + def get(self, key, default=None): + for value in self.all(key): + return value + return default + + def all(self, key): + """Yields a sequence of values associated with the given key. + """ + + dbfile = self.dbfile + for datapos, datalen in self.ranges_for_key(key): + yield dbfile.get(datapos, datalen) + + def ranges_for_key(self, key): + """Yields a sequence of ``(datapos, datalength)`` tuples associated + with the given key. + """ + + if not isinstance(key, bytes_type): + raise TypeError("Key %r should be bytes" % key) + dbfile = self.dbfile + + # Hash the key + keyhash = self.hashfn(key) + # Get the position and number of slots for the hash table in which the + # key may be found + tablestart, numslots = self.tables[keyhash & 255] + # If the hash table is empty, we know the key doesn't exists + if not numslots: + return + + ptrsize = _pointer.size + unpackptr = _pointer.unpack + lenssize = _lengths.size + unpacklens = _lengths.unpack + + # Calculate where the key's slot should be + slotpos = tablestart + (((keyhash >> 8) % numslots) * ptrsize) + # Read slots looking for our key's hash value + for _ in xrange(numslots): + slothash, itempos = unpackptr(dbfile.get(slotpos, ptrsize)) + # If this slot is empty, we're done + if not itempos: + return + + # If the key hash in this slot matches our key's hash, we might have + # a match, so read the actual key and see if it's our key + if slothash == keyhash: + # Read the key and value lengths + keylen, datalen = unpacklens(dbfile.get(itempos, lenssize)) + # Only bother reading the actual key if the lengths match + if keylen == len(key): + keystart = itempos + lenssize + if key == dbfile.get(keystart, keylen): + # The keys match, so yield (datapos, datalen) + yield (keystart + keylen, datalen) + + slotpos += ptrsize + # If we reach the end of the hashtable, wrap around + if slotpos == tablestart + (numslots * ptrsize): + slotpos = tablestart + + def range_for_key(self, key): + for item in self.ranges_for_key(key): + return item + raise KeyError(key) + + +# Ordered hash file + +class OrderedHashWriter(HashWriter): + """Implements an on-disk hash, but requires that keys be added in order. + An :class:`OrderedHashReader` can then look up "nearest keys" based on + the ordering. + """ + + def __init__(self, dbfile): + HashWriter.__init__(self, dbfile) + # Keep an array of the positions of all keys + self.index = GrowableArray("H") + # Keep track of the last key added + self.lastkey = emptybytes + + def add(self, key, value): + if key <= self.lastkey: + raise ValueError("Keys must increase: %r..%r" + % (self.lastkey, key)) + self.index.append(self.dbfile.tell()) + HashWriter.add(self, key, value) + self.lastkey = key + + def _write_extras(self): + dbfile = self.dbfile + index = self.index + + # Store metadata about the index array + self.extras["indextype"] = index.typecode + self.extras["indexlen"] = len(index) + # Write the extras + HashWriter._write_extras(self) + # Write the index array + index.to_file(dbfile) + + +class OrderedHashReader(HashReader): + def closest_key(self, key): + """Returns the closest key equal to or greater than the given key. If + there is no key in the file equal to or greater than the given key, + returns None. + """ + + pos = self.closest_key_pos(key) + if pos is None: + return None + return self.key_at(pos) + + def ranges_from(self, key): + """Yields a series of ``(keypos, keylen, datapos, datalen)`` tuples + for the ordered series of keys equal or greater than the given key. + """ + + pos = self.closest_key_pos(key) + if pos is None: + return + + for item in self._ranges(pos=pos): + yield item + + def keys_from(self, key): + """Yields an ordered series of keys equal to or greater than the given + key. + """ + + dbfile = self.dbfile + for keypos, keylen, _, _ in self.ranges_from(key): + yield dbfile.get(keypos, keylen) + + def items_from(self, key): + """Yields an ordered series of ``(key, value)`` tuples for keys equal + to or greater than the given key. + """ + + dbfile = self.dbfile + for keypos, keylen, datapos, datalen in self.ranges_from(key): + yield (dbfile.get(keypos, keylen), dbfile.get(datapos, datalen)) + + def _read_extras(self): + dbfile = self.dbfile + + # Read the extras + HashReader._read_extras(self) + + # Set up for reading the index array + indextype = self.extras["indextype"] + self.indexbase = dbfile.tell() + self.indexlen = self.extras["indexlen"] + self.indexsize = struct.calcsize(indextype) + # Set up the function to read values from the index array + if indextype == "B": + self._get_pos = dbfile.get_byte + elif indextype == "H": + self._get_pos = dbfile.get_ushort + elif indextype == "i": + self._get_pos = dbfile.get_int + elif indextype == "I": + self._get_pos = dbfile.get_uint + elif indextype == "q": + self._get_pos = dbfile.get_long + else: + raise Exception("Unknown index type %r" % indextype) + + def closest_key_pos(self, key): + # Given a key, return the position of that key OR the next highest key + # if the given key does not exist + if not isinstance(key, bytes_type): + raise TypeError("Key %r should be bytes" % key) + + indexbase = self.indexbase + indexsize = self.indexsize + key_at = self.key_at + _get_pos = self._get_pos + + # Do a binary search of the positions in the index array + lo = 0 + hi = self.indexlen + while lo < hi: + mid = (lo + hi) // 2 + midkey = key_at(_get_pos(indexbase + mid * indexsize)) + if midkey < key: + lo = mid + 1 + else: + hi = mid + + # If we went off the end, return None + if lo == self.indexlen: + return None + # Return the closest key + return _get_pos(indexbase + lo * indexsize) + + +# Fielded Ordered hash file + +class FieldedOrderedHashWriter(HashWriter): + """Implements an on-disk hash, but writes separate position indexes for + each field. + """ + + def __init__(self, dbfile): + HashWriter.__init__(self, dbfile) + # Map field names to (startpos, indexpos, length, typecode) + self.fieldmap = self.extras["fieldmap"] = {} + + # Keep track of the last key added + self.lastkey = emptybytes + + def start_field(self, fieldname): + self.fieldstart = self.dbfile.tell() + self.fieldname = fieldname + # Keep an array of the positions of all keys + self.poses = GrowableArray("H") + self.lastkey = emptybytes + + def add(self, key, value): + if key <= self.lastkey: + raise ValueError("Keys must increase: %r..%r" + % (self.lastkey, key)) + self.poses.append(self.dbfile.tell() - self.fieldstart) + HashWriter.add(self, key, value) + self.lastkey = key + + def end_field(self): + dbfile = self.dbfile + fieldname = self.fieldname + poses = self.poses + self.fieldmap[fieldname] = (self.fieldstart, dbfile.tell(), len(poses), + poses.typecode) + poses.to_file(dbfile) + + +class FieldedOrderedHashReader(HashReader): + def __init__(self, *args, **kwargs): + HashReader.__init__(self, *args, **kwargs) + self.fieldmap = self.extras["fieldmap"] + # Make a sorted list of the field names with their start and end ranges + self.fieldlist = [] + for fieldname in sorted(self.fieldmap.keys()): + startpos, ixpos, ixsize, ixtype = self.fieldmap[fieldname] + self.fieldlist.append((fieldname, startpos, ixpos)) + + def field_start(self, fieldname): + return self.fieldmap[fieldname][0] + + def fielded_ranges(self, pos=None, eod=None): + flist = self.fieldlist + fpos = 0 + fieldname, start, end = flist[fpos] + for keypos, keylen, datapos, datalen in self._ranges(pos, eod): + if keypos >= end: + fpos += 1 + fieldname, start, end = flist[fpos] + yield fieldname, keypos, keylen, datapos, datalen + + def iter_terms(self): + get = self.dbfile.get + for fieldname, keypos, keylen, _, _ in self.fielded_ranges(): + yield fieldname, get(keypos, keylen) + + def iter_term_items(self): + get = self.dbfile.get + for item in self.fielded_ranges(): + fieldname, keypos, keylen, datapos, datalen = item + yield fieldname, get(keypos, keylen), get(datapos, datalen) + + def contains_term(self, fieldname, btext): + try: + x = self.range_for_term(fieldname, btext) + return True + except KeyError: + return False + + def range_for_term(self, fieldname, btext): + start, ixpos, ixsize, code = self.fieldmap[fieldname] + for datapos, datalen in self.ranges_for_key(btext): + if start < datapos < ixpos: + return datapos, datalen + raise KeyError((fieldname, btext)) + + def term_data(self, fieldname, btext): + datapos, datalen = self.range_for_term(fieldname, btext) + return self.dbfile.get(datapos, datalen) + + def term_get(self, fieldname, btext, default=None): + try: + return self.term_data(fieldname, btext) + except KeyError: + return default + + def closest_term_pos(self, fieldname, key): + # Given a key, return the position of that key OR the next highest key + # if the given key does not exist + if not isinstance(key, bytes_type): + raise TypeError("Key %r should be bytes" % key) + + dbfile = self.dbfile + key_at = self.key_at + startpos, ixpos, ixsize, ixtype = self.fieldmap[fieldname] + + if ixtype == "B": + get_pos = dbfile.get_byte + elif ixtype == "H": + get_pos = dbfile.get_ushort + elif ixtype == "i": + get_pos = dbfile.get_int + elif ixtype == "I": + get_pos = dbfile.get_uint + elif ixtype == "q": + get_pos = dbfile.get_long + else: + raise Exception("Unknown index type %r" % ixtype) + + # Do a binary search of the positions in the index array + lo = 0 + hi = ixsize + while lo < hi: + mid = (lo + hi) // 2 + midkey = key_at(startpos + get_pos(ixpos + mid * ixsize)) + if midkey < key: + lo = mid + 1 + else: + hi = mid + + # If we went off the end, return None + if lo == ixsize: + return None + # Return the closest key + return startpos + get_pos(ixpos + lo * ixsize) + + def closest_term(self, fieldname, btext): + pos = self.closest_term_pos(fieldname, btext) + if pos is None: + return None + return self.key_at(pos) + + def term_ranges_from(self, fieldname, btext): + pos = self.closest_term_pos(fieldname, btext) + if pos is None: + return + + startpos, ixpos, ixsize, ixtype = self.fieldmap[fieldname] + for item in self._ranges(pos, ixpos): + yield item + + def terms_from(self, fieldname, btext): + dbfile = self.dbfile + for keypos, keylen, _, _ in self.term_ranges_from(fieldname, btext): + yield dbfile.get(keypos, keylen) + + def term_items_from(self, fieldname, btext): + dbfile = self.dbfile + for item in self.term_ranges_from(fieldname, btext): + keypos, keylen, datapos, datalen = item + yield (dbfile.get(keypos, keylen), dbfile.get(datapos, datalen)) + + + diff --git a/nstock/modules/whoosh/filedb/gae.py b/nstock/modules/whoosh/filedb/gae.py new file mode 100644 index 0000000..bf0d5d2 --- /dev/null +++ b/nstock/modules/whoosh/filedb/gae.py @@ -0,0 +1,164 @@ +""" +This module contains EXPERIMENTAL support for storing a Whoosh index's files in +the Google App Engine blobstore. This will use a lot of RAM since all files are +loaded into RAM, but it potentially useful as a workaround for the lack of file +storage in Google App Engine. + +Use at your own risk, but please report any problems to me so I can fix them. + +To create a new index:: + + from whoosh.filedb.gae import DatastoreStorage + + ix = DatastoreStorage().create_index(schema) + +To open an existing index:: + + ix = DatastoreStorage().open_index() +""" + +import time + +from google.appengine.api import memcache # @UnresolvedImport +from google.appengine.ext import db # @UnresolvedImport + +from whoosh.compat import BytesIO +from whoosh.index import TOC, FileIndex, _DEF_INDEX_NAME +from whoosh.filedb.filestore import ReadOnlyError, Storage +from whoosh.filedb.structfile import StructFile + + +class DatastoreFile(db.Model): + """A file-like object that is backed by a BytesIO() object whose contents + is loaded from a BlobProperty in the app engine datastore. + """ + + value = db.BlobProperty() + mtime = db.IntegerProperty(default=0) + + def __init__(self, *args, **kwargs): + super(DatastoreFile, self).__init__(*args, **kwargs) + self.data = BytesIO() + + @classmethod + def loadfile(cls, name): + value = memcache.get(name, namespace="DatastoreFile") + if value is None: + file = cls.get_by_key_name(name) + memcache.set(name, file.value, namespace="DatastoreFile") + else: + file = cls(value=value) + file.data = BytesIO(file.value) + return file + + def close(self): + oldvalue = self.value + self.value = self.getvalue() + if oldvalue != self.value: + self.mtime = int(time.time()) + self.put() + memcache.set(self.key().id_or_name(), self.value, + namespace="DatastoreFile") + + def tell(self): + return self.data.tell() + + def write(self, data): + return self.data.write(data) + + def read(self, length): + return self.data.read(length) + + def seek(self, *args): + return self.data.seek(*args) + + def readline(self): + return self.data.readline() + + def getvalue(self): + return self.data.getvalue() + + +class MemcacheLock(object): + def __init__(self, name): + self.name = name + + def acquire(self, blocking=False): + val = memcache.add(self.name, "L", 360, namespace="whooshlocks") + + if blocking and not val: + # Simulate blocking by retrying the acquire over and over + import time + while not val: + time.sleep(0.1) + val = memcache.add(self.name, "", 360, namespace="whooshlocks") + + return val + + def release(self): + memcache.delete(self.name, namespace="whooshlocks") + + +class DatastoreStorage(Storage): + """An implementation of :class:`whoosh.store.Storage` that stores files in + the app engine datastore as blob properties. + """ + + def create_index(self, schema, indexname=_DEF_INDEX_NAME): + if self.readonly: + raise ReadOnlyError + + TOC.create(self, schema, indexname) + return FileIndex(self, schema, indexname) + + def open_index(self, indexname=_DEF_INDEX_NAME, schema=None): + return FileIndex(self, schema=schema, indexname=indexname) + + def list(self): + query = DatastoreFile.all() + keys = [] + for file in query: + keys.append(file.key().id_or_name()) + return keys + + def clean(self): + pass + + def total_size(self): + return sum(self.file_length(f) for f in self.list()) + + def file_exists(self, name): + return DatastoreFile.get_by_key_name(name) is not None + + def file_modified(self, name): + return DatastoreFile.get_by_key_name(name).mtime + + def file_length(self, name): + return len(DatastoreFile.get_by_key_name(name).value) + + def delete_file(self, name): + memcache.delete(name, namespace="DatastoreFile") + return DatastoreFile.get_by_key_name(name).delete() + + def rename_file(self, name, newname, safe=False): + file = DatastoreFile.get_by_key_name(name) + newfile = DatastoreFile(key_name=newname) + newfile.value = file.value + newfile.mtime = file.mtime + newfile.put() + file.delete() + + def create_file(self, name, **kwargs): + f = StructFile(DatastoreFile(key_name=name), name=name, + onclose=lambda sfile: sfile.file.close()) + return f + + def open_file(self, name, *args, **kwargs): + return StructFile(DatastoreFile.loadfile(name)) + + def lock(self, name): + return MemcacheLock(name) + + def temp_storage(self, name=None): + tempstore = DatastoreStorage() + return tempstore.create() diff --git a/nstock/modules/whoosh/filedb/structfile.py b/nstock/modules/whoosh/filedb/structfile.py new file mode 100644 index 0000000..8bf1cbc --- /dev/null +++ b/nstock/modules/whoosh/filedb/structfile.py @@ -0,0 +1,402 @@ +# Copyright 2009 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from array import array +from copy import copy +from struct import calcsize + +from whoosh.compat import BytesIO, bytes_type +from whoosh.compat import dump as dump_pickle +from whoosh.compat import load as load_pickle +from whoosh.compat import array_frombytes, array_tobytes +from whoosh.system import _INT_SIZE, _SHORT_SIZE, _FLOAT_SIZE, _LONG_SIZE +from whoosh.system import IS_LITTLE +from whoosh.system import pack_byte, unpack_byte, pack_sbyte, unpack_sbyte +from whoosh.system import pack_ushort, unpack_ushort +from whoosh.system import pack_ushort_le, unpack_ushort_le +from whoosh.system import pack_int, unpack_int, pack_uint, unpack_uint +from whoosh.system import pack_uint_le, unpack_uint_le +from whoosh.system import pack_long, unpack_long, pack_ulong, unpack_ulong +from whoosh.system import pack_float, unpack_float +from whoosh.util.varints import varint, read_varint +from whoosh.util.varints import signed_varint, decode_signed_varint + + +_SIZEMAP = dict((typecode, calcsize(typecode)) for typecode in "bBiIhHqQf") +_ORDERMAP = {"little": "<", "big": ">"} + +_types = (("sbyte", "b"), ("ushort", "H"), ("int", "i"), + ("long", "q"), ("float", "f")) + + +# Main function + +class StructFile(object): + """Returns a "structured file" object that wraps the given file object and + provides numerous additional methods for writing structured data, such as + "write_varint" and "write_long". + """ + + def __init__(self, fileobj, name=None, onclose=None): + self.file = fileobj + self._name = name + self.onclose = onclose + self.is_closed = False + + self.is_real = hasattr(fileobj, "fileno") + if self.is_real: + self.fileno = fileobj.fileno + + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self._name) + + def __str__(self): + return self._name + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.close() + + def __iter__(self): + return iter(self.file) + + def raw_file(self): + return self.file + + def read(self, *args, **kwargs): + return self.file.read(*args, **kwargs) + + def readline(self, *args, **kwargs): + return self.file.readline(*args, **kwargs) + + def write(self, *args, **kwargs): + return self.file.write(*args, **kwargs) + + def tell(self, *args, **kwargs): + return self.file.tell(*args, **kwargs) + + def seek(self, *args, **kwargs): + return self.file.seek(*args, **kwargs) + + def truncate(self, *args, **kwargs): + return self.file.truncate(*args, **kwargs) + + def flush(self): + """Flushes the buffer of the wrapped file. This is a no-op if the + wrapped file does not have a flush method. + """ + + if hasattr(self.file, "flush"): + self.file.flush() + + def close(self): + """Closes the wrapped file. + """ + + if self.is_closed: + raise Exception("This file is already closed") + if self.onclose: + self.onclose(self) + if hasattr(self.file, "close"): + self.file.close() + self.is_closed = True + + def subset(self, offset, length, name=None): + from whoosh.filedb.compound import SubFile + + name = name or self._name + return StructFile(SubFile(self.file, offset, length), name=name) + + def write_string(self, s): + """Writes a string to the wrapped file. This method writes the length + of the string first, so you can read the string back without having to + know how long it was. + """ + self.write_varint(len(s)) + self.write(s) + + def write_string2(self, s): + self.write(pack_ushort(len(s)) + s) + + def write_string4(self, s): + self.write(pack_int(len(s)) + s) + + def read_string(self): + """Reads a string from the wrapped file. + """ + return self.read(self.read_varint()) + + def read_string2(self): + l = self.read_ushort() + return self.read(l) + + def read_string4(self): + l = self.read_int() + return self.read(l) + + def get_string2(self, pos): + l = self.get_ushort(pos) + base = pos + _SHORT_SIZE + return self.get(base, l), base + l + + def get_string4(self, pos): + l = self.get_int(pos) + base = pos + _INT_SIZE + return self.get(base, l), base + l + + def skip_string(self): + l = self.read_varint() + self.seek(l, 1) + + def write_varint(self, i): + """Writes a variable-length unsigned integer to the wrapped file. + """ + self.write(varint(i)) + + def write_svarint(self, i): + """Writes a variable-length signed integer to the wrapped file. + """ + self.write(signed_varint(i)) + + def read_varint(self): + """Reads a variable-length encoded unsigned integer from the wrapped + file. + """ + return read_varint(self.read) + + def read_svarint(self): + """Reads a variable-length encoded signed integer from the wrapped + file. + """ + return decode_signed_varint(read_varint(self.read)) + + def write_tagint(self, i): + """Writes a sometimes-compressed unsigned integer to the wrapped file. + This is similar to the varint methods but uses a less compressed but + faster format. + """ + + # Store numbers 0-253 in one byte. Byte 254 means "an unsigned 16-bit + # int follows." Byte 255 means "An unsigned 32-bit int follows." + if i <= 253: + self.write(chr(i)) + elif i <= 65535: + self.write("\xFE" + pack_ushort(i)) + else: + self.write("\xFF" + pack_uint(i)) + + def read_tagint(self): + """Reads a sometimes-compressed unsigned integer from the wrapped file. + This is similar to the varint methods but uses a less compressed but + faster format. + """ + + tb = ord(self.read(1)) + if tb == 254: + return self.read_ushort() + elif tb == 255: + return self.read_uint() + else: + return tb + + def write_byte(self, n): + """Writes a single byte to the wrapped file, shortcut for + ``file.write(chr(n))``. + """ + self.write(pack_byte(n)) + + def read_byte(self): + return ord(self.read(1)) + + def write_pickle(self, obj, protocol=-1): + """Writes a pickled representation of obj to the wrapped file. + """ + dump_pickle(obj, self.file, protocol) + + def read_pickle(self): + """Reads a pickled object from the wrapped file. + """ + return load_pickle(self.file) + + def write_sbyte(self, n): + self.write(pack_sbyte(n)) + + def write_int(self, n): + self.write(pack_int(n)) + + def write_uint(self, n): + self.write(pack_uint(n)) + + def write_uint_le(self, n): + self.write(pack_uint_le(n)) + + def write_ushort(self, n): + self.write(pack_ushort(n)) + + def write_ushort_le(self, n): + self.write(pack_ushort_le(n)) + + def write_long(self, n): + self.write(pack_long(n)) + + def write_ulong(self, n): + self.write(pack_ulong(n)) + + def write_float(self, n): + self.write(pack_float(n)) + + def write_array(self, arry): + if IS_LITTLE: + arry = copy(arry) + arry.byteswap() + if self.is_real: + arry.tofile(self.file) + else: + self.write(array_tobytes(arry)) + + def read_sbyte(self): + return unpack_sbyte(self.read(1))[0] + + def read_int(self): + return unpack_int(self.read(_INT_SIZE))[0] + + def read_uint(self): + return unpack_uint(self.read(_INT_SIZE))[0] + + def read_uint_le(self): + return unpack_uint_le(self.read(_INT_SIZE))[0] + + def read_ushort(self): + return unpack_ushort(self.read(_SHORT_SIZE))[0] + + def read_ushort_le(self): + return unpack_ushort_le(self.read(_SHORT_SIZE))[0] + + def read_long(self): + return unpack_long(self.read(_LONG_SIZE))[0] + + def read_ulong(self): + return unpack_ulong(self.read(_LONG_SIZE))[0] + + def read_float(self): + return unpack_float(self.read(_FLOAT_SIZE))[0] + + def read_array(self, typecode, length): + a = array(typecode) + if self.is_real: + a.fromfile(self.file, length) + else: + array_frombytes(a, self.read(length * _SIZEMAP[typecode])) + if IS_LITTLE: + a.byteswap() + return a + + def get(self, position, length): + self.seek(position) + return self.read(length) + + def get_byte(self, position): + return unpack_byte(self.get(position, 1))[0] + + def get_sbyte(self, position): + return unpack_sbyte(self.get(position, 1))[0] + + def get_int(self, position): + return unpack_int(self.get(position, _INT_SIZE))[0] + + def get_uint(self, position): + return unpack_uint(self.get(position, _INT_SIZE))[0] + + def get_ushort(self, position): + return unpack_ushort(self.get(position, _SHORT_SIZE))[0] + + def get_long(self, position): + return unpack_long(self.get(position, _LONG_SIZE))[0] + + def get_ulong(self, position): + return unpack_ulong(self.get(position, _LONG_SIZE))[0] + + def get_float(self, position): + return unpack_float(self.get(position, _FLOAT_SIZE))[0] + + def get_array(self, position, typecode, length): + self.seek(position) + return self.read_array(typecode, length) + + +class BufferFile(StructFile): + def __init__(self, buf, name=None, onclose=None): + self._buf = buf + self._name = name + self.file = BytesIO(buf) + self.onclose = onclose + + self.is_real = False + self.is_closed = False + + def subset(self, position, length, name=None): + name = name or self._name + return BufferFile(self.get(position, length), name=name) + + def get(self, position, length): + return bytes_type(self._buf[position:position + length]) + + def get_array(self, position, typecode, length): + a = array(typecode) + array_frombytes(a, self.get(position, length * _SIZEMAP[typecode])) + if IS_LITTLE: + a.byteswap() + return a + + +class ChecksumFile(StructFile): + def __init__(self, *args, **kwargs): + StructFile.__init__(self, *args, **kwargs) + self._check = 0 + self._crc32 = __import__("zlib").crc32 + + def __iter__(self): + for line in self.file: + self._check = self._crc32(line, self._check) + yield line + + def seek(self, *args): + raise Exception("Cannot seek on a ChecksumFile") + + def read(self, *args, **kwargs): + b = self.file.read(*args, **kwargs) + self._check = self._crc32(b, self._check) + return b + + def write(self, b): + self._check = self._crc32(b, self._check) + self.file.write(b) + + def checksum(self): + return self._check & 0xffffffff diff --git a/nstock/modules/whoosh/formats.py b/nstock/modules/whoosh/formats.py new file mode 100644 index 0000000..b97435e --- /dev/null +++ b/nstock/modules/whoosh/formats.py @@ -0,0 +1,481 @@ +# Copyright 2009 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +""" +The classes in this module encode and decode posting information for a field. +The field format essentially determines what information is stored about each +occurance of a term. +""" + +from collections import defaultdict + +from whoosh.analysis import unstopped, entoken +from whoosh.compat import iteritems, dumps, loads, b +from whoosh.system import emptybytes +from whoosh.system import _INT_SIZE, _FLOAT_SIZE +from whoosh.system import pack_uint, unpack_uint, pack_float, unpack_float + + +# Format base class + +class Format(object): + """Abstract base class representing a storage format for a field or vector. + Format objects are responsible for writing and reading the low-level + representation of a field. It controls what kind/level of information to + store about the indexed fields. + """ + + posting_size = -1 + textual = True + __inittypes__ = dict(field_boost=float) + + def __init__(self, field_boost=1.0, **options): + """ + :param field_boost: A constant boost factor to scale to the score + of all queries matching terms in this field. + """ + + self.field_boost = field_boost + self.options = options + + def __eq__(self, other): + return (other + and self.__class__ is other.__class__ + and self.__dict__ == other.__dict__) + + def __repr__(self): + return "%s(boost=%s)" % (self.__class__.__name__, self.field_boost) + + def fixed_value_size(self): + if self.posting_size < 0: + return None + return self.posting_size + + def word_values(self, value, analyzer, **kwargs): + """Takes the text value to be indexed and yields a series of + ("tokentext", frequency, weight, valuestring) tuples, where frequency + is the number of times "tokentext" appeared in the value, weight is the + weight (a float usually equal to frequency in the absence of per-term + boosts) and valuestring is encoded field-specific posting value for the + token. For example, in a Frequency format, the value string would be + the same as frequency; in a Positions format, the value string would + encode a list of token positions at which "tokentext" occured. + + :param value: The unicode text to index. + :param analyzer: The analyzer to use to process the text. + """ + + raise NotImplementedError + + def supports(self, name): + """Returns True if this format supports interpreting its posting + value as 'name' (e.g. "frequency" or "positions"). + """ + return hasattr(self, "decode_" + name) + + def decoder(self, name): + """Returns the bound method for interpreting value as 'name', + where 'name' is for example "frequency" or "positions". This + object must have a corresponding Format.decode_() method. + """ + return getattr(self, "decode_" + name) + + def decode_as(self, astype, valuestring): + """Interprets the encoded value string as 'astype', where 'astype' is + for example "frequency" or "positions". This object must have a + corresponding decode_() method. + """ + return self.decoder(astype)(valuestring) + + +# Concrete field classes + +# TODO: as a legacy thing most of these formats store the frequency but not the +# weight in the value string, so if you use field or term boosts +# postreader.value_as("weight") will not match postreader.weight() + +def tokens(value, analyzer, kwargs): + if isinstance(value, (tuple, list)): + gen = entoken(value, **kwargs) + else: + gen = analyzer(value, **kwargs) + return unstopped(gen) + + +class Existence(Format): + """Only indexes whether a given term occurred in a given document; it does + not store frequencies or positions. This is useful for fields that should + be searchable but not scorable, such as file path. + + Supports: frequency, weight (always reports frequency = 1). + """ + + posting_size = 0 + __inittypes__ = dict(field_boost=float) + + def __init__(self, field_boost=1.0, **options): + self.field_boost = field_boost + self.options = options + + def word_values(self, value, analyzer, **kwargs): + fb = self.field_boost + wordset = set(t.text for t in tokens(value, analyzer, kwargs)) + return ((w, 1, fb, emptybytes) for w in wordset) + + def encode(self, value): + return emptybytes + + def decode_frequency(self, valuestring): + return 1 + + def decode_weight(self, valuestring): + return self.field_boost + + def combine(self, vs): + return emptybytes + + +class Frequency(Format): + """Stores frequency information for each posting. + + Supports: frequency, weight. + """ + + posting_size = _INT_SIZE + __inittypes__ = dict(field_boost=float, boost_as_freq=bool) + + def __init__(self, field_boost=1.0, boost_as_freq=False, + **options): + """ + :param field_boost: A constant boost factor to scale to the score of + all queries matching terms in this field. + """ + + assert isinstance(field_boost, float) + self.field_boost = field_boost + self.options = options + + def word_values(self, value, analyzer, **kwargs): + fb = self.field_boost + length = 0 + freqs = defaultdict(int) + weights = defaultdict(float) + + kwargs["boosts"] = True + for t in tokens(value, analyzer, kwargs): + length += 1 + freqs[t.text] += 1 + weights[t.text] += t.boost + + wvs = ((w, freq, weights[w] * fb, pack_uint(freq)) for w, freq + in iteritems(freqs)) + return wvs + + def decode_frequency(self, valuestring): + return unpack_uint(valuestring)[0] + + def decode_weight(self, valuestring): + freq = unpack_uint(valuestring)[0] + return freq * self.field_boost + + def combine(self, vs): + return pack_uint(sum(self.decode_value(v) for v in vs)) + + +class Positions(Format): + """Stores position information in each posting, to allow phrase searching + and "near" queries. + + Supports: frequency, weight, positions, position_boosts (always reports + position boost = 1.0). + """ + + def word_values(self, value, analyzer, **kwargs): + fb = self.field_boost + poses = defaultdict(list) + weights = defaultdict(float) + kwargs["positions"] = True + kwargs["boosts"] = True + for t in tokens(value, analyzer, kwargs): + poses[t.text].append(t.pos) + weights[t.text] += t.boost + + for w, poslist in iteritems(poses): + value = self.encode(poslist) + yield (w, len(poslist), weights[w] * fb, value) + + def encode(self, poslist): + deltas = [] + base = 0 + for pos in poslist: + deltas.append(pos - base) + base = pos + return pack_uint(len(deltas)) + dumps(deltas, 2) + + def decode_positions(self, valuestring): + if not valuestring.endswith(b(".")): + valuestring += b(".") + codes = loads(valuestring[_INT_SIZE:]) + position = 0 + positions = [] + for code in codes: + position += code + positions.append(position) + return positions + + def decode_frequency(self, valuestring): + return unpack_uint(valuestring[:_INT_SIZE])[0] + + def decode_weight(self, valuestring): + return self.decode_frequency(valuestring) * self.field_boost + + def decode_position_boosts(self, valuestring): + return [(pos, 1) for pos in self.decode_positions(valuestring)] + + def combine(self, vs): + s = set() + for v in vs: + s.update(self.decode_positions(v)) + return self.encode(sorted(s)) + + +class Characters(Positions): + """Stores token position and character start and end information for each + posting. + + Supports: frequency, weight, positions, position_boosts (always reports + position boost = 1.0), characters. + """ + + def word_values(self, value, analyzer, **kwargs): + fb = self.field_boost + seen = defaultdict(list) + weights = defaultdict(float) + + kwargs["positions"] = True + kwargs["chars"] = True + kwargs["boosts"] = True + for t in tokens(value, analyzer, kwargs): + seen[t.text].append((t.pos, t.startchar, t.endchar)) + weights[t.text] += t.boost + + for w, poslist in iteritems(seen): + value = self.encode(poslist) + yield (w, len(poslist), weights[w] * fb, value) + + def encode(self, poslist): + deltas = [] + posbase = 0 + charbase = 0 + for pos, startchar, endchar in poslist: + deltas.append((pos - posbase, startchar - charbase, + endchar - startchar)) + posbase = pos + charbase = endchar + return pack_uint(len(deltas)) + dumps(deltas, 2) + + def decode_characters(self, valuestring): + if not valuestring.endswith(b(".")): + valuestring += b(".") + codes = loads(valuestring[_INT_SIZE:]) + position = 0 + endchar = 0 + posns_chars = [] + for code in codes: + position = code[0] + position + startchar = code[1] + endchar + endchar = code[2] + startchar + posns_chars.append((position, startchar, endchar)) + return posns_chars + + def decode_positions(self, valuestring): + if not valuestring.endswith(b(".")): + valuestring += b(".") + codes = loads(valuestring[_INT_SIZE:]) + position = 0 + posns = [] + for code in codes: + position = code[0] + position + posns.append(position) + return posns + + def combine(self, vs): + s = {} + for v in vs: + for pos, sc, ec in self.decode_characters(v): + if pos in s: + old_sc, old_ec = pos[s] + s[pos] = (min(sc, old_sc), max(ec, old_ec)) + else: + s[pos] = (sc, ec) + poses = [(pos, s[pos][0], s[pos][1]) for pos in sorted(s.keys())] + return self.encode(poses) + + +class PositionBoosts(Positions): + """A format that stores positions and per-position boost information + in each posting. + + Supports: frequency, weight, positions, position_boosts. + """ + + def word_values(self, value, analyzer, **kwargs): + fb = self.field_boost + seen = defaultdict(list) + + kwargs["positions"] = True + kwargs["boosts"] = True + for t in tokens(value, analyzer, kwargs): + pos = t.pos + boost = t.boost + seen[t.text].append((pos, boost)) + + for w, poses in iteritems(seen): + value = self.encode(poses) + yield (w, len(poses), sum(p[1] for p in poses) * fb, value) + + def encode(self, poses): + codes = [] + base = 0 + summedboost = 0 + for pos, boost in poses: + summedboost += boost + codes.append((pos - base, boost)) + base = pos + return (pack_uint(len(poses)) + pack_float(summedboost) + + dumps(codes, 2)) + + def decode_position_boosts(self, valuestring): + if not valuestring.endswith(b(".")): + valuestring += b(".") + codes = loads(valuestring[_INT_SIZE + _FLOAT_SIZE:]) + position = 0 + posns_boosts = [] + for code in codes: + position = code[0] + position + posns_boosts.append((position, code[1])) + return posns_boosts + + def decode_positions(self, valuestring): + if not valuestring.endswith(b(".")): + valuestring += b(".") + codes = loads(valuestring[_INT_SIZE + _FLOAT_SIZE:]) + position = 0 + posns = [] + for code in codes: + position = code[0] + position + posns.append(position) + return posns + + def decode_weight(self, v): + summedboost = unpack_float(v[_INT_SIZE:_INT_SIZE + _FLOAT_SIZE])[0] + return summedboost * self.field_boost + + def combine(self, vs): + s = defaultdict(float) + for v in vs: + for pos, boost in self.decode_position_boosts(v): + s[pos] += boost + return self.encode(sorted(s.items())) + + +class CharacterBoosts(Characters): + """A format that stores positions, character start and end, and + per-position boost information in each posting. + + Supports: frequency, weight, positions, position_boosts, characters, + character_boosts. + """ + + def word_values(self, value, analyzer, **kwargs): + seen = defaultdict(list) + + kwargs["positions"] = True + kwargs["chars"] = True + kwargs["boosts"] = True + for t in tokens(value, analyzer, kwargs): + seen[t.text].append((t.pos, t.startchar, t.endchar, t.boost)) + + for w, poses in iteritems(seen): + value, summedboost = self.encode(poses) + yield (w, len(poses), summedboost, value) + + def encode(self, poses): + fb = self.field_boost + # posns_chars_boosts = [(pos, startchar, endchar, boost), ...] + codes = [] + posbase = 0 + charbase = 0 + summedboost = 0 + for pos, startchar, endchar, boost in poses: + codes.append((pos - posbase, startchar - charbase, + endchar - startchar, boost)) + posbase = pos + charbase = endchar + summedboost += boost + + return ((pack_uint(len(poses)) + pack_float(summedboost * fb) + + dumps(codes, 2)), summedboost) + + def decode_character_boosts(self, valuestring): + if not valuestring.endswith(b(".")): + valuestring += b(".") + codes = loads(valuestring[_INT_SIZE + _FLOAT_SIZE:]) + position = 0 + endchar = 0 + posn_char_boosts = [] + for code in codes: + position = position + code[0] + startchar = endchar + code[1] + endchar = startchar + code[2] + posn_char_boosts.append((position, startchar, endchar, code[3])) + return posn_char_boosts + + def decode_positions(self, valuestring): + return [item[0] for item in self.decode_character_boosts(valuestring)] + + def decode_characters(self, valuestring): + return [(pos, startchar, endchar) for pos, startchar, endchar, _ + in self.decode_character_boosts(valuestring)] + + def decode_position_boosts(self, valuestring): + return [(pos, boost) for pos, _, _, boost + in self.decode_character_boosts(valuestring)] + + def combine(self, vs): + s = {} + for v in vs: + for pos, sc, ec, boost in self.decode_character_boosts(v): + if pos in s: + old_sc, old_ec, old_boost = pos[s] + s[pos] = (min(sc, old_sc), max(ec, old_ec), + old_boost + boost) + else: + s[pos] = (sc, ec, boost) + poses = [(pos, sc, ec, boost) for pos, (sc, ec, boost) + in sorted(s.items())] + return self.encode(poses)[0] # encode() returns value, summedboost diff --git a/nstock/modules/whoosh/highlight.py b/nstock/modules/whoosh/highlight.py new file mode 100644 index 0000000..8218086 --- /dev/null +++ b/nstock/modules/whoosh/highlight.py @@ -0,0 +1,954 @@ +# Copyright 2008 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +"""The highlight module contains classes and functions for displaying short +excerpts from hit documents in the search results you present to the user, with +query terms highlighted. + +The highlighting system has four main elements. + +* **Fragmenters** chop up the original text into __fragments__, based on the + locations of matched terms in the text. + +* **Scorers** assign a score to each fragment, allowing the system to rank the + best fragments by whatever criterion. + +* **Order functions** control in what order the top-scoring fragments are + presented to the user. For example, you can show the fragments in the order + they appear in the document (FIRST) or show higher-scoring fragments first + (SCORE) + +* **Formatters** turn the fragment objects into human-readable output, such as + an HTML string. + +See :doc:`/highlight` for more information. +""" + +from __future__ import division +from collections import deque +from heapq import nlargest +from itertools import groupby + +from whoosh.compat import htmlescape +from whoosh.analysis import Token + + +# The default value for the maximum chars to examine when fragmenting +DEFAULT_CHARLIMIT = 2 ** 15 + + +# Fragment object + +def mkfrag(text, tokens, startchar=None, endchar=None, + charsbefore=0, charsafter=0): + """Returns a :class:`Fragment` object based on the :class:`analysis.Token` + objects in ``tokens`. + """ + + if startchar is None: + startchar = tokens[0].startchar if tokens else 0 + if endchar is None: + endchar = tokens[-1].endchar if tokens else len(text) + + startchar = max(0, startchar - charsbefore) + endchar = min(len(text), endchar + charsafter) + + return Fragment(text, tokens, startchar, endchar) + + +class Fragment(object): + """Represents a fragment (extract) from a hit document. This object is + mainly used to keep track of the start and end points of the fragment and + the "matched" character ranges inside; it does not contain the text of the + fragment or do much else. + + The useful attributes are: + + ``Fragment.text`` + The entire original text from which this fragment is taken. + + ``Fragment.matches`` + An ordered list of objects representing the matched terms in the + fragment. These objects have ``startchar`` and ``endchar`` attributes. + + ``Fragment.startchar`` + The index of the first character in the fragment. + + ``Fragment.endchar`` + The index of the last character in the fragment. + + ``Fragment.matched_terms`` + A ``set`` of the ``text`` of the matched terms in the fragment (if + available). + """ + + def __init__(self, text, matches, startchar=0, endchar= -1): + """ + :param text: the source text of the fragment. + :param matches: a list of objects which have ``startchar`` and + ``endchar`` attributes, and optionally a ``text`` attribute. + :param startchar: the index into ``text`` at which the fragment starts. + The default is 0. + :param endchar: the index into ``text`` at which the fragment ends. + The default is -1, which is interpreted as the length of ``text``. + """ + + self.text = text + self.matches = matches + + if endchar == -1: + endchar = len(text) + self.startchar = startchar + self.endchar = endchar + + self.matched_terms = set() + for t in matches: + if hasattr(t, "text"): + self.matched_terms.add(t.text) + + def __repr__(self): + return "" % (self.startchar, self.endchar, + len(self.matches)) + + def __len__(self): + return self.endchar - self.startchar + + def overlaps(self, fragment): + sc = self.startchar + ec = self.endchar + fsc = fragment.startchar + fec = fragment.endchar + return (sc < fsc < ec) or (sc < fec < ec) + + def overlapped_length(self, fragment): + sc = self.startchar + ec = self.endchar + fsc = fragment.startchar + fec = fragment.endchar + return max(ec, fec) - min(sc, fsc) + + def __lt__(self, other): + return id(self) < id(other) + + +# Tokenizing + +def set_matched_filter(tokens, termset): + for t in tokens: + t.matched = t.text in termset + yield t + + +# Fragmenters + +class Fragmenter(object): + def must_retokenize(self): + """Returns True if this fragmenter requires retokenized text. + + If this method returns True, the fragmenter's ``fragment_tokens`` + method will be called with an iterator of ALL tokens from the text, + with the tokens for matched terms having the ``matched`` attribute set + to True. + + If this method returns False, the fragmenter's ``fragment_matches`` + method will be called with a LIST of matching tokens. + """ + + return True + + def fragment_tokens(self, text, all_tokens): + """Yields :class:`Fragment` objects based on the tokenized text. + + :param text: the string being highlighted. + :param all_tokens: an iterator of :class:`analysis.Token` + objects from the string. + """ + + raise NotImplementedError + + def fragment_matches(self, text, matched_tokens): + """Yields :class:`Fragment` objects based on the text and the matched + terms. + + :param text: the string being highlighted. + :param matched_tokens: a list of :class:`analysis.Token` objects + representing the term matches in the string. + """ + + raise NotImplementedError + + +class WholeFragmenter(Fragmenter): + """Doesn't fragment the token stream. This object just returns the entire + entire stream as one "fragment". This is useful if you want to highlight + the entire text. + + Note that even if you use the `WholeFragmenter`, the highlight code will + return no fragment if no terms matched in the given field. To return the + whole fragment even in that case, call `highlights()` with `minscore=0`:: + + # Query where no terms match in the "text" field + q = query.Term("tag", "new") + + r = mysearcher.search(q) + r.fragmenter = highlight.WholeFragmenter() + r.formatter = highlight.UppercaseFormatter() + # Since no terms in the "text" field matched, we get no fragments back + assert r[0].highlights("text") == "" + + # If we lower the minimum score to 0, we get a fragment even though it + # has no matching terms + assert r[0].highlights("text", minscore=0) == "This is the text field." + + """ + + def __init__(self, charlimit=DEFAULT_CHARLIMIT): + self.charlimit = charlimit + + def fragment_tokens(self, text, tokens): + charlimit = self.charlimit + matches = [] + for t in tokens: + if charlimit and t.endchar > charlimit: + break + if t.matched: + matches.append(t.copy()) + return [Fragment(text, matches)] + + +# Backwards compatiblity +NullFragmeter = WholeFragmenter + + +class SentenceFragmenter(Fragmenter): + """Breaks the text up on sentence end punctuation characters + (".", "!", or "?"). This object works by looking in the original text for a + sentence end as the next character after each token's 'endchar'. + + When highlighting with this fragmenter, you should use an analyzer that + does NOT remove stop words, for example:: + + sa = StandardAnalyzer(stoplist=None) + """ + + def __init__(self, maxchars=200, sentencechars=".!?", + charlimit=DEFAULT_CHARLIMIT): + """ + :param maxchars: The maximum number of characters allowed in a + fragment. + """ + + self.maxchars = maxchars + self.sentencechars = frozenset(sentencechars) + self.charlimit = charlimit + + def fragment_tokens(self, text, tokens): + maxchars = self.maxchars + sentencechars = self.sentencechars + charlimit = self.charlimit + + textlen = len(text) + # startchar of first token in the current sentence + first = None + # Buffer for matched tokens in the current sentence + tks = [] + endchar = None + # Number of chars in the current sentence + currentlen = 0 + + for t in tokens: + startchar = t.startchar + endchar = t.endchar + if charlimit and endchar > charlimit: + break + + if first is None: + # Remember the startchar of the first token in a sentence + first = startchar + currentlen = 0 + + tlength = endchar - startchar + currentlen += tlength + + if t.matched: + tks.append(t.copy()) + + # If the character after the current token is end-of-sentence + # punctuation, finish the sentence and reset + if endchar < textlen and text[endchar] in sentencechars: + # Don't break for two periods in a row (e.g. ignore "...") + if endchar + 1 < textlen and text[endchar + 1] in sentencechars: + continue + + # If the sentence had matches and it's not too long, yield it + # as a token + if tks and currentlen <= maxchars: + yield mkfrag(text, tks, startchar=first, endchar=endchar) + # Reset the counts + tks = [] + first = None + currentlen = 0 + + # If we get to the end of the text and there's still a sentence + # in the buffer, yield it + if tks: + yield mkfrag(text, tks, startchar=first, endchar=endchar) + + +class ContextFragmenter(Fragmenter): + """Looks for matched terms and aggregates them with their surrounding + context. + """ + + def __init__(self, maxchars=200, surround=20, charlimit=DEFAULT_CHARLIMIT): + """ + :param maxchars: The maximum number of characters allowed in a + fragment. + :param surround: The number of extra characters of context to add both + before the first matched term and after the last matched term. + """ + + self.maxchars = maxchars + self.surround = surround + self.charlimit = charlimit + + def fragment_tokens(self, text, tokens): + maxchars = self.maxchars + surround = self.surround + charlimit = self.charlimit + + # startchar of the first token in the fragment + first = None + # Stack of startchars + firsts = deque() + # Each time we see a matched token, we reset the countdown to finishing + # the fragment. This also indicates whether we're currently inside a + # fragment (< 0 not in fragment, >= 0 in fragment) + countdown = -1 + # Tokens in current fragment + tks = [] + endchar = None + # Number of chars in the current fragment + currentlen = 0 + + for t in tokens: + startchar = t.startchar + endchar = t.endchar + tlength = endchar - startchar + if charlimit and endchar > charlimit: + break + + if countdown < 0 and not t.matched: + # We're not in a fragment currently, so just maintain the + # "charsbefore" buffer + firsts.append(startchar) + while firsts and endchar - firsts[0] > surround: + firsts.popleft() + elif currentlen + tlength > maxchars: + # We're in a fragment, but adding this token would put us past + # the maximum size. Zero the countdown so the code below will + # cause the fragment to be emitted + countdown = 0 + elif t.matched: + # Start/restart the countdown + countdown = surround + # Remember the first char of this fragment + if first is None: + if firsts: + first = firsts[0] + else: + first = startchar + # Add on unused front context + countdown += surround + tks.append(t.copy()) + + # If we're in a fragment... + if countdown >= 0: + # Update the counts + currentlen += tlength + countdown -= tlength + + # If the countdown is expired + if countdown <= 0: + # Finish the fragment + yield mkfrag(text, tks, startchar=first, endchar=endchar) + # Reset the counts + tks = [] + firsts = deque() + first = None + currentlen = 0 + + # If there's a fragment left over at the end, yield it + if tks: + yield mkfrag(text, tks, startchar=first, endchar=endchar) + + +class PinpointFragmenter(Fragmenter): + """This is a NON-RETOKENIZING fragmenter. It builds fragments from the + positions of the matched terms. + """ + + def __init__(self, maxchars=200, surround=20, autotrim=False, + charlimit=DEFAULT_CHARLIMIT): + """ + :param maxchars: The maximum number of characters allowed in a + fragment. + :param surround: The number of extra characters of context to add both + before the first matched term and after the last matched term. + :param autotrim: automatically trims text before the first space and + after the last space in the fragments, to try to avoid truncated + words at the start and end. For short fragments or fragments with + long runs between spaces this may give strange results. + """ + + self.maxchars = maxchars + self.surround = surround + self.autotrim = autotrim + self.charlimit = charlimit + + def must_retokenize(self): + return False + + def fragment_tokens(self, text, tokens): + matched = [t for t in tokens if t.matched] + return self.fragment_matches(text, matched) + + @staticmethod + def _autotrim(fragment): + text = fragment.text + startchar = fragment.startchar + endchar = fragment.endchar + + firstspace = text.find(" ", startchar, endchar) + if firstspace > 0: + startchar = firstspace + 1 + lastspace = text.rfind(" ", startchar, endchar) + if lastspace > 0: + endchar = lastspace + + if fragment.matches: + startchar = min(startchar, fragment.matches[0].startchar) + endchar = max(endchar, fragment.matches[-1].endchar) + + fragment.startchar = startchar + fragment.endchar = endchar + + def fragment_matches(self, text, tokens): + maxchars = self.maxchars + surround = self.surround + autotrim = self.autotrim + charlimit = self.charlimit + + j = -1 + + for i, t in enumerate(tokens): + if j >= i: + continue + j = i + left = t.startchar + right = t.endchar + if charlimit and right > charlimit: + break + + currentlen = right - left + while j < len(tokens) - 1 and currentlen < maxchars: + next = tokens[j + 1] + ec = next.endchar + if ec - right <= surround and ec - left <= maxchars: + j += 1 + right = ec + currentlen += (ec - next.startchar) + else: + break + + left = max(0, left - surround) + right = min(len(text), right + surround) + fragment = Fragment(text, tokens[i:j + 1], left, right) + if autotrim: + self._autotrim(fragment) + yield fragment + + +# Fragment scorers + +class FragmentScorer(object): + pass + + +class BasicFragmentScorer(FragmentScorer): + def __call__(self, f): + # Add up the boosts for the matched terms in this passage + score = sum(t.boost for t in f.matches) + + # Favor diversity: multiply score by the number of separate + # terms matched + score *= (len(f.matched_terms) * 100) or 1 + + return score + + +# Fragment sorters + +def SCORE(fragment): + "Sorts higher scored passages first." + return 1 + + +def FIRST(fragment): + "Sorts passages from earlier in the document first." + return fragment.startchar + + +def LONGER(fragment): + "Sorts longer passages first." + return 0 - len(fragment) + + +def SHORTER(fragment): + "Sort shorter passages first." + return len(fragment) + + +# Formatters + +def get_text(original, token, replace): + """Convenience function for getting the text to use for a match when + formatting. + + If ``replace`` is False, returns the part of ``original`` between + ``token.startchar`` and ``token.endchar``. If ``replace`` is True, returns + ``token.text``. + """ + + if replace: + return token.text + else: + return original[token.startchar:token.endchar] + + +class Formatter(object): + """Base class for formatters. + + For highlighters that return strings, it is usually only necessary to + override :meth:`Formatter.format_token`. + + Use the :func:`get_text` function as a convenience to get the token text:: + + class MyFormatter(Formatter): + def format_token(text, token, replace=False): + ttext = get_text(text, token, replace) + return "[%s]" % ttext + """ + + between = "..." + + def _text(self, text): + return text + + def format_token(self, text, token, replace=False): + """Returns a formatted version of the given "token" object, which + should have at least ``startchar`` and ``endchar`` attributes, and + a ``text`` attribute if ``replace`` is True. + + :param text: the original fragment text being highlighted. + :param token: an object having ``startchar`` and ``endchar`` attributes + and optionally a ``text`` attribute (if ``replace`` is True). + :param replace: if True, the original text between the token's + ``startchar`` and ``endchar`` indices will be replaced with the + value of the token's ``text`` attribute. + """ + + raise NotImplementedError + + def format_fragment(self, fragment, replace=False): + """Returns a formatted version of the given text, using the "token" + objects in the given :class:`Fragment`. + + :param fragment: a :class:`Fragment` object representing a list of + matches in the text. + :param replace: if True, the original text corresponding to each + match will be replaced with the value of the token object's + ``text`` attribute. + """ + + output = [] + index = fragment.startchar + text = fragment.text + + for t in fragment.matches: + if t.startchar is None: + continue + if t.startchar < index: + continue + if t.startchar > index: + output.append(self._text(text[index:t.startchar])) + output.append(self.format_token(text, t, replace)) + index = t.endchar + output.append(self._text(text[index:fragment.endchar])) + + out_string = "".join(output) + return out_string + + def format(self, fragments, replace=False): + """Returns a formatted version of the given text, using a list of + :class:`Fragment` objects. + """ + + formatted = [self.format_fragment(f, replace=replace) + for f in fragments] + return self.between.join(formatted) + + def __call__(self, text, fragments): + # For backwards compatibility + return self.format(fragments) + + +class NullFormatter(Formatter): + """Formatter that does not modify the string. + """ + + def format_token(self, text, token, replace=False): + return get_text(text, token, replace) + + +class UppercaseFormatter(Formatter): + """Returns a string in which the matched terms are in UPPERCASE. + """ + + def __init__(self, between="..."): + """ + :param between: the text to add between fragments. + """ + + self.between = between + + def format_token(self, text, token, replace=False): + ttxt = get_text(text, token, replace) + return ttxt.upper() + + +class HtmlFormatter(Formatter): + """Returns a string containing HTML formatting around the matched terms. + + This formatter wraps matched terms in an HTML element with two class names. + The first class name (set with the constructor argument ``classname``) is + the same for each match. The second class name (set with the constructor + argument ``termclass`` is different depending on which term matched. This + allows you to give different formatting (for example, different background + colors) to the different terms in the excerpt. + + >>> hf = HtmlFormatter(tagname="span", classname="match", termclass="term") + >>> hf(mytext, myfragments) + "The template geometry is..." + + This object maintains a dictionary mapping terms to HTML class names (e.g. + ``term0`` and ``term1`` above), so that multiple excerpts will use the same + class for the same term. If you want to re-use the same HtmlFormatter + object with different searches, you should call HtmlFormatter.clear() + between searches to clear the mapping. + """ + + template = '<%(tag)s class=%(q)s%(cls)s%(tn)s%(q)s>%(t)s' + + def __init__(self, tagname="strong", between="...", + classname="match", termclass="term", maxclasses=5, + attrquote='"'): + """ + :param tagname: the tag to wrap around matching terms. + :param between: the text to add between fragments. + :param classname: the class name to add to the elements wrapped around + matching terms. + :param termclass: the class name prefix for the second class which is + different for each matched term. + :param maxclasses: the maximum number of term classes to produce. This + limits the number of classes you have to define in CSS by recycling + term class names. For example, if you set maxclasses to 3 and have + 5 terms, the 5 terms will use the CSS classes ``term0``, ``term1``, + ``term2``, ``term0``, ``term1``. + """ + + self.between = between + self.tagname = tagname + self.classname = classname + self.termclass = termclass + self.attrquote = attrquote + self.maxclasses = maxclasses + self.seen = {} + self.htmlclass = " ".join((self.classname, self.termclass)) + + def _text(self, text): + return htmlescape(text, quote=False) + + def format_token(self, text, token, replace=False): + seen = self.seen + ttext = self._text(get_text(text, token, replace)) + if ttext in seen: + termnum = seen[ttext] + else: + termnum = len(seen) % self.maxclasses + seen[ttext] = termnum + + return self.template % {"tag": self.tagname, "q": self.attrquote, + "cls": self.htmlclass, "t": ttext, + "tn": termnum} + + def clean(self): + """Clears the dictionary mapping terms to HTML classnames. + """ + self.seen = {} + + +class GenshiFormatter(Formatter): + """Returns a Genshi event stream containing HTML formatting around the + matched terms. + """ + + def __init__(self, qname="strong", between="..."): + """ + :param qname: the QName for the tag to wrap around matched terms. + :param between: the text to add between fragments. + """ + + self.qname = qname + self.between = between + + from genshi.core import START, END, TEXT # @UnresolvedImport + from genshi.core import Attrs, Stream # @UnresolvedImport + self.START, self.END, self.TEXT = START, END, TEXT + self.Attrs, self.Stream = Attrs, Stream + + def _add_text(self, text, output): + if output and output[-1][0] == self.TEXT: + output[-1] = (self.TEXT, output[-1][1] + text, output[-1][2]) + else: + output.append((self.TEXT, text, (None, -1, -1))) + + def format_token(self, text, token, replace=False): + qn = self.qname + txt = get_text(text, token, replace) + return self.Stream([(self.START, (qn, self.Attrs()), (None, -1, -1)), + (self.TEXT, txt, (None, -1, -1)), + (self.END, qn, (None, -1, -1))]) + + def format_fragment(self, fragment, replace=False): + output = [] + index = fragment.startchar + text = fragment.text + + for t in fragment.matches: + if t.startchar > index: + self._add_text(text[index:t.startchar], output) + output.append((text, t, replace)) + index = t.endchar + if index < len(text): + self._add_text(text[index:], output) + return self.Stream(output) + + def format(self, fragments, replace=False): + output = [] + first = True + for fragment in fragments: + if not first: + self._add_text(self.between, output) + output += self.format_fragment(fragment, replace=replace) + first = False + return self.Stream(output) + + +# Highlighting + +def top_fragments(fragments, count, scorer, order, minscore=1): + scored_fragments = ((scorer(f), f) for f in fragments) + scored_fragments = nlargest(count, scored_fragments) + best_fragments = [sf for score, sf in scored_fragments if score >= minscore] + best_fragments.sort(key=order) + return best_fragments + + +def highlight(text, terms, analyzer, fragmenter, formatter, top=3, + scorer=None, minscore=1, order=FIRST, mode="query"): + + if scorer is None: + scorer = BasicFragmentScorer() + + if type(fragmenter) is type: + fragmenter = fragmenter() + if type(formatter) is type: + formatter = formatter() + if type(scorer) is type: + scorer = scorer() + + if scorer is None: + scorer = BasicFragmentScorer() + + termset = frozenset(terms) + tokens = analyzer(text, chars=True, mode=mode, removestops=False) + tokens = set_matched_filter(tokens, termset) + fragments = fragmenter.fragment_tokens(text, tokens) + fragments = top_fragments(fragments, top, scorer, order, minscore) + return formatter(text, fragments) + + +class Highlighter(object): + def __init__(self, fragmenter=None, scorer=None, formatter=None, + always_retokenize=False, order=FIRST): + self.fragmenter = fragmenter or ContextFragmenter() + self.scorer = scorer or BasicFragmentScorer() + self.formatter = formatter or HtmlFormatter(tagname="b") + self.order = order + self.always_retokenize = always_retokenize + + def can_load_chars(self, results, fieldname): + # Is it possible to build a mapping between the matched terms/docs and + # their start and end chars for "pinpoint" highlighting (ie not require + # re-tokenizing text)? + + if self.always_retokenize: + # No, we've been configured to always retokenize some text + return False + if not results.has_matched_terms(): + # No, we don't know what the matched terms are yet + return False + if self.fragmenter.must_retokenize(): + # No, the configured fragmenter doesn't support it + return False + + # Maybe, if the field was configured to store characters + field = results.searcher.schema[fieldname] + return field.supports("characters") + + @staticmethod + def _load_chars(results, fieldname, texts, to_bytes): + # For each docnum, create a mapping of text -> [(startchar, endchar)] + # for the matched terms + + results._char_cache[fieldname] = cache = {} + sorted_ids = sorted(docnum for _, docnum in results.top_n) + + for docnum in sorted_ids: + cache[docnum] = {} + + for text in texts: + btext = to_bytes(text) + m = results.searcher.postings(fieldname, btext) + docset = set(results.termdocs[(fieldname, btext)]) + for docnum in sorted_ids: + if docnum in docset: + m.skip_to(docnum) + assert m.id() == docnum + cache[docnum][text] = m.value_as("characters") + + @staticmethod + def _merge_matched_tokens(tokens): + # Merges consecutive matched tokens together, so they are highlighted + # as one + + token = None + + for t in tokens: + if not t.matched: + if token is not None: + yield token + token = None + yield t + continue + + if token is None: + token = t.copy() + elif t.startchar <= token.endchar: + if t.endchar > token.endchar: + token.text += t.text[token.endchar-t.endchar:] + token.endchar = t.endchar + else: + yield token + token = None + # t was not merged, also has to be yielded + yield t + + if token is not None: + yield token + + def highlight_hit(self, hitobj, fieldname, text=None, top=3, minscore=1): + results = hitobj.results + schema = results.searcher.schema + field = schema[fieldname] + to_bytes = field.to_bytes + from_bytes = field.from_bytes + + if text is None: + if fieldname not in hitobj: + raise KeyError("Field %r is not stored." % fieldname) + text = hitobj[fieldname] + + # Get the terms searched for/matched in this field + if results.has_matched_terms(): + bterms = (term for term in results.matched_terms() + if term[0] == fieldname) + else: + bterms = results.query_terms(expand=True, fieldname=fieldname) + # Convert bytes to unicode + words = frozenset(from_bytes(term[1]) for term in bterms) + + # If we can do "pinpoint" highlighting... + if self.can_load_chars(results, fieldname): + # Build the docnum->[(startchar, endchar),] map + if fieldname not in results._char_cache: + self._load_chars(results, fieldname, words, to_bytes) + + hitterms = (from_bytes(term[1]) for term in hitobj.matched_terms() + if term[0] == fieldname) + + # Grab the word->[(startchar, endchar)] map for this docnum + cmap = results._char_cache[fieldname][hitobj.docnum] + # A list of Token objects for matched words + tokens = [] + charlimit = self.fragmenter.charlimit + for word in hitterms: + chars = cmap[word] + for pos, startchar, endchar in chars: + if charlimit and endchar > charlimit: + break + tokens.append(Token(text=word, pos=pos, + startchar=startchar, endchar=endchar)) + tokens.sort(key=lambda t: t.startchar) + tokens = [max(group, key=lambda t: t.endchar - t.startchar) + for key, group in groupby(tokens, lambda t: t.startchar)] + fragments = self.fragmenter.fragment_matches(text, tokens) + else: + # Retokenize the text + analyzer = results.searcher.schema[fieldname].analyzer + tokens = analyzer(text, positions=True, chars=True, mode="index", + removestops=False) + # Set Token.matched attribute for tokens that match a query term + tokens = set_matched_filter(tokens, words) + tokens = self._merge_matched_tokens(tokens) + fragments = self.fragmenter.fragment_tokens(text, tokens) + + fragments = top_fragments(fragments, top, self.scorer, self.order, + minscore=minscore) + output = self.formatter.format(fragments) + return output diff --git a/nstock/modules/whoosh/idsets.py b/nstock/modules/whoosh/idsets.py new file mode 100644 index 0000000..b505a39 --- /dev/null +++ b/nstock/modules/whoosh/idsets.py @@ -0,0 +1,703 @@ +""" +An implementation of an object that acts like a collection of on/off bits. +""" + +import operator +from array import array +from bisect import bisect_left, bisect_right, insort + +from whoosh.compat import integer_types, izip, izip_longest, next, xrange +from whoosh.util.numeric import bytes_for_bits + + +# Number of '1' bits in each byte (0-255) +_1SPERBYTE = array('B', [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, +2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, +3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, +3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, +2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, +5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, +3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, +5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, +3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, +4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, +6, 7, 7, 8]) + + +class DocIdSet(object): + """Base class for a set of positive integers, implementing a subset of the + built-in ``set`` type's interface with extra docid-related methods. + + This is a superclass for alternative set implementations to the built-in + ``set`` which are more memory-efficient and specialized toward storing + sorted lists of positive integers, though they will inevitably be slower + than ``set`` for most operations since they're pure Python. + """ + + def __eq__(self, other): + for a, b in izip(self, other): + if a != b: + return False + return True + + def __neq__(self, other): + return not self.__eq__(other) + + def __len__(self): + raise NotImplementedError + + def __iter__(self): + raise NotImplementedError + + def __contains__(self, i): + raise NotImplementedError + + def __or__(self, other): + return self.union(other) + + def __and__(self, other): + return self.intersection(other) + + def __sub__(self, other): + return self.difference(other) + + def copy(self): + raise NotImplementedError + + def add(self, n): + raise NotImplementedError + + def discard(self, n): + raise NotImplementedError + + def update(self, other): + add = self.add + for i in other: + add(i) + + def intersection_update(self, other): + for n in self: + if n not in other: + self.discard(n) + + def difference_update(self, other): + for n in other: + self.discard(n) + + def invert_update(self, size): + """Updates the set in-place to contain numbers in the range + ``[0 - size)`` except numbers that are in this set. + """ + + for i in xrange(size): + if i in self: + self.discard(i) + else: + self.add(i) + + def intersection(self, other): + c = self.copy() + c.intersection_update(other) + return c + + def union(self, other): + c = self.copy() + c.update(other) + return c + + def difference(self, other): + c = self.copy() + c.difference_update(other) + return c + + def invert(self, size): + c = self.copy() + c.invert_update(size) + return c + + def isdisjoint(self, other): + a = self + b = other + if len(other) < len(self): + a, b = other, self + for num in a: + if num in b: + return False + return True + + def before(self, i): + """Returns the previous integer in the set before ``i``, or None. + """ + raise NotImplementedError + + def after(self, i): + """Returns the next integer in the set after ``i``, or None. + """ + raise NotImplementedError + + def first(self): + """Returns the first (lowest) integer in the set. + """ + raise NotImplementedError + + def last(self): + """Returns the last (highest) integer in the set. + """ + raise NotImplementedError + + +class BaseBitSet(DocIdSet): + # Methods to override + + def byte_count(self): + raise NotImplementedError + + def _get_byte(self, i): + raise NotImplementedError + + def _iter_bytes(self): + raise NotImplementedError + + # Base implementations + + def __len__(self): + return sum(_1SPERBYTE[b] for b in self._iter_bytes()) + + def __iter__(self): + base = 0 + for byte in self._iter_bytes(): + for i in xrange(8): + if byte & (1 << i): + yield base + i + base += 8 + + def __nonzero__(self): + return any(n for n in self._iter_bytes()) + + __bool__ = __nonzero__ + + def __contains__(self, i): + bucket = i // 8 + if bucket >= self.byte_count(): + return False + return bool(self._get_byte(bucket) & (1 << (i & 7))) + + def first(self): + return self.after(-1) + + def last(self): + return self.before(self.byte_count() * 8 + 1) + + def before(self, i): + _get_byte = self._get_byte + size = self.byte_count() * 8 + + if i <= 0: + return None + elif i >= size: + i = size - 1 + else: + i -= 1 + bucket = i // 8 + + while i >= 0: + byte = _get_byte(bucket) + if not byte: + bucket -= 1 + i = bucket * 8 + 7 + continue + if byte & (1 << (i & 7)): + return i + if i % 8 == 0: + bucket -= 1 + i -= 1 + + return None + + def after(self, i): + _get_byte = self._get_byte + size = self.byte_count() * 8 + + if i >= size: + return None + elif i < 0: + i = 0 + else: + i += 1 + bucket = i // 8 + + while i < size: + byte = _get_byte(bucket) + if not byte: + bucket += 1 + i = bucket * 8 + continue + if byte & (1 << (i & 7)): + return i + i += 1 + if i % 8 == 0: + bucket += 1 + + return None + + +class OnDiskBitSet(BaseBitSet): + """A DocIdSet backed by an array of bits on disk. + + >>> st = RamStorage() + >>> f = st.create_file("test.bin") + >>> bs = BitSet([1, 10, 15, 7, 2]) + >>> bytecount = bs.to_disk(f) + >>> f.close() + >>> # ... + >>> f = st.open_file("test.bin") + >>> odbs = OnDiskBitSet(f, bytecount) + >>> list(odbs) + [1, 2, 7, 10, 15] + """ + + def __init__(self, dbfile, basepos, bytecount): + """ + :param dbfile: a :class:`~whoosh.filedb.structfile.StructFile` object + to read from. + :param basepos: the base position of the bytes in the given file. + :param bytecount: the number of bytes to use for the bit array. + """ + + self._dbfile = dbfile + self._basepos = basepos + self._bytecount = bytecount + + def __repr__(self): + return "%s(%s, %d, %d)" % (self.__class__.__name__, self.dbfile, + self._basepos, self.bytecount) + + def byte_count(self): + return self._bytecount + + def _get_byte(self, n): + return self._dbfile.get_byte(self._basepos + n) + + def _iter_bytes(self): + dbfile = self._dbfile + dbfile.seek(self._basepos) + for _ in xrange(self._bytecount): + yield dbfile.read_byte() + + +class BitSet(BaseBitSet): + """A DocIdSet backed by an array of bits. This can also be useful as a bit + array (e.g. for a Bloom filter). It is much more memory efficient than a + large built-in set of integers, but wastes memory for sparse sets. + """ + + def __init__(self, source=None, size=0): + """ + :param maxsize: the maximum size of the bit array. + :param source: an iterable of positive integers to add to this set. + :param bits: an array of unsigned bytes ("B") to use as the underlying + bit array. This is used by some of the object's methods. + """ + + # If the source is a list, tuple, or set, we can guess the size + if not size and isinstance(source, (list, tuple, set, frozenset)): + size = max(source) + bytecount = bytes_for_bits(size) + self.bits = array("B", (0 for _ in xrange(bytecount))) + + if source: + add = self.add + for num in source: + add(num) + + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, list(self)) + + def byte_count(self): + return len(self.bits) + + def _get_byte(self, n): + return self.bits[n] + + def _iter_bytes(self): + return iter(self.bits) + + def _trim(self): + bits = self.bits + last = len(self.bits) - 1 + while last >= 0 and not bits[last]: + last -= 1 + del self.bits[last + 1:] + + def _resize(self, tosize): + curlength = len(self.bits) + newlength = bytes_for_bits(tosize) + if newlength > curlength: + self.bits.extend((0,) * (newlength - curlength)) + elif newlength < curlength: + del self.bits[newlength + 1:] + + def _zero_extra_bits(self, size): + bits = self.bits + spill = size - ((len(bits) - 1) * 8) + if spill: + mask = 2 ** spill - 1 + bits[-1] = bits[-1] & mask + + def _logic(self, obj, op, other): + objbits = obj.bits + for i, (byte1, byte2) in enumerate(izip_longest(objbits, other.bits, + fillvalue=0)): + value = op(byte1, byte2) & 0xFF + if i >= len(objbits): + objbits.append(value) + else: + objbits[i] = value + + obj._trim() + return obj + + def to_disk(self, dbfile): + dbfile.write_array(self.bits) + return len(self.bits) + + @classmethod + def from_bytes(cls, bs): + b = cls() + b.bits = array("B", bs) + return b + + @classmethod + def from_disk(cls, dbfile, bytecount): + return cls.from_bytes(dbfile.read_array("B", bytecount)) + + def copy(self): + b = self.__class__() + b.bits = array("B", iter(self.bits)) + return b + + def clear(self): + for i in xrange(len(self.bits)): + self.bits[i] = 0 + + def add(self, i): + bucket = i >> 3 + if bucket >= len(self.bits): + self._resize(i + 1) + self.bits[bucket] |= 1 << (i & 7) + + def discard(self, i): + bucket = i >> 3 + self.bits[bucket] &= ~(1 << (i & 7)) + + def _resize_to_other(self, other): + if isinstance(other, (list, tuple, set, frozenset)): + maxbit = max(other) + if maxbit // 8 > len(self.bits): + self._resize(maxbit) + + def update(self, iterable): + self._resize_to_other(iterable) + DocIdSet.update(self, iterable) + + def intersection_update(self, other): + if isinstance(other, BitSet): + return self._logic(self, operator.__and__, other) + discard = self.discard + for n in self: + if n not in other: + discard(n) + + def difference_update(self, other): + if isinstance(other, BitSet): + return self._logic(self, lambda x, y: x & ~y, other) + discard = self.discard + for n in other: + discard(n) + + def invert_update(self, size): + bits = self.bits + for i in xrange(len(bits)): + bits[i] = ~bits[i] & 0xFF + self._zero_extra_bits(size) + + def union(self, other): + if isinstance(other, BitSet): + return self._logic(self.copy(), operator.__or__, other) + b = self.copy() + b.update(other) + return b + + def intersection(self, other): + if isinstance(other, BitSet): + return self._logic(self.copy(), operator.__and__, other) + return BitSet(source=(n for n in self if n in other)) + + def difference(self, other): + if isinstance(other, BitSet): + return self._logic(self.copy(), lambda x, y: x & ~y, other) + return BitSet(source=(n for n in self if n not in other)) + + +class SortedIntSet(DocIdSet): + """A DocIdSet backed by a sorted array of integers. + """ + + def __init__(self, source=None, typecode="I"): + if source: + self.data = array(typecode, sorted(source)) + else: + self.data = array(typecode) + self.typecode = typecode + + def copy(self): + sis = SortedIntSet() + sis.data = array(self.typecode, self.data) + return sis + + def size(self): + return len(self.data) * self.data.itemsize + + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self.data) + + def __len__(self): + return len(self.data) + + def __iter__(self): + return iter(self.data) + + def __nonzero__(self): + return bool(self.data) + + __bool__ = __nonzero__ + + def __contains__(self, i): + data = self.data + if not data or i < data[0] or i > data[-1]: + return False + + pos = bisect_left(data, i) + if pos == len(data): + return False + return data[pos] == i + + def add(self, i): + data = self.data + if not data or i > data[-1]: + data.append(i) + else: + mn = data[0] + mx = data[-1] + if i == mn or i == mx: + return + elif i > mx: + data.append(i) + elif i < mn: + data.insert(0, i) + else: + pos = bisect_left(data, i) + if data[pos] != i: + data.insert(pos, i) + + def discard(self, i): + data = self.data + pos = bisect_left(data, i) + if data[pos] == i: + data.pop(pos) + + def clear(self): + self.data = array(self.typecode) + + def intersection_update(self, other): + self.data = array(self.typecode, (num for num in self if num in other)) + + def difference_update(self, other): + self.data = array(self.typecode, + (num for num in self if num not in other)) + + def intersection(self, other): + return SortedIntSet((num for num in self if num in other)) + + def difference(self, other): + return SortedIntSet((num for num in self if num not in other)) + + def first(self): + return self.data[0] + + def last(self): + return self.data[-1] + + def before(self, i): + data = self.data + pos = bisect_left(data, i) + if pos < 1: + return None + else: + return data[pos - 1] + + def after(self, i): + data = self.data + if not data or i >= data[-1]: + return None + elif i < data[0]: + return data[0] + + pos = bisect_right(data, i) + return data[pos] + + +class ReverseIdSet(DocIdSet): + """ + Wraps a DocIdSet object and reverses its semantics, so docs in the wrapped + set are not in this set, and vice-versa. + """ + + def __init__(self, idset, limit): + """ + :param idset: the DocIdSet object to wrap. + :param limit: the highest possible ID plus one. + """ + + self.idset = idset + self.limit = limit + + def __len__(self): + return self.limit - len(self.idset) + + def __contains__(self, i): + return i not in self.idset + + def __iter__(self): + ids = iter(self.idset) + try: + nx = next(ids) + except StopIteration: + nx = -1 + + for i in xrange(self.limit): + if i == nx: + try: + nx = next(ids) + except StopIteration: + nx = -1 + else: + yield i + + def add(self, n): + self.idset.discard(n) + + def discard(self, n): + self.idset.add(n) + + def first(self): + for i in self: + return i + + def last(self): + idset = self.idset + maxid = self.limit - 1 + if idset.last() < maxid - 1: + return maxid + + for i in xrange(maxid, -1, -1): + if i not in idset: + return i + +ROARING_CUTOFF = 1 << 12 + + +class RoaringIdSet(DocIdSet): + """ + Separates IDs into ranges of 2^16 bits, and stores each range in the most + efficient type of doc set, either a BitSet (if the range has >= 2^12 IDs) + or a sorted ID set of 16-bit shorts. + """ + + cutoff = 2**12 + + def __init__(self, source=None): + self.idsets = [] + if source: + self.update(source) + + def __len__(self): + if not self.idsets: + return 0 + + return sum(len(idset) for idset in self.idsets) + + def __contains__(self, n): + bucket = n >> 16 + if bucket >= len(self.idsets): + return False + return (n - (bucket << 16)) in self.idsets[bucket] + + def __iter__(self): + for i, idset in self.idsets: + floor = i << 16 + for n in idset: + yield floor + n + + def _find(self, n): + bucket = n >> 16 + floor = n << 16 + if bucket >= len(self.idsets): + self.idsets.extend([SortedIntSet() for _ + in xrange(len(self.idsets), bucket + 1)]) + idset = self.idsets[bucket] + return bucket, floor, idset + + def add(self, n): + bucket, floor, idset = self._find(n) + oldlen = len(idset) + idset.add(n - floor) + if oldlen <= ROARING_CUTOFF < len(idset): + self.idsets[bucket] = BitSet(idset) + + def discard(self, n): + bucket, floor, idset = self._find(n) + oldlen = len(idset) + idset.discard(n - floor) + if oldlen > ROARING_CUTOFF >= len(idset): + self.idsets[bucket] = SortedIntSet(idset) + + +class MultiIdSet(DocIdSet): + """Wraps multiple SERIAL sub-DocIdSet objects and presents them as an + aggregated, read-only set. + """ + + def __init__(self, idsets, offsets): + """ + :param idsets: a list of DocIdSet objects. + :param offsets: a list of offsets corresponding to the DocIdSet objects + in ``idsets``. + """ + + assert len(idsets) == len(offsets) + self.idsets = idsets + self.offsets = offsets + + def _document_set(self, n): + offsets = self.offsets + return max(bisect_left(offsets, n), len(self.offsets) - 1) + + def _set_and_docnum(self, n): + setnum = self._document_set(n) + offset = self.offsets[setnum] + return self.idsets[setnum], n - offset + + def __len__(self): + return sum(len(idset) for idset in self.idsets) + + def __iter__(self): + for idset, offset in izip(self.idsets, self.offsets): + for docnum in idset: + yield docnum + offset + + def __contains__(self, item): + idset, n = self._set_and_docnum(item) + return n in idset + + diff --git a/nstock/modules/whoosh/index.py b/nstock/modules/whoosh/index.py new file mode 100644 index 0000000..2beea3d --- /dev/null +++ b/nstock/modules/whoosh/index.py @@ -0,0 +1,710 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +"""Contains the main functions/classes for creating, maintaining, and using +an index. +""" + +from __future__ import division +import os.path, re, sys +from time import time, sleep + +from whoosh import __version__ +from whoosh.legacy import toc_loaders +from whoosh.compat import pickle, string_type +from whoosh.fields import ensure_schema +from whoosh.system import _INT_SIZE, _FLOAT_SIZE, _LONG_SIZE + + +_DEF_INDEX_NAME = "MAIN" +_CURRENT_TOC_VERSION = -111 + + +# Exceptions + +class LockError(Exception): + pass + + +class IndexError(Exception): + """Generic index error.""" + + +class IndexVersionError(IndexError): + """Raised when you try to open an index using a format that the current + version of Whoosh cannot read. That is, when the index you're trying to + open is either not backward or forward compatible with this version of + Whoosh. + """ + + def __init__(self, msg, version, release=None): + Exception.__init__(self, msg) + self.version = version + self.release = release + + +class OutOfDateError(IndexError): + """Raised when you try to commit changes to an index which is not the + latest generation. + """ + + +class EmptyIndexError(IndexError): + """Raised when you try to work with an index that has no indexed terms. + """ + + +# Convenience functions + +def create_in(dirname, schema, indexname=None): + """Convenience function to create an index in a directory. Takes care of + creating a FileStorage object for you. + + :param dirname: the path string of the directory in which to create the + index. + :param schema: a :class:`whoosh.fields.Schema` object describing the + index's fields. + :param indexname: the name of the index to create; you only need to specify + this if you are creating multiple indexes within the same storage + object. + :returns: :class:`Index` + """ + + from whoosh.filedb.filestore import FileStorage + + if not indexname: + indexname = _DEF_INDEX_NAME + storage = FileStorage(dirname) + return FileIndex.create(storage, schema, indexname) + + +def open_dir(dirname, indexname=None, readonly=False, schema=None): + """Convenience function for opening an index in a directory. Takes care of + creating a FileStorage object for you. dirname is the filename of the + directory in containing the index. indexname is the name of the index to + create; you only need to specify this if you have multiple indexes within + the same storage object. + + :param dirname: the path string of the directory in which to create the + index. + :param indexname: the name of the index to create; you only need to specify + this if you have multiple indexes within the same storage object. + """ + + from whoosh.filedb.filestore import FileStorage + + if indexname is None: + indexname = _DEF_INDEX_NAME + storage = FileStorage(dirname, readonly=readonly) + return FileIndex(storage, schema=schema, indexname=indexname) + + +def exists_in(dirname, indexname=None): + """Returns True if dirname contains a Whoosh index. + + :param dirname: the file path of a directory. + :param indexname: the name of the index. If None, the default index name is + used. + """ + + if os.path.exists(dirname): + try: + ix = open_dir(dirname, indexname=indexname) + return ix.latest_generation() > -1 + except EmptyIndexError: + pass + + return False + + +def exists(storage, indexname=None): + """Deprecated; use ``storage.index_exists()``. + + :param storage: a store.Storage object. + :param indexname: the name of the index. If None, the default index name is + used. + """ + + return storage.index_exists(indexname) + + +def version_in(dirname, indexname=None): + """Returns a tuple of (release_version, format_version), where + release_version is the release version number of the Whoosh code that + created the index -- e.g. (0, 1, 24) -- and format_version is the version + number of the on-disk format used for the index -- e.g. -102. + + You should avoid attaching significance to the second number (the index + version). This is simply a version number for the TOC file and probably + should not have been exposed in a public interface. The best way to check + if the current version of Whoosh can open an index is to actually try to + open it and see if it raises a ``whoosh.index.IndexVersionError`` exception. + + Note that the release and format version are available as attributes on the + Index object in Index.release and Index.version. + + :param dirname: the file path of a directory containing an index. + :param indexname: the name of the index. If None, the default index name is + used. + :returns: ((major_ver, minor_ver, build_ver), format_ver) + """ + + from whoosh.filedb.filestore import FileStorage + storage = FileStorage(dirname) + return version(storage, indexname=indexname) + + +def version(storage, indexname=None): + """Returns a tuple of (release_version, format_version), where + release_version is the release version number of the Whoosh code that + created the index -- e.g. (0, 1, 24) -- and format_version is the version + number of the on-disk format used for the index -- e.g. -102. + + You should avoid attaching significance to the second number (the index + version). This is simply a version number for the TOC file and probably + should not have been exposed in a public interface. The best way to check + if the current version of Whoosh can open an index is to actually try to + open it and see if it raises a ``whoosh.index.IndexVersionError`` exception. + + Note that the release and format version are available as attributes on the + Index object in Index.release and Index.version. + + :param storage: a store.Storage object. + :param indexname: the name of the index. If None, the default index name is + used. + :returns: ((major_ver, minor_ver, build_ver), format_ver) + """ + + try: + if indexname is None: + indexname = _DEF_INDEX_NAME + + ix = storage.open_index(indexname) + return (ix.release, ix.version) + except IndexVersionError: + e = sys.exc_info()[1] + return (None, e.version) + + +# Index base class + +class Index(object): + """Represents an indexed collection of documents. + """ + + def close(self): + """Closes any open resources held by the Index object itself. This may + not close all resources being used everywhere, for example by a + Searcher object. + """ + pass + + def add_field(self, fieldname, fieldspec): + """Adds a field to the index's schema. + + :param fieldname: the name of the field to add. + :param fieldspec: an instantiated :class:`whoosh.fields.FieldType` + object. + """ + + w = self.writer() + w.add_field(fieldname, fieldspec) + w.commit() + + def remove_field(self, fieldname): + """Removes the named field from the index's schema. Depending on the + backend implementation, this may or may not actually remove existing + data for the field from the index. Optimizing the index should always + clear out existing data for a removed field. + """ + + w = self.writer() + w.remove_field(fieldname) + w.commit() + + def latest_generation(self): + """Returns the generation number of the latest generation of this + index, or -1 if the backend doesn't support versioning. + """ + return -1 + + def refresh(self): + """Returns a new Index object representing the latest generation + of this index (if this object is the latest generation, or the backend + doesn't support versioning, returns self). + + :returns: :class:`Index` + """ + return self + + def up_to_date(self): + """Returns True if this object represents the latest generation of + this index. Returns False if this object is not the latest generation + (that is, someone else has updated the index since you opened this + object). + """ + return True + + def last_modified(self): + """Returns the last modified time of the index, or -1 if the backend + doesn't support last-modified times. + """ + return -1 + + def is_empty(self): + """Returns True if this index is empty (that is, it has never had any + documents successfully written to it. + """ + raise NotImplementedError + + def optimize(self): + """Optimizes this index, if necessary. + """ + pass + + def doc_count_all(self): + """Returns the total number of documents, DELETED OR UNDELETED, + in this index. + """ + + r = self.reader() + try: + return r.doc_count_all() + finally: + r.close() + + def doc_count(self): + """Returns the total number of UNDELETED documents in this index. + """ + + r = self.reader() + try: + return r.doc_count() + finally: + r.close() + + def searcher(self, **kwargs): + """Returns a Searcher object for this index. Keyword arguments are + passed to the Searcher object's constructor. + + :rtype: :class:`whoosh.searching.Searcher` + """ + + from whoosh.searching import Searcher + return Searcher(self.reader(), fromindex=self, **kwargs) + + def field_length(self, fieldname): + """Returns the total length of the field across all documents. + """ + + r = self.reader() + try: + return r.field_length(fieldname) + finally: + r.close() + + def max_field_length(self, fieldname): + """Returns the maximum length of the field across all documents. + """ + + r = self.reader() + try: + return r.max_field_length(fieldname) + finally: + r.close() + + def reader(self, reuse=None): + """Returns an IndexReader object for this index. + + :param reuse: an existing reader. Some implementations may recycle + resources from this existing reader to create the new reader. Note + that any resources in the "recycled" reader that are not used by + the new reader will be CLOSED, so you CANNOT use it afterward. + :rtype: :class:`whoosh.reading.IndexReader` + """ + + raise NotImplementedError + + def writer(self, **kwargs): + """Returns an IndexWriter object for this index. + + :rtype: :class:`whoosh.writing.IndexWriter` + """ + raise NotImplementedError + + def delete_by_term(self, fieldname, text, searcher=None): + w = self.writer() + w.delete_by_term(fieldname, text, searcher=searcher) + w.commit() + + def delete_by_query(self, q, searcher=None): + w = self.writer() + w.delete_by_query(q, searcher=searcher) + w.commit() + + +# Codec-based index implementation + +def clean_files(storage, indexname, gen, segments): + # Attempts to remove unused index files (called when a new generation + # is created). If existing Index and/or reader objects have the files + # open, they may not be deleted immediately (i.e. on Windows) but will + # probably be deleted eventually by a later call to clean_files. + + current_segment_names = set(s.segment_id() for s in segments) + tocpattern = TOC._pattern(indexname) + segpattern = TOC._segment_pattern(indexname) + + todelete = set() + for filename in storage: + if filename.startswith("."): + continue + tocm = tocpattern.match(filename) + segm = segpattern.match(filename) + if tocm: + if int(tocm.group(1)) != gen: + todelete.add(filename) + elif segm: + name = segm.group(1) + if name not in current_segment_names: + todelete.add(filename) + + for filename in todelete: + try: + storage.delete_file(filename) + except OSError: + # Another process still has this file open, I guess + pass + + +class FileIndex(Index): + def __init__(self, storage, schema=None, indexname=_DEF_INDEX_NAME): + from whoosh.filedb.filestore import Storage + + if not isinstance(storage, Storage): + raise ValueError("%r is not a Storage object" % storage) + if not isinstance(indexname, string_type): + raise ValueError("indexname %r is not a string" % indexname) + + if schema: + schema = ensure_schema(schema) + + self.storage = storage + self._schema = schema + self.indexname = indexname + + # Try reading the TOC to see if it's possible + TOC.read(self.storage, self.indexname, schema=self._schema) + + @classmethod + def create(cls, storage, schema, indexname=_DEF_INDEX_NAME): + TOC.create(storage, schema, indexname) + return cls(storage, schema, indexname) + + def __repr__(self): + return "%s(%r, %r)" % (self.__class__.__name__, + self.storage, self.indexname) + + def close(self): + pass + + # add_field + # remove_field + + def latest_generation(self): + return TOC._latest_generation(self.storage, self.indexname) + + # refresh + # up_to_date + + def last_modified(self): + gen = self.latest_generation() + filename = TOC._filename(self.indexname, gen) + return self.storage.file_modified(filename) + + def is_empty(self): + return len(self._read_toc().segments) == 0 + + def optimize(self, **kwargs): + w = self.writer(**kwargs) + w.commit(optimize=True) + + # searcher + + def writer(self, procs=1, **kwargs): + if procs > 1: + from whoosh.multiproc import MpWriter + return MpWriter(self, procs=procs, **kwargs) + else: + from whoosh.writing import SegmentWriter + return SegmentWriter(self, **kwargs) + + def lock(self, name): + """Returns a lock object that you can try to call acquire() on to + lock the index. + """ + + return self.storage.lock(self.indexname + "_" + name) + + def _read_toc(self): + return TOC.read(self.storage, self.indexname, schema=self._schema) + + def _segments(self): + return self._read_toc().segments + + def _current_schema(self): + return self._read_toc().schema + + @property + def schema(self): + return self._current_schema() + + @property + def release(self): + return self._read_toc().release + + @property + def version(self): + return self._read_toc().version + + @classmethod + def _reader(cls, storage, schema, segments, generation, reuse=None): + # Returns a reader for the given segments, possibly reusing already + # opened readers + from whoosh.reading import SegmentReader, MultiReader, EmptyReader + + reusable = {} + try: + if len(segments) == 0: + # This index has no segments! Return an EmptyReader object, + # which simply returns empty or zero to every method + return EmptyReader(schema) + + if reuse: + # Put all atomic readers in a dictionary keyed by their + # generation, so we can re-use them if them if possible + readers = [r for r, _ in reuse.leaf_readers()] + reusable = dict((r.generation(), r) for r in readers) + + # Make a function to open readers, which reuses reusable readers. + # It removes any readers it reuses from the "reusable" dictionary, + # so later we can close any readers left in the dictionary. + def segreader(segment): + segid = segment.segment_id() + if segid in reusable: + r = reusable[segid] + del reusable[segid] + return r + else: + return SegmentReader(storage, schema, segment, + generation=generation) + + if len(segments) == 1: + # This index has one segment, so return a SegmentReader object + # for the segment + return segreader(segments[0]) + else: + # This index has multiple segments, so create a list of + # SegmentReaders for the segments, then composite them with a + # MultiReader + + readers = [segreader(segment) for segment in segments] + return MultiReader(readers, generation=generation) + finally: + for r in reusable.values(): + r.close() + + def reader(self, reuse=None): + retries = 10 + while retries > 0: + # Read the information from the TOC file + try: + info = self._read_toc() + return self._reader(self.storage, info.schema, info.segments, + info.generation, reuse=reuse) + except IOError: + # Presume that we got a "file not found error" because a writer + # deleted one of the files just as we were trying to open it, + # and so retry a few times before actually raising the + # exception + e = sys.exc_info()[1] + retries -= 1 + if retries <= 0: + raise e + sleep(0.05) + + +# TOC class + +class TOC(object): + """Object representing the state of the index after a commit. Essentially + a container for the index's schema and the list of segment objects. + """ + + def __init__(self, schema, segments, generation, + version=_CURRENT_TOC_VERSION, release=__version__): + self.schema = schema + self.segments = segments + self.generation = generation + self.version = version + self.release = release + + @classmethod + def _filename(cls, indexname, gen): + return "_%s_%s.toc" % (indexname, gen) + + @classmethod + def _pattern(cls, indexname): + return re.compile("^_%s_([0-9]+).toc$" % indexname) + + @classmethod + def _segment_pattern(cls, indexname): + return re.compile("(%s_[0-9a-z]+)[.][A-Za-z0-9_.]+" % indexname) + + @classmethod + def _latest_generation(cls, storage, indexname): + pattern = cls._pattern(indexname) + + mx = -1 + for filename in storage: + m = pattern.match(filename) + if m: + mx = max(int(m.group(1)), mx) + return mx + + @classmethod + def create(cls, storage, schema, indexname=_DEF_INDEX_NAME): + schema = ensure_schema(schema) + + # Clear existing files + prefix = "_%s_" % indexname + for filename in storage: + if filename.startswith(prefix): + storage.delete_file(filename) + + # Write a TOC file with an empty list of segments + toc = cls(schema, [], 0) + toc.write(storage, indexname) + + @classmethod + def read(cls, storage, indexname, gen=None, schema=None): + if gen is None: + gen = cls._latest_generation(storage, indexname) + if gen < 0: + raise EmptyIndexError("Index %r does not exist in %r" + % (indexname, storage)) + + # Read the content of this index from the .toc file. + tocfilename = cls._filename(indexname, gen) + stream = storage.open_file(tocfilename) + + def check_size(name, target): + sz = stream.read_varint() + if sz != target: + raise IndexError("Index was created on different architecture:" + " saved %s = %s, this computer = %s" + % (name, sz, target)) + + check_size("int", _INT_SIZE) + check_size("long", _LONG_SIZE) + check_size("float", _FLOAT_SIZE) + + if not stream.read_int() == -12345: + raise IndexError("Number misread: byte order problem") + + version = stream.read_int() + release = (stream.read_varint(), stream.read_varint(), + stream.read_varint()) + + if version != _CURRENT_TOC_VERSION: + if version in toc_loaders: + loader = toc_loaders[version] + schema, segments = loader(stream, gen, schema, version) + else: + raise IndexVersionError("Can't read format %s" % version, + version) + else: + # If the user supplied a schema object with the constructor, don't + # load the pickled schema from the saved index. + if schema: + stream.skip_string() + else: + schema = pickle.loads(stream.read_string()) + schema = ensure_schema(schema) + + # Generation + index_gen = stream.read_int() + assert gen == index_gen + + _ = stream.read_int() # Unused + segments = stream.read_pickle() + + stream.close() + return cls(schema, segments, gen, version=version, release=release) + + def write(self, storage, indexname): + schema = ensure_schema(self.schema) + schema.clean() + + # Use a temporary file for atomic write. + tocfilename = self._filename(indexname, self.generation) + tempfilename = '%s.%s' % (tocfilename, time()) + stream = storage.create_file(tempfilename) + + stream.write_varint(_INT_SIZE) + stream.write_varint(_LONG_SIZE) + stream.write_varint(_FLOAT_SIZE) + stream.write_int(-12345) + + stream.write_int(_CURRENT_TOC_VERSION) + for num in __version__[:3]: + stream.write_varint(num) + + try: + stream.write_string(pickle.dumps(schema, 2)) + except pickle.PicklingError: + # Try to narrow down the error to a single field + for fieldname, field in schema.items(): + try: + pickle.dumps(field) + except pickle.PicklingError: + e = sys.exc_info()[1] + raise pickle.PicklingError("%s %s=%r" % (e, fieldname, field)) + except TypeError: + e = sys.exc_info()[1] + raise TypeError("%s %s=%r" % (e, fieldname, field)) + # Otherwise, re-raise the original exception + raise + + stream.write_int(self.generation) + stream.write_int(0) # Unused + stream.write_pickle(self.segments) + stream.close() + + # Rename temporary file to the proper filename + storage.rename_file(tempfilename, tocfilename, safe=True) + diff --git a/nstock/modules/whoosh/lang/__init__.py b/nstock/modules/whoosh/lang/__init__.py new file mode 100644 index 0000000..54a7e04 --- /dev/null +++ b/nstock/modules/whoosh/lang/__init__.py @@ -0,0 +1,140 @@ +# coding=utf-8 + +# Copyright 2012 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + + +# Exceptions + +class NoStemmer(Exception): + pass + + +class NoStopWords(Exception): + pass + + +# Data and functions for language names + +languages = ("ar", "da", "nl", "en", "fi", "fr", "de", "hu", "it", "no", "pt", + "ro", "ru", "es", "sv", "tr") + +aliases = { + # By ISO 639-1 three letter codes + "ara": "ar", + "dan": "da", "nld": "nl", "eng": "en", "fin": "fi", "fra": "fr", + "deu": "de", "hun": "hu", "ita": "it", "nor": "no", "por": "pt", + "ron": "ro", "rus": "ru", "spa": "es", "swe": "sv", "tur": "tr", + + # By name in English + "arabic": "ar", + "danish": "da", + "dutch": "nl", + "english": "en", + "finnish": "fi", + "french": "fr", + "german": "de", + "hungarian": "hu", + "italian": "it", + "norwegian": "no", + "portuguese": "pt", + "romanian": "ro", + "russian": "ru", + "spanish": "es", + "swedish": "sv", + "turkish": "tr", + + # By name in own language + "العربية": "ar", + "dansk": "da", + "nederlands": "nl", + "suomi": "fi", + "français": "fr", + "deutsch": "de", + "magyar": "hu", + "italiano": "it", + "norsk": "no", + "português": "pt", + "русский язык": "ru", + "español": "es", + "svenska": "sv", + "türkçe": "tr", + } + + +def two_letter_code(name): + if name in languages: + return name + if name in aliases: + return aliases[name] + return None + + +# Getter functions + +def has_stemmer(lang): + try: + return bool(stemmer_for_language(lang)) + except NoStemmer: + return False + + +def has_stopwords(lang): + try: + return bool(stopwords_for_language(lang)) + except NoStopWords: + return False + + +def stemmer_for_language(lang): + if lang == "en_porter": + # Original porter stemming algorithm is several times faster than the + # more correct porter2 algorithm in snowball package + from .porter import stem as porter_stem + return porter_stem + + tlc = two_letter_code(lang) + + if tlc == "ar": + from .isri import ISRIStemmer + return ISRIStemmer().stem + + from .snowball import classes as snowball_classes + if tlc in snowball_classes: + return snowball_classes[tlc]().stem + + raise NoStemmer("No stemmer available for %r" % lang) + + +def stopwords_for_language(lang): + from .stopwords import stoplists + + tlc = two_letter_code(lang) + if tlc in stoplists: + return stoplists[tlc] + + raise NoStopWords("No stop-word list available for %r" % lang) diff --git a/nstock/modules/whoosh/lang/dmetaphone.py b/nstock/modules/whoosh/lang/dmetaphone.py new file mode 100644 index 0000000..d586c29 --- /dev/null +++ b/nstock/modules/whoosh/lang/dmetaphone.py @@ -0,0 +1,415 @@ +# coding= utf-8 + +# This script implements the Double Metaphone algorythm (c) 1998, 1999 by +# Lawrence Philips. It was translated to Python from the C source written by +# Kevin Atkinson (http://aspell.net/metaphone/) By Andrew Collins - January 12, +# 2007 who claims no rights to this work. +# http://atomboy.isa-geek.com:8080/plone/Members/acoil/programing/double-metaphone + +import re + +from whoosh.compat import u + +vowels = frozenset("AEIOUY") +slavo_germ_exp = re.compile("W|K|CZ|WITZ") +silent_starts = re.compile("GN|KN|PN|WR|PS") + + +def double_metaphone(text): + text = text.upper() + slavo_germanic = bool(slavo_germ_exp.search(text)) + + length = len(text) + text = "--" + text + " " + first = pos = 2 + last = first + length - 1 + primary = secondary = "" + + if silent_starts.match(text, pos): + pos += 1 + + while pos < length + 2: + ch = text[pos] + + if ch in vowels: + # all init vowels now map to 'A' + if pos != first: + next = (None, 1) + else: + next = ("A", 1) + elif ch == "B": + #"-mb", e.g", "dumb", already skipped over... see 'M' below + if text[pos + 1] == "B": + next = ("P", 2) + else: + next = ("P", 1) + elif ch == "C": + # various germanic + if (pos > (first + 1) and text[pos - 2] not in vowels and text[pos - 1:pos + 2] == 'ACH' and \ + (text[pos + 2] not in ['I', 'E'] or text[pos - 2:pos + 4] in ['BACHER', 'MACHER'])): + next = ('K', 2) + # special case 'CAESAR' + elif pos == first and text[first:first + 6] == 'CAESAR': + next = ('S', 2) + elif text[pos:pos + 4] == 'CHIA': # italian 'chianti' + next = ('K', 2) + elif text[pos:pos + 2] == 'CH': + # find 'michael' + if pos > first and text[pos:pos + 4] == 'CHAE': + next = ('K', 'X', 2) + elif pos == first and (text[pos + 1:pos + 6] in ['HARAC', 'HARIS'] or \ + text[pos + 1:pos + 4] in ["HOR", "HYM", "HIA", "HEM"]) and text[first:first + 5] != 'CHORE': + next = ('K', 2) + # germanic, greek, or otherwise 'ch' for 'kh' sound + elif text[first:first + 4] in ['VAN ', 'VON '] or text[first:first + 3] == 'SCH' \ + or text[pos - 2:pos + 4] in ["ORCHES", "ARCHIT", "ORCHID"] \ + or text[pos + 2] in ['T', 'S'] \ + or ((text[pos - 1] in ["A", "O", "U", "E"] or pos == first) \ + and text[pos + 2] in ["L", "R", "N", "M", "B", "H", "F", "V", "W", " "]): + next = ('K', 1) + else: + if pos > first: + if text[first:first + 2] == 'MC': + next = ('K', 2) + else: + next = ('X', 'K', 2) + else: + next = ('X', 2) + # e.g, 'czerny' + elif text[pos:pos + 2] == 'CZ' and text[pos - 2:pos + 2] != 'WICZ': + next = ('S', 'X', 2) + # e.g., 'focaccia' + elif text[pos + 1:pos + 4] == 'CIA': + next = ('X', 3) + # double 'C', but not if e.g. 'McClellan' + elif text[pos:pos + 2] == 'CC' and not (pos == (first + 1) and text[first] == 'M'): + # 'bellocchio' but not 'bacchus' + if text[pos + 2] in ["I", "E", "H"] and text[pos + 2:pos + 4] != 'HU': + # 'accident', 'accede' 'succeed' + if (pos == (first + 1) and text[first] == 'A') or \ + text[pos - 1:pos + 4] in ['UCCEE', 'UCCES']: + next = ('KS', 3) + # 'bacci', 'bertucci', other italian + else: + next = ('X', 3) + else: + next = ('K', 2) + elif text[pos:pos + 2] in ["CK", "CG", "CQ"]: + next = ('K', 'K', 2) + elif text[pos:pos + 2] in ["CI", "CE", "CY"]: + # italian vs. english + if text[pos:pos + 3] in ["CIO", "CIE", "CIA"]: + next = ('S', 'X', 2) + else: + next = ('S', 2) + else: + # name sent in 'mac caffrey', 'mac gregor + if text[pos + 1:pos + 3] in [" C", " Q", " G"]: + next = ('K', 3) + else: + if text[pos + 1] in ["C", "K", "Q"] and text[pos + 1:pos + 3] not in ["CE", "CI"]: + next = ('K', 2) + else: # default for 'C' + next = ('K', 1) + elif ch == u('\xc7'): + next = ('S', 1) + elif ch == 'D': + if text[pos:pos + 2] == 'DG': + if text[pos + 2] in ['I', 'E', 'Y']: # e.g. 'edge' + next = ('J', 3) + else: + next = ('TK', 2) + elif text[pos:pos + 2] in ['DT', 'DD']: + next = ('T', 2) + else: + next = ('T', 1) + elif ch == 'F': + if text[pos + 1] == 'F': + next = ('F', 2) + else: + next = ('F', 1) + elif ch == 'G': + if text[pos + 1] == 'H': + if pos > first and text[pos - 1] not in vowels: + next = ('K', 2) + elif pos < (first + 3): + if pos == first: # 'ghislane', ghiradelli + if text[pos + 2] == 'I': + next = ('J', 2) + else: + next = ('K', 2) + # Parker's rule (with some further refinements) - e.g., 'hugh' + elif (pos > (first + 1) and text[pos - 2] in ['B', 'H', 'D']) \ + or (pos > (first + 2) and text[pos - 3] in ['B', 'H', 'D']) \ + or (pos > (first + 3) and text[pos - 4] in ['B', 'H']): + next = (None, 2) + else: + # e.g., 'laugh', 'McLaughlin', 'cough', 'gough', 'rough', 'tough' + if pos > (first + 2) and text[pos - 1] == 'U' \ + and text[pos - 3] in ["C", "G", "L", "R", "T"]: + next = ('F', 2) + else: + if pos > first and text[pos - 1] != 'I': + next = ('K', 2) + elif text[pos + 1] == 'N': + if pos == (first + 1) and text[first] in vowels and not slavo_germanic: + next = ('KN', 'N', 2) + else: + # not e.g. 'cagney' + if text[pos + 2:pos + 4] != 'EY' and text[pos + 1] != 'Y' and not slavo_germanic: + next = ('N', 'KN', 2) + else: + next = ('KN', 2) + # 'tagliaro' + elif text[pos + 1:pos + 3] == 'LI' and not slavo_germanic: + next = ('KL', 'L', 2) + # -ges-,-gep-,-gel-, -gie- at beginning + elif pos == first and (text[pos + 1] == 'Y' \ + or text[pos + 1:pos + 3] in ["ES", "EP", "EB", "EL", "EY", "IB", "IL", "IN", "IE", "EI", "ER"]): + next = ('K', 'J', 2) + # -ger-, -gy- + elif (text[pos + 1:pos + 2] == 'ER' or text[pos + 1] == 'Y') \ + and text[first:first + 6] not in ["DANGER", "RANGER", "MANGER"] \ + and text[pos - 1] not in ['E', 'I'] and text[pos - 1:pos + 2] not in ['RGY', 'OGY']: + next = ('K', 'J', 2) + # italian e.g, 'biaggi' + elif text[pos + 1] in ['E', 'I', 'Y'] or text[pos - 1:pos + 3] in ["AGGI", "OGGI"]: + # obvious germanic + if text[first:first + 4] in ['VON ', 'VAN '] or text[first:first + 3] == 'SCH' \ + or text[pos + 1:pos + 3] == 'ET': + next = ('K', 2) + else: + # always soft if french ending + if text[pos + 1:pos + 5] == 'IER ': + next = ('J', 2) + else: + next = ('J', 'K', 2) + elif text[pos + 1] == 'G': + next = ('K', 2) + else: + next = ('K', 1) + elif ch == 'H': + # only keep if first & before vowel or btw. 2 vowels + if (pos == first or text[pos - 1] in vowels) and text[pos + 1] in vowels: + next = ('H', 2) + else: # (also takes care of 'HH') + next = (None, 1) + elif ch == 'J': + # obvious spanish, 'jose', 'san jacinto' + if text[pos:pos + 4] == 'JOSE' or text[first:first + 4] == 'SAN ': + if (pos == first and text[pos + 4] == ' ') or text[first:first + 4] == 'SAN ': + next = ('H',) + else: + next = ('J', 'H') + elif pos == first and text[pos:pos + 4] != 'JOSE': + next = ('J', 'A') # Yankelovich/Jankelowicz + else: + # spanish pron. of e.g. 'bajador' + if text[pos - 1] in vowels and not slavo_germanic \ + and text[pos + 1] in ['A', 'O']: + next = ('J', 'H') + else: + if pos == last: + next = ('J', ' ') + else: + if text[pos + 1] not in ["L", "T", "K", "S", "N", "M", "B", "Z"] \ + and text[pos - 1] not in ["S", "K", "L"]: + next = ('J',) + else: + next = (None,) + if text[pos + 1] == 'J': + next = next + (2,) + else: + next = next + (1,) + elif ch == 'K': + if text[pos + 1] == 'K': + next = ('K', 2) + else: + next = ('K', 1) + elif ch == 'L': + if text[pos + 1] == 'L': + # spanish e.g. 'cabrillo', 'gallegos' + if (pos == (last - 2) and text[pos - 1:pos + 3] in ["ILLO", "ILLA", "ALLE"]) \ + or ((text[last - 1:last + 1] in ["AS", "OS"] or text[last] in ["A", "O"]) \ + and text[pos - 1:pos + 3] == 'ALLE'): + next = ('L', '', 2) + else: + next = ('L', 2) + else: + next = ('L', 1) + elif ch == 'M': + if text[pos + 1:pos + 4] == 'UMB' \ + and (pos + 1 == last or text[pos + 2:pos + 4] == 'ER') \ + or text[pos + 1] == 'M': + next = ('M', 2) + else: + next = ('M', 1) + elif ch == 'N': + if text[pos + 1] == 'N': + next = ('N', 2) + else: + next = ('N', 1) + elif ch == u('\xd1'): + next = ('N', 1) + elif ch == 'P': + if text[pos + 1] == 'H': + next = ('F', 2) + elif text[pos + 1] in ['P', 'B']: # also account for "campbell", "raspberry" + next = ('P', 2) + else: + next = ('P', 1) + elif ch == 'Q': + if text[pos + 1] == 'Q': + next = ('K', 2) + else: + next = ('K', 1) + elif ch == 'R': + # french e.g. 'rogier', but exclude 'hochmeier' + if pos == last and not slavo_germanic \ + and text[pos - 2:pos] == 'IE' and text[pos - 4:pos - 2] not in ['ME', 'MA']: + next = ('', 'R') + else: + next = ('R',) + if text[pos + 1] == 'R': + next = next + (2,) + else: + next = next + (1,) + elif ch == 'S': + # special cases 'island', 'isle', 'carlisle', 'carlysle' + if text[pos - 1:pos + 2] in ['ISL', 'YSL']: + next = (None, 1) + # special case 'sugar-' + elif pos == first and text[first:first + 5] == 'SUGAR': + next = ('X', 'S', 1) + elif text[pos:pos + 2] == 'SH': + # germanic + if text[pos + 1:pos + 5] in ["HEIM", "HOEK", "HOLM", "HOLZ"]: + next = ('S', 2) + else: + next = ('X', 2) + # italian & armenian + elif text[pos:pos + 3] in ["SIO", "SIA"] or text[pos:pos + 4] == 'SIAN': + if not slavo_germanic: + next = ('S', 'X', 3) + else: + next = ('S', 3) + # german & anglicisations, e.g. 'smith' match 'schmidt', 'snider' match 'schneider' + # also, -sz- in slavic language altho in hungarian it is pronounced 's' + elif (pos == first and text[pos + 1] in ["M", "N", "L", "W"]) or text[pos + 1] == 'Z': + next = ('S', 'X') + if text[pos + 1] == 'Z': + next = next + (2,) + else: + next = next + (1,) + elif text[pos:pos + 2] == 'SC': + # Schlesinger's rule + if text[pos + 2] == 'H': + # dutch origin, e.g. 'school', 'schooner' + if text[pos + 3:pos + 5] in ["OO", "ER", "EN", "UY", "ED", "EM"]: + # 'schermerhorn', 'schenker' + if text[pos + 3:pos + 5] in ['ER', 'EN']: + next = ('X', 'SK', 3) + else: + next = ('SK', 3) + else: + if pos == first and text[first + 3] not in vowels and text[first + 3] != 'W': + next = ('X', 'S', 3) + else: + next = ('X', 3) + elif text[pos + 2] in ['I', 'E', 'Y']: + next = ('S', 3) + else: + next = ('SK', 3) + # french e.g. 'resnais', 'artois' + elif pos == last and text[pos - 2:pos] in ['AI', 'OI']: + next = ('', 'S', 1) + else: + next = ('S',) + if text[pos + 1] in ['S', 'Z']: + next = next + (2,) + else: + next = next + (1,) + elif ch == 'T': + if text[pos:pos + 4] == 'TION': + next = ('X', 3) + elif text[pos:pos + 3] in ['TIA', 'TCH']: + next = ('X', 3) + elif text[pos:pos + 2] == 'TH' or text[pos:pos + 3] == 'TTH': + # special case 'thomas', 'thames' or germanic + if text[pos + 2:pos + 4] in ['OM', 'AM'] or text[first:first + 4] in ['VON ', 'VAN '] \ + or text[first:first + 3] == 'SCH': + next = ('T', 2) + else: + next = ('0', 'T', 2) + elif text[pos + 1] in ['T', 'D']: + next = ('T', 2) + else: + next = ('T', 1) + elif ch == 'V': + if text[pos + 1] == 'V': + next = ('F', 2) + else: + next = ('F', 1) + elif ch == 'W': + # can also be in middle of word + if text[pos:pos + 2] == 'WR': + next = ('R', 2) + elif pos == first and (text[pos + 1] in vowels or text[pos:pos + 2] == 'WH'): + # Wasserman should match Vasserman + if text[pos + 1] in vowels: + next = ('A', 'F', 1) + else: + next = ('A', 1) + # Arnow should match Arnoff + elif (pos == last and text[pos - 1] in vowels) \ + or text[pos - 1:pos + 5] in ["EWSKI", "EWSKY", "OWSKI", "OWSKY"] \ + or text[first:first + 3] == 'SCH': + next = ('', 'F', 1) + # polish e.g. 'filipowicz' + elif text[pos:pos + 4] in ["WICZ", "WITZ"]: + next = ('TS', 'FX', 4) + else: # default is to skip it + next = (None, 1) + elif ch == 'X': + # french e.g. breaux + next = (None,) + if not(pos == last and (text[pos - 3:pos] in ["IAU", "EAU"] \ + or text[pos - 2:pos] in ['AU', 'OU'])): + next = ('KS',) + if text[pos + 1] in ['C', 'X']: + next = next + (2,) + else: + next = next + (1,) + elif ch == 'Z': + # chinese pinyin e.g. 'zhao' + if text[pos + 1] == 'H': + next = ('J',) + elif text[pos + 1:pos + 3] in ["ZO", "ZI", "ZA"] \ + or (slavo_germanic and pos > first and text[pos - 1] != 'T'): + next = ('S', 'TS') + else: + next = ('S',) + if text[pos + 1] == 'Z': + next = next + (2,) + else: + next = next + (1,) + else: + next = (None, 1) + + if len(next) == 2: + if next[0]: + primary += next[0] + secondary += next[0] + pos += next[1] + elif len(next) == 3: + if next[0]: + primary += next[0] + if next[1]: + secondary += next[1] + pos += next[2] + + if primary == secondary: + return (primary, None) + else: + return (primary, secondary) + diff --git a/nstock/modules/whoosh/lang/isri.py b/nstock/modules/whoosh/lang/isri.py new file mode 100644 index 0000000..b5061e6 --- /dev/null +++ b/nstock/modules/whoosh/lang/isri.py @@ -0,0 +1,382 @@ +# -*- coding: utf-8 -*- +# +# Natural Language Toolkit: The ISRI Arabic Stemmer +# +# Copyright (C) 2001-2012 NLTK Proejct +# Algorithm: Kazem Taghva, Rania Elkhoury, and Jeffrey Coombs (2005) +# Author: Hosam Algasaier +# URL: +# For license information, see LICENSE.TXT + +""" +ISRI Arabic Stemmer + +The algorithm for this stemmer is described in: + +Taghva, K., Elkoury, R., and Coombs, J. 2005. Arabic Stemming without a root +dictionary. Information Science Research Institute. University of Nevada, Las +Vegas, USA. + +The Information Science Research Institute’s (ISRI) Arabic stemmer shares many +features with the Khoja stemmer. However, the main difference is that ISRI +stemmer does not use root dictionary. Also, if a root is not found, ISRI +stemmer returned normalized form, rather than returning the original +unmodified word. + +Additional adjustments were made to improve the algorithm: + +1- Adding 60 stop words. + +2- Adding the pattern (تفاعيل) to ISRI pattern set. + +3- The step 2 in the original algorithm was normalizing all hamza. This step is +discarded because it increases the word ambiguities and changes the original +root. +""" + +from __future__ import unicode_literals +import re + + +class ISRIStemmer(object): + ''' + ISRI Arabic stemmer based on algorithm: Arabic Stemming without a root dictionary. + Information Science Research Institute. University of Nevada, Las Vegas, USA. + + A few minor modifications have been made to ISRI basic algorithm. + See the source code of this module for more information. + + isri.stem(token) returns Arabic root for the given token. + + The ISRI Stemmer requires that all tokens have Unicode string types. + If you use Python IDLE on Arabic Windows you have to decode text first + using Arabic '1256' coding. + ''' + + def __init__(self): + self.stm = 'defult none' + + self.p3 = ['\u0643\u0627\u0644', '\u0628\u0627\u0644', + '\u0648\u0644\u0644', '\u0648\u0627\u0644'] # length three prefixes + self.p2 = ['\u0627\u0644', '\u0644\u0644'] # length two prefixes + self.p1 = ['\u0644', '\u0628', '\u0641', '\u0633', '\u0648', + '\u064a', '\u062a', '\u0646', '\u0627'] # length one prefixes + + self.s3 = ['\u062a\u0645\u0644', '\u0647\u0645\u0644', + '\u062a\u0627\u0646', '\u062a\u064a\u0646', + '\u0643\u0645\u0644'] # length three suffixes + self.s2 = ['\u0648\u0646', '\u0627\u062a', '\u0627\u0646', + '\u064a\u0646', '\u062a\u0646', '\u0643\u0645', + '\u0647\u0646', '\u0646\u0627', '\u064a\u0627', + '\u0647\u0627', '\u062a\u0645', '\u0643\u0646', + '\u0646\u064a', '\u0648\u0627', '\u0645\u0627', + '\u0647\u0645'] # length two suffixes + self.s1 = ['\u0629', '\u0647', '\u064a', '\u0643', '\u062a', + '\u0627', '\u0646'] # length one suffixes + + self.pr4 = {0: ['\u0645'], 1:['\u0627'], + 2: ['\u0627', '\u0648', '\u064A'], 3:['\u0629']} # groups of length four patterns + self.pr53 = {0: ['\u0627', '\u062a'], + 1: ['\u0627', '\u064a', '\u0648'], + 2: ['\u0627', '\u062a', '\u0645'], + 3: ['\u0645', '\u064a', '\u062a'], + 4: ['\u0645', '\u062a'], + 5: ['\u0627', '\u0648'], + 6: ['\u0627', '\u0645']} # Groups of length five patterns and length three roots + + self.re_short_vowels = re.compile(r'[\u064B-\u0652]') + self.re_hamza = re.compile(r'[\u0621\u0624\u0626]') + self.re_intial_hamza = re.compile(r'^[\u0622\u0623\u0625]') + + self.stop_words = ['\u064a\u0643\u0648\u0646', + '\u0648\u0644\u064a\u0633', + '\u0648\u0643\u0627\u0646', + '\u0643\u0630\u0644\u0643', + '\u0627\u0644\u062a\u064a', + '\u0648\u0628\u064a\u0646', + '\u0639\u0644\u064a\u0647\u0627', + '\u0645\u0633\u0627\u0621', + '\u0627\u0644\u0630\u064a', + '\u0648\u0643\u0627\u0646\u062a', + '\u0648\u0644\u0643\u0646', + '\u0648\u0627\u0644\u062a\u064a', + '\u062a\u0643\u0648\u0646', + '\u0627\u0644\u064a\u0648\u0645', + '\u0627\u0644\u0644\u0630\u064a\u0646', + '\u0639\u0644\u064a\u0647', + '\u0643\u0627\u0646\u062a', + '\u0644\u0630\u0644\u0643', + '\u0623\u0645\u0627\u0645', + '\u0647\u0646\u0627\u0643', + '\u0645\u0646\u0647\u0627', + '\u0645\u0627\u0632\u0627\u0644', + '\u0644\u0627\u0632\u0627\u0644', + '\u0644\u0627\u064a\u0632\u0627\u0644', + '\u0645\u0627\u064a\u0632\u0627\u0644', + '\u0627\u0635\u0628\u062d', + '\u0623\u0635\u0628\u062d', + '\u0623\u0645\u0633\u0649', + '\u0627\u0645\u0633\u0649', + '\u0623\u0636\u062d\u0649', + '\u0627\u0636\u062d\u0649', + '\u0645\u0627\u0628\u0631\u062d', + '\u0645\u0627\u0641\u062a\u0626', + '\u0645\u0627\u0627\u0646\u0641\u0643', + '\u0644\u0627\u0633\u064a\u0645\u0627', + '\u0648\u0644\u0627\u064a\u0632\u0627\u0644', + '\u0627\u0644\u062d\u0627\u0644\u064a', + '\u0627\u0644\u064a\u0647\u0627', + '\u0627\u0644\u0630\u064a\u0646', + '\u0641\u0627\u0646\u0647', + '\u0648\u0627\u0644\u0630\u064a', + '\u0648\u0647\u0630\u0627', + '\u0644\u0647\u0630\u0627', + '\u0641\u0643\u0627\u0646', + '\u0633\u062a\u0643\u0648\u0646', + '\u0627\u0644\u064a\u0647', + '\u064a\u0645\u0643\u0646', + '\u0628\u0647\u0630\u0627', + '\u0627\u0644\u0630\u0649'] + + + def stem(self, token): + """ + Stemming a word token using the ISRI stemmer. + """ + + self.stm = token + self.norm(1) # remove diacritics which representing Arabic short vowels + if self.stm in self.stop_words: return self.stm # exclude stop words from being processed + self.pre32() # remove length three and length two prefixes in this order + self.suf32() # remove length three and length two suffixes in this order + self.waw() # remove connective ‘و’ if it precedes a word beginning with ‘و’ + self.norm(2) # normalize initial hamza to bare alif + if len(self.stm) <= 3: return self.stm # return stem if less than or equal to three + + if len(self.stm) == 4: # length 4 word + self.pro_w4() + return self.stm + elif len(self.stm) == 5: # length 5 word + self.pro_w53() + self.end_w5() + return self.stm + elif len(self.stm) == 6: # length 6 word + self.pro_w6() + self.end_w6() + return self.stm + elif len(self.stm) == 7: # length 7 word + self.suf1() + if len(self.stm) == 7: + self.pre1() + if len(self.stm) == 6: + self.pro_w6() + self.end_w6() + return self.stm + return self.stm # if word length >7 , then no stemming + + def norm(self, num): + """ + normalization: + num=1 normalize diacritics + num=2 normalize initial hamza + num=3 both 1&2 + """ + self.k = num + + if self.k == 1: + self.stm = self.re_short_vowels.sub('', self.stm) + return self.stm + elif self.k == 2: + self.stm = self.re_intial_hamza.sub(r'\u0627', self.stm) + return self.stm + elif self.k == 3: + self.stm = self.re_short_vowels.sub('', self.stm) + self.stm = self.re_intial_hamza.sub(r'\u0627', self.stm) + return self.stm + + def pre32(self): + """remove length three and length two prefixes in this order""" + if len(self.stm) >= 6: + for pre3 in self.p3: + if self.stm.startswith(pre3): + self.stm = self.stm[3:] + return self.stm + elif len(self.stm) >= 5: + for pre2 in self.p2: + if self.stm.startswith(pre2): + self.stm = self.stm[2:] + return self.stm + + def suf32(self): + """remove length three and length two suffixes in this order""" + if len(self.stm) >= 6: + for suf3 in self.s3: + if self.stm.endswith(suf3): + self.stm = self.stm[:-3] + return self.stm + elif len(self.stm) >= 5: + for suf2 in self.s2: + if self.stm.endswith(suf2): + self.stm = self.stm[:-2] + return self.stm + + + def waw(self): + """remove connective ‘و’ if it precedes a word beginning with ‘و’ """ + if (len(self.stm) >= 4) & (self.stm[:2] == '\u0648\u0648'): + self.stm = self.stm[1:] + return self.stm + + def pro_w4(self): + """process length four patterns and extract length three roots""" + if self.stm[0] in self.pr4[0]: # مفعل + self.stm = self.stm[1:] + return self.stm + elif self.stm[1] in self.pr4[1]: # فاعل + self.stm = self.stm[0] + self.stm[2:] + return self.stm + elif self.stm[2] in self.pr4[2]: # فعال - فعول - فعيل + self.stm = self.stm[:2] + self.stm[3] + return self.stm + elif self.stm[3] in self.pr4[3]: # فعلة + self.stm = self.stm[:-1] + return self.stm + else: + self.suf1() # do - normalize short sufix + if len(self.stm) == 4: + self.pre1() # do - normalize short prefix + return self.stm + + def pro_w53(self): + """process length five patterns and extract length three roots""" + if ((self.stm[2] in self.pr53[0]) & (self.stm[0] == '\u0627')): # افتعل - افاعل + self.stm = self.stm[1] + self.stm[3:] + return self.stm + elif ((self.stm[3] in self.pr53[1]) & (self.stm[0] == '\u0645')): # مفعول - مفعال - مفعيل + self.stm = self.stm[1:3] + self.stm[4] + return self.stm + elif ((self.stm[0] in self.pr53[2]) & (self.stm[4] == '\u0629')): # مفعلة - تفعلة - افعلة + self.stm = self.stm[1:4] + return self.stm + elif ((self.stm[0] in self.pr53[3]) & (self.stm[2] == '\u062a')): # مفتعل - يفتعل - تفتعل + self.stm = self.stm[1] + self.stm[3:] + return self.stm + elif ((self.stm[0] in self.pr53[4]) & (self.stm[2] == '\u0627')): #مفاعل - تفاعل + self.stm = self.stm[1] + self.stm[3:] + return self.stm + elif ((self.stm[2] in self.pr53[5]) & (self.stm[4] == '\u0629')): # فعولة - فعالة + self.stm = self.stm[:2] + self.stm[3] + return self.stm + elif ((self.stm[0] in self.pr53[6]) & (self.stm[1] == '\u0646')): # انفعل - منفعل + self.stm = self.stm[2:] + return self.stm + elif ((self.stm[3] == '\u0627') & (self.stm[0] == '\u0627')): # افعال + self.stm = self.stm[1:3] + self.stm[4] + return self.stm + elif ((self.stm[4] == '\u0646') & (self.stm[3] == '\u0627')): # فعلان + self.stm = self.stm[:3] + return self.stm + elif ((self.stm[3] == '\u064a') & (self.stm[0] == '\u062a')): # تفعيل + self.stm = self.stm[1:3] + self.stm[4] + return self.stm + elif ((self.stm[3] == '\u0648') & (self.stm[1] == '\u0627')): # فاعول + self.stm = self.stm[0] + self.stm[2] + self.stm[4] + return self.stm + elif ((self.stm[2] == '\u0627') & (self.stm[1] == '\u0648')): # فواعل + self.stm = self.stm[0] + self.stm[3:] + return self.stm + elif ((self.stm[3] == '\u0626') & (self.stm[2] == '\u0627')): # فعائل + self.stm = self.stm[:2] + self.stm[4] + return self.stm + elif ((self.stm[4] == '\u0629') & (self.stm[1] == '\u0627')): # فاعلة + self.stm = self.stm[0] + self.stm[2:4] + return self.stm + elif ((self.stm[4] == '\u064a') & (self.stm[2] == '\u0627')): # فعالي + self.stm = self.stm[:2] + self.stm[3] + return self.stm + else: + self.suf1() # do - normalize short sufix + if len(self.stm) == 5: + self.pre1() # do - normalize short prefix + return self.stm + + def pro_w54(self): + """process length five patterns and extract length four roots""" + if (self.stm[0] in self.pr53[2]): #تفعلل - افعلل - مفعلل + self.stm = self.stm[1:] + return self.stm + elif (self.stm[4] == '\u0629'): # فعللة + self.stm = self.stm[:4] + return self.stm + elif (self.stm[2] == '\u0627'): # فعالل + self.stm = self.stm[:2] + self.stm[3:] + return self.stm + + def end_w5(self): + """ending step (word of length five)""" + if len(self.stm) == 3: + return self.stm + elif len(self.stm) == 4: + self.pro_w4() + return self.stm + elif len(self.stm) == 5: + self.pro_w54() + return self.stm + + def pro_w6(self): + """process length six patterns and extract length three roots""" + if ((self.stm.startswith('\u0627\u0633\u062a')) or (self.stm.startswith('\u0645\u0633\u062a'))): # مستفعل - استفعل + self.stm = self.stm[3:] + return self.stm + elif (self.stm[0] == '\u0645' and self.stm[3] == '\u0627' and self.stm[5] == '\u0629'): # مفعالة + self.stm = self.stm[1:3] + self.stm[4] + return self.stm + elif (self.stm[0] == '\u0627' and self.stm[2] == '\u062a' and self.stm[4] == '\u0627'): # افتعال + self.stm = self.stm[1] + self.stm[3] + self.stm[5] + return self.stm + elif (self.stm[0] == '\u0627' and self.stm[3] == '\u0648' and self.stm[2] == self.stm[4]): # افعوعل + self.stm = self.stm[1] + self.stm[4:] + return self.stm + elif (self.stm[0] == '\u062a' and self.stm[2] == '\u0627' and self.stm[4] == '\u064a'): # تفاعيل new pattern + self.stm = self.stm[1] + self.stm[3] + self.stm[5] + return self.stm + else: + self.suf1() # do - normalize short sufix + if len(self.stm) == 6: + self.pre1() # do - normalize short prefix + return self.stm + + def pro_w64(self): + """process length six patterns and extract length four roots""" + if (self.stm[0] and self.stm[4]) == '\u0627': # افعلال + self.stm = self.stm[1:4] + self.stm[5] + return self.stm + elif (self.stm.startswith('\u0645\u062a')): # متفعلل + self.stm = self.stm[2:] + return self.stm + + def end_w6(self): + """ending step (word of length six)""" + if len(self.stm) == 3: + return self.stm + elif len(self.stm) == 5: + self.pro_w53() + self.end_w5() + return self.stm + elif len (self.stm) == 6: + self.pro_w64() + return self.stm + + def suf1(self): + """normalize short sufix""" + for sf1 in self.s1: + if self.stm.endswith(sf1): + self.stm = self.stm[:-1] + return self.stm + + def pre1(self): + """normalize short prefix""" + for sp1 in self.p1: + if self.stm.startswith(sp1): + self.stm = self.stm[1:] + return self.stm diff --git a/nstock/modules/whoosh/lang/lovins.py b/nstock/modules/whoosh/lang/lovins.py new file mode 100644 index 0000000..1e5a933 --- /dev/null +++ b/nstock/modules/whoosh/lang/lovins.py @@ -0,0 +1,570 @@ +"""This module implements the Lovins stemming algorithm. Use the ``stem()`` +function:: + + stemmed_word = stem(word) +""" + +from collections import defaultdict + + +# Conditions + +def A(base): + # A No restrictions on stem + return True + + +def B(base): + # B Minimum stem length = 3 + return len(base) > 2 + + +def C(base): + # C Minimum stem length = 4 + return len(base) > 3 + + +def D(base): + # D Minimum stem length = 5 + return len(base) > 4 + + +def E(base): + # E Do not remove ending after e + return base[-1] != "e" + + +def F(base): + # F Minimum stem length = 3 and do not remove ending after e + return len(base) > 2 and base[-1] != "e" + + +def G(base): + # G Minimum stem length = 3 and remove ending only after f + return len(base) > 2 and base[-1] == "f" + + +def H(base): + # H Remove ending only after t or ll + c1, c2 = base[-2:] + return c2 == "t" or (c2 == "l" and c1 == "l") + + +def I(base): + # I Do not remove ending after o or e + c = base[-1] + return c != "o" and c != "e" + + +def J(base): + # J Do not remove ending after a or e + c = base[-1] + return c != "a" and c != "e" + + +def K(base): + # K Minimum stem length = 3 and remove ending only after l, i or u*e + c = base[-1] + cc = base[-3] + return len(base) > 2 and (c == "l" or c == "i" or (c == "e" and cc == "u")) + + +def L(base): + # L Do not remove ending after u, x or s, unless s follows o + c1, c2 = base[-2:] + return c2 != "u" and c2 != "x" and (c2 != "s" or c1 == "o") + + +def M(base): + # M Do not remove ending after a, c, e or m + c = base[-1] + return c != "a" and c != "c" and c != "e" and c != "m" + + +def N(base): + # N Minimum stem length = 4 after s**, elsewhere = 3 + return len(base) > 3 or (len(base) == 3 and base[-1] != "s") + + +def O(base): + # O Remove ending only after l or i + c = base[-1] + return c == "l" or c == "i" + + +def P(base): + # P Do not remove ending after c + return base[-1] != "c" + + +def Q(base): + # Q Minimum stem length = 3 and do not remove ending after l or n + c = base[-1] + return len(base) > 2 and (c != "l" and c != "n") + + +def R(base): + # R Remove ending only after n or r + c = base[-1] + return c == "n" or c == "r" + + +def S(base): + # S Remove ending only after dr or t, unless t follows t + l2 = base[-2] + return l2 == "rd" or (base[-1] == "t" and l2 != "tt") + + +def T(base): + # T Remove ending only after s or t, unless t follows o + c1, c2 = base[-2:] + return c2 == "s" or (c2 == "t" and c1 != "o") + + +def U(base): + # U Remove ending only after l, m, n or r + c = base[-1] + return c == "l" or c == "m" or c == "n" or c == "r" + + +def V(base): + # V Remove ending only after c + return base[-1] == "c" + + +def W(base): + # W Do not remove ending after s or u + c = base[-1] + return c != "s" and c != "u" + + +def X(base): + # X Remove ending only after l, i or u*e + c = base[-1] + cc = base[-3] + return c == "l" or c == "i" or (c == "e" and cc == "u") + + +def Y(base): + # Y Remove ending only after in + return base[-2:] == "in" + + +def Z(base): + # Z Do not remove ending after f + return base[-1] != "f" + + +def a(base): + # a Remove ending only after d, f, ph, th, l, er, or, es or t + c = base[-1] + l2 = base[-2:] + return (c == "d" or c == "f" or l2 == "ph" or l2 == "th" or c == "l" + or l2 == "er" or l2 == "or" or l2 == "es" or c == "t") + + +def b(base): + # b Minimum stem length = 3 and do not remove ending after met or ryst + return len(base) > 2 and not (base.endswith("met") + or base.endswith("ryst")) + + +def c(base): + # c Remove ending only after l + return base[-1] == "l" + + +# Endings + +m = [None] * 12 + +m[11] = dict(( + ("alistically", B), + ("arizability", A), + ("izationally", B))) +m[10] = dict(( + ("antialness", A), + ("arisations", A), + ("arizations", A), + ("entialness", A))) +m[9] = dict(( + ("allically", C), + ("antaneous", A), + ("antiality", A), + ("arisation", A), + ("arization", A), + ("ationally", B), + ("ativeness", A), + ("eableness", E), + ("entations", A), + ("entiality", A), + ("entialize", A), + ("entiation", A), + ("ionalness", A), + ("istically", A), + ("itousness", A), + ("izability", A), + ("izational", A))) +m[8] = dict(( + ("ableness", A), + ("arizable", A), + ("entation", A), + ("entially", A), + ("eousness", A), + ("ibleness", A), + ("icalness", A), + ("ionalism", A), + ("ionality", A), + ("ionalize", A), + ("iousness", A), + ("izations", A), + ("lessness", A))) +m[7] = dict(( + ("ability", A), + ("aically", A), + ("alistic", B), + ("alities", A), + ("ariness", E), + ("aristic", A), + ("arizing", A), + ("ateness", A), + ("atingly", A), + ("ational", B), + ("atively", A), + ("ativism", A), + ("elihood", E), + ("encible", A), + ("entally", A), + ("entials", A), + ("entiate", A), + ("entness", A), + ("fulness", A), + ("ibility", A), + ("icalism", A), + ("icalist", A), + ("icality", A), + ("icalize", A), + ("ication", G), + ("icianry", A), + ("ination", A), + ("ingness", A), + ("ionally", A), + ("isation", A), + ("ishness", A), + ("istical", A), + ("iteness", A), + ("iveness", A), + ("ivistic", A), + ("ivities", A), + ("ization", F), + ("izement", A), + ("oidally", A), + ("ousness", A))) +m[6] = dict(( + ("aceous", A), + ("acious", B), + ("action", G), + ("alness", A), + ("ancial", A), + ("ancies", A), + ("ancing", B), + ("ariser", A), + ("arized", A), + ("arizer", A), + ("atable", A), + ("ations", B), + ("atives", A), + ("eature", Z), + ("efully", A), + ("encies", A), + ("encing", A), + ("ential", A), + ("enting", C), + ("entist", A), + ("eously", A), + ("ialist", A), + ("iality", A), + ("ialize", A), + ("ically", A), + ("icance", A), + ("icians", A), + ("icists", A), + ("ifully", A), + ("ionals", A), + ("ionate", D), + ("ioning", A), + ("ionist", A), + ("iously", A), + ("istics", A), + ("izable", E), + ("lessly", A), + ("nesses", A), + ("oidism", A))) +m[5] = dict(( + ("acies", A), + ("acity", A), + ("aging", B), + ("aical", A), + ("alist", A), + ("alism", B), + ("ality", A), + ("alize", A), + ("allic", b), + ("anced", B), + ("ances", B), + ("antic", C), + ("arial", A), + ("aries", A), + ("arily", A), + ("arity", B), + ("arize", A), + ("aroid", A), + ("ately", A), + ("ating", I), + ("ation", B), + ("ative", A), + ("ators", A), + ("atory", A), + ("ature", E), + ("early", Y), + ("ehood", A), + ("eless", A), + ("elily", A), + ("ement", A), + ("enced", A), + ("ences", A), + ("eness", E), + ("ening", E), + ("ental", A), + ("ented", C), + ("ently", A), + ("fully", A), + ("ially", A), + ("icant", A), + ("ician", A), + ("icide", A), + ("icism", A), + ("icist", A), + ("icity", A), + ("idine", I), + ("iedly", A), + ("ihood", A), + ("inate", A), + ("iness", A), + ("ingly", B), + ("inism", J), + ("inity", c), + ("ional", A), + ("ioned", A), + ("ished", A), + ("istic", A), + ("ities", A), + ("itous", A), + ("ively", A), + ("ivity", A), + ("izers", F), + ("izing", F), + ("oidal", A), + ("oides", A), + ("otide", A), + ("ously", A))) +m[4] = dict(( + ("able", A), + ("ably", A), + ("ages", B), + ("ally", B), + ("ance", B), + ("ancy", B), + ("ants", B), + ("aric", A), + ("arly", K), + ("ated", I), + ("ates", A), + ("atic", B), + ("ator", A), + ("ealy", Y), + ("edly", E), + ("eful", A), + ("eity", A), + ("ence", A), + ("ency", A), + ("ened", E), + ("enly", E), + ("eous", A), + ("hood", A), + ("ials", A), + ("ians", A), + ("ible", A), + ("ibly", A), + ("ical", A), + ("ides", L), + ("iers", A), + ("iful", A), + ("ines", M), + ("ings", N), + ("ions", B), + ("ious", A), + ("isms", B), + ("ists", A), + ("itic", H), + ("ized", F), + ("izer", F), + ("less", A), + ("lily", A), + ("ness", A), + ("ogen", A), + ("ward", A), + ("wise", A), + ("ying", B), + ("yish", A))) +m[3] = dict(( + ("acy", A), + ("age", B), + ("aic", A), + ("als", b), + ("ant", B), + ("ars", O), + ("ary", F), + ("ata", A), + ("ate", A), + ("eal", Y), + ("ear", Y), + ("ely", E), + ("ene", E), + ("ent", C), + ("ery", E), + ("ese", A), + ("ful", A), + ("ial", A), + ("ian", A), + ("ics", A), + ("ide", L), + ("ied", A), + ("ier", A), + ("ies", P), + ("ily", A), + ("ine", M), + ("ing", N), + ("ion", Q), + ("ish", C), + ("ism", B), + ("ist", A), + ("ite", a), + ("ity", A), + ("ium", A), + ("ive", A), + ("ize", F), + ("oid", A), + ("one", R), + ("ous", A))) +m[2] = dict(( + ("ae", A), + ("al", b), + ("ar", X), + ("as", B), + ("ed", E), + ("en", F), + ("es", E), + ("ia", A), + ("ic", A), + ("is", A), + ("ly", B), + ("on", S), + ("or", T), + ("um", U), + ("us", V), + ("yl", R), + ("s'", A), + ("'s", A))) +m[1] = dict(( + ("a", A), + ("e", A), + ("i", A), + ("o", A), + ("s", W), + ("y", B))) + + +def remove_ending(word): + length = len(word) + el = 11 + while el > 0: + if length - el > 1: + ending = word[length - el:] + cond = m[el].get(ending) + if cond: + base = word[:length - el] + if cond(base): + return base + el -= 1 + return word + + +_endings = (("iev", "ief"), + ("uct", "uc"), + ("iev", "ief"), + ("uct", "uc"), + ("umpt", "um"), + ("rpt", "rb"), + ("urs", "ur"), + ("istr", "ister"), + ("metr", "meter"), + ("olv", "olut"), + ("ul", "l", "aoi"), + ("bex", "bic"), + ("dex", "dic"), + ("pex", "pic"), + ("tex", "tic"), + ("ax", "ac"), + ("ex", "ec"), + ("ix", "ic"), + ("lux", "luc"), + ("uad", "uas"), + ("vad", "vas"), + ("cid", "cis"), + ("lid", "lis"), + ("erid", "eris"), + ("pand", "pans"), + ("end", "ens", "s"), + ("ond", "ons"), + ("lud", "lus"), + ("rud", "rus"), + ("her", "hes", "pt"), + ("mit", "mis"), + ("ent", "ens", "m"), + ("ert", "ers"), + ("et", "es", "n"), + ("yt", "ys"), + ("yz", "ys")) + + +# Hash the ending rules by the last letter of the target ending +_endingrules = defaultdict(list) +for rule in _endings: + _endingrules[rule[0][-1]].append(rule) + +_doubles = frozenset(("dd", "gg", "ll", "mm", "nn", "pp", "rr", "ss", "tt")) + + +def fix_ending(word): + if word[-2:] in _doubles: + word = word[:-1] + + for endingrule in _endingrules[word[-1]]: + target, newend = endingrule[:2] + if word.endswith(target): + if len(endingrule) > 2: + exceptafter = endingrule[2] + c = word[0 - (len(target) + 1)] + if c in exceptafter: + return word + + return word[:0 - len(target)] + newend + + return word + + +def stem(word): + """Returns the stemmed version of the argument string. + """ + return fix_ending(remove_ending(word)) diff --git a/nstock/modules/whoosh/lang/morph_en.py b/nstock/modules/whoosh/lang/morph_en.py new file mode 100644 index 0000000..bb63573 --- /dev/null +++ b/nstock/modules/whoosh/lang/morph_en.py @@ -0,0 +1,933 @@ +""" +Contains the variations() function for expanding an English word into multiple +variations by programatically adding and removing suffixes. + +Translated to Python from the ``com.sun.labs.minion.lexmorph.LiteMorph_en`` +class of Sun's `Minion search engine `_. +""" + +import re + +from whoosh.compat import xrange, iteritems +# Rule exceptions + +exceptions = [ + "a", + "abandoner abandon abandons abandoned abandoning abandonings abandoners", + "abdomen abdomens", + "about", + "above", + "acid acids acidic acidity acidities", + "across", + "act acts acted acting actor actors", + "ad ads", + "add adds added adding addings addition additions adder adders", + "advertise advertises advertised advertising advertiser advertisers advertisement advertisements advertisings", + "after", + "again", + "against", + "ago", + "all", + "almost", + "along", + "already", + "also", + "although", + "alumna alumnae alumnus alumni", + "always", + "amen amens", + "amidships", + "amid amidst", + "among amongst", + "an", + "analysis analyses", + "and", + "another other others", + "antenna antennas antennae", + "antitheses antithesis", + "any", + "anyone anybody", + "anything", + "appendix appendixes appendices", + "apropos", + "aquarium aquariums aquaria", + "argument arguments argue argues argued arguing arguings arguer arguers", + "arise arises arose arisen ariser arisers arising arisings", + "around", + "as", + "asbestos", + "at", + "atlas atlases", + "auger augers augered augering augerings augerer augerers", + "augment augments augmented augmenting augmentings augmentation augmentations augmenter augmenters", + "automata automaton automatons", + "automation automating automate automates automated automatic", + "avoirdupois", + "awake awakes awoke awaked awoken awaker awakers awaking awakings awakening awakenings", + "away", + "awful awfully awfulness", + "axis axes axises", + "bacillus bacilli", + "bacterium bacteria", + "bad worse worst badly badness", + "bas", + "bases basis", + "bases base based basing basings basely baseness basenesses basement basements baseless basic basics", + "be am are is was were been being", + "bear bears bore borne bearing bearings bearer bearers", + "beat beats beaten beating beatings beater beaters", + "because", + "become becomes became becoming", + "beef beefs beeves beefed beefing", + "beer beers", + "before", + "begin begins began begun beginning beginnings beginner beginners", + "behalf behalves", + "being beings", + "bend bends bent bending bendings bender benders", + "bereave bereaves bereaved bereft bereaving bereavings bereavement bereavements", + "beside besides", + "best bests bested besting", + "bet bets betting bettor bettors", + "betimes", + "between", + "beyond", + "bid bids bade bidden bidding biddings bidder bidders", + "bier biers", + "bind binds bound binding bindings binder binders", + "bit bits", + "bite bites bit bitten biting bitings biter biters", + "blackfoot blackfeet", + "bleed bleeds bled bleeding bleedings bleeder bleeders", + "blow blows blew blown blowing blowings blower blowers", + "bookshelf bookshelves", + "both", + "bound bounds bounded bounding boundings bounder bounders boundless", + "bourgeois bourgeoisie", + "bra bras", + "brahman brahmans", + "break breaks broke broken breaking breakings breaker breakers", + "breed breeds bred breeding breedings breeder breeders", + "bring brings brought bringing bringings bringer bringers", + "build builds built building buildings builder builders", + "bus buses bused bussed busing bussing busings bussings buser busers busser bussers", + "buss busses bussed bussing bussings busser bussers", + "but", + "buy buys bought buying buyings buyer buyers", + "by", + "calf calves calved calving calvings calver calvers", + "can cans canned canning cannings canner canners", + "can could cannot", + "canoes canoe canoed canoeing canoeings canoer canoers", + "catch catches caught catching catchings catcher catchers", + "cement cements cemented cementing cementings cementer cementers", + "cent cents", + "center centers centered centering centerings centerless", + "child children childless childish childishly", + "choose chooses chose chosen choosing choosings chooser choosers", + "cling clings clung clinging clingings clinger clingers", + "colloquium colloquia colloquiums", + "come comes came coming comings comer comers", + "comment comments commented commenting commentings commenter commenters", + "compendium compendia compendiums", + "complement complements complemented complementing complementings complementer complementers complementary", + "compliment compliments complimented complimenting complimentings complimenter complimenters complimentary", + "concerto concertos concerti", + "condiment condiments", + "corps", + "cortex cortices cortexes cortical", + "couscous", + "creep creeps crept creeping creepings creeper creepers creepy", + "crisis crises", + "criterion criteria criterial", + "cryptanalysis cryptanalyses", + "curriculum curricula curriculums curricular", + "datum data", + "day days daily", + "deal deals dealt dealing dealings dealer dealers", + "decrement decrements decremented decrementing decrementings decrementer decrementers decremental", + "deer deers", + "demented dementia", + "desideratum desiderata", + "diagnosis diagnoses diagnose diagnosed diagnosing diagnostic", + "dialysis dialyses", + "dice dices diced dicing dicings dicer dicers", + "die dice", + "die dies died dying dyings", + "dig digs dug digging diggings digger diggers", + "dive dives diver divers dove dived diving divings", + "divest divests divester divesters divested divesting divestings divestment divestments", + "do does did done doing doings doer doers", + "document documents documented documenting documentings documenter documenters documentation documentations documentary", + "doe does", + "dove doves", + "downstairs", + "dozen", + "draw draws drew drawn drawing drawings drawer drawers", + "drink drinks drank drunk drinking drinkings drinker drinkers", + "drive drives drove driven driving drivings driver drivers driverless", + "due dues duly", + "during", + "e", + "each", + "eager eagerer eagerest eagerly eagerness eagernesses", + "early earlier earliest", + "easement easements", + "eat eats ate eaten eating eatings eater eaters", + "effluvium effluvia", + "either", + "element elements elementary", + "elf elves elfen", + "ellipse ellipses elliptic elliptical elliptically", + "ellipsis ellipses elliptic elliptical elliptically", + "else", + "embolus emboli embolic embolism", + "emolument emoluments", + "emphasis emphases", + "employ employs employed employing employer employers employee employees employment employments employable", + "enough", + "equilibrium equilibria equilibriums", + "erratum errata", + "ever", + "every", + "everything", + "exotic exotically exoticness exotica", + "experiment experiments experimented experimenting experimentings experimenter experimenters experimentation experimental", + "extra extras", + "fall falls fell fallen falling fallings faller fallers", + "far farther farthest", + "fee fees feeless", + "feed feeds fed feeding feedings feeder feeders", + "feel feels felt feeling feelings feeler feelers", + "ferment ferments fermented fermenting fermentings fermentation fermentations fermenter fermenters", + "few fewer fewest", + "fight fights fought fighting fightings fighter fighters", + "figment figments", + "filament filaments", + "find finds found finding findings finder finders", + "firmament firmaments", + "flee flees fled fleeing fleeings", + "fling flings flung flinging flingings flinger flingers", + "floe floes", + "fly flies flew flown flying flyings flier fliers flyer flyers", + "focus foci focuses focused focusing focusses focussed focussing focuser focal", + "foment foments fomented fomenting fomentings fomenter fomenters", + "foot feet", + "foot foots footed footing footer footers", + "footing footings footer footers", + "for", + "forbid forbids forbade forbidden forbidding forbiddings forbidder forbidders", + "foresee foresaw foreseen foreseeing foreseeings foreseer foreseers", + "forest forests forester foresting forestation forestations", + "forget forgets forgot forgotten forgetting forgettings forgetter forgetters forgetful", + "forsake forsakes forsook forsaken forsaking forsakings forsaker forsakers", + "found founds founded founding foundings founder founders", + "fragment fragments fragmented fragmenting fragmentings fragmentation fragmentations fragmenter fragmenters", + "free frees freer freest freed freeing freely freeness freenesses", + "freeze freezes froze frozen freezing freezings freezer freezers", + "from", + "full fully fuller fullest", + "fuller fullers full fulls fulled fulling fullings", + "fungus fungi funguses fungal", + "gallows", + "ganglion ganglia ganglions ganglionic", + "garment garments", + "gas gasses gassed gassing gassings gasser gassers", + "gas gases gasses gaseous gasless", + "gel gels gelled gelling gellings geller gellers", + "german germans germanic germany German Germans Germanic Germany", + "get gets got gotten getting gettings getter getters", + "give gives gave given giving givings giver givers", + "gladiolus gladioli gladioluses gladiola gladiolas gladiolae", + "glans glandes", + "gluiness gluey glue glues glued gluing gluings gluer gluers", + "go goes went gone going goings goer goers", + "godchild godchildren", + "good better best goodly goodness goodnesses", + "goods", + "goose geese", + "goose gooses goosed goosing goosings gooser goosers", + "grandchild grandchildren", + "grind grinds ground grinding grindings grinder grinders", + "ground grounds grounded grounding groundings grounder grounders groundless", + "grow grows grew grown growing growings grower growers growth", + "gum gums gummed gumming gummings gummer gummers", + "half halves", + "halve halves halved halving halvings halver halvers", + "hang hangs hung hanged hanging hangings hanger hangers", + "have has had having havings haver havers", + "he him his himself", + "hear hears heard hearing hearings hearer hearers", + "here", + "hide hides hid hidden hiding hidings hider hiders", + "hippopotamus hippopotami hippopotamuses", + "hold holds held holding holdings holder holders", + "honorarium honoraria honorariums", + "hoof hoofs hooves hoofed hoofing hoofer hoofers", + "how", + "hum hums hummed humming hummings hummer hummers", + "hymen hymens hymenal", + "hypotheses hypothesis hypothesize hypothesizes hypothesized hypothesizer hypothesizing hypothetical hypothetically", + "i", + "if iffy", + "impediment impediments", + "implement implements implemented implementing implementings implementation implementations implementer implementers", + "imply implies implied implying implyings implier impliers", + "in inner", + "inclement", + "increment increments incremented incrementing incrementings incrementer incrementers incremental incrementally", + "index indexes indexed indexing indexings indexer indexers", + "index indexes indices indexical indexicals", + "indoor indoors", + "instrument instruments instrumented instrumenting instrumentings instrumenter instrumenters instrumentation instrumentations instrumental", + "integument integumentary", + "into", + "it its itself", + "java", + "july julys", + "keep keeps kept keeping keepings keeper keepers", + "knife knifes knifed knifing knifings knifer knifers", + "knife knives", + "know knows knew known knowing knowings knower knowers knowledge", + "lament laments lamented lamenting lamentings lamentation lamentations lamenter lamenters lamentable lamentably", + "larva larvae larvas larval", + "late later latest lately lateness", + "latter latterly", + "lay lays laid laying layer layers", + "layer layers layered layering layerings", + "lead leads led leading leadings leader leaders leaderless", + "leaf leafs leafed leafing leafings leafer leafers", + "leaf leaves leafless", + "leave leaves left leaving leavings leaver leavers", + "lend lends lent lending lendings lender lenders", + "less lesser least", + "let lets letting lettings", + "lie lies lay lain lying lier liers", + "lie lies lied lying liar liars", + "life lives lifeless", + "light lights lit lighted lighting lightings lightly lighter lighters lightness lightnesses lightless", + "likely likelier likeliest", + "limen limens", + "lineament lineaments", + "liniment liniments", + "live alive living", + "live lives lived living livings", + "liver livers", + "loaf loafs loafed loafing loafings loafer loafers", + "loaf loaves", + "logic logics logical logically", + "lose loses lost losing loser losers loss losses", + "louse lice", + "lumen lumens", + "make makes made making makings maker makers", + "man mans manned manning mannings", + "man men", + "manly manlier manliest manliness manful manfulness manhood", + "manic manically", + "manner manners mannered mannerly mannerless mannerful", + "many", + "matrix matrices matrixes", + "may might", + "maximum maxima maximums maximal maximize maximizes maximized maximizing", + "mean means meant meaning meanings meaningless meaningful", + "mean meaner meanest meanly meanness meannesses", + "median medians medianly medial", + "medium media mediums", + "meet meets met meeting meetings", + "memorandum memoranda memorandums", + "mere merely", + "metal metals metallic", + "might mighty mightily", + "millenium millennia milleniums millennial", + "mine mines mined mining minings miner miners", + "mine my our ours", + "minimum minima minimums minimal", + "minus minuses", + "miscellaneous miscellanea miscellaneously miscellaneousness miscellany", + "molest molests molested molesting molestings molester molesters", + "moment moments", + "monument monuments monumental", + "more most", + "mouse mice mouseless", + "much", + "multiply multiplies multiplier multipliers multiple multiples multiplying multiplyings multiplication multiplications", + "mum mums mummed mumming mummings mummer mummers", + "must musts", + "neither", + "nemeses nemesis", + "neurosis neuroses neurotic neurotics", + "nomen", + "none", + "nos no noes", + "not", + "nothing nothings nothingness", + "now", + "nowadays", + "nucleus nuclei nucleuses nuclear", + "number numbers numbered numbering numberings numberless", + "nutriment nutriments nutrient nutrients nutrition nutritions", + "oasis oases", + "octopus octopi octopuses", + "of", + "off", + "offer offers offered offering offerings offerer offerers offeror offerors", + "often", + "oftentimes", + "ointment ointments", + "omen omens", + "on", + "once", + "only", + "ornament ornaments ornamented ornamenting ornamentings ornamentation ornamenter ornamenters ornamental", + "outdoor outdoors", + "outlay outlays", + "outlie outlies outlay outlied outlain outlying outlier outliers", + "ovum ova", + "ox oxen", + "parentheses parenthesis", + "parliament parliaments parliamentary", + "passerby passer-by passersby passers-by", + "past pasts", + "pay pays paid paying payings payer payers payee payees payment payments", + "per", + "perhaps", + "person persons people", + "phenomenon phenomena phenomenal", + "pi", + "picnic picnics picnicker picnickers picnicked picnicking picnickings", + "pigment pigments pigmented pigmenting pigmentings pigmenter pigmenters pigmentation pigmentations", + "please pleases pleased pleasing pleasings pleaser pleasers pleasure pleasures pleasuring pleasurings pleasant pleasantly pleasureless pleasureful", + "plus pluses plusses", + "polyhedra polyhedron polyhedral", + "priest priests priestly priestlier priestliest priestliness priestless", + "prognosis prognoses", + "prostheses prosthesis", + "prove proves proved proving provings proofs proof prover provers provable", + "psychosis psychoses psychotic psychotics", + "qed", + "quiz quizzes quizzed quizzing quizzings quizzer quizzers", + "raiment", + "rather", + "re", + "real really", + "redo redoes redid redone redoing redoings redoer redoers", + "regiment regiments regimented regimenting regimenter regimenters regimentation regimental", + "rendezvous", + "requiz requizzes requizzed requizzing requizzings requizzer requizzers", + "ride rides rode ridden riding ridings rider riders rideless", + "ring rings rang rung ringing ringings ringer ringers ringless", + "rise rises rose risen rising risings riser risers", + "rose roses", + "rudiment rudiments rudimentary", + "rum rums rummed rumming rummings rummer rummers", + "run runs ran running runnings runner runners", + "sacrament sacraments sacramental", + "same sameness", + "sans", + "saw saws sawed sawn sawing sawings sawyer sawyers", + "say says said saying sayings sayer sayers", + "scarf scarfs scarves scarfless", + "schema schemata schemas", + "sediment sediments sedimentary sedimentation sedimentations", + "see sees saw seen seeing seeings seer seers", + "seek seeks sought seeking seekings seeker seekers", + "segment segments segmented segmenting segmentings segmenter segmenters segmentation segmentations", + "self selves selfless", + "sell sells sold selling sellings seller sellers", + "semen", + "send sends sent sending sendings sender senders", + "sentiment sentiments sentimental", + "series", + "set sets setting settings", + "several severally", + "sew sews sewed sewn sewing sewings sewer sewers", + "sewer sewers sewerless", + "shake shakes shook shaken shaking shakings shaker shakers", + "shall should", + "shaman shamans", + "shave shaves shaved shaven shaving shavings shaver shavers shaveless", + "she her hers herself", + "sheaf sheaves sheafless", + "sheep", + "shelf shelves shelved shelfing shelvings shelver shelvers shelfless", + "shine shines shined shone shining shinings shiner shiners shineless", + "shoe shoes shoed shod shoeing shoeings shoer shoers shoeless", + "shoot shoots shot shooting shootings shooter shooters", + "shot shots", + "show shows showed shown showing showings shower showers", + "shower showers showery showerless", + "shrink shrinks shrank shrunk shrinking shrinkings shrinker shrinkers shrinkable", + "sideways", + "simply simple simpler simplest", + "since", + "sing sings sang sung singing singings singer singers singable", + "sink sinks sank sunk sinking sinkings sinker sinkers sinkable", + "sit sits sat sitting sittings sitter sitters", + "ski skis skied skiing skiings skier skiers skiless skiable", + "sky skies", + "slay slays slew slain slaying slayings slayer slayers", + "sleep sleeps slept sleeping sleepings sleeper sleepers sleepless", + "so", + "some", + "something", + "sometime sometimes", + "soon", + "spa spas", + "speak speaks spoke spoken speaking speakings speaker speakers", + "species specie", + "spectrum spectra spectrums", + "speed speeds sped speeded speeding speedings speeder speeders", + "spend spends spent spending spendings spender spenders spendable", + "spin spins spun spinning spinnings spinner spinners", + "spoke spokes", + "spring springs sprang sprung springing springings springer springers springy springiness", + "staff staffs staves staffed staffing staffings staffer staffers", + "stand stands stood standing standings", + "stasis stases", + "steal steals stole stolen stealing stealings stealer stealers", + "stick sticks stuck sticking stickings sticker stickers", + "stigma stigmata stigmas stigmatize stigmatizes stigmatized stigmatizing", + "stimulus stimuli", + "sting stings stung stinging stingings stinger stingers", + "stink stinks stank stunk stinking stinkings stinker stinkers", + "stomach stomachs", + "stratum strata stratums", + "stride strides strode stridden striding stridings strider striders", + "string strings strung stringing stringings stringer stringers stringless", + "strive strives strove striven striving strivings striver strivers", + "strum strums strummed strumming strummings strummer strummers strummable", + "such", + "suffer suffers suffered suffering sufferings sufferer sufferers sufferable", + "suggest suggests suggested suggesting suggestings suggester suggesters suggestor suggestors suggestive suggestion suggestions suggestible suggestable", + "sum sums summed summing summings summer summers", + "summer summers summered summering summerings", + "supplement supplements supplemented supplementing supplementings supplementation supplementer supplementers supplementary supplemental", + "supply supplies supplied supplying supplyings supplier suppliers", + "swear swears swore sworn swearing swearings swearer swearers", + "sweep sweeps swept sweeping sweepings sweeper sweepers", + "swell swells swelled swollen swelling swellings", + "swim swims swam swum swimming swimmings swimmer swimmers swimable", + "swine", + "swing swings swung swinging swingings swinger swingers", + "syllabus syllabi syllabuses", + "symposium symposia symposiums", + "synapse synapses", + "synapsis synapses", + "synopsis synopses", + "synthesis syntheses", + "tableau tableaux tableaus", + "take takes took taken taking takings taker takers takable", + "teach teaches taught teaching teachings teacher teachers teachable", + "tear tears tore torn tearing tearings tearer tearers tearable", + "tegument teguments", + "tell tells told telling tellings teller tellers tellable", + "temperament temperaments temperamental temperamentally", + "tenement tenements", + "the", + "there theres", + "theses thesis", + "they them their theirs themselves", + "thief thieves thieving thievings", + "think thinks thought thinking thinker thinkers thinkable", + "this that these those", + "thought thoughts thougtful thoughtless", + "throw throws threw thrown throwing throwings thrower throwers throwable", + "tic tics", + "tie ties tied tying tyings tier tiers tieable tieless", + "tier tiers tiered tiering tierings tierer tierers", + "to", + "toe toes toed toeing toeings toer toers toeless", + "together togetherness", + "too", + "tooth teeth toothless", + "topaz topazes", + "torment torments tormented tormenting tormentings tormenter tormenters tormentable", + "toward towards", + "tread treads trod trodden treading treadings treader treaders", + "tread treads treadless retread retreads", + "true truly trueness", + "two twos", + "u", + "under", + "underlay underlays underlaid underlaying underlayings underlayer underlayers", + "underlie underlies underlay underlain underlying underlier underliers", + "undo undoes undid undone undoing undoings undoer undoers undoable", + "unrest unrestful", + "until", + "unto", + "up", + "upon", + "upstairs", + "use uses user users used using useful useless", + "various variously", + "vehement vehemently vehemence", + "versus", + "very", + "visit visits visited visiting visitings visitor visitors", + "vortex vortexes vortices", + "wake wakes woke waked woken waking wakings waker wakers wakeful wakefulness wakefulnesses wakeable", + "wear wears wore worn wearing wearings wearer wearers wearable", + "weather weathers weathered weathering weatherly", + "weave weaves wove woven weaving weavings weaver weavers weaveable", + "weep weeps wept weeping weepings weeper weepers", + "wharf wharfs wharves", + "where wheres", + "whereas whereases", + "whether whethers", + "while whiles whilst whiled whiling", + "whiz whizzes whizzed whizzing whizzings whizzer whizzers", + "who whom whos whose whoses", + "why whys", + "wife wives wifeless", + "will wills willed willing willings willful", + "will would", + "win wins won winning winnings winner winners winnable", + "wind winds wound winding windings winder winders windable", + "wind winds windy windless", + "with", + "within", + "without", + "wolf wolves", + "woman women womanless womanly", + "wound wounds wounded wounding woundings", + "write writes wrote written writing writings writer writers writeable", + "yeses yes", + "yet yets", + "you your yours yourself" + ] + +_exdict = {} +for exlist in exceptions: + for ex in exlist.split(" "): + _exdict[ex] = exlist + +# Programmatic rules + +vowels = "aeiouy" +cons = "bcdfghjklmnpqrstvwxyz" + +rules = ( + # Words ending in S + + # (e.g., happiness, business) + (r"[%s].*[%s](iness)" % (vowels, cons), "y,ies,ier,iers,iest,ied,ying,yings,ily,inesses,iment,iments,iless,iful"), + # (e.g., baseless, shoeless) + (r"[%s].*(eless)" % vowels, "e,es,er,ers,est,ed,ing,ings,eing,eings,ely,eness,enesses,ement,ements,eness,enesses,eful"), + # (e.g., gutless, hatless, spotless) + (r"[%s][%s][bdgklmnprt]?(less)" % (cons, vowels), ",s,&er,&ers,&est,&ed,&ing,&ings,ly,ness,nesses,ment,ments,ful"), + # (e.g., thoughtless, worthless) + (r"[%s].*?(less)" % vowels, ",s,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,ful"), + # (e.g., baseness, toeness) + (r"[%s].*(eness)" % vowels, "e,es,er,ers,est,ed,ing,ings,eing,eings,ely,enesses,ement,ements,eless,eful"), + # (e.g., bluntness, grayness) + (r"[%s].*(ness)" % vowels, ",s,er,ers,est,ed,ing,ings,ly,nesses,ment,ments,less,ful"), + # (e.g., albatross, kiss) + (r"[%s]ss" % vowels, "es,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful"), + # (e.g., joyous, fractious, gaseous) + (r"[%s].*(ous)" % vowels, "ly,ness"), + # (e.g., tries, unties, jollies, beauties) + (r"(ies)", "y,ie,yer,yers,ier,iers,iest,ied,ying,yings,yness,iness,ieness,ynesses,inesses,ienesses,iment,iement,iments,iements,yless,iless,ieless,yful,iful,ieful"), + # (e.g., crisis, kinesis) + (r"[%s].*(sis)" % vowels, "ses,sises,sisness,sisment,sisments,sisless,sisful"), + # (e.g., bronchitis, bursitis) + (r"[%s].*(is)" % vowels, "es,ness,ment,ments,less,ful"), + (r"[%s].*[cs]h(es)" % vowels, ",e,er,ers,est,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment,ement,ments,ements,less,eless,ful,eful"), + # (e.g., tokenizes) // adds British variations + (r"[%s].*[%s](izes)" % (vowels, cons), "ize,izes,izer,izers,ized,izing,izings,ization,izations,ise,iser,isers,ised,ising,isings,isation,isations"), + # (e.g., tokenises) // British variant // ~expertise + (r"[%s].*[%s](ises)" % (vowels, cons), "ize,izes,izer,izers,ized,izing,izings,ization,izations,ise,iser,isers,ised,ising,isings,isation,isations"), + # (e.g., aches, arches) + (r"[%s].*[jsxz](es)" % vowels, ",e,er,ers,est,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment,ement,ments,ements,less,eless,ful,eful"), + # (e.g., judges, abridges) + (r"[%s].*dg(es)" % vowels, "e,er,ers,est,ed,ing,ings,ely,eness,enesses,ment,ments,ement,ements,eless,eful"), + # (e.g., trees, races, likes, agrees) covers all other -es words + (r"e(s)", ",*"), + # (e.g., segments, bisegments, cosegments) + (r"segment(s)", ",*"), + # (e.g., pigments, depigments, repigments) + (r"pigment(s)", ",*"), + # (e.g., judgments, abridgments) + (r"[%s].*dg(ments)" % vowels, "ment,*ments"), + # (e.g., merriments, embodiments) -iment in turn will generate y and *y (redo y) + (r"[%s].*[%s]iment(s)" % (vowels, cons), ",*"), + # (e.g., atonements, entrapments) + (r"[%s].*ment(s)" % vowels, ",*"), + # (e.g., viewers, meters, traders, transfers) + (r"[%s].*er(s)" % vowels, ",*"), + # (e.g., unflags) polysyllables + (r"[%s].*[%s][%s][bdglmnprt](s)" % (vowels, cons, vowels), ",*"), + # (e.g., frogs) monosyllables + (r"[%s][%s][bdglmnprt](s)" % (vowels, cons), ",*"), + # (e.g., killings, muggings) + (r"[%s].*ing(s)" % vowels, ",*"), + # (e.g., hulls, tolls) + (r"[%s].*ll(s)" % vowels, ",*"), + # e.g., boas, polkas, spas) don't generate latin endings + (r"a(s)", ",er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful"), + # (e.g., beads, toads) + (r"[%s].*[%s].*(s)" % (vowels, cons), ",*"), + # (e.g., boas, zoos) + (r"[%s].*[%s](s)" % (cons, vowels), ",er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful"), + # (e.g., ss, sss, ssss) no vowel (vowel case is already handled above) + (r"ss()", ""), + # (e.g., cds, lcds, m-16s) no vowel (can be a plural noun, but not verb) + (r"[%s].*[%s1234567890](s)" % (cons, cons), ""), + + # Words ending in E + + # (e.g., apple, so it doesn't include apply) + (r"appl(e)", "es,er,ers,est,ed,ing,ings,ely,eness,enesses,ement,ements,eless,eful"), + # (e.g., supple, so it doesn't include supply) + (r"suppl(e)", "es,er,ers,est,ed,ing,ings,ely,eness,enesses,ement,ements,eless,eful"), + # (e.g., able, abominable, fungible, table, enable, idle, subtle) + (r"[%s].*[%s]l(e)" % (vowels, cons), "es,er,ers,est,ed,ing,ings,y,ely,eness,enesses,ement,ements,eless,eful"), + # (e.g., bookie, magpie, vie) + (r"(ie)", "ies,ier,iers,iest,ied,ying,yings,iely,ieness,ienesses,iement,iements,ieless,ieful"), + # (e.g., dye, redye, redeye) + (r"ye()", "s,r,rs,st,d,ing,ings,ly,ness,nesses,ment,ments,less,ful"), + # (e.g., judge, abridge) + (r"[%s].*dg(e)" % vowels, "es,er,ers,est,ed,ing,ings,ely,eness,enesses,ment,ments,less,ful,ement,ements,eless,eful"), + # (e.g., true, due, imbue) + (r"u(e)", "es,er,ers,est,ed,ing,ings,eing,eings,ly,ely,eness,enesses,ment,ments,less,ful,ement,ements,eless,eful"), + # (e.g., tokenize) // adds British variations + (r"[%s].*[%s](ize)" % (vowels, cons), "izes,izer,izers,ized,izing,izings,ization,izations,ise,ises,iser,isers,ised,ising,isings,isation,isations"), + # (e.g., tokenise) // British variant // ~expertise + (r"[%s].*[%s](ise)" % (vowels, cons), "ize,izes,izer,izers,ized,izing,izings,ization,izations,ises,iser,isers,ised,ising,isings,isation,isations"), + # (e.g., tree, agree, rage, horse, hoarse) + (r"[%s].*[%s](e)" % (vowels, cons), "es,er,ers,est,ed,ing,ings,eing,eings,ely,eness,enesses,ement,ements,eless,eful"), + + # Words ending in -ED + + # (e.g., agreed, freed, decreed, treed) + (r"ree(d)", "ds,der,ders,ded,ding,dings,dly,dness,dnesses,dment,dments,dless,dful,,*"), + # (e.g., feed, seed, Xweed) + (r"ee(d)", "ds,der,ders,ded,ding,dings,dly,dness,dnesses,dment,dments,dless,dful"), + # (e.g., tried) + (r"[%s](ied)" % cons, "y,ie,ies,ier,iers,iest,ying,yings,ily,yly,iness,yness,inesses,ynesses,iment,iments,iless,iful,yment,yments,yless,yful"), + # (e.g., controlled, fulfilled, rebelled) + (r"[%s].*[%s].*l(led)" % (vowels, cons), ",s,er,ers,est,ing,ings,ly,ness,nesses,ment,ments,less,ful,&,&s,&er,&ers,&est,&ing,&ings,&y,&ness,&nesses,&ment,&ments,&ful"), + # (e.g., pulled, filled, fulled) + (r"[%s].*l(led)" % vowels, "&,&s,&er,&ers,&est,&ing,&ings,&y,&ness,&nesses,&ment,&ments,&ful"), + # (e.g., hissed, grossed) + (r"[%s].*s(sed)" % vowels, "&,&es,&er,&ers,&est,&ing,&ings,&ly,&ness,&nesses,&ment,&ments,&less,&ful"), + # (e.g., hugged, trekked) + (r"[%s][%s](?P[bdgklmnprt])((?P=ed1)ed)", ",s,&er,&ers,&est,&ing,&ings,ly,ness,nesses,ment,ments,less,ful"), + # (e.g., tokenize) // adds British variations + (r"[%s].*[%s](ized)" % (vowels, cons), "izes,izer,izers,ize,izing,izings,ization,izations,ise,ises,iser,isers,ised,ising,isings,isation,isations"), + # (e.g., tokenise) // British variant // ~expertise + (r"[%s].*[%s](ized)" % (vowels, cons), "ize,izes,izer,izers,ized,izing,izings,ization,izations,ises,iser,isers,ise,ising,isings,isation,isations"), + # (e.g., spoiled, tooled, tracked, roasted, atoned, abridged) + (r"[%s].*(ed)" % vowels, ",e,s,es,er,ers,est,ing,ings,ly,ely,ness,eness,nesses,enesses,ment,ement,ments,ements,less,eless,ful,eful"), + # (e.g., bed, sled) words with a single e as the only vowel + (r"ed()", "s,&er,&ers,&est,&ed,&ing,&ings,ly,ness,nesses,ment,ments,less,ful"), + + # Words ending in -ER + + # (e.g., altimeter, ammeter, odometer, perimeter) + (r"meter()", "s,er,ers,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful"), + # (e.g., agreer, beer, budgeteer, engineer, freer) + (r"eer()", "eers,eered,eering,eerings,eerly,eerness,eernesses,eerment,eerments,eerless,eerful,ee,ees,eest,eed,eeing,eeings,eely,eeness,eenesses,eement,eements,eeless,eeful,eerer,eerers,eerest"), + # (e.g., acidifier, saltier) + (r"[%s].*[%s](ier)" % (vowels, cons), "y,ie,ies,iest,ied,ying,yings,ily,yly,iness,yness,inesses,ynesses,yment,yments,yless,yful,iment,iments,iless,iful,iers,iered,iering,ierings,ierly,ierness,iernesses,ierment,ierments,ierless,ierful,ierer,ierers,ierest"), + # (e.g., puller, filler, fuller) + (r"[%s].*l(ler)" % vowels, "&,&s,&est,&ed,&ing,&ings,ly,lely,&ness,&nesses,&ment,&ments,&ful,&ers,&ered,&ering,&erings,&erly,&erness,&ernesses,&erments,&erless,&erful"), + # (e.g., hisser, grosser) + (r"[%s].*s(ser)" % vowels, "&,&es,&est,&ed,&ing,&ings,&ly,&ness,&nesses,&ment,&ments,&less,&ful,&ers,&ered,&ering,&erings,&erly,&erness,&ernesses,&erment,&erments,&erless,&erful"), + # (e.g., bigger, trekker, hitter) + (r"[%s][%s](?P[bdgkmnprt])((?P=er1)er)" % (cons, vowels), "s,&est,&ed,&ing,&ings,ly,ness,nesses,ment,ments,less,ful,&ers,&ered,&ering,&erings,&erly,&erness,&ernesses,&erments,&erless,&erful"), + # (e.g., tokenize) // adds British variations + (r"[%s].*[%s](izer)" % (vowels, cons), "izes,ize,izers,ized,izing,izings,ization,izations,ise,ises,iser,isers,ised,ising,isings,isation,isations"), + # (e.g., tokenise) // British variant // ~expertise + (r"[%s].*[%s](iser)" % (vowels, cons), "ize,izes,izer,izers,ized,izing,izings,ization,izations,ises,ise,isers,ised,ising,isings,isation,isations"), + #(e.g., actioner, atoner, icer, trader, accruer, churchgoer, prefer) + (r"[%s].*(er)" % vowels, ",e,s,es,est,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment,ments,less,ful,ement,ements,eless,eful,ers,ered,erred,ering,erring,erings,errings,erly,erness,ernesses,erment,erments,erless,erful,erer,erers,erest,errer,errers,errest"), + + # Words ending in -EST + + # (e.g., sliest, happiest, wittiest) + (r"[%s](iest)" % cons, "y,ies,ier,iers,ied,ying,yings,ily,yly,iness,yness,inesses,ynesses,iment,iments,iless,iful"), + # (e.g., fullest) + (r"[%s].*l(lest)" % vowels, "&,&s,&er,&ers,&ed,&ing,&ings,ly,&ness,&nesses,&ment,&ments,&ful"), + # (e.g., grossest) + (r"[%s].*s(sest)" % vowels, "&,&es,&er,&ers,&ed,&ing,&ings,&ly,&ness,&nesses,&ment,&ments,&less,&ful"), + # (e.g., biggest) + (r"[%s][%s](?P[bdglmnprst])((?P=est1)est)" % (cons, vowels), ",s,&er,&ers,&ed,&ing,&ings,ly,ness,nesses,ment,ments,less,ful"), + # (e.g., basest, archest, rashest) + (r"[%s].*([cs]h|[jsxz])(est)" % vowels, "e,es,er,ers,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment,ments,less,ful,ement,ements,eless,eful,ests,ester,esters,ested,esting,estings,estly,estness,estnesses,estment,estments,estless,estful"), + # (e.g., severest, Xinterest, merest) + (r"er(est)", "e,es,er,ers,ed,eing,eings,ely,eness,enesses,ement,ements,eless,eful,ests,ester,esters,ested,esting,estings,estly,estness,estnesses,estment,estments,estless,estful"), + # (e.g., slickest, coolest, ablest, amplest, protest, quest) + (r"[%s].*(est)" % vowels, ",e,s,es,er,ers,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment,ments,less,ful,ement,ements,eless,eful,ests,ester,esters,ested,esting,estings,estly,estness,estnesses,estment,estments,estless,estful"), + # (e.g., rest, test) + (r"est", "s,er,ers,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful"), + + # Words ending in -FUL + + # (e.g., beautiful, plentiful) + (r"[%s].*[%s](iful)" % (vowels, cons), "ifully,ifulness,*y"), + # (e.g., hopeful, sorrowful) + (r"[%s].*(ful)" % vowels, "fully,fulness,,*"), + + # Words ending in -ICAL + + (r"[%s].*(ical)" % vowels, "ic,ics,ically"), + + # Words ending in -IC + + (r"[%s].*(ic)" % vowels, "ics,ical,ically"), + + # Words ending in -ING + + # (e.g., dying, crying, supplying) + (r"[%s](ying)" % cons, "yings,ie,y,ies,ier,iers,iest,ied,iely,yly,ieness,yness,ienesses,ynesses,iment,iments,iless,iful"), + # (e.g., pulling, filling, fulling) + (r"[%s].*l(ling)" % vowels, ",*,&,&s,&er,&ers,&est,&ed,&ings,&ness,&nesses,&ment,&ments,&ful"), + # (e.g., hissing, grossing, processing) + (r"[%s].*s(sing)" % vowels, "&,&s,&er,&ers,&est,&ed,&ings,&ly,&ness,&nesses,&ment,&ments,&less,&ful"), + # (e.g., hugging, trekking) + (r"[%s][%s](?P[bdgklmnprt])((?P=ing1)ing)" % (cons, vowels), ",s,&er,&ers,&est,&ed,&ings,ly,ness,nesses,ment,ments,less,ful"), + # (e.g., freeing, agreeing) + (r"eeing()", "ee,ees,eer,eers,eest,eed,eeings,eely,eeness,eenesses,eement,eements,eeless,eeful"), + # (e.g., ageing, aweing) + (r"[%s].*(eing)" % vowels, "e,es,er,ers,est,ed,eings,ely,eness,enesses,ement,ements,eless,eful"), + # (e.g., toying, playing) + (r"[%s].*y(ing)" % vowels, ",s,er,ers,est,ed,ings,ly,ingly,ness,nesses,ment,ments,less,ful"), + # (e.g., editing, crediting, expediting, siting, exciting) + (r"[%s].*[%s][eio]t(ing)" % (vowels, cons), ",*,*e,ings,inger,ingers,ingest,inged,inging,ingings,ingly,ingness,ingnesses,ingment,ingments,ingless,ingful"), + # (e.g., robing, siding, doling, translating, flaking) + (r"[%s][%s][bdgklmt](ing)" % (cons, vowels), "*e,ings,inger,ingers,ingest,inged,ingly,ingness,ingnesses,ingment,ingments,ingless,ingful"), + # (e.g., tokenize) // adds British variations + (r"[%s].*[%s](izing)" % (vowels, cons), "izes,izer,izers,ized,ize,izings,ization,izations,ise,ises,iser,isers,ised,ising,isings,isation,isations"), + # (e.g., tokenise) // British variant // ~expertise + (r"[%s].*[%s](ising)" % (vowels, cons), "ize,izes,izer,izers,ized,izing,izings,ization,izations,ises,iser,isers,ised,ise,isings,isation,isations"), + # (e.g., icing, aging, achieving, amazing, housing) + (r"[%s][cgsvz](ing)" % vowels, "*e,ings,inger,ingers,ingest,inged,inging,ingings,ingly,ingness,ingnesses,ingment,ingments,ingless,ingful"), + # (e.g., dancing, troubling, arguing, bluing, carving) + (r"[%s][clsuv](ing)" % cons, "*e,ings,inger,ingers,ingest,inged,inging,ingings,ingly,ingness,ingnesses,ingment,ingments,ingless,ingful"), + # (e.g., charging, bulging) + (r"[%s].*[lr]g(ing)" % vowels, "*e,ings,inger,ingers,ingest,inged,inging,ingings,ingly,ingness,ingnesses,ingment,ingments,ingless,ingful"), + # (e.g., farming, harping, interesting, bedspring, redwing) + (r"[%s].*[%s][bdfjkmnpqrtwxz](ing)" % (vowels, cons), ",*,ings,inger,ingers,ingest,inged,inging,ingings,ingly,ingness,ingnesses,ingment,ingments,ingless,ingful"), + # (e.g., spoiling, reviling, autoing, egging, hanging, hingeing) + (r"[%s].*(ing)" % vowels, ",*,*e,ings,inger,ingers,ingest,inged,inging,ingings,ingly,ingness,ingnesses,ingment,ingments,ingless,ingful"), + # (e.g., wing, thing) monosyllables + (r"(ing)", "ings,inger,ingers,ingest,inged,inging,ingings,ingly,ingness,ingnesses,ingment,ingments,ingless,ingful"), + + # -LEAF rules omitted + + # Words ending in -MAN + # (e.g., policewomen, hatchetmen, dolmen) + (r"(man)", "man,mens,mener,meners,menest,mened,mening,menings,menly,menness,mennesses,menless,menful"), + + # Words ending in -MENT + + # (e.g., segment, bisegment, cosegment, pigment, depigment, repigment) + (r"segment|pigment", "s,ed,ing,ings,er,ers,ly,ness,nesses,less,ful"), + # (e.g., judgment, abridgment) + (r"[%s].*dg(ment)" % vowels, "*e"), + # (e.g., merriment, embodiment) + (r"[%s].*[%s](iment)" % (vowels, cons), "*y"), + # (e.g., atonement, entrapment) + (r"[%s].*[%s](ment)" % (vowels, cons), ",*"), + + # Words ending in -O + + # (e.g., taboo, rodeo) + (r"[%s]o()" % vowels, "s,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful"), + # (e.g., tomato, bonito) + (r"[%s].*o()" % vowels, "s,es,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful"), + + # Words ending in -UM + + # (e.g., datum, quantum, tedium, strum, [oil]drum, vacuum) + (r"[%s].*(um)" % vowels, "a,ums,umer,ummer,umers,ummers,umed,ummed,uming,umming,umings,ummings,umness,umments,umless,umful"), + + # Words ending in -Y + + # (e.g., ably, horribly, wobbly) + (r"[%s].*b(ly)" % vowels, "le,les,ler,lers,lest,led,ling,lings,leness,lenesses,lement,lements,leless,leful"), + # (e.g., happily, dizzily) + (r"[%s].*[%s](ily)" % (vowels, cons), "y,ies,ier,iers,iest,ied,ying,yings,yness,iness,ynesses,inesses,iment,iments,iless,iful"), + # (e.g., peaceful+ly) + (r"[%s].*ful(ly)" % vowels, ",*"), + # (e.g., fully, folly, coolly, fatally, dally) + (r"[%s].*l(ly)" % vowels, ",*,lies,lier,liers,liest,lied,lying,lyings,liness,linesses,liment,liments,liless,liful,*l"), + # (e.g., monopoly, Xcephaly, holy) + (r"[%s](ly)" % vowels, "lies,lier,liers,liest,lied,lying,lyings,liness,linesses,liment,liments,liless,liful"), + # (e.g., frequently, comely, deeply, apply, badly) + (r"[%s].*(ly)" % vowels, ",*,lies,lier,liers,liest,lied,lying,lyings,liness,linesses,lyless,lyful"), + # (e.g., happy, ply, spy, cry) + (r"[%s](y)" % cons, "ies,ier,iers,iest,ied,ying,yings,ily,yness,iness,ynesses,inesses,iment,iments,iless,iful,yment,yments,yless,yful"), + # (e.g., betray, gay, stay) + (r"[%s]y()" % vowels, "s,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful"), + + # Root rules + + # (e.g., fix, arch, rash) + (r"[%s].*(ch|sh|[jxz])()" % vowels, "es,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful"), + # (e.g., unflag, open, besot) + (r"[%s].*[%s][%s][bdglmnprt]()" % (vowels, cons, vowels), "s,er,ers,est,ed,ing,ings,&er,&ers,&est,&ed,&ing,&ings,ly,ness,nesses,ment,ments,less,ful"), + # (e.g., bed, cop) + (r"[%s][%s][bdglmnprt]()" % (cons, vowels), "s,&er,&ers,&est,&ed,&ing,&ings,ly,ness,nesses,ment,ments,less,ful"), + # (e.g., schemata, automata) + (r"[%s].*[%s][%s]ma(ta)" % (vowels, cons, vowels), ",s,tas,tum,tums,ton,tons,tic,tical"), + # (e.g., chordata, data, errata, sonata, toccata) + (r"[%s].*t(a)" % vowels, "as,ae,um,ums,on,ons,ic,ical"), + # (e.g., polka, spa, schema, ova, polyhedra) + (r"[%s].*[%s](a)" % (vowels, cons), "as,aed,aing,ae,ata,um,ums,on,ons,al,atic,atical"), + # (e.g., full) + (r"[%s].*ll()" % vowels, "s,er,ers,est,ed,ing,ings,y,ness,nesses,ment,ments,-less,ful"), + # (e.g., spoon, rhythm) + (r"[%s].*()", "s,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful"), + ) + +# There are a limited number of named groups available in a single +# regular expression, so we'll partition the list of rules into +# smaller chunks. + +_partition_size = 20 +_partitions = [] +for p in xrange(0, len(rules) // _partition_size + 1): + start = p * _partition_size + end = (p + 1) * _partition_size + pattern = "|".join("(?P<_g%s>%s)$" % (i, r[0]) + for i, r in enumerate(rules[start:end])) + _partitions.append(re.compile(pattern)) + + +def variations(word): + """Given an English word, returns a collection of morphological variations + on the word by algorithmically adding and removing suffixes. The variation + list may contain non-words (e.g. render -> renderment). + + >>> variations("pull") + set(['pull', 'pullings', 'pullnesses', 'pullful', 'pullment', 'puller', ... ]) + """ + + if word in _exdict: + return _exdict[word].split(" ") + + for i, p in enumerate(_partitions): + match = p.search(word) + if match: + # Get the named group that matched + num = int([k for k, v in iteritems(match.groupdict()) + if v is not None and k.startswith("_g")][0][2:]) + # Get the positional groups for the matched group (all other + # positional groups are None) + groups = [g for g in match.groups() if g is not None] + ending = groups[-1] + root = word[:0 - len(ending)] if ending else word + + out = set((word,)) + results = rules[i * _partition_size + num][1] + for result in results.split(","): + if result.startswith("&"): + out.add(root + root[-1] + result[1:]) + elif result.startswith("*"): + out.union(variations(root + result[1:])) + else: + out.add(root + result) + return set(out) + + return [word] diff --git a/nstock/modules/whoosh/lang/paicehusk.py b/nstock/modules/whoosh/lang/paicehusk.py new file mode 100644 index 0000000..481c3e4 --- /dev/null +++ b/nstock/modules/whoosh/lang/paicehusk.py @@ -0,0 +1,242 @@ +"""This module contains an object that implements the Paice-Husk stemming +algorithm. + +If you just want to use the standard Paice-Husk stemming rules, use the +module's ``stem()`` function:: + + stemmed_word = stem(word) + +If you want to use a custom rule set, read the rules into a string where the +rules are separated by newlines, and instantiate the object with the string, +then use the object's stem method to stem words:: + + stemmer = PaiceHuskStemmer(my_rules_string) + stemmed_word = stemmer.stem(word) +""" + +import re +from collections import defaultdict + + +class PaiceHuskStemmer(object): + """Implements the Paice-Husk stemming algorithm. + """ + + rule_expr = re.compile(r""" + ^(?P\w+) + (?P[*]?) + (?P\d+) + (?P\w*) + (?P[.>]) + """, re.UNICODE | re.VERBOSE) + + stem_expr = re.compile("^\w+", re.UNICODE) + + def __init__(self, ruletable): + """ + :param ruletable: a string containing the rule data, separated + by newlines. + """ + self.rules = defaultdict(list) + self.read_rules(ruletable) + + def read_rules(self, ruletable): + rule_expr = self.rule_expr + rules = self.rules + + for line in ruletable.split("\n"): + line = line.strip() + if not line: + continue + + match = rule_expr.match(line) + if match: + ending = match.group("ending")[::-1] + lastchar = ending[-1] + intact = match.group("intact") == "*" + num = int(match.group("num")) + append = match.group("append") + cont = match.group("cont") == ">" + + rules[lastchar].append((ending, intact, num, append, cont)) + else: + raise Exception("Bad rule: %r" % line) + + def first_vowel(self, word): + vp = min([p for p in [word.find(v) for v in "aeiou"] + if p > -1]) + yp = word.find("y") + if yp > 0 and yp < vp: + return yp + return vp + + def strip_prefix(self, word): + for prefix in ("kilo", "micro", "milli", "intra", "ultra", "mega", + "nano", "pico", "pseudo"): + if word.startswith(prefix): + return word[len(prefix):] + return word + + def stem(self, word): + """Returns a stemmed version of the argument string. + """ + + rules = self.rules + match = self.stem_expr.match(word) + if not match: + return word + stem = self.strip_prefix(match.group(0)) + + is_intact = True + continuing = True + while continuing: + pfv = self.first_vowel(stem) + rulelist = rules.get(stem[-1]) + if not rulelist: + break + + continuing = False + for ending, intact, num, append, cont in rulelist: + if stem.endswith(ending): + if intact and not is_intact: + continue + newlen = len(stem) - num + len(append) + + if ((pfv == 0 and newlen < 2) + or (pfv > 0 and newlen < 3)): + # If word starts with vowel, minimum stem length is 2. + # If word starts with consonant, minimum stem length is + # 3. + continue + + is_intact = False + stem = stem[:0 - num] + append + + continuing = cont + break + + return stem + +# The default rules for the Paice-Husk stemming algorithm + +defaultrules = """ +ai*2. { -ia > - if intact } +a*1. { -a > - if intact } +bb1. { -bb > -b } +city3s. { -ytic > -ys } +ci2> { -ic > - } +cn1t> { -nc > -nt } +dd1. { -dd > -d } +dei3y> { -ied > -y } +deec2ss. { -ceed > -cess } +dee1. { -eed > -ee } +de2> { -ed > - } +dooh4> { -hood > - } +e1> { -e > - } +feil1v. { -lief > -liev } +fi2> { -if > - } +gni3> { -ing > - } +gai3y. { -iag > -y } +ga2> { -ag > - } +gg1. { -gg > -g } +ht*2. { -th > - if intact } +hsiug5ct. { -guish > -ct } +hsi3> { -ish > - } +i*1. { -i > - if intact } +i1y> { -i > -y } +ji1d. { -ij > -id -- see nois4j> & vis3j> } +juf1s. { -fuj > -fus } +ju1d. { -uj > -ud } +jo1d. { -oj > -od } +jeh1r. { -hej > -her } +jrev1t. { -verj > -vert } +jsim2t. { -misj > -mit } +jn1d. { -nj > -nd } +j1s. { -j > -s } +lbaifi6. { -ifiabl > - } +lbai4y. { -iabl > -y } +lba3> { -abl > - } +lbi3. { -ibl > - } +lib2l> { -bil > -bl } +lc1. { -cl > c } +lufi4y. { -iful > -y } +luf3> { -ful > - } +lu2. { -ul > - } +lai3> { -ial > - } +lau3> { -ual > - } +la2> { -al > - } +ll1. { -ll > -l } +mui3. { -ium > - } +mu*2. { -um > - if intact } +msi3> { -ism > - } +mm1. { -mm > -m } +nois4j> { -sion > -j } +noix4ct. { -xion > -ct } +noi3> { -ion > - } +nai3> { -ian > - } +na2> { -an > - } +nee0. { protect -een } +ne2> { -en > - } +nn1. { -nn > -n } +pihs4> { -ship > - } +pp1. { -pp > -p } +re2> { -er > - } +rae0. { protect -ear } +ra2. { -ar > - } +ro2> { -or > - } +ru2> { -ur > - } +rr1. { -rr > -r } +rt1> { -tr > -t } +rei3y> { -ier > -y } +sei3y> { -ies > -y } +sis2. { -sis > -s } +si2> { -is > - } +ssen4> { -ness > - } +ss0. { protect -ss } +suo3> { -ous > - } +su*2. { -us > - if intact } +s*1> { -s > - if intact } +s0. { -s > -s } +tacilp4y. { -plicat > -ply } +ta2> { -at > - } +tnem4> { -ment > - } +tne3> { -ent > - } +tna3> { -ant > - } +tpir2b. { -ript > -rib } +tpro2b. { -orpt > -orb } +tcud1. { -duct > -duc } +tpmus2. { -sumpt > -sum } +tpec2iv. { -cept > -ceiv } +tulo2v. { -olut > -olv } +tsis0. { protect -sist } +tsi3> { -ist > - } +tt1. { -tt > -t } +uqi3. { -iqu > - } +ugo1. { -ogu > -og } +vis3j> { -siv > -j } +vie0. { protect -eiv } +vi2> { -iv > - } +ylb1> { -bly > -bl } +yli3y> { -ily > -y } +ylp0. { protect -ply } +yl2> { -ly > - } +ygo1. { -ogy > -og } +yhp1. { -phy > -ph } +ymo1. { -omy > -om } +ypo1. { -opy > -op } +yti3> { -ity > - } +yte3> { -ety > - } +ytl2. { -lty > -l } +yrtsi5. { -istry > - } +yra3> { -ary > - } +yro3> { -ory > - } +yfi3. { -ify > - } +ycn2t> { -ncy > -nt } +yca3> { -acy > - } +zi2> { -iz > - } +zy1s. { -yz > -ys } +""" + +# Make the standard rules available as a module-level function + +stem = PaiceHuskStemmer(defaultrules).stem diff --git a/nstock/modules/whoosh/lang/phonetic.py b/nstock/modules/whoosh/lang/phonetic.py new file mode 100644 index 0000000..1cee86a --- /dev/null +++ b/nstock/modules/whoosh/lang/phonetic.py @@ -0,0 +1,119 @@ +#encoding: utf-8 + +""" +This module contains quasi-phonetic encoders for words in different languages. +""" + +import re + +from whoosh.compat import iteritems + +# This soundex implementation is adapted from the recipe here: +# http://code.activestate.com/recipes/52213/ + +english_codes = '01230120022455012623010202' + + +def soundex_en(word): + # digits holds the soundex values for the alphabet + r = "" + if word: + # Remember first character + fc = None + prevcode = None + for char in word.lower(): + c = ord(char) + if c >= 97 and c <= 122: # a-z + if not fc: + fc = char + code = english_codes[c - 97] + # Don't append the code if it's the same as the previous + if code != prevcode: + r += code + prevcode = code + + # Replace first digit with first alpha character + r = fc + r[1:] + + return r + + +# Quasi-phonetic coder for Spanish, translated to Python from Sebastian +# Ferreyra's version here: +# http://www.javalobby.org/java/forums/t16936.html + +_esp_codes = (("\\Aw?[uh]?([aeiou])", ""), + ("c[eiéí]|z|ll|sh|ch|sch|cc|y[aeiouáéíóú]|ps|bs|x|j|g[eiéí]", "s"), + ("[aeiouhwáéíóúü]+", ""), + ("y", ""), + ("ñ|gn", "n"), + ("[dpc]t", "t"), + ("c[aouáóú]|ck|q", "k"), + ("v", "b"), + ("d$", "t"), # Change a trailing d to a t + ) +_esp_codes = tuple((re.compile(pat), repl) for pat, repl in _esp_codes) + + +def soundex_esp(word): + word = word.lower() + r = "" + + prevcode = None + i = 0 + while i < len(word): + code = None + for expr, ecode in _esp_codes: + match = expr.match(word, i) + if match: + i = match.end() + code = ecode + break + + if code is None: + code = word[i] + i += 1 + + if code != prevcode: + r += code + prevcode = code + + return r + + +# This version of soundex for Arabic is translated to Python from Tammam +# Koujan's C# version here: +# http://www.codeproject.com/KB/recipes/ArabicSoundex.aspx + +# Create a dictionary mapping arabic characters to digits +_arabic_codes = {} +for chars, code in iteritems({'\u0627\u0623\u0625\u0622\u062d\u062e\u0647\u0639\u063a\u0634\u0648\u064a': "0", + '\u0641\u0628': "1", + '\u062c\u0632\u0633\u0635\u0638\u0642\u0643': "2", + '\u062a\u062b\u062f\u0630\u0636\u0637': "3", + '\u0644': "4", + '\u0645\u0646': "5", + '\u0631': "6", + }): + for char in chars: + _arabic_codes[char] = code + + +def soundex_ar(word): + if word[0] in "\u0627\u0623\u0625\u0622": + word = word[1:] + + r = "0" + prevcode = "0" + if len(word) > 1: + # Discard the first character + for char in word[1:]: + if char in _arabic_codes: + code = _arabic_codes.get(char, "0") + # Don't append the code if it's the same as the previous + if code != prevcode: + # If the code is a 0 (vowel), don't process it + if code != "0": + r += code + prevcode = code + return r diff --git a/nstock/modules/whoosh/lang/porter.py b/nstock/modules/whoosh/lang/porter.py new file mode 100755 index 0000000..65d169a --- /dev/null +++ b/nstock/modules/whoosh/lang/porter.py @@ -0,0 +1,175 @@ +""" +Reimplementation of the +`Porter stemming algorithm `_ +in Python. + +In my quick tests, this implementation about 3.5 times faster than the +seriously weird Python linked from the official page. +""" + +import re + +# Suffix replacement lists + +_step2list = { + "ational": "ate", + "tional": "tion", + "enci": "ence", + "anci": "ance", + "izer": "ize", + "bli": "ble", + "alli": "al", + "entli": "ent", + "eli": "e", + "ousli": "ous", + "ization": "ize", + "ation": "ate", + "ator": "ate", + "alism": "al", + "iveness": "ive", + "fulness": "ful", + "ousness": "ous", + "aliti": "al", + "iviti": "ive", + "biliti": "ble", + "logi": "log", + } + +_step3list = { + "icate": "ic", + "ative": "", + "alize": "al", + "iciti": "ic", + "ical": "ic", + "ful": "", + "ness": "", + } + + +_cons = "[^aeiou]" +_vowel = "[aeiouy]" +_cons_seq = "[^aeiouy]+" +_vowel_seq = "[aeiou]+" + +# m > 0 +_mgr0 = re.compile("^(" + _cons_seq + ")?" + _vowel_seq + _cons_seq) +# m == 0 +_meq1 = re.compile("^(" + _cons_seq + ")?" + _vowel_seq + _cons_seq + "(" + _vowel_seq + ")?$") +# m > 1 +_mgr1 = re.compile("^(" + _cons_seq + ")?" + _vowel_seq + _cons_seq + _vowel_seq + _cons_seq) +# vowel in stem +_s_v = re.compile("^(" + _cons_seq + ")?" + _vowel) +# ??? +_c_v = re.compile("^" + _cons_seq + _vowel + "[^aeiouwxy]$") + +# Patterns used in the rules + +_ed_ing = re.compile("^(.*)(ed|ing)$") +_at_bl_iz = re.compile("(at|bl|iz)$") +_step1b = re.compile("([^aeiouylsz])\\1$") +_step2 = re.compile("^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$") +_step3 = re.compile("^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$") +_step4_1 = re.compile("^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$") +_step4_2 = re.compile("^(.+?)(s|t)(ion)$") +_step5 = re.compile("^(.+?)e$") + + +# Stemming function + +def stem(w): + """Uses the Porter stemming algorithm to remove suffixes from English + words. + + >>> stem("fundamentally") + "fundament" + """ + + if len(w) < 3: + return w + + first_is_y = w[0] == "y" + if first_is_y: + w = "Y" + w[1:] + + # Step 1a + if w.endswith("s"): + if w.endswith("sses"): + w = w[:-2] + elif w.endswith("ies"): + w = w[:-2] + elif w[-2] != "s": + w = w[:-1] + + # Step 1b + + if w.endswith("eed"): + s = w[:-3] + if _mgr0.match(s): + w = w[:-1] + else: + m = _ed_ing.match(w) + if m: + stem = m.group(1) + if _s_v.match(stem): + w = stem + if _at_bl_iz.match(w): + w += "e" + elif _step1b.match(w): + w = w[:-1] + elif _c_v.match(w): + w += "e" + + # Step 1c + + if w.endswith("y"): + stem = w[:-1] + if _s_v.match(stem): + w = stem + "i" + + # Step 2 + + m = _step2.match(w) + if m: + stem = m.group(1) + suffix = m.group(2) + if _mgr0.match(stem): + w = stem + _step2list[suffix] + + # Step 3 + + m = _step3.match(w) + if m: + stem = m.group(1) + suffix = m.group(2) + if _mgr0.match(stem): + w = stem + _step3list[suffix] + + # Step 4 + + m = _step4_1.match(w) + if m: + stem = m.group(1) + if _mgr1.match(stem): + w = stem + else: + m = _step4_2.match(w) + if m: + stem = m.group(1) + m.group(2) + if _mgr1.match(stem): + w = stem + + # Step 5 + + m = _step5.match(w) + if m: + stem = m.group(1) + if _mgr1.match(stem) or (_meq1.match(stem) and not _c_v.match(stem)): + w = stem + + if w.endswith("ll") and _mgr1.match(w): + w = w[:-1] + + if first_is_y: + w = "y" + w[1:] + + return w diff --git a/nstock/modules/whoosh/lang/porter2.py b/nstock/modules/whoosh/lang/porter2.py new file mode 100644 index 0000000..4c74047 --- /dev/null +++ b/nstock/modules/whoosh/lang/porter2.py @@ -0,0 +1,313 @@ +"""An implementation of the Porter2 stemming algorithm. +See http://snowball.tartarus.org/algorithms/english/stemmer.html + +Adapted from pyporter2 by Michael Dirolf. + +This algorithm is more correct but (at least in this implementation) +several times slower than the original porter algorithm as implemented +in stemming.porter. +""" + +import re + +r_exp = re.compile(r"[^aeiouy]*[aeiouy]+[^aeiouy](\w*)") +ewss_exp1 = re.compile(r"^[aeiouy][^aeiouy]$") +ewss_exp2 = re.compile(r".*[^aeiouy][aeiouy][^aeiouywxY]$") +ccy_exp = re.compile(r"([aeiouy])y") +s1a_exp = re.compile(r"[aeiouy].") +s1b_exp = re.compile(r"[aeiouy]") + + +def get_r1(word): + # exceptional forms + if word.startswith('gener') or word.startswith('arsen'): + return 5 + if word.startswith('commun'): + return 6 + + # normal form + match = r_exp.match(word) + if match: + return match.start(1) + return len(word) + + +def get_r2(word): + match = r_exp.match(word, get_r1(word)) + if match: + return match.start(1) + return len(word) + + +def ends_with_short_syllable(word): + if len(word) == 2: + if ewss_exp1.match(word): + return True + if ewss_exp2.match(word): + return True + return False + + +def is_short_word(word): + if ends_with_short_syllable(word): + if get_r1(word) == len(word): + return True + return False + + +def remove_initial_apostrophe(word): + if word.startswith("'"): + return word[1:] + return word + + +def capitalize_consonant_ys(word): + if word.startswith('y'): + word = 'Y' + word[1:] + return ccy_exp.sub('\g<1>Y', word) + + +def step_0(word): + if word.endswith("'s'"): + return word[:-3] + if word.endswith("'s"): + return word[:-2] + if word.endswith("'"): + return word[:-1] + return word + + +def step_1a(word): + if word.endswith('sses'): + return word[:-4] + 'ss' + if word.endswith('ied') or word.endswith('ies'): + if len(word) > 4: + return word[:-3] + 'i' + else: + return word[:-3] + 'ie' + if word.endswith('us') or word.endswith('ss'): + return word + if word.endswith('s'): + preceding = word[:-1] + if s1a_exp.search(preceding): + return preceding + return word + return word + + +doubles = ('bb', 'dd', 'ff', 'gg', 'mm', 'nn', 'pp', 'rr', 'tt') + + +def ends_with_double(word): + for double in doubles: + if word.endswith(double): + return True + return False + + +def step_1b_helper(word): + if word.endswith('at') or word.endswith('bl') or word.endswith('iz'): + return word + 'e' + if ends_with_double(word): + return word[:-1] + if is_short_word(word): + return word + 'e' + return word + + +s1b_suffixes = ('ed', 'edly', 'ing', 'ingly') + + +def step_1b(word, r1): + if word.endswith('eedly'): + if len(word) - 5 >= r1: + return word[:-3] + return word + if word.endswith('eed'): + if len(word) - 3 >= r1: + return word[:-1] + return word + + for suffix in s1b_suffixes: + if word.endswith(suffix): + preceding = word[:-len(suffix)] + if s1b_exp.search(preceding): + return step_1b_helper(preceding) + return word + + return word + + +def step_1c(word): + if word.endswith('y') or word.endswith('Y') and len(word) > 1: + if word[-2] not in 'aeiouy': + if len(word) > 2: + return word[:-1] + 'i' + return word + + +def step_2_helper(word, r1, end, repl, prev): + if word.endswith(end): + if len(word) - len(end) >= r1: + if prev == []: + return word[:-len(end)] + repl + for p in prev: + if word[:-len(end)].endswith(p): + return word[:-len(end)] + repl + return word + return None + + +s2_triples = (('ization', 'ize', []), + ('ational', 'ate', []), + ('fulness', 'ful', []), + ('ousness', 'ous', []), + ('iveness', 'ive', []), + ('tional', 'tion', []), + ('biliti', 'ble', []), + ('lessli', 'less', []), + ('entli', 'ent', []), + ('ation', 'ate', []), + ('alism', 'al', []), + ('aliti', 'al', []), + ('ousli', 'ous', []), + ('iviti', 'ive', []), + ('fulli', 'ful', []), + ('enci', 'ence', []), + ('anci', 'ance', []), + ('abli', 'able', []), + ('izer', 'ize', []), + ('ator', 'ate', []), + ('alli', 'al', []), + ('bli', 'ble', []), + ('ogi', 'og', ['l']), + ('li', '', ['c', 'd', 'e', 'g', 'h', 'k', 'm', 'n', 'r', 't'])) + + +def step_2(word, r1): + for trip in s2_triples: + attempt = step_2_helper(word, r1, trip[0], trip[1], trip[2]) + if attempt: + return attempt + return word + + +def step_3_helper(word, r1, r2, end, repl, r2_necessary): + if word.endswith(end): + if len(word) - len(end) >= r1: + if not r2_necessary: + return word[:-len(end)] + repl + else: + if len(word) - len(end) >= r2: + return word[:-len(end)] + repl + return word + return None + + +s3_triples = (('ational', 'ate', False), + ('tional', 'tion', False), + ('alize', 'al', False), + ('icate', 'ic', False), + ('iciti', 'ic', False), + ('ative', '', True), + ('ical', 'ic', False), + ('ness', '', False), + ('ful', '', False)) + + +def step_3(word, r1, r2): + for trip in s3_triples: + attempt = step_3_helper(word, r1, r2, trip[0], trip[1], trip[2]) + if attempt: + return attempt + return word + + +s4_delete_list = ('al', 'ance', 'ence', 'er', 'ic', 'able', 'ible', 'ant', 'ement', + 'ment', 'ent', 'ism', 'ate', 'iti', 'ous', 'ive', 'ize') + + +def step_4(word, r2): + for end in s4_delete_list: + if word.endswith(end): + if len(word) - len(end) >= r2: + return word[:-len(end)] + return word + + if word.endswith('sion') or word.endswith('tion'): + if len(word) - 3 >= r2: + return word[:-3] + + return word + + +def step_5(word, r1, r2): + if word.endswith('l'): + if len(word) - 1 >= r2 and word[-2] == 'l': + return word[:-1] + return word + + if word.endswith('e'): + if len(word) - 1 >= r2: + return word[:-1] + if len(word) - 1 >= r1 and not ends_with_short_syllable(word[:-1]): + return word[:-1] + + return word + + +def normalize_ys(word): + return word.replace('Y', 'y') + + +exceptional_forms = {'skis': 'ski', + 'skies': 'sky', + 'dying': 'die', + 'lying': 'lie', + 'tying': 'tie', + 'idly': 'idl', + 'gently': 'gentl', + 'ugly': 'ugli', + 'early': 'earli', + 'only': 'onli', + 'singly': 'singl', + 'sky': 'sky', + 'news': 'news', + 'howe': 'howe', + 'atlas': 'atlas', + 'cosmos': 'cosmos', + 'bias': 'bias', + 'andes': 'andes'} + +exceptional_early_exit_post_1a = frozenset(['inning', 'outing', 'canning', 'herring', + 'earring', 'proceed', 'exceed', 'succeed']) + + +def stem(word): + if len(word) <= 2: + return word + word = remove_initial_apostrophe(word) + + # handle some exceptional forms + if word in exceptional_forms: + return exceptional_forms[word] + + word = capitalize_consonant_ys(word) + r1 = get_r1(word) + r2 = get_r2(word) + word = step_0(word) + word = step_1a(word) + + # handle some more exceptional forms + if word in exceptional_early_exit_post_1a: + return word + + word = step_1b(word, r1) + word = step_1c(word) + word = step_2(word, r1) + word = step_3(word, r1, r2) + word = step_4(word, r2) + word = step_5(word, r1, r2) + word = normalize_ys(word) + + return word diff --git a/nstock/modules/whoosh/lang/snowball/__init__.py b/nstock/modules/whoosh/lang/snowball/__init__.py new file mode 100644 index 0000000..d450288 --- /dev/null +++ b/nstock/modules/whoosh/lang/snowball/__init__.py @@ -0,0 +1,74 @@ +# Copyright (C) 2001-2012 NLTK Project +# +# Licensed under the Apache License, Version 2.0 (the 'License'); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an 'AS IS' BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Natural Language Toolkit: Snowball Stemmer +# +# Copyright (C) 2001-2012 NLTK Project +# Author: Peter Michael Stahl +# Peter Ljunglof (revisions) +# Algorithms: Dr Martin Porter +# URL: +# For license information, see LICENSE.TXT + +# HJ 2012/07/19 adapted from https://github.com/kmike/nltk.git (branch 2and3) +# 2.0.1rc4-256-g45768f8 + +""" +This module provides a port of the Snowball stemmers developed by Martin +Porter. + +At the moment, this port is able to stem words from fourteen languages: Danish, +Dutch, English, Finnish, French, German, Hungarian, Italian, Norwegian, +Portuguese, Romanian, Russian, Spanish and Swedish. + +The algorithms have been developed by Martin Porter. These stemmers are called +Snowball, because he invented a programming language with this name for +creating new stemming algorithms. There is more information available at +http://snowball.tartarus.org/ +""" + +from .danish import DanishStemmer +from .dutch import DutchStemmer +from .english import EnglishStemmer +from .finnish import FinnishStemmer +from .french import FrenchStemmer +from .german import GermanStemmer +from .hungarian import HungarianStemmer +from .italian import ItalianStemmer +from .norwegian import NorwegianStemmer +from .portugese import PortugueseStemmer +from .romanian import RomanianStemmer +from .russian import RussianStemmer +from .spanish import SpanishStemmer +from .swedish import SwedishStemmer + + +# Map two-letter codes to stemming classes + +classes = {"da": DanishStemmer, + "nl": DutchStemmer, + "en": EnglishStemmer, + "fi": FinnishStemmer, + "fr": FrenchStemmer, + "de": GermanStemmer, + "hu": HungarianStemmer, + "it": ItalianStemmer, + "no": NorwegianStemmer, + "pt": PortugueseStemmer, + "ro": RomanianStemmer, + "ru": RussianStemmer, + "es": SpanishStemmer, + "sv": SwedishStemmer, + } diff --git a/nstock/modules/whoosh/lang/snowball/bases.py b/nstock/modules/whoosh/lang/snowball/bases.py new file mode 100644 index 0000000..0602385 --- /dev/null +++ b/nstock/modules/whoosh/lang/snowball/bases.py @@ -0,0 +1,133 @@ +# Base classes + + +class _ScandinavianStemmer(object): + + """ + This subclass encapsulates a method for defining the string region R1. + It is used by the Danish, Norwegian, and Swedish stemmer. + + """ + + def _r1_scandinavian(self, word, vowels): + """ + Return the region R1 that is used by the Scandinavian stemmers. + + R1 is the region after the first non-vowel following a vowel, + or is the null region at the end of the word if there is no + such non-vowel. But then R1 is adjusted so that the region + before it contains at least three letters. + + :param word: The word whose region R1 is determined. + :type word: str or unicode + :param vowels: The vowels of the respective language that are + used to determine the region R1. + :type vowels: unicode + :return: the region R1 for the respective word. + :rtype: unicode + :note: This helper method is invoked by the respective stem method of + the subclasses DanishStemmer, NorwegianStemmer, and + SwedishStemmer. It is not to be invoked directly! + + """ + r1 = "" + for i in range(1, len(word)): + if word[i] not in vowels and word[i - 1] in vowels: + if len(word[:i + 1]) < 3 and len(word[:i + 1]) > 0: + r1 = word[3:] + elif len(word[:i + 1]) >= 3: + r1 = word[i + 1:] + else: + return word + break + + return r1 + + +class _StandardStemmer(object): + """ + This subclass encapsulates two methods for defining the standard versions + of the string regions R1, R2, and RV. + """ + + def _r1r2_standard(self, word, vowels): + """ + Return the standard interpretations of the string regions R1 and R2. + + R1 is the region after the first non-vowel following a vowel, + or is the null region at the end of the word if there is no + such non-vowel. + + R2 is the region after the first non-vowel following a vowel + in R1, or is the null region at the end of the word if there + is no such non-vowel. + + :param word: The word whose regions R1 and R2 are determined. + :type word: str or unicode + :param vowels: The vowels of the respective language that are + used to determine the regions R1 and R2. + :type vowels: unicode + :return: (r1,r2), the regions R1 and R2 for the respective word. + :rtype: tuple + :note: This helper method is invoked by the respective stem method of + the subclasses DutchStemmer, FinnishStemmer, + FrenchStemmer, GermanStemmer, ItalianStemmer, + PortugueseStemmer, RomanianStemmer, and SpanishStemmer. + It is not to be invoked directly! + :note: A detailed description of how to define R1 and R2 + can be found at http://snowball.tartarus.org/texts/r1r2.html + + """ + r1 = "" + r2 = "" + for i in range(1, len(word)): + if word[i] not in vowels and word[i - 1] in vowels: + r1 = word[i + 1:] + break + + for i in range(1, len(r1)): + if r1[i] not in vowels and r1[i - 1] in vowels: + r2 = r1[i + 1:] + break + + return (r1, r2) + + def _rv_standard(self, word, vowels): + """ + Return the standard interpretation of the string region RV. + + If the second letter is a consonant, RV is the region after the + next following vowel. If the first two letters are vowels, RV is + the region after the next following consonant. Otherwise, RV is + the region after the third letter. + + :param word: The word whose region RV is determined. + :type word: str or unicode + :param vowels: The vowels of the respective language that are + used to determine the region RV. + :type vowels: unicode + :return: the region RV for the respective word. + :rtype: unicode + :note: This helper method is invoked by the respective stem method of + the subclasses ItalianStemmer, PortugueseStemmer, + RomanianStemmer, and SpanishStemmer. It is not to be + invoked directly! + + """ + rv = "" + if len(word) >= 2: + if word[1] not in vowels: + for i in range(2, len(word)): + if word[i] in vowels: + rv = word[i + 1:] + break + + elif word[:2] in vowels: + for i in range(2, len(word)): + if word[i] not in vowels: + rv = word[i + 1:] + break + else: + rv = word[3:] + + return rv diff --git a/nstock/modules/whoosh/lang/snowball/danish.py b/nstock/modules/whoosh/lang/snowball/danish.py new file mode 100644 index 0000000..759a1bf --- /dev/null +++ b/nstock/modules/whoosh/lang/snowball/danish.py @@ -0,0 +1,115 @@ +from .bases import _ScandinavianStemmer + +from whoosh.compat import u + + +class DanishStemmer(_ScandinavianStemmer): + """ + The Danish Snowball stemmer. + + :cvar __vowels: The Danish vowels. + :type __vowels: unicode + :cvar __consonants: The Danish consonants. + :type __consonants: unicode + :cvar __double_consonants: The Danish double consonants. + :type __double_consonants: tuple + :cvar __s_ending: Letters that may directly appear before a word final 's'. + :type __s_ending: unicode + :cvar __step1_suffixes: Suffixes to be deleted in step 1 of the algorithm. + :type __step1_suffixes: tuple + :cvar __step2_suffixes: Suffixes to be deleted in step 2 of the algorithm. + :type __step2_suffixes: tuple + :cvar __step3_suffixes: Suffixes to be deleted in step 3 of the algorithm. + :type __step3_suffixes: tuple + :note: A detailed description of the Danish + stemming algorithm can be found under + http://snowball.tartarus.org/algorithms/danish/stemmer.html + + """ + + # The language's vowels and other important characters are defined. + __vowels = u("aeiouy\xE6\xE5\xF8") + __consonants = "bcdfghjklmnpqrstvwxz" + __double_consonants = ("bb", "cc", "dd", "ff", "gg", "hh", "jj", + "kk", "ll", "mm", "nn", "pp", "qq", "rr", + "ss", "tt", "vv", "ww", "xx", "zz") + __s_ending = u("abcdfghjklmnoprtvyz\xE5") + + # The different suffixes, divided into the algorithm's steps + # and organized by length, are listed in tuples. + __step1_suffixes = ("erendes", "erende", "hedens", "ethed", + "erede", "heden", "heder", "endes", + "ernes", "erens", "erets", "ered", + "ende", "erne", "eren", "erer", "heds", + "enes", "eres", "eret", "hed", "ene", "ere", + "ens", "ers", "ets", "en", "er", "es", "et", + "e", "s") + __step2_suffixes = ("gd", "dt", "gt", "kt") + __step3_suffixes = ("elig", u("l\xF8st"), "lig", "els", "ig") + + def stem(self, word): + """ + Stem a Danish word and return the stemmed form. + + :param word: The word that is stemmed. + :type word: str or unicode + :return: The stemmed form. + :rtype: unicode + + """ + # Every word is put into lower case for normalization. + word = word.lower() + + # After this, the required regions are generated + # by the respective helper method. + r1 = self._r1_scandinavian(word, self.__vowels) + + # Then the actual stemming process starts. + # Every new step is explicitly indicated + # according to the descriptions on the Snowball website. + + # STEP 1 + for suffix in self.__step1_suffixes: + if r1.endswith(suffix): + if suffix == "s": + if word[-2] in self.__s_ending: + word = word[:-1] + r1 = r1[:-1] + else: + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + break + + # STEP 2 + for suffix in self.__step2_suffixes: + if r1.endswith(suffix): + word = word[:-1] + r1 = r1[:-1] + break + + # STEP 3 + if r1.endswith("igst"): + word = word[:-2] + r1 = r1[:-2] + + for suffix in self.__step3_suffixes: + if r1.endswith(suffix): + if suffix == u("l\xF8st"): + word = word[:-1] + r1 = r1[:-1] + else: + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + + if r1.endswith(self.__step2_suffixes): + word = word[:-1] + r1 = r1[:-1] + break + + # STEP 4: Undouble + for double_cons in self.__double_consonants: + if word.endswith(double_cons) and len(word) > 3: + word = word[:-1] + break + + return word diff --git a/nstock/modules/whoosh/lang/snowball/dutch.py b/nstock/modules/whoosh/lang/snowball/dutch.py new file mode 100644 index 0000000..22573f6 --- /dev/null +++ b/nstock/modules/whoosh/lang/snowball/dutch.py @@ -0,0 +1,173 @@ +from .bases import _StandardStemmer + +from whoosh.compat import u + + +class DutchStemmer(_StandardStemmer): + """ + The Dutch Snowball stemmer. + + :cvar __vowels: The Dutch vowels. + :type __vowels: unicode + :cvar __step1_suffixes: Suffixes to be deleted in step 1 of the algorithm. + :type __step1_suffixes: tuple + :cvar __step3b_suffixes: Suffixes to be deleted in step 3b of the algorithm. + :type __step3b_suffixes: tuple + :note: A detailed description of the Dutch + stemming algorithm can be found under + http://snowball.tartarus.org/algorithms/dutch/stemmer.html + """ + + __vowels = u("aeiouy\xE8") + __step1_suffixes = ("heden", "ene", "en", "se", "s") + __step3b_suffixes = ("baar", "lijk", "bar", "end", "ing", "ig") + + def stem(self, word): + """ + Stem a Dutch word and return the stemmed form. + + :param word: The word that is stemmed. + :type word: str or unicode + :return: The stemmed form. + :rtype: unicode + + """ + word = word.lower() + + step2_success = False + + # Vowel accents are removed. + word = (word.replace(u("\xE4"), "a").replace(u("\xE1"), "a") + .replace(u("\xEB"), "e").replace(u("\xE9"), "e") + .replace(u("\xED"), "i").replace(u("\xEF"), "i") + .replace(u("\xF6"), "o").replace(u("\xF3"), "o") + .replace(u("\xFC"), "u").replace(u("\xFA"), "u")) + + # An initial 'y', a 'y' after a vowel, + # and an 'i' between self.__vowels is put into upper case. + # As from now these are treated as consonants. + if word.startswith("y"): + word = "".join(("Y", word[1:])) + + for i in range(1, len(word)): + if word[i - 1] in self.__vowels and word[i] == "y": + word = "".join((word[:i], "Y", word[i + 1:])) + + for i in range(1, len(word) - 1): + if (word[i - 1] in self.__vowels and word[i] == "i" and + word[i + 1] in self.__vowels): + word = "".join((word[:i], "I", word[i + 1:])) + + r1, r2 = self._r1r2_standard(word, self.__vowels) + + # R1 is adjusted so that the region before it + # contains at least 3 letters. + for i in range(1, len(word)): + if word[i] not in self.__vowels and word[i - 1] in self.__vowels: + if len(word[:i + 1]) < 3 and len(word[:i + 1]) > 0: + r1 = word[3:] + elif len(word[:i + 1]) == 0: + return word + break + + # STEP 1 + for suffix in self.__step1_suffixes: + if r1.endswith(suffix): + if suffix == "heden": + word = "".join((word[:-5], "heid")) + r1 = "".join((r1[:-5], "heid")) + if r2.endswith("heden"): + r2 = "".join((r2[:-5], "heid")) + + elif (suffix in ("ene", "en") and + not word.endswith("heden") and + word[-len(suffix) - 1] not in self.__vowels and + word[-len(suffix) - 3:-len(suffix)] != "gem"): + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + r2 = r2[:-len(suffix)] + if word.endswith(("kk", "dd", "tt")): + word = word[:-1] + r1 = r1[:-1] + r2 = r2[:-1] + + elif (suffix in ("se", "s") and + word[-len(suffix) - 1] not in self.__vowels and + word[-len(suffix) - 1] != "j"): + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + r2 = r2[:-len(suffix)] + break + + # STEP 2 + if r1.endswith("e") and word[-2] not in self.__vowels: + step2_success = True + word = word[:-1] + r1 = r1[:-1] + r2 = r2[:-1] + + if word.endswith(("kk", "dd", "tt")): + word = word[:-1] + r1 = r1[:-1] + r2 = r2[:-1] + + # STEP 3a + if r2.endswith("heid") and word[-5] != "c": + word = word[:-4] + r1 = r1[:-4] + r2 = r2[:-4] + + if (r1.endswith("en") and word[-3] not in self.__vowels and + word[-5:-2] != "gem"): + word = word[:-2] + r1 = r1[:-2] + r2 = r2[:-2] + + if word.endswith(("kk", "dd", "tt")): + word = word[:-1] + r1 = r1[:-1] + r2 = r2[:-1] + + # STEP 3b: Derivational suffixes + for suffix in self.__step3b_suffixes: + if r2.endswith(suffix): + if suffix in ("end", "ing"): + word = word[:-3] + r2 = r2[:-3] + + if r2.endswith("ig") and word[-3] != "e": + word = word[:-2] + else: + if word.endswith(("kk", "dd", "tt")): + word = word[:-1] + + elif suffix == "ig" and word[-3] != "e": + word = word[:-2] + + elif suffix == "lijk": + word = word[:-4] + r1 = r1[:-4] + + if r1.endswith("e") and word[-2] not in self.__vowels: + word = word[:-1] + if word.endswith(("kk", "dd", "tt")): + word = word[:-1] + + elif suffix == "baar": + word = word[:-4] + + elif suffix == "bar" and step2_success: + word = word[:-3] + break + + # STEP 4: Undouble vowel + if len(word) >= 4: + if word[-1] not in self.__vowels and word[-1] != "I": + if word[-3:-1] in ("aa", "ee", "oo", "uu"): + if word[-4] not in self.__vowels: + word = "".join((word[:-3], word[-3], word[-1])) + + # All occurrences of 'I' and 'Y' are put back into lower case. + word = word.replace("I", "i").replace("Y", "y") + + return word diff --git a/nstock/modules/whoosh/lang/snowball/english.py b/nstock/modules/whoosh/lang/snowball/english.py new file mode 100644 index 0000000..0ed9240 --- /dev/null +++ b/nstock/modules/whoosh/lang/snowball/english.py @@ -0,0 +1,465 @@ +from .bases import _StandardStemmer + +from whoosh.compat import u + + +class EnglishStemmer(_StandardStemmer): + """ + The English Snowball stemmer. + + :cvar __vowels: The English vowels. + :type __vowels: unicode + :cvar __double_consonants: The English double consonants. + :type __double_consonants: tuple + :cvar __li_ending: Letters that may directly appear before a word final 'li'. + :type __li_ending: unicode + :cvar __step0_suffixes: Suffixes to be deleted in step 0 of the algorithm. + :type __step0_suffixes: tuple + :cvar __step1a_suffixes: Suffixes to be deleted in step 1a of the algorithm. + :type __step1a_suffixes: tuple + :cvar __step1b_suffixes: Suffixes to be deleted in step 1b of the algorithm. + :type __step1b_suffixes: tuple + :cvar __step2_suffixes: Suffixes to be deleted in step 2 of the algorithm. + :type __step2_suffixes: tuple + :cvar __step3_suffixes: Suffixes to be deleted in step 3 of the algorithm. + :type __step3_suffixes: tuple + :cvar __step4_suffixes: Suffixes to be deleted in step 4 of the algorithm. + :type __step4_suffixes: tuple + :cvar __step5_suffixes: Suffixes to be deleted in step 5 of the algorithm. + :type __step5_suffixes: tuple + :cvar __special_words: A dictionary containing words + which have to be stemmed specially. + :type __special_words: dict + :note: A detailed description of the English + stemming algorithm can be found under + http://snowball.tartarus.org/algorithms/english/stemmer.html + """ + + __vowels = "aeiouy" + __double_consonants = ("bb", "dd", "ff", "gg", "mm", "nn", + "pp", "rr", "tt") + __li_ending = "cdeghkmnrt" + __step0_suffixes = ("'s'", "'s", "'") + __step1a_suffixes = ("sses", "ied", "ies", "us", "ss", "s") + __step1b_suffixes = ("eedly", "ingly", "edly", "eed", "ing", "ed") + __step2_suffixes = ('ization', 'ational', 'fulness', 'ousness', + 'iveness', 'tional', 'biliti', 'lessli', + 'entli', 'ation', 'alism', 'aliti', 'ousli', + 'iviti', 'fulli', 'enci', 'anci', 'abli', + 'izer', 'ator', 'alli', 'bli', 'ogi', 'li') + __step3_suffixes = ('ational', 'tional', 'alize', 'icate', 'iciti', + 'ative', 'ical', 'ness', 'ful') + __step4_suffixes = ('ement', 'ance', 'ence', 'able', 'ible', 'ment', + 'ant', 'ent', 'ism', 'ate', 'iti', 'ous', + 'ive', 'ize', 'ion', 'al', 'er', 'ic') + __step5_suffixes = ("e", "l") + __special_words = {"skis": "ski", + "skies": "sky", + "dying": "die", + "lying": "lie", + "tying": "tie", + "idly": "idl", + "gently": "gentl", + "ugly": "ugli", + "early": "earli", + "only": "onli", + "singly": "singl", + "sky": "sky", + "news": "news", + "howe": "howe", + "atlas": "atlas", + "cosmos": "cosmos", + "bias": "bias", + "andes": "andes", + "inning": "inning", + "innings": "inning", + "outing": "outing", + "outings": "outing", + "canning": "canning", + "cannings": "canning", + "herring": "herring", + "herrings": "herring", + "earring": "earring", + "earrings": "earring", + "proceed": "proceed", + "proceeds": "proceed", + "proceeded": "proceed", + "proceeding": "proceed", + "exceed": "exceed", + "exceeds": "exceed", + "exceeded": "exceed", + "exceeding": "exceed", + "succeed": "succeed", + "succeeds": "succeed", + "succeeded": "succeed", + "succeeding": "succeed"} + + def stem(self, word): + + """ + Stem an English word and return the stemmed form. + + :param word: The word that is stemmed. + :type word: str or unicode + :return: The stemmed form. + :rtype: unicode + + """ + word = word.lower() + + if word in self.__special_words: + return self.__special_words[word] + + # Map the different apostrophe characters to a single consistent one + word = (word.replace(u("\u2019"), u("\x27")) + .replace(u("\u2018"), u("\x27")) + .replace(u("\u201B"), u("\x27"))) + + if word.startswith(u("\x27")): + word = word[1:] + + if word.startswith("y"): + word = "".join(("Y", word[1:])) + + for i in range(1, len(word)): + if word[i - 1] in self.__vowels and word[i] == "y": + word = "".join((word[:i], "Y", word[i + 1:])) + + step1a_vowel_found = False + step1b_vowel_found = False + + r1 = "" + r2 = "" + + if word.startswith(("gener", "commun", "arsen")): + if word.startswith(("gener", "arsen")): + r1 = word[5:] + else: + r1 = word[6:] + + for i in range(1, len(r1)): + if r1[i] not in self.__vowels and r1[i - 1] in self.__vowels: + r2 = r1[i + 1:] + break + else: + r1, r2 = self._r1r2_standard(word, self.__vowels) + + # STEP 0 + for suffix in self.__step0_suffixes: + if word.endswith(suffix): + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + r2 = r2[:-len(suffix)] + break + + # STEP 1a + for suffix in self.__step1a_suffixes: + if word.endswith(suffix): + + if suffix == "sses": + word = word[:-2] + r1 = r1[:-2] + r2 = r2[:-2] + + elif suffix in ("ied", "ies"): + if len(word[:-len(suffix)]) > 1: + word = word[:-2] + r1 = r1[:-2] + r2 = r2[:-2] + else: + word = word[:-1] + r1 = r1[:-1] + r2 = r2[:-1] + + elif suffix == "s": + for letter in word[:-2]: + if letter in self.__vowels: + step1a_vowel_found = True + break + + if step1a_vowel_found: + word = word[:-1] + r1 = r1[:-1] + r2 = r2[:-1] + break + + # STEP 1b + for suffix in self.__step1b_suffixes: + if word.endswith(suffix): + if suffix in ("eed", "eedly"): + + if r1.endswith(suffix): + word = "".join((word[:-len(suffix)], "ee")) + + if len(r1) >= len(suffix): + r1 = "".join((r1[:-len(suffix)], "ee")) + else: + r1 = "" + + if len(r2) >= len(suffix): + r2 = "".join((r2[:-len(suffix)], "ee")) + else: + r2 = "" + else: + for letter in word[:-len(suffix)]: + if letter in self.__vowels: + step1b_vowel_found = True + break + + if step1b_vowel_found: + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + r2 = r2[:-len(suffix)] + + if word.endswith(("at", "bl", "iz")): + word = "".join((word, "e")) + r1 = "".join((r1, "e")) + + if len(word) > 5 or len(r1) >= 3: + r2 = "".join((r2, "e")) + + elif word.endswith(self.__double_consonants): + word = word[:-1] + r1 = r1[:-1] + r2 = r2[:-1] + + elif ((r1 == "" and len(word) >= 3 and + word[-1] not in self.__vowels and + word[-1] not in "wxY" and + word[-2] in self.__vowels and + word[-3] not in self.__vowels) + or + (r1 == "" and len(word) == 2 and + word[0] in self.__vowels and + word[1] not in self.__vowels)): + + word = "".join((word, "e")) + + if len(r1) > 0: + r1 = "".join((r1, "e")) + + if len(r2) > 0: + r2 = "".join((r2, "e")) + break + + # STEP 1c + if (len(word) > 2 + and word[-1] in "yY" + and word[-2] not in self.__vowels): + word = "".join((word[:-1], "i")) + if len(r1) >= 1: + r1 = "".join((r1[:-1], "i")) + else: + r1 = "" + + if len(r2) >= 1: + r2 = "".join((r2[:-1], "i")) + else: + r2 = "" + + # STEP 2 + for suffix in self.__step2_suffixes: + if word.endswith(suffix): + if r1.endswith(suffix): + if suffix == "tional": + word = word[:-2] + r1 = r1[:-2] + r2 = r2[:-2] + + elif suffix in ("enci", "anci", "abli"): + word = "".join((word[:-1], "e")) + + if len(r1) >= 1: + r1 = "".join((r1[:-1], "e")) + else: + r1 = "" + + if len(r2) >= 1: + r2 = "".join((r2[:-1], "e")) + else: + r2 = "" + + elif suffix == "entli": + word = word[:-2] + r1 = r1[:-2] + r2 = r2[:-2] + + elif suffix in ("izer", "ization"): + word = "".join((word[:-len(suffix)], "ize")) + + if len(r1) >= len(suffix): + r1 = "".join((r1[:-len(suffix)], "ize")) + else: + r1 = "" + + if len(r2) >= len(suffix): + r2 = "".join((r2[:-len(suffix)], "ize")) + else: + r2 = "" + + elif suffix in ("ational", "ation", "ator"): + word = "".join((word[:-len(suffix)], "ate")) + + if len(r1) >= len(suffix): + r1 = "".join((r1[:-len(suffix)], "ate")) + else: + r1 = "" + + if len(r2) >= len(suffix): + r2 = "".join((r2[:-len(suffix)], "ate")) + else: + r2 = "e" + + elif suffix in ("alism", "aliti", "alli"): + word = "".join((word[:-len(suffix)], "al")) + + if len(r1) >= len(suffix): + r1 = "".join((r1[:-len(suffix)], "al")) + else: + r1 = "" + + if len(r2) >= len(suffix): + r2 = "".join((r2[:-len(suffix)], "al")) + else: + r2 = "" + + elif suffix == "fulness": + word = word[:-4] + r1 = r1[:-4] + r2 = r2[:-4] + + elif suffix in ("ousli", "ousness"): + word = "".join((word[:-len(suffix)], "ous")) + + if len(r1) >= len(suffix): + r1 = "".join((r1[:-len(suffix)], "ous")) + else: + r1 = "" + + if len(r2) >= len(suffix): + r2 = "".join((r2[:-len(suffix)], "ous")) + else: + r2 = "" + + elif suffix in ("iveness", "iviti"): + word = "".join((word[:-len(suffix)], "ive")) + + if len(r1) >= len(suffix): + r1 = "".join((r1[:-len(suffix)], "ive")) + else: + r1 = "" + + if len(r2) >= len(suffix): + r2 = "".join((r2[:-len(suffix)], "ive")) + else: + r2 = "e" + + elif suffix in ("biliti", "bli"): + word = "".join((word[:-len(suffix)], "ble")) + + if len(r1) >= len(suffix): + r1 = "".join((r1[:-len(suffix)], "ble")) + else: + r1 = "" + + if len(r2) >= len(suffix): + r2 = "".join((r2[:-len(suffix)], "ble")) + else: + r2 = "" + + elif suffix == "ogi" and word[-4] == "l": + word = word[:-1] + r1 = r1[:-1] + r2 = r2[:-1] + + elif suffix in ("fulli", "lessli"): + word = word[:-2] + r1 = r1[:-2] + r2 = r2[:-2] + + elif suffix == "li" and word[-3] in self.__li_ending: + word = word[:-2] + r1 = r1[:-2] + r2 = r2[:-2] + break + + # STEP 3 + for suffix in self.__step3_suffixes: + if word.endswith(suffix): + if r1.endswith(suffix): + if suffix == "tional": + word = word[:-2] + r1 = r1[:-2] + r2 = r2[:-2] + + elif suffix == "ational": + word = "".join((word[:-len(suffix)], "ate")) + + if len(r1) >= len(suffix): + r1 = "".join((r1[:-len(suffix)], "ate")) + else: + r1 = "" + + if len(r2) >= len(suffix): + r2 = "".join((r2[:-len(suffix)], "ate")) + else: + r2 = "" + + elif suffix == "alize": + word = word[:-3] + r1 = r1[:-3] + r2 = r2[:-3] + + elif suffix in ("icate", "iciti", "ical"): + word = "".join((word[:-len(suffix)], "ic")) + + if len(r1) >= len(suffix): + r1 = "".join((r1[:-len(suffix)], "ic")) + else: + r1 = "" + + if len(r2) >= len(suffix): + r2 = "".join((r2[:-len(suffix)], "ic")) + else: + r2 = "" + + elif suffix in ("ful", "ness"): + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + r2 = r2[:-len(suffix)] + + elif suffix == "ative" and r2.endswith(suffix): + word = word[:-5] + r1 = r1[:-5] + r2 = r2[:-5] + break + + # STEP 4 + for suffix in self.__step4_suffixes: + if word.endswith(suffix): + if r2.endswith(suffix): + if suffix == "ion": + if word[-4] in "st": + word = word[:-3] + r1 = r1[:-3] + r2 = r2[:-3] + else: + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + r2 = r2[:-len(suffix)] + break + + # STEP 5 + if r2.endswith("l") and word[-2] == "l": + word = word[:-1] + elif r2.endswith("e"): + word = word[:-1] + elif r1.endswith("e"): + if len(word) >= 4 and (word[-2] in self.__vowels or + word[-2] in "wxY" or + word[-3] not in self.__vowels or + word[-4] in self.__vowels): + word = word[:-1] + + word = word.replace("Y", "y") + return word diff --git a/nstock/modules/whoosh/lang/snowball/finnish.py b/nstock/modules/whoosh/lang/snowball/finnish.py new file mode 100644 index 0000000..d05207f --- /dev/null +++ b/nstock/modules/whoosh/lang/snowball/finnish.py @@ -0,0 +1,266 @@ +from .bases import _StandardStemmer + +from whoosh.compat import u + + +class FinnishStemmer(_StandardStemmer): + """ + The Finnish Snowball stemmer. + + :cvar __vowels: The Finnish vowels. + :type __vowels: unicode + :cvar __restricted_vowels: A subset of the Finnish vowels. + :type __restricted_vowels: unicode + :cvar __long_vowels: The Finnish vowels in their long forms. + :type __long_vowels: tuple + :cvar __consonants: The Finnish consonants. + :type __consonants: unicode + :cvar __double_consonants: The Finnish double consonants. + :type __double_consonants: tuple + :cvar __step1_suffixes: Suffixes to be deleted in step 1 of the algorithm. + :type __step1_suffixes: tuple + :cvar __step2_suffixes: Suffixes to be deleted in step 2 of the algorithm. + :type __step2_suffixes: tuple + :cvar __step3_suffixes: Suffixes to be deleted in step 3 of the algorithm. + :type __step3_suffixes: tuple + :cvar __step4_suffixes: Suffixes to be deleted in step 4 of the algorithm. + :type __step4_suffixes: tuple + :note: A detailed description of the Finnish + stemming algorithm can be found under + http://snowball.tartarus.org/algorithms/finnish/stemmer.html + """ + + __vowels = u("aeiouy\xE4\xF6") + __restricted_vowels = u("aeiou\xE4\xF6") + __long_vowels = ("aa", "ee", "ii", "oo", "uu", u("\xE4\xE4"), + u("\xF6\xF6")) + __consonants = "bcdfghjklmnpqrstvwxz" + __double_consonants = ("bb", "cc", "dd", "ff", "gg", "hh", "jj", + "kk", "ll", "mm", "nn", "pp", "qq", "rr", + "ss", "tt", "vv", "ww", "xx", "zz") + __step1_suffixes = ('kaan', u('k\xE4\xE4n'), 'sti', 'kin', 'han', + u('h\xE4n'), 'ko', u('k\xF6'), 'pa', u('p\xE4')) + __step2_suffixes = ('nsa', u('ns\xE4'), 'mme', 'nne', 'si', 'ni', + 'an', u('\xE4n'), 'en') + __step3_suffixes = ('siin', 'tten', 'seen', 'han', 'hen', 'hin', + 'hon', u('h\xE4n'), u('h\xF6n'), 'den', 'tta', + u('tt\xE4'), 'ssa', u('ss\xE4'), 'sta', + u('st\xE4'), 'lla', u('ll\xE4'), 'lta', + u('lt\xE4'), 'lle', 'ksi', 'ine', 'ta', + u('t\xE4'), 'na', u('n\xE4'), 'a', u('\xE4'), + 'n') + __step4_suffixes = ('impi', 'impa', u('imp\xE4'), 'immi', 'imma', + u('imm\xE4'), 'mpi', 'mpa', u('mp\xE4'), 'mmi', + 'mma', u('mm\xE4'), 'eja', u('ej\xE4')) + + def stem(self, word): + """ + Stem a Finnish word and return the stemmed form. + + :param word: The word that is stemmed. + :type word: str or unicode + :return: The stemmed form. + :rtype: unicode + + """ + word = word.lower() + + step3_success = False + + r1, r2 = self._r1r2_standard(word, self.__vowels) + + # STEP 1: Particles etc. + for suffix in self.__step1_suffixes: + if r1.endswith(suffix): + if suffix == "sti": + if suffix in r2: + word = word[:-3] + r1 = r1[:-3] + r2 = r2[:-3] + else: + if word[-len(suffix) - 1] in u("ntaeiouy\xE4\xF6"): + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + r2 = r2[:-len(suffix)] + break + + # STEP 2: Possessives + for suffix in self.__step2_suffixes: + if r1.endswith(suffix): + if suffix == "si": + if word[-3] != "k": + word = word[:-2] + r1 = r1[:-2] + r2 = r2[:-2] + + elif suffix == "ni": + word = word[:-2] + r1 = r1[:-2] + r2 = r2[:-2] + if word.endswith("kse"): + word = "".join((word[:-3], "ksi")) + + if r1.endswith("kse"): + r1 = "".join((r1[:-3], "ksi")) + + if r2.endswith("kse"): + r2 = "".join((r2[:-3], "ksi")) + + elif suffix == "an": + if (word[-4:-2] in ("ta", "na") or + word[-5:-2] in ("ssa", "sta", "lla", "lta")): + word = word[:-2] + r1 = r1[:-2] + r2 = r2[:-2] + + elif suffix == u("\xE4n"): + if (word[-4:-2] in (u("t\xE4"), u("n\xE4")) or + word[-5:-2] in (u("ss\xE4"), u("st\xE4"), + u("ll\xE4"), u("lt\xE4"))): + word = word[:-2] + r1 = r1[:-2] + r2 = r2[:-2] + + elif suffix == "en": + if word[-5:-2] in ("lle", "ine"): + word = word[:-2] + r1 = r1[:-2] + r2 = r2[:-2] + else: + word = word[:-3] + r1 = r1[:-3] + r2 = r2[:-3] + break + + # STEP 3: Cases + for suffix in self.__step3_suffixes: + if r1.endswith(suffix): + if suffix in ("han", "hen", "hin", "hon", u("h\xE4n"), + u("h\xF6n")): + if ((suffix == "han" and word[-4] == "a") or + (suffix == "hen" and word[-4] == "e") or + (suffix == "hin" and word[-4] == "i") or + (suffix == "hon" and word[-4] == "o") or + (suffix == u("h\xE4n") and word[-4] == u("\xE4")) or + (suffix == u("h\xF6n") and word[-4] == u("\xF6"))): + word = word[:-3] + r1 = r1[:-3] + r2 = r2[:-3] + step3_success = True + + elif suffix in ("siin", "den", "tten"): + if (word[-len(suffix) - 1] == "i" and + word[-len(suffix) - 2] in self.__restricted_vowels): + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + r2 = r2[:-len(suffix)] + step3_success = True + else: + continue + + elif suffix == "seen": + if word[-6:-4] in self.__long_vowels: + word = word[:-4] + r1 = r1[:-4] + r2 = r2[:-4] + step3_success = True + else: + continue + + elif suffix in ("a", u("\xE4")): + if word[-2] in self.__vowels and word[-3] in self.__consonants: + word = word[:-1] + r1 = r1[:-1] + r2 = r2[:-1] + step3_success = True + + elif suffix in ("tta", u("tt\xE4")): + if word[-4] == "e": + word = word[:-3] + r1 = r1[:-3] + r2 = r2[:-3] + step3_success = True + + elif suffix == "n": + word = word[:-1] + r1 = r1[:-1] + r2 = r2[:-1] + step3_success = True + + if word[-2:] == "ie" or word[-2:] in self.__long_vowels: + word = word[:-1] + r1 = r1[:-1] + r2 = r2[:-1] + else: + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + r2 = r2[:-len(suffix)] + step3_success = True + break + + # STEP 4: Other endings + for suffix in self.__step4_suffixes: + if r2.endswith(suffix): + if suffix in ("mpi", "mpa", u("mp\xE4"), "mmi", "mma", + u("mm\xE4")): + if word[-5:-3] != "po": + word = word[:-3] + r1 = r1[:-3] + r2 = r2[:-3] + else: + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + r2 = r2[:-len(suffix)] + break + + # STEP 5: Plurals + if step3_success and len(r1) >= 1 and r1[-1] in "ij": + word = word[:-1] + r1 = r1[:-1] + + elif (not step3_success and len(r1) >= 2 and + r1[-1] == "t" and r1[-2] in self.__vowels): + word = word[:-1] + r1 = r1[:-1] + r2 = r2[:-1] + if r2.endswith("imma"): + word = word[:-4] + r1 = r1[:-4] + elif r2.endswith("mma") and r2[-5:-3] != "po": + word = word[:-3] + r1 = r1[:-3] + + # STEP 6: Tidying up + if r1[-2:] in self.__long_vowels: + word = word[:-1] + r1 = r1[:-1] + + if (len(r1) >= 2 and r1[-2] in self.__consonants and + r1[-1] in u("a\xE4ei")): + word = word[:-1] + r1 = r1[:-1] + + if r1.endswith(("oj", "uj")): + word = word[:-1] + r1 = r1[:-1] + + if r1.endswith("jo"): + word = word[:-1] + r1 = r1[:-1] + + # If the word ends with a double consonant + # followed by zero or more vowels, the last consonant is removed. + for i in range(1, len(word)): + if word[-i] in self.__vowels: + continue + else: + if i == 1: + if word[-i - 1:] in self.__double_consonants: + word = word[:-1] + else: + if word[-i - 1:-i + 1] in self.__double_consonants: + word = "".join((word[:-i], word[-i + 1:])) + break + + + return word diff --git a/nstock/modules/whoosh/lang/snowball/french.py b/nstock/modules/whoosh/lang/snowball/french.py new file mode 100644 index 0000000..72a7e30 --- /dev/null +++ b/nstock/modules/whoosh/lang/snowball/french.py @@ -0,0 +1,348 @@ +from .bases import _StandardStemmer + +from whoosh.compat import u + + +class FrenchStemmer(_StandardStemmer): + + """ + The French Snowball stemmer. + + :cvar __vowels: The French vowels. + :type __vowels: unicode + :cvar __step1_suffixes: Suffixes to be deleted in step 1 of the algorithm. + :type __step1_suffixes: tuple + :cvar __step2a_suffixes: Suffixes to be deleted in step 2a of the algorithm. + :type __step2a_suffixes: tuple + :cvar __step2b_suffixes: Suffixes to be deleted in step 2b of the algorithm. + :type __step2b_suffixes: tuple + :cvar __step4_suffixes: Suffixes to be deleted in step 4 of the algorithm. + :type __step4_suffixes: tuple + :note: A detailed description of the French + stemming algorithm can be found under + http://snowball.tartarus.org/algorithms/french/stemmer.html + """ + + __vowels = u("aeiouy\xE2\xE0\xEB\xE9\xEA\xE8\xEF\xEE\xF4\xFB\xF9") + __step1_suffixes = ('issements', 'issement', 'atrices', 'atrice', + 'ateurs', 'ations', 'logies', 'usions', + 'utions', 'ements', 'amment', 'emment', + 'ances', 'iqUes', 'ismes', 'ables', 'istes', + 'ateur', 'ation', 'logie', 'usion', 'ution', + 'ences', 'ement', 'euses', 'ments', 'ance', + 'iqUe', 'isme', 'able', 'iste', 'ence', + u('it\xE9s'), 'ives', 'eaux', 'euse', 'ment', + 'eux', u('it\xE9'), 'ive', 'ifs', 'aux', 'if') + __step2a_suffixes = ('issaIent', 'issantes', 'iraIent', 'issante', + 'issants', 'issions', 'irions', 'issais', + 'issait', 'issant', 'issent', 'issiez', 'issons', + 'irais', 'irait', 'irent', 'iriez', 'irons', + 'iront', 'isses', 'issez', u('\xEEmes'), + u('\xEEtes'), 'irai', 'iras', 'irez', 'isse', + 'ies', 'ira', u('\xEEt'), 'ie', 'ir', 'is', + 'it', 'i') + __step2b_suffixes = ('eraIent', 'assions', 'erions', 'assent', + 'assiez', u('\xE8rent'), 'erais', 'erait', + 'eriez', 'erons', 'eront', 'aIent', 'antes', + 'asses', 'ions', 'erai', 'eras', 'erez', + u('\xE2mes'), u('\xE2tes'), 'ante', 'ants', + 'asse', u('\xE9es'), 'era', 'iez', 'ais', + 'ait', 'ant', u('\xE9e'), u('\xE9s'), 'er', + 'ez', u('\xE2t'), 'ai', 'as', u('\xE9'), 'a') + __step4_suffixes = (u('i\xE8re'), u('I\xE8re'), 'ion', 'ier', 'Ier', + 'e', u('\xEB')) + + def stem(self, word): + """ + Stem a French word and return the stemmed form. + + :param word: The word that is stemmed. + :type word: str or unicode + :return: The stemmed form. + :rtype: unicode + + """ + word = word.lower() + + step1_success = False + rv_ending_found = False + step2a_success = False + step2b_success = False + + # Every occurrence of 'u' after 'q' is put into upper case. + for i in range(1, len(word)): + if word[i - 1] == "q" and word[i] == "u": + word = "".join((word[:i], "U", word[i + 1:])) + + # Every occurrence of 'u' and 'i' + # between vowels is put into upper case. + # Every occurrence of 'y' preceded or + # followed by a vowel is also put into upper case. + for i in range(1, len(word) - 1): + if word[i - 1] in self.__vowels and word[i + 1] in self.__vowels: + if word[i] == "u": + word = "".join((word[:i], "U", word[i + 1:])) + + elif word[i] == "i": + word = "".join((word[:i], "I", word[i + 1:])) + + if word[i - 1] in self.__vowels or word[i + 1] in self.__vowels: + if word[i] == "y": + word = "".join((word[:i], "Y", word[i + 1:])) + + r1, r2 = self._r1r2_standard(word, self.__vowels) + rv = self.__rv_french(word, self.__vowels) + + # STEP 1: Standard suffix removal + for suffix in self.__step1_suffixes: + if word.endswith(suffix): + if suffix == "eaux": + word = word[:-1] + step1_success = True + + elif suffix in ("euse", "euses"): + if suffix in r2: + word = word[:-len(suffix)] + step1_success = True + + elif suffix in r1: + word = "".join((word[:-len(suffix)], "eux")) + step1_success = True + + elif suffix in ("ement", "ements") and suffix in rv: + word = word[:-len(suffix)] + step1_success = True + + if word[-2:] == "iv" and "iv" in r2: + word = word[:-2] + + if word[-2:] == "at" and "at" in r2: + word = word[:-2] + + elif word[-3:] == "eus": + if "eus" in r2: + word = word[:-3] + elif "eus" in r1: + word = "".join((word[:-1], "x")) + + elif word[-3:] in ("abl", "iqU"): + if "abl" in r2 or "iqU" in r2: + word = word[:-3] + + elif word[-3:] in (u("i\xE8r"), u("I\xE8r")): + if u("i\xE8r") in rv or u("I\xE8r") in rv: + word = "".join((word[:-3], "i")) + + elif suffix == "amment" and suffix in rv: + word = "".join((word[:-6], "ant")) + rv = "".join((rv[:-6], "ant")) + rv_ending_found = True + + elif suffix == "emment" and suffix in rv: + word = "".join((word[:-6], "ent")) + rv_ending_found = True + + elif (suffix in ("ment", "ments") and suffix in rv and + not rv.startswith(suffix) and + rv[rv.rindex(suffix) - 1] in self.__vowels): + word = word[:-len(suffix)] + rv = rv[:-len(suffix)] + rv_ending_found = True + + elif suffix == "aux" and suffix in r1: + word = "".join((word[:-2], "l")) + step1_success = True + + elif (suffix in ("issement", "issements") and suffix in r1 + and word[-len(suffix) - 1] not in self.__vowels): + word = word[:-len(suffix)] + step1_success = True + + elif suffix in ("ance", "iqUe", "isme", "able", "iste", + "eux", "ances", "iqUes", "ismes", + "ables", "istes") and suffix in r2: + word = word[:-len(suffix)] + step1_success = True + + elif suffix in ("atrice", "ateur", "ation", "atrices", + "ateurs", "ations") and suffix in r2: + word = word[:-len(suffix)] + step1_success = True + + if word[-2:] == "ic": + if "ic" in r2: + word = word[:-2] + else: + word = "".join((word[:-2], "iqU")) + + elif suffix in ("logie", "logies") and suffix in r2: + word = "".join((word[:-len(suffix)], "log")) + step1_success = True + + elif (suffix in ("usion", "ution", "usions", "utions") and + suffix in r2): + word = "".join((word[:-len(suffix)], "u")) + step1_success = True + + elif suffix in ("ence", "ences") and suffix in r2: + word = "".join((word[:-len(suffix)], "ent")) + step1_success = True + + elif suffix in (u("it\xE9"), u("it\xE9s")) and suffix in r2: + word = word[:-len(suffix)] + step1_success = True + + if word[-4:] == "abil": + if "abil" in r2: + word = word[:-4] + else: + word = "".join((word[:-2], "l")) + + elif word[-2:] == "ic": + if "ic" in r2: + word = word[:-2] + else: + word = "".join((word[:-2], "iqU")) + + elif word[-2:] == "iv": + if "iv" in r2: + word = word[:-2] + + elif (suffix in ("if", "ive", "ifs", "ives") and + suffix in r2): + word = word[:-len(suffix)] + step1_success = True + + if word[-2:] == "at" and "at" in r2: + word = word[:-2] + + if word[-2:] == "ic": + if "ic" in r2: + word = word[:-2] + else: + word = "".join((word[:-2], "iqU")) + break + + # STEP 2a: Verb suffixes beginning 'i' + if not step1_success or rv_ending_found: + for suffix in self.__step2a_suffixes: + if word.endswith(suffix): + if (suffix in rv and len(rv) > len(suffix) and + rv[rv.rindex(suffix) - 1] not in self.__vowels): + word = word[:-len(suffix)] + step2a_success = True + break + + # STEP 2b: Other verb suffixes + if not step2a_success: + for suffix in self.__step2b_suffixes: + if rv.endswith(suffix): + if suffix == "ions" and "ions" in r2: + word = word[:-4] + step2b_success = True + + elif suffix in ('eraIent', 'erions', u('\xE8rent'), + 'erais', 'erait', 'eriez', + 'erons', 'eront', 'erai', 'eras', + 'erez', u('\xE9es'), 'era', 'iez', + u('\xE9e'), u('\xE9s'), 'er', 'ez', + u('\xE9')): + word = word[:-len(suffix)] + step2b_success = True + + elif suffix in ('assions', 'assent', 'assiez', + 'aIent', 'antes', 'asses', + u('\xE2mes'), u('\xE2tes'), 'ante', + 'ants', 'asse', 'ais', 'ait', + 'ant', u('\xE2t'), 'ai', 'as', + 'a'): + word = word[:-len(suffix)] + rv = rv[:-len(suffix)] + step2b_success = True + if rv.endswith("e"): + word = word[:-1] + break + + # STEP 3 + if step1_success or step2a_success or step2b_success: + if word[-1] == "Y": + word = "".join((word[:-1], "i")) + elif word[-1] == u("\xE7"): + word = "".join((word[:-1], "c")) + + # STEP 4: Residual suffixes + else: + if (len(word) >= 2 and word[-1] == "s" and + word[-2] not in u("aiou\xE8s")): + word = word[:-1] + + for suffix in self.__step4_suffixes: + if word.endswith(suffix): + if suffix in rv: + if (suffix == "ion" and suffix in r2 and + rv[-4] in "st"): + word = word[:-3] + + elif suffix in ("ier", u("i\xE8re"), "Ier", + u("I\xE8re")): + word = "".join((word[:-len(suffix)], "i")) + + elif suffix == "e": + word = word[:-1] + + elif suffix == u("\xEB") and word[-3:-1] == "gu": + word = word[:-1] + break + + # STEP 5: Undouble + if word.endswith(("enn", "onn", "ett", "ell", "eill")): + word = word[:-1] + + # STEP 6: Un-accent + for i in range(1, len(word)): + if word[-i] not in self.__vowels: + i += 1 + else: + if i != 1 and word[-i] in (u("\xE9"), u("\xE8")): + word = "".join((word[:-i], "e", word[-i + 1:])) + break + + word = (word.replace("I", "i") + .replace("U", "u") + .replace("Y", "y")) + return word + + def __rv_french(self, word, vowels): + """ + Return the region RV that is used by the French stemmer. + + If the word begins with two vowels, RV is the region after + the third letter. Otherwise, it is the region after the first + vowel not at the beginning of the word, or the end of the word + if these positions cannot be found. (Exceptionally, u'par', + u'col' or u'tap' at the beginning of a word is also taken to + define RV as the region to their right.) + + :param word: The French word whose region RV is determined. + :type word: str or unicode + :param vowels: The French vowels that are used to determine + the region RV. + :type vowels: unicode + :return: the region RV for the respective French word. + :rtype: unicode + :note: This helper method is invoked by the stem method of + the subclass FrenchStemmer. It is not to be invoked directly! + + """ + rv = "" + if len(word) >= 2: + if (word.startswith(("par", "col", "tap")) or + (word[0] in vowels and word[1] in vowels)): + rv = word[3:] + else: + for i in range(1, len(word)): + if word[i] in vowels: + rv = word[i + 1:] + break + + return rv diff --git a/nstock/modules/whoosh/lang/snowball/german.py b/nstock/modules/whoosh/lang/snowball/german.py new file mode 100644 index 0000000..73743f1 --- /dev/null +++ b/nstock/modules/whoosh/lang/snowball/german.py @@ -0,0 +1,144 @@ +from .bases import _StandardStemmer + +from whoosh.compat import u + + +class GermanStemmer(_StandardStemmer): + + """ + The German Snowball stemmer. + + :cvar __vowels: The German vowels. + :type __vowels: unicode + :cvar __s_ending: Letters that may directly appear before a word final 's'. + :type __s_ending: unicode + :cvar __st_ending: Letter that may directly appear before a word final 'st'. + :type __st_ending: unicode + :cvar __step1_suffixes: Suffixes to be deleted in step 1 of the algorithm. + :type __step1_suffixes: tuple + :cvar __step2_suffixes: Suffixes to be deleted in step 2 of the algorithm. + :type __step2_suffixes: tuple + :cvar __step3_suffixes: Suffixes to be deleted in step 3 of the algorithm. + :type __step3_suffixes: tuple + :note: A detailed description of the German + stemming algorithm can be found under + http://snowball.tartarus.org/algorithms/german/stemmer.html + + """ + + __vowels = u("aeiouy\xE4\xF6\xFC") + __s_ending = "bdfghklmnrt" + __st_ending = "bdfghklmnt" + + __step1_suffixes = ("ern", "em", "er", "en", "es", "e", "s") + __step2_suffixes = ("est", "en", "er", "st") + __step3_suffixes = ("isch", "lich", "heit", "keit", + "end", "ung", "ig", "ik") + + def stem(self, word): + """ + Stem a German word and return the stemmed form. + + :param word: The word that is stemmed. + :type word: str or unicode + :return: The stemmed form. + :rtype: unicode + + """ + word = word.lower() + + word = word.replace(u("\xDF"), "ss") + + # Every occurrence of 'u' and 'y' + # between vowels is put into upper case. + for i in range(1, len(word) - 1): + if word[i - 1] in self.__vowels and word[i + 1] in self.__vowels: + if word[i] == "u": + word = "".join((word[:i], "U", word[i + 1:])) + + elif word[i] == "y": + word = "".join((word[:i], "Y", word[i + 1:])) + + r1, r2 = self._r1r2_standard(word, self.__vowels) + + # R1 is adjusted so that the region before it + # contains at least 3 letters. + for i in range(1, len(word)): + if word[i] not in self.__vowels and word[i - 1] in self.__vowels: + if len(word[:i + 1]) < 3 and len(word[:i + 1]) > 0: + r1 = word[3:] + elif len(word[:i + 1]) == 0: + return word + break + + # STEP 1 + for suffix in self.__step1_suffixes: + if r1.endswith(suffix): + if (suffix in ("en", "es", "e") and + word[-len(suffix) - 4:-len(suffix)] == "niss"): + word = word[:-len(suffix) - 1] + r1 = r1[:-len(suffix) - 1] + r2 = r2[:-len(suffix) - 1] + + elif suffix == "s": + if word[-2] in self.__s_ending: + word = word[:-1] + r1 = r1[:-1] + r2 = r2[:-1] + else: + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + r2 = r2[:-len(suffix)] + break + + # STEP 2 + for suffix in self.__step2_suffixes: + if r1.endswith(suffix): + if suffix == "st": + if word[-3] in self.__st_ending and len(word[:-3]) >= 3: + word = word[:-2] + r1 = r1[:-2] + r2 = r2[:-2] + else: + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + r2 = r2[:-len(suffix)] + break + + # STEP 3: Derivational suffixes + for suffix in self.__step3_suffixes: + if r2.endswith(suffix): + if suffix in ("end", "ung"): + if ("ig" in r2[-len(suffix) - 2:-len(suffix)] and + "e" not in r2[-len(suffix) - 3:-len(suffix) - 2]): + word = word[:-len(suffix) - 2] + else: + word = word[:-len(suffix)] + + elif (suffix in ("ig", "ik", "isch") and + "e" not in r2[-len(suffix) - 1:-len(suffix)]): + word = word[:-len(suffix)] + + elif suffix in ("lich", "heit"): + if ("er" in r1[-len(suffix) - 2:-len(suffix)] or + "en" in r1[-len(suffix) - 2:-len(suffix)]): + word = word[:-len(suffix) - 2] + else: + word = word[:-len(suffix)] + + elif suffix == "keit": + if "lich" in r2[-len(suffix) - 4:-len(suffix)]: + word = word[:-len(suffix) - 4] + + elif "ig" in r2[-len(suffix) - 2:-len(suffix)]: + word = word[:-len(suffix) - 2] + else: + word = word[:-len(suffix)] + break + + # Umlaut accents are removed and + # 'u' and 'y' are put back into lower case. + word = (word.replace(u("\xE4"), "a").replace(u("\xF6"), "o") + .replace(u("\xFC"), "u").replace("U", "u") + .replace("Y", "y")) + return word diff --git a/nstock/modules/whoosh/lang/snowball/hungarian.py b/nstock/modules/whoosh/lang/snowball/hungarian.py new file mode 100644 index 0000000..ed98b6f --- /dev/null +++ b/nstock/modules/whoosh/lang/snowball/hungarian.py @@ -0,0 +1,268 @@ +from whoosh.compat import u + +class HungarianStemmer(object): + + """ + The Hungarian Snowball stemmer. + + :cvar __vowels: The Hungarian vowels. + :type __vowels: unicode + :cvar __digraphs: The Hungarian digraphs. + :type __digraphs: tuple + :cvar __double_consonants: The Hungarian double consonants. + :type __double_consonants: tuple + :cvar __step1_suffixes: Suffixes to be deleted in step 1 of the algorithm. + :type __step1_suffixes: tuple + :cvar __step2_suffixes: Suffixes to be deleted in step 2 of the algorithm. + :type __step2_suffixes: tuple + :cvar __step3_suffixes: Suffixes to be deleted in step 3 of the algorithm. + :type __step3_suffixes: tuple + :cvar __step4_suffixes: Suffixes to be deleted in step 4 of the algorithm. + :type __step4_suffixes: tuple + :cvar __step5_suffixes: Suffixes to be deleted in step 5 of the algorithm. + :type __step5_suffixes: tuple + :cvar __step6_suffixes: Suffixes to be deleted in step 6 of the algorithm. + :type __step6_suffixes: tuple + :cvar __step7_suffixes: Suffixes to be deleted in step 7 of the algorithm. + :type __step7_suffixes: tuple + :cvar __step8_suffixes: Suffixes to be deleted in step 8 of the algorithm. + :type __step8_suffixes: tuple + :cvar __step9_suffixes: Suffixes to be deleted in step 9 of the algorithm. + :type __step9_suffixes: tuple + :note: A detailed description of the Hungarian + stemming algorithm can be found under + http://snowball.tartarus.org/algorithms/hungarian/stemmer.html + + """ + + __vowels = u("aeiou\xF6\xFC\xE1\xE9\xED\xF3\xF5\xFA\xFB") + __digraphs = ("cs", "dz", "dzs", "gy", "ly", "ny", "ty", "zs") + __double_consonants = ("bb", "cc", "ccs", "dd", "ff", "gg", + "ggy", "jj", "kk", "ll", "lly", "mm", + "nn", "nny", "pp", "rr", "ss", "ssz", + "tt", "tty", "vv", "zz", "zzs") + + __step1_suffixes = ("al", "el") + __step2_suffixes = (u('k\xE9ppen'), u('onk\xE9nt'), u('enk\xE9nt'), + u('ank\xE9nt'), u('k\xE9pp'), u('k\xE9nt'), 'ban', + 'ben', 'nak', 'nek', 'val', 'vel', u('t\xF3l'), + u('t\xF5l'), u('r\xF3l'), u('r\xF5l'), u('b\xF3l'), + u('b\xF5l'), 'hoz', 'hez', u('h\xF6z'), + u('n\xE1l'), u('n\xE9l'), u('\xE9rt'), 'kor', + 'ba', 'be', 'ra', 're', 'ig', 'at', 'et', + 'ot', u('\xF6t'), 'ul', u('\xFCl'), u('v\xE1'), + u('v\xE9'), 'en', 'on', 'an', u('\xF6n'), + 'n', 't') + __step3_suffixes = (u("\xE1nk\xE9nt"), u("\xE1n"), u("\xE9n")) + __step4_suffixes = ('astul', u('est\xFCl'), u('\xE1stul'), + u('\xE9st\xFCl'), 'stul', u('st\xFCl')) + __step5_suffixes = (u("\xE1"), u("\xE9")) + __step6_suffixes = (u('ok\xE9'), u('\xF6k\xE9'), u('ak\xE9'), + u('ek\xE9'), u('\xE1k\xE9'), u('\xE1\xE9i'), + u('\xE9k\xE9'), u('\xE9\xE9i'), u('k\xE9'), + u('\xE9i'), u('\xE9\xE9'), u('\xE9')) + __step7_suffixes = (u('\xE1juk'), u('\xE9j\xFCk'), u('\xFCnk'), + 'unk', 'juk', u('j\xFCk'), u('\xE1nk'), + u('\xE9nk'), 'nk', 'uk', u('\xFCk'), 'em', + 'om', 'am', 'od', 'ed', 'ad', u('\xF6d'), + 'ja', 'je', u('\xE1m'), u('\xE1d'), u('\xE9m'), + u('\xE9d'), 'm', 'd', 'a', 'e', 'o', + u('\xE1'), u('\xE9')) + __step8_suffixes = ('jaitok', 'jeitek', 'jaink', 'jeink', 'aitok', + 'eitek', u('\xE1itok'), u('\xE9itek'), 'jaim', + 'jeim', 'jaid', 'jeid', 'eink', 'aink', + 'itek', 'jeik', 'jaik', u('\xE1ink'), + u('\xE9ink'), 'aim', 'eim', 'aid', 'eid', + 'jai', 'jei', 'ink', 'aik', 'eik', + u('\xE1im'), u('\xE1id'), u('\xE1ik'), u('\xE9im'), + u('\xE9id'), u('\xE9ik'), 'im', 'id', 'ai', + 'ei', 'ik', u('\xE1i'), u('\xE9i'), 'i') + __step9_suffixes = (u("\xE1k"), u("\xE9k"), u("\xF6k"), "ok", + "ek", "ak", "k") + + def stem(self, word): + """ + Stem an Hungarian word and return the stemmed form. + + :param word: The word that is stemmed. + :type word: str or unicode + :return: The stemmed form. + :rtype: unicode + + """ + word = word.lower() + + r1 = self.__r1_hungarian(word, self.__vowels, self.__digraphs) + + # STEP 1: Remove instrumental case + if r1.endswith(self.__step1_suffixes): + for double_cons in self.__double_consonants: + if word[-2 - len(double_cons):-2] == double_cons: + word = "".join((word[:-4], word[-3])) + + if r1[-2 - len(double_cons):-2] == double_cons: + r1 = "".join((r1[:-4], r1[-3])) + break + + # STEP 2: Remove frequent cases + for suffix in self.__step2_suffixes: + if word.endswith(suffix): + if r1.endswith(suffix): + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + + if r1.endswith(u("\xE1")): + word = "".join((word[:-1], "a")) + r1 = "".join((r1[:-1], "a")) + + elif r1.endswith(u("\xE9")): + word = "".join((word[:-1], "e")) + r1 = "".join((r1[:-1], "e")) + break + + # STEP 3: Remove special cases + for suffix in self.__step3_suffixes: + if r1.endswith(suffix): + if suffix == u("\xE9n"): + word = "".join((word[:-2], "e")) + r1 = "".join((r1[:-2], "e")) + else: + word = "".join((word[:-len(suffix)], "a")) + r1 = "".join((r1[:-len(suffix)], "a")) + break + + # STEP 4: Remove other cases + for suffix in self.__step4_suffixes: + if r1.endswith(suffix): + if suffix == u("\xE1stul"): + word = "".join((word[:-5], "a")) + r1 = "".join((r1[:-5], "a")) + + elif suffix == u("\xE9st\xFCl"): + word = "".join((word[:-5], "e")) + r1 = "".join((r1[:-5], "e")) + else: + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + break + + # STEP 5: Remove factive case + for suffix in self.__step5_suffixes: + if r1.endswith(suffix): + for double_cons in self.__double_consonants: + if word[-1 - len(double_cons):-1] == double_cons: + word = "".join((word[:-3], word[-2])) + + if r1[-1 - len(double_cons):-1] == double_cons: + r1 = "".join((r1[:-3], r1[-2])) + break + + # STEP 6: Remove owned + for suffix in self.__step6_suffixes: + if r1.endswith(suffix): + if suffix in (u("\xE1k\xE9"), u("\xE1\xE9i")): + word = "".join((word[:-3], "a")) + r1 = "".join((r1[:-3], "a")) + + elif suffix in (u("\xE9k\xE9"), u("\xE9\xE9i"), + u("\xE9\xE9")): + word = "".join((word[:-len(suffix)], "e")) + r1 = "".join((r1[:-len(suffix)], "e")) + else: + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + break + + # STEP 7: Remove singular owner suffixes + for suffix in self.__step7_suffixes: + if word.endswith(suffix): + if r1.endswith(suffix): + if suffix in (u("\xE1nk"), u("\xE1juk"), u("\xE1m"), + u("\xE1d"), u("\xE1")): + word = "".join((word[:-len(suffix)], "a")) + r1 = "".join((r1[:-len(suffix)], "a")) + + elif suffix in (u("\xE9nk"), u("\xE9j\xFCk"), + u("\xE9m"), u("\xE9d"), u("\xE9")): + word = "".join((word[:-len(suffix)], "e")) + r1 = "".join((r1[:-len(suffix)], "e")) + else: + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + break + + # STEP 8: Remove plural owner suffixes + for suffix in self.__step8_suffixes: + if word.endswith(suffix): + if r1.endswith(suffix): + if suffix in (u("\xE1im"), u("\xE1id"), u("\xE1i"), + u("\xE1ink"), u("\xE1itok"), u("\xE1ik")): + word = "".join((word[:-len(suffix)], "a")) + r1 = "".join((r1[:-len(suffix)], "a")) + + elif suffix in (u("\xE9im"), u("\xE9id"), u("\xE9i"), + u("\xE9ink"), u("\xE9itek"), u("\xE9ik")): + word = "".join((word[:-len(suffix)], "e")) + r1 = "".join((r1[:-len(suffix)], "e")) + else: + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + break + + # STEP 9: Remove plural suffixes + for suffix in self.__step9_suffixes: + if word.endswith(suffix): + if r1.endswith(suffix): + if suffix == u("\xE1k"): + word = "".join((word[:-2], "a")) + elif suffix == u("\xE9k"): + word = "".join((word[:-2], "e")) + else: + word = word[:-len(suffix)] + break + + return word + + def __r1_hungarian(self, word, vowels, digraphs): + """ + Return the region R1 that is used by the Hungarian stemmer. + + If the word begins with a vowel, R1 is defined as the region + after the first consonant or digraph (= two letters stand for + one phoneme) in the word. If the word begins with a consonant, + it is defined as the region after the first vowel in the word. + If the word does not contain both a vowel and consonant, R1 + is the null region at the end of the word. + + :param word: The Hungarian word whose region R1 is determined. + :type word: str or unicode + :param vowels: The Hungarian vowels that are used to determine + the region R1. + :type vowels: unicode + :param digraphs: The digraphs that are used to determine the + region R1. + :type digraphs: tuple + :return: the region R1 for the respective word. + :rtype: unicode + :note: This helper method is invoked by the stem method of the subclass + HungarianStemmer. It is not to be invoked directly! + + """ + r1 = "" + if word[0] in vowels: + for digraph in digraphs: + if digraph in word[1:]: + r1 = word[word.index(digraph[-1]) + 1:] + return r1 + + for i in range(1, len(word)): + if word[i] not in vowels: + r1 = word[i + 1:] + break + else: + for i in range(1, len(word)): + if word[i] in vowels: + r1 = word[i + 1:] + break + + return r1 diff --git a/nstock/modules/whoosh/lang/snowball/italian.py b/nstock/modules/whoosh/lang/snowball/italian.py new file mode 100644 index 0000000..8a98146 --- /dev/null +++ b/nstock/modules/whoosh/lang/snowball/italian.py @@ -0,0 +1,230 @@ +from .bases import _StandardStemmer + +from whoosh.compat import u + + +class ItalianStemmer(_StandardStemmer): + + """ + The Italian Snowball stemmer. + + :cvar __vowels: The Italian vowels. + :type __vowels: unicode + :cvar __step0_suffixes: Suffixes to be deleted in step 0 of the algorithm. + :type __step0_suffixes: tuple + :cvar __step1_suffixes: Suffixes to be deleted in step 1 of the algorithm. + :type __step1_suffixes: tuple + :cvar __step2_suffixes: Suffixes to be deleted in step 2 of the algorithm. + :type __step2_suffixes: tuple + :note: A detailed description of the Italian + stemming algorithm can be found under + http://snowball.tartarus.org/algorithms/italian/stemmer.html + + """ + + __vowels = u("aeiou\xE0\xE8\xEC\xF2\xF9") + __step0_suffixes = ('gliela', 'gliele', 'glieli', 'glielo', + 'gliene', 'sene', 'mela', 'mele', 'meli', + 'melo', 'mene', 'tela', 'tele', 'teli', + 'telo', 'tene', 'cela', 'cele', 'celi', + 'celo', 'cene', 'vela', 'vele', 'veli', + 'velo', 'vene', 'gli', 'ci', 'la', 'le', + 'li', 'lo', 'mi', 'ne', 'si', 'ti', 'vi') + __step1_suffixes = ('atrice', 'atrici', 'azione', 'azioni', + 'uzione', 'uzioni', 'usione', 'usioni', + 'amento', 'amenti', 'imento', 'imenti', + 'amente', 'abile', 'abili', 'ibile', 'ibili', + 'mente', 'atore', 'atori', 'logia', 'logie', + 'anza', 'anze', 'iche', 'ichi', 'ismo', + 'ismi', 'ista', 'iste', 'isti', u('ist\xE0'), + u('ist\xE8'), u('ist\xEC'), 'ante', 'anti', + 'enza', 'enze', 'ico', 'ici', 'ica', 'ice', + 'oso', 'osi', 'osa', 'ose', u('it\xE0'), + 'ivo', 'ivi', 'iva', 'ive') + __step2_suffixes = ('erebbero', 'irebbero', 'assero', 'assimo', + 'eranno', 'erebbe', 'eremmo', 'ereste', + 'eresti', 'essero', 'iranno', 'irebbe', + 'iremmo', 'ireste', 'iresti', 'iscano', + 'iscono', 'issero', 'arono', 'avamo', 'avano', + 'avate', 'eremo', 'erete', 'erono', 'evamo', + 'evano', 'evate', 'iremo', 'irete', 'irono', + 'ivamo', 'ivano', 'ivate', 'ammo', 'ando', + 'asse', 'assi', 'emmo', 'enda', 'ende', + 'endi', 'endo', 'erai', 'erei', 'Yamo', + 'iamo', 'immo', 'irai', 'irei', 'isca', + 'isce', 'isci', 'isco', 'ano', 'are', 'ata', + 'ate', 'ati', 'ato', 'ava', 'avi', 'avo', + u('er\xE0'), 'ere', u('er\xF2'), 'ete', 'eva', + 'evi', 'evo', u('ir\xE0'), 'ire', u('ir\xF2'), + 'ita', 'ite', 'iti', 'ito', 'iva', 'ivi', + 'ivo', 'ono', 'uta', 'ute', 'uti', 'uto', + 'ar', 'ir') + + def stem(self, word): + """ + Stem an Italian word and return the stemmed form. + + :param word: The word that is stemmed. + :type word: str or unicode + :return: The stemmed form. + :rtype: unicode + + """ + word = word.lower() + + step1_success = False + + # All acute accents are replaced by grave accents. + word = (word.replace(u("\xE1"), u("\xE0")) + .replace(u("\xE9"), u("\xE8")) + .replace(u("\xED"), u("\xEC")) + .replace(u("\xF3"), u("\xF2")) + .replace(u("\xFA"), u("\xF9"))) + + # Every occurrence of 'u' after 'q' + # is put into upper case. + for i in range(1, len(word)): + if word[i - 1] == "q" and word[i] == "u": + word = "".join((word[:i], "U", word[i + 1:])) + + # Every occurrence of 'u' and 'i' + # between vowels is put into upper case. + for i in range(1, len(word) - 1): + if word[i - 1] in self.__vowels and word[i + 1] in self.__vowels: + if word[i] == "u": + word = "".join((word[:i], "U", word[i + 1:])) + elif word[i] == "i": + word = "".join((word[:i], "I", word[i + 1:])) + + r1, r2 = self._r1r2_standard(word, self.__vowels) + rv = self._rv_standard(word, self.__vowels) + + # STEP 0: Attached pronoun + for suffix in self.__step0_suffixes: + if rv.endswith(suffix): + if rv[-len(suffix) - 4:-len(suffix)] in ("ando", "endo"): + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + r2 = r2[:-len(suffix)] + rv = rv[:-len(suffix)] + + elif (rv[-len(suffix) - 2:-len(suffix)] in + ("ar", "er", "ir")): + word = "".join((word[:-len(suffix)], "e")) + r1 = "".join((r1[:-len(suffix)], "e")) + r2 = "".join((r2[:-len(suffix)], "e")) + rv = "".join((rv[:-len(suffix)], "e")) + break + + # STEP 1: Standard suffix removal + for suffix in self.__step1_suffixes: + if word.endswith(suffix): + if suffix == "amente" and r1.endswith(suffix): + step1_success = True + word = word[:-6] + r2 = r2[:-6] + rv = rv[:-6] + + if r2.endswith("iv"): + word = word[:-2] + r2 = r2[:-2] + rv = rv[:-2] + + if r2.endswith("at"): + word = word[:-2] + rv = rv[:-2] + + elif r2.endswith(("os", "ic")): + word = word[:-2] + rv = rv[:-2] + + elif r2 .endswith("abil"): + word = word[:-4] + rv = rv[:-4] + + elif (suffix in ("amento", "amenti", + "imento", "imenti") and + rv.endswith(suffix)): + step1_success = True + word = word[:-6] + rv = rv[:-6] + + elif r2.endswith(suffix): + step1_success = True + if suffix in ("azione", "azioni", "atore", "atori"): + word = word[:-len(suffix)] + r2 = r2[:-len(suffix)] + rv = rv[:-len(suffix)] + + if r2.endswith("ic"): + word = word[:-2] + rv = rv[:-2] + + elif suffix in ("logia", "logie"): + word = word[:-2] + rv = word[:-2] + + elif suffix in ("uzione", "uzioni", + "usione", "usioni"): + word = word[:-5] + rv = rv[:-5] + + elif suffix in ("enza", "enze"): + word = "".join((word[:-2], "te")) + rv = "".join((rv[:-2], "te")) + + elif suffix == u("it\xE0"): + word = word[:-3] + r2 = r2[:-3] + rv = rv[:-3] + + if r2.endswith(("ic", "iv")): + word = word[:-2] + rv = rv[:-2] + + elif r2.endswith("abil"): + word = word[:-4] + rv = rv[:-4] + + elif suffix in ("ivo", "ivi", "iva", "ive"): + word = word[:-3] + r2 = r2[:-3] + rv = rv[:-3] + + if r2.endswith("at"): + word = word[:-2] + r2 = r2[:-2] + rv = rv[:-2] + + if r2.endswith("ic"): + word = word[:-2] + rv = rv[:-2] + else: + word = word[:-len(suffix)] + rv = rv[:-len(suffix)] + break + + # STEP 2: Verb suffixes + if not step1_success: + for suffix in self.__step2_suffixes: + if rv.endswith(suffix): + word = word[:-len(suffix)] + rv = rv[:-len(suffix)] + break + + # STEP 3a + if rv.endswith(("a", "e", "i", "o", u("\xE0"), u("\xE8"), + u("\xEC"), u("\xF2"))): + word = word[:-1] + rv = rv[:-1] + + if rv.endswith("i"): + word = word[:-1] + rv = rv[:-1] + + # STEP 3b + if rv.endswith(("ch", "gh")): + word = word[:-1] + + word = word.replace("I", "i").replace("U", "u") + return word diff --git a/nstock/modules/whoosh/lang/snowball/norwegian.py b/nstock/modules/whoosh/lang/snowball/norwegian.py new file mode 100644 index 0000000..79f872a --- /dev/null +++ b/nstock/modules/whoosh/lang/snowball/norwegian.py @@ -0,0 +1,84 @@ +from .bases import _ScandinavianStemmer + +from whoosh.compat import u + + +class NorwegianStemmer(_ScandinavianStemmer): + + """ + The Norwegian Snowball stemmer. + + :cvar __vowels: The Norwegian vowels. + :type __vowels: unicode + :cvar __s_ending: Letters that may directly appear before a word final 's'. + :type __s_ending: unicode + :cvar __step1_suffixes: Suffixes to be deleted in step 1 of the algorithm. + :type __step1_suffixes: tuple + :cvar __step2_suffixes: Suffixes to be deleted in step 2 of the algorithm. + :type __step2_suffixes: tuple + :cvar __step3_suffixes: Suffixes to be deleted in step 3 of the algorithm. + :type __step3_suffixes: tuple + :note: A detailed description of the Norwegian + stemming algorithm can be found under + http://snowball.tartarus.org/algorithms/norwegian/stemmer.html + + """ + + __vowels = u("aeiouy\xE6\xE5\xF8") + __s_ending = "bcdfghjlmnoprtvyz" + __step1_suffixes = ("hetenes", "hetene", "hetens", "heter", + "heten", "endes", "ande", "ende", "edes", + "enes", "erte", "ede", "ane", "ene", "ens", + "ers", "ets", "het", "ast", "ert", "en", + "ar", "er", "as", "es", "et", "a", "e", "s") + + __step2_suffixes = ("dt", "vt") + + __step3_suffixes = ("hetslov", "eleg", "elig", "elov", "slov", + "leg", "eig", "lig", "els", "lov", "ig") + + def stem(self, word): + """ + Stem a Norwegian word and return the stemmed form. + + :param word: The word that is stemmed. + :type word: str or unicode + :return: The stemmed form. + :rtype: unicode + + """ + word = word.lower() + + r1 = self._r1_scandinavian(word, self.__vowels) + + # STEP 1 + for suffix in self.__step1_suffixes: + if r1.endswith(suffix): + if suffix in ("erte", "ert"): + word = "".join((word[:-len(suffix)], "er")) + r1 = "".join((r1[:-len(suffix)], "er")) + + elif suffix == "s": + if (word[-2] in self.__s_ending or + (word[-2] == "k" and word[-3] not in self.__vowels)): + word = word[:-1] + r1 = r1[:-1] + else: + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + break + + # STEP 2 + for suffix in self.__step2_suffixes: + if r1.endswith(suffix): + word = word[:-1] + r1 = r1[:-1] + break + + # STEP 3 + for suffix in self.__step3_suffixes: + if r1.endswith(suffix): + word = word[:-len(suffix)] + break + + return word diff --git a/nstock/modules/whoosh/lang/snowball/portugese.py b/nstock/modules/whoosh/lang/snowball/portugese.py new file mode 100644 index 0000000..c5fe0c3 --- /dev/null +++ b/nstock/modules/whoosh/lang/snowball/portugese.py @@ -0,0 +1,205 @@ +from .bases import _StandardStemmer + +from whoosh.compat import u + + +class PortugueseStemmer(_StandardStemmer): + + """ + The Portuguese Snowball stemmer. + + :cvar __vowels: The Portuguese vowels. + :type __vowels: unicode + :cvar __step1_suffixes: Suffixes to be deleted in step 1 of the algorithm. + :type __step1_suffixes: tuple + :cvar __step2_suffixes: Suffixes to be deleted in step 2 of the algorithm. + :type __step2_suffixes: tuple + :cvar __step4_suffixes: Suffixes to be deleted in step 4 of the algorithm. + :type __step4_suffixes: tuple + :note: A detailed description of the Portuguese + stemming algorithm can be found under + http://snowball.tartarus.org/algorithms/portuguese/stemmer.html + + """ + + __vowels = u("aeiou\xE1\xE9\xED\xF3\xFA\xE2\xEA\xF4") + __step1_suffixes = ('amentos', 'imentos', 'uciones', 'amento', + 'imento', 'adoras', 'adores', u('a\xE7o~es'), + u('log\xEDas'), u('\xEAncias'), 'amente', + 'idades', 'ismos', 'istas', 'adora', + u('a\xE7a~o'), 'antes', u('\xE2ncia'), + u('log\xEDa'), u('uci\xF3n'), u('\xEAncia'), + 'mente', 'idade', 'ezas', 'icos', 'icas', + 'ismo', u('\xE1vel'), u('\xEDvel'), 'ista', + 'osos', 'osas', 'ador', 'ante', 'ivas', + 'ivos', 'iras', 'eza', 'ico', 'ica', + 'oso', 'osa', 'iva', 'ivo', 'ira') + __step2_suffixes = (u('ar\xEDamos'), u('er\xEDamos'), u('ir\xEDamos'), + u('\xE1ssemos'), u('\xEAssemos'), u('\xEDssemos'), + u('ar\xEDeis'), u('er\xEDeis'), u('ir\xEDeis'), + u('\xE1sseis'), u('\xE9sseis'), u('\xEDsseis'), + u('\xE1ramos'), u('\xE9ramos'), u('\xEDramos'), + u('\xE1vamos'), 'aremos', 'eremos', 'iremos', + 'ariam', 'eriam', 'iriam', 'assem', 'essem', + 'issem', 'ara~o', 'era~o', 'ira~o', 'arias', + 'erias', 'irias', 'ardes', 'erdes', 'irdes', + 'asses', 'esses', 'isses', 'astes', 'estes', + 'istes', u('\xE1reis'), 'areis', u('\xE9reis'), + 'ereis', u('\xEDreis'), 'ireis', u('\xE1veis'), + u('\xEDamos'), 'armos', 'ermos', 'irmos', + 'aria', 'eria', 'iria', 'asse', 'esse', + 'isse', 'aste', 'este', 'iste', 'arei', + 'erei', 'irei', 'aram', 'eram', 'iram', + 'avam', 'arem', 'erem', 'irem', + 'ando', 'endo', 'indo', 'adas', 'idas', + u('ar\xE1s'), 'aras', u('er\xE1s'), 'eras', + u('ir\xE1s'), 'avas', 'ares', 'eres', 'ires', + u('\xEDeis'), 'ados', 'idos', u('\xE1mos'), + 'amos', 'emos', 'imos', 'iras', 'ada', 'ida', + u('ar\xE1'), 'ara', u('er\xE1'), 'era', + u('ir\xE1'), 'ava', 'iam', 'ado', 'ido', + 'ias', 'ais', 'eis', 'ira', 'ia', 'ei', 'am', + 'em', 'ar', 'er', 'ir', 'as', + 'es', 'is', 'eu', 'iu', 'ou') + __step4_suffixes = ("os", "a", "i", "o", u("\xE1"), + u("\xED"), u("\xF3")) + + def stem(self, word): + """ + Stem a Portuguese word and return the stemmed form. + + :param word: The word that is stemmed. + :type word: str or unicode + :return: The stemmed form. + :rtype: unicode + + """ + word = word.lower() + + step1_success = False + step2_success = False + + word = (word.replace(u("\xE3"), "a~") + .replace(u("\xF5"), "o~")) + + r1, r2 = self._r1r2_standard(word, self.__vowels) + rv = self._rv_standard(word, self.__vowels) + + # STEP 1: Standard suffix removal + for suffix in self.__step1_suffixes: + if word.endswith(suffix): + if suffix == "amente" and r1.endswith(suffix): + step1_success = True + + word = word[:-6] + r2 = r2[:-6] + rv = rv[:-6] + + if r2.endswith("iv"): + word = word[:-2] + r2 = r2[:-2] + rv = rv[:-2] + + if r2.endswith("at"): + word = word[:-2] + rv = rv[:-2] + + elif r2.endswith(("os", "ic", "ad")): + word = word[:-2] + rv = rv[:-2] + + elif (suffix in ("ira", "iras") and rv.endswith(suffix) and + word[-len(suffix) - 1:-len(suffix)] == "e"): + step1_success = True + + word = "".join((word[:-len(suffix)], "ir")) + rv = "".join((rv[:-len(suffix)], "ir")) + + elif r2.endswith(suffix): + step1_success = True + + if suffix in (u("log\xEDa"), u("log\xEDas")): + word = word[:-2] + rv = rv[:-2] + + elif suffix in (u("uci\xF3n"), "uciones"): + word = "".join((word[:-len(suffix)], "u")) + rv = "".join((rv[:-len(suffix)], "u")) + + elif suffix in (u("\xEAncia"), u("\xEAncias")): + word = "".join((word[:-len(suffix)], "ente")) + rv = "".join((rv[:-len(suffix)], "ente")) + + elif suffix == "mente": + word = word[:-5] + r2 = r2[:-5] + rv = rv[:-5] + + if r2.endswith(("ante", "avel", u("\xEDvel"))): + word = word[:-4] + rv = rv[:-4] + + elif suffix in ("idade", "idades"): + word = word[:-len(suffix)] + r2 = r2[:-len(suffix)] + rv = rv[:-len(suffix)] + + if r2.endswith(("ic", "iv")): + word = word[:-2] + rv = rv[:-2] + + elif r2.endswith("abil"): + word = word[:-4] + rv = rv[:-4] + + elif suffix in ("iva", "ivo", "ivas", "ivos"): + word = word[:-len(suffix)] + r2 = r2[:-len(suffix)] + rv = rv[:-len(suffix)] + + if r2.endswith("at"): + word = word[:-2] + rv = rv[:-2] + else: + word = word[:-len(suffix)] + rv = rv[:-len(suffix)] + break + + # STEP 2: Verb suffixes + if not step1_success: + for suffix in self.__step2_suffixes: + if rv.endswith(suffix): + step2_success = True + + word = word[:-len(suffix)] + rv = rv[:-len(suffix)] + break + + # STEP 3 + if step1_success or step2_success: + if rv.endswith("i") and word[-2] == "c": + word = word[:-1] + rv = rv[:-1] + + ### STEP 4: Residual suffix + if not step1_success and not step2_success: + for suffix in self.__step4_suffixes: + if rv.endswith(suffix): + word = word[:-len(suffix)] + rv = rv[:-len(suffix)] + break + + # STEP 5 + if rv.endswith(("e", u("\xE9"), u("\xEA"))): + word = word[:-1] + rv = rv[:-1] + + if ((word.endswith("gu") and rv.endswith("u")) or + (word.endswith("ci") and rv.endswith("i"))): + word = word[:-1] + + elif word.endswith(u("\xE7")): + word = "".join((word[:-1], "c")) + + word = word.replace("a~", u("\xE3")).replace("o~", u("\xF5")) + return word diff --git a/nstock/modules/whoosh/lang/snowball/romanian.py b/nstock/modules/whoosh/lang/snowball/romanian.py new file mode 100644 index 0000000..fa38276 --- /dev/null +++ b/nstock/modules/whoosh/lang/snowball/romanian.py @@ -0,0 +1,257 @@ +from .bases import _StandardStemmer + +from whoosh.compat import u + + +class RomanianStemmer(_StandardStemmer): + + """ + The Romanian Snowball stemmer. + + :cvar __vowels: The Romanian vowels. + :type __vowels: unicode + :cvar __step0_suffixes: Suffixes to be deleted in step 0 of the algorithm. + :type __step0_suffixes: tuple + :cvar __step1_suffixes: Suffixes to be deleted in step 1 of the algorithm. + :type __step1_suffixes: tuple + :cvar __step2_suffixes: Suffixes to be deleted in step 2 of the algorithm. + :type __step2_suffixes: tuple + :cvar __step3_suffixes: Suffixes to be deleted in step 3 of the algorithm. + :type __step3_suffixes: tuple + :note: A detailed description of the Romanian + stemming algorithm can be found under + http://snowball.tartarus.org/algorithms/romanian/stemmer.html + + """ + + __vowels = u("aeiou\u0103\xE2\xEE") + __step0_suffixes = ('iilor', 'ului', 'elor', 'iile', 'ilor', + 'atei', u('a\u0163ie'), u('a\u0163ia'), 'aua', + 'ele', 'iua', 'iei', 'ile', 'ul', 'ea', + 'ii') + __step1_suffixes = ('abilitate', 'abilitati', u('abilit\u0103\u0163i'), + 'ibilitate', u('abilit\u0103i'), 'ivitate', + 'ivitati', u('ivit\u0103\u0163i'), 'icitate', + 'icitati', u('icit\u0103\u0163i'), 'icatori', + u('ivit\u0103i'), u('icit\u0103i'), 'icator', + u('a\u0163iune'), 'atoare', u('\u0103toare'), + u('i\u0163iune'), 'itoare', 'iciva', 'icive', + 'icivi', u('iciv\u0103'), 'icala', 'icale', + 'icali', u('ical\u0103'), 'ativa', 'ative', + 'ativi', u('ativ\u0103'), 'atori', u('\u0103tori'), + 'itiva', 'itive', 'itivi', u('itiv\u0103'), + 'itori', 'iciv', 'ical', 'ativ', 'ator', + u('\u0103tor'), 'itiv', 'itor') + __step2_suffixes = ('abila', 'abile', 'abili', u('abil\u0103'), + 'ibila', 'ibile', 'ibili', u('ibil\u0103'), + 'atori', 'itate', 'itati', u('it\u0103\u0163i'), + 'abil', 'ibil', 'oasa', u('oas\u0103'), 'oase', + 'anta', 'ante', 'anti', u('ant\u0103'), 'ator', + u('it\u0103i'), 'iune', 'iuni', 'isme', 'ista', + 'iste', 'isti', u('ist\u0103'), u('i\u015Fti'), + 'ata', u('at\u0103'), 'ati', 'ate', 'uta', + u('ut\u0103'), 'uti', 'ute', 'ita', u('it\u0103'), + 'iti', 'ite', 'ica', 'ice', 'ici', u('ic\u0103'), + 'osi', u('o\u015Fi'), 'ant', 'iva', 'ive', 'ivi', + u('iv\u0103'), 'ism', 'ist', 'at', 'ut', 'it', + 'ic', 'os', 'iv') + __step3_suffixes = (u('seser\u0103\u0163i'), u('aser\u0103\u0163i'), + u('iser\u0103\u0163i'), u('\xE2ser\u0103\u0163i'), + u('user\u0103\u0163i'), u('seser\u0103m'), + u('aser\u0103m'), u('iser\u0103m'), u('\xE2ser\u0103m'), + u('user\u0103m'), u('ser\u0103\u0163i'), u('sese\u015Fi'), + u('seser\u0103'), u('easc\u0103'), u('ar\u0103\u0163i'), + u('ur\u0103\u0163i'), u('ir\u0103\u0163i'), + u('\xE2r\u0103\u0163i'), u('ase\u015Fi'), + u('aser\u0103'), u('ise\u015Fi'), u('iser\u0103'), + u('\xe2se\u015Fi'), u('\xE2ser\u0103'), + u('use\u015Fi'), u('user\u0103'), u('ser\u0103m'), + 'sesem', 'indu', '\xE2ndu', u('eaz\u0103'), + u('e\u015Fti'), u('e\u015Fte'), u('\u0103\u015Fti'), + u('\u0103\u015Fte'), u('ea\u0163i'), u('ia\u0163i'), + u('ar\u0103m'), u('ur\u0103m'), u('ir\u0103m'), + u('\xE2r\u0103m'), 'asem', 'isem', + '\xE2sem', 'usem', u('se\u015Fi'), u('ser\u0103'), + 'sese', 'are', 'ere', 'ire', '\xE2re', + 'ind', '\xE2nd', 'eze', 'ezi', 'esc', + u('\u0103sc'), 'eam', 'eai', 'eau', 'iam', + 'iai', 'iau', u('a\u015Fi'), u('ar\u0103'), + u('u\u015Fi'), u('ur\u0103'), u('i\u015Fi'), u('ir\u0103'), + u('\xE2\u015Fi'), u('\xe2r\u0103'), 'ase', + 'ise', '\xE2se', 'use', u('a\u0163i'), + u('e\u0163i'), u('i\u0163i'), u('\xe2\u0163i'), 'sei', + 'ez', 'am', 'ai', 'au', 'ea', 'ia', 'ui', + '\xE2i', u('\u0103m'), 'em', 'im', '\xE2m', + 'se') + + def stem(self, word): + """ + Stem a Romanian word and return the stemmed form. + + :param word: The word that is stemmed. + :type word: str or unicode + :return: The stemmed form. + :rtype: unicode + + """ + word = word.lower() + + step1_success = False + step2_success = False + + for i in range(1, len(word) - 1): + if word[i - 1] in self.__vowels and word[i + 1] in self.__vowels: + if word[i] == "u": + word = "".join((word[:i], "U", word[i + 1:])) + + elif word[i] == "i": + word = "".join((word[:i], "I", word[i + 1:])) + + r1, r2 = self._r1r2_standard(word, self.__vowels) + rv = self._rv_standard(word, self.__vowels) + + # STEP 0: Removal of plurals and other simplifications + for suffix in self.__step0_suffixes: + if word.endswith(suffix): + if suffix in r1: + if suffix in ("ul", "ului"): + word = word[:-len(suffix)] + + if suffix in rv: + rv = rv[:-len(suffix)] + else: + rv = "" + + elif (suffix == "aua" or suffix == "atei" or + (suffix == "ile" and word[-5:-3] != "ab")): + word = word[:-2] + + elif suffix in ("ea", "ele", "elor"): + word = "".join((word[:-len(suffix)], "e")) + + if suffix in rv: + rv = "".join((rv[:-len(suffix)], "e")) + else: + rv = "" + + elif suffix in ("ii", "iua", "iei", + "iile", "iilor", "ilor"): + word = "".join((word[:-len(suffix)], "i")) + + if suffix in rv: + rv = "".join((rv[:-len(suffix)], "i")) + else: + rv = "" + + elif suffix in ("a\u0163ie", "a\u0163ia"): + word = word[:-1] + break + + # STEP 1: Reduction of combining suffixes + while True: + + replacement_done = False + + for suffix in self.__step1_suffixes: + if word.endswith(suffix): + if suffix in r1: + step1_success = True + replacement_done = True + + if suffix in ("abilitate", "abilitati", + "abilit\u0103i", + "abilit\u0103\u0163i"): + word = "".join((word[:-len(suffix)], "abil")) + + elif suffix == "ibilitate": + word = word[:-5] + + elif suffix in ("ivitate", "ivitati", + "ivit\u0103i", + "ivit\u0103\u0163i"): + word = "".join((word[:-len(suffix)], "iv")) + + elif suffix in ("icitate", "icitati", "icit\u0103i", + "icit\u0103\u0163i", "icator", + "icatori", "iciv", "iciva", + "icive", "icivi", "iciv\u0103", + "ical", "icala", "icale", "icali", + "ical\u0103"): + word = "".join((word[:-len(suffix)], "ic")) + + elif suffix in ("ativ", "ativa", "ative", "ativi", + "ativ\u0103", "a\u0163iune", + "atoare", "ator", "atori", + "\u0103toare", + "\u0103tor", "\u0103tori"): + word = "".join((word[:-len(suffix)], "at")) + + if suffix in r2: + r2 = "".join((r2[:-len(suffix)], "at")) + + elif suffix in ("itiv", "itiva", "itive", "itivi", + "itiv\u0103", "i\u0163iune", + "itoare", "itor", "itori"): + word = "".join((word[:-len(suffix)], "it")) + + if suffix in r2: + r2 = "".join((r2[:-len(suffix)], "it")) + else: + step1_success = False + break + + if not replacement_done: + break + + # STEP 2: Removal of standard suffixes + for suffix in self.__step2_suffixes: + if word.endswith(suffix): + if suffix in r2: + step2_success = True + + if suffix in ("iune", "iuni"): + if word[-5] == "\u0163": + word = "".join((word[:-5], "t")) + + elif suffix in ("ism", "isme", "ist", "ista", "iste", + "isti", "ist\u0103", "i\u015Fti"): + word = "".join((word[:-len(suffix)], "ist")) + + else: + word = word[:-len(suffix)] + break + + # STEP 3: Removal of verb suffixes + if not step1_success and not step2_success: + for suffix in self.__step3_suffixes: + try: + if word.endswith(suffix): + if suffix in rv: + if suffix in (u('seser\u0103\u0163i'), u('seser\u0103m'), + u('ser\u0103\u0163i'), u('sese\u015Fi'), + u('seser\u0103'), u('ser\u0103m'), 'sesem', + u('se\u015Fi'), u('ser\u0103'), 'sese', + u('a\u0163i'), u('e\u0163i'), u('i\u0163i'), + u('\xE2\u0163i'), 'sei', u('\u0103m'), + 'em', 'im', '\xE2m', 'se'): + word = word[:-len(suffix)] + rv = rv[:-len(suffix)] + else: + if (not rv.startswith(suffix) and + rv[rv.index(suffix) - 1] not in + "aeio\u0103\xE2\xEE"): + word = word[:-len(suffix)] + break + except UnicodeDecodeError: + # The word is unicode, but suffix is not + continue + + # STEP 4: Removal of final vowel + for suffix in ("ie", "a", "e", "i", "\u0103"): + if word.endswith(suffix): + if suffix in rv: + word = word[:-len(suffix)] + break + + word = word.replace("I", "i").replace("U", "u") + return word diff --git a/nstock/modules/whoosh/lang/snowball/russian.py b/nstock/modules/whoosh/lang/snowball/russian.py new file mode 100644 index 0000000..80cf0dc --- /dev/null +++ b/nstock/modules/whoosh/lang/snowball/russian.py @@ -0,0 +1,422 @@ +from whoosh.compat import u + +class RussianStemmer(object): + """ + The Russian Snowball stemmer. + + :cvar __perfective_gerund_suffixes: Suffixes to be deleted. + :type __perfective_gerund_suffixes: tuple + :cvar __adjectival_suffixes: Suffixes to be deleted. + :type __adjectival_suffixes: tuple + :cvar __reflexive_suffixes: Suffixes to be deleted. + :type __reflexive_suffixes: tuple + :cvar __verb_suffixes: Suffixes to be deleted. + :type __verb_suffixes: tuple + :cvar __noun_suffixes: Suffixes to be deleted. + :type __noun_suffixes: tuple + :cvar __superlative_suffixes: Suffixes to be deleted. + :type __superlative_suffixes: tuple + :cvar __derivational_suffixes: Suffixes to be deleted. + :type __derivational_suffixes: tuple + :note: A detailed description of the Russian + stemming algorithm can be found under + http://snowball.tartarus.org/algorithms/russian/stemmer.html + + """ + + __perfective_gerund_suffixes = ("ivshis'", "yvshis'", "vshis'", + "ivshi", "yvshi", "vshi", "iv", + "yv", "v") + __adjectival_suffixes = ('ui^ushchi^ui^u', 'ui^ushchi^ai^a', + 'ui^ushchimi', 'ui^ushchymi', 'ui^ushchego', + 'ui^ushchogo', 'ui^ushchemu', 'ui^ushchomu', + 'ui^ushchikh', 'ui^ushchykh', + 'ui^ushchui^u', 'ui^ushchaia', + 'ui^ushchoi^u', 'ui^ushchei^u', + 'i^ushchi^ui^u', 'i^ushchi^ai^a', + 'ui^ushchee', 'ui^ushchie', + 'ui^ushchye', 'ui^ushchoe', 'ui^ushchei`', + 'ui^ushchii`', 'ui^ushchyi`', + 'ui^ushchoi`', 'ui^ushchem', 'ui^ushchim', + 'ui^ushchym', 'ui^ushchom', 'i^ushchimi', + 'i^ushchymi', 'i^ushchego', 'i^ushchogo', + 'i^ushchemu', 'i^ushchomu', 'i^ushchikh', + 'i^ushchykh', 'i^ushchui^u', 'i^ushchai^a', + 'i^ushchoi^u', 'i^ushchei^u', 'i^ushchee', + 'i^ushchie', 'i^ushchye', 'i^ushchoe', + 'i^ushchei`', 'i^ushchii`', + 'i^ushchyi`', 'i^ushchoi`', 'i^ushchem', + 'i^ushchim', 'i^ushchym', 'i^ushchom', + 'shchi^ui^u', 'shchi^ai^a', 'ivshi^ui^u', + 'ivshi^ai^a', 'yvshi^ui^u', 'yvshi^ai^a', + 'shchimi', 'shchymi', 'shchego', 'shchogo', + 'shchemu', 'shchomu', 'shchikh', 'shchykh', + 'shchui^u', 'shchai^a', 'shchoi^u', + 'shchei^u', 'ivshimi', 'ivshymi', + 'ivshego', 'ivshogo', 'ivshemu', 'ivshomu', + 'ivshikh', 'ivshykh', 'ivshui^u', + 'ivshai^a', 'ivshoi^u', 'ivshei^u', + 'yvshimi', 'yvshymi', 'yvshego', 'yvshogo', + 'yvshemu', 'yvshomu', 'yvshikh', 'yvshykh', + 'yvshui^u', 'yvshai^a', 'yvshoi^u', + 'yvshei^u', 'vshi^ui^u', 'vshi^ai^a', + 'shchee', 'shchie', 'shchye', 'shchoe', + 'shchei`', 'shchii`', 'shchyi`', 'shchoi`', + 'shchem', 'shchim', 'shchym', 'shchom', + 'ivshee', 'ivshie', 'ivshye', 'ivshoe', + 'ivshei`', 'ivshii`', 'ivshyi`', + 'ivshoi`', 'ivshem', 'ivshim', 'ivshym', + 'ivshom', 'yvshee', 'yvshie', 'yvshye', + 'yvshoe', 'yvshei`', 'yvshii`', + 'yvshyi`', 'yvshoi`', 'yvshem', + 'yvshim', 'yvshym', 'yvshom', 'vshimi', + 'vshymi', 'vshego', 'vshogo', 'vshemu', + 'vshomu', 'vshikh', 'vshykh', 'vshui^u', + 'vshai^a', 'vshoi^u', 'vshei^u', + 'emi^ui^u', 'emi^ai^a', 'nni^ui^u', + 'nni^ai^a', 'vshee', + 'vshie', 'vshye', 'vshoe', 'vshei`', + 'vshii`', 'vshyi`', 'vshoi`', + 'vshem', 'vshim', 'vshym', 'vshom', + 'emimi', 'emymi', 'emego', 'emogo', + 'ememu', 'emomu', 'emikh', 'emykh', + 'emui^u', 'emai^a', 'emoi^u', 'emei^u', + 'nnimi', 'nnymi', 'nnego', 'nnogo', + 'nnemu', 'nnomu', 'nnikh', 'nnykh', + 'nnui^u', 'nnai^a', 'nnoi^u', 'nnei^u', + 'emee', 'emie', 'emye', 'emoe', + 'emei`', 'emii`', 'emyi`', + 'emoi`', 'emem', 'emim', 'emym', + 'emom', 'nnee', 'nnie', 'nnye', 'nnoe', + 'nnei`', 'nnii`', 'nnyi`', + 'nnoi`', 'nnem', 'nnim', 'nnym', + 'nnom', 'i^ui^u', 'i^ai^a', 'imi', 'ymi', + 'ego', 'ogo', 'emu', 'omu', 'ikh', + 'ykh', 'ui^u', 'ai^a', 'oi^u', 'ei^u', + 'ee', 'ie', 'ye', 'oe', 'ei`', + 'ii`', 'yi`', 'oi`', 'em', + 'im', 'ym', 'om') + __reflexive_suffixes = ("si^a", "s'") + __verb_suffixes = ("esh'", 'ei`te', 'ui`te', 'ui^ut', + "ish'", 'ete', 'i`te', 'i^ut', 'nno', + 'ila', 'yla', 'ena', 'ite', 'ili', 'yli', + 'ilo', 'ylo', 'eno', 'i^at', 'uet', 'eny', + "it'", "yt'", 'ui^u', 'la', 'na', 'li', + 'em', 'lo', 'no', 'et', 'ny', "t'", + 'ei`', 'ui`', 'il', 'yl', 'im', + 'ym', 'en', 'it', 'yt', 'i^u', 'i`', + 'l', 'n') + __noun_suffixes = ('ii^ami', 'ii^akh', 'i^ami', 'ii^am', 'i^akh', + 'ami', 'iei`', 'i^am', 'iem', 'akh', + 'ii^u', "'i^u", 'ii^a', "'i^a", 'ev', 'ov', + 'ie', "'e", 'ei', 'ii', 'ei`', + 'oi`', 'ii`', 'em', 'am', 'om', + 'i^u', 'i^a', 'a', 'e', 'i', 'i`', + 'o', 'u', 'y', "'") + __superlative_suffixes = ("ei`she", "ei`sh") + __derivational_suffixes = ("ost'", "ost") + + def stem(self, word): + """ + Stem a Russian word and return the stemmed form. + + :param word: The word that is stemmed. + :type word: str or unicode + :return: The stemmed form. + :rtype: unicode + + """ + chr_exceeded = False + for i in range(len(word)): + if ord(word[i]) > 255: + chr_exceeded = True + break + + if chr_exceeded: + word = self.__cyrillic_to_roman(word) + + step1_success = False + adjectival_removed = False + verb_removed = False + undouble_success = False + superlative_removed = False + + rv, r2 = self.__regions_russian(word) + + # Step 1 + for suffix in self.__perfective_gerund_suffixes: + if rv.endswith(suffix): + if suffix in ("v", "vshi", "vshis'"): + if (rv[-len(suffix) - 3:-len(suffix)] == "i^a" or + rv[-len(suffix) - 1:-len(suffix)] == "a"): + word = word[:-len(suffix)] + r2 = r2[:-len(suffix)] + rv = rv[:-len(suffix)] + step1_success = True + break + else: + word = word[:-len(suffix)] + r2 = r2[:-len(suffix)] + rv = rv[:-len(suffix)] + step1_success = True + break + + if not step1_success: + for suffix in self.__reflexive_suffixes: + if rv.endswith(suffix): + word = word[:-len(suffix)] + r2 = r2[:-len(suffix)] + rv = rv[:-len(suffix)] + break + + for suffix in self.__adjectival_suffixes: + if rv.endswith(suffix): + if suffix in ('i^ushchi^ui^u', 'i^ushchi^ai^a', + 'i^ushchui^u', 'i^ushchai^a', 'i^ushchoi^u', + 'i^ushchei^u', 'i^ushchimi', 'i^ushchymi', + 'i^ushchego', 'i^ushchogo', 'i^ushchemu', + 'i^ushchomu', 'i^ushchikh', 'i^ushchykh', + 'shchi^ui^u', 'shchi^ai^a', 'i^ushchee', + 'i^ushchie', 'i^ushchye', 'i^ushchoe', + 'i^ushchei`', 'i^ushchii`', 'i^ushchyi`', + 'i^ushchoi`', 'i^ushchem', 'i^ushchim', + 'i^ushchym', 'i^ushchom', 'vshi^ui^u', + 'vshi^ai^a', 'shchui^u', 'shchai^a', + 'shchoi^u', 'shchei^u', 'emi^ui^u', + 'emi^ai^a', 'nni^ui^u', 'nni^ai^a', + 'shchimi', 'shchymi', 'shchego', 'shchogo', + 'shchemu', 'shchomu', 'shchikh', 'shchykh', + 'vshui^u', 'vshai^a', 'vshoi^u', 'vshei^u', + 'shchee', 'shchie', 'shchye', 'shchoe', + 'shchei`', 'shchii`', 'shchyi`', 'shchoi`', + 'shchem', 'shchim', 'shchym', 'shchom', + 'vshimi', 'vshymi', 'vshego', 'vshogo', + 'vshemu', 'vshomu', 'vshikh', 'vshykh', + 'emui^u', 'emai^a', 'emoi^u', 'emei^u', + 'nnui^u', 'nnai^a', 'nnoi^u', 'nnei^u', + 'vshee', 'vshie', 'vshye', 'vshoe', + 'vshei`', 'vshii`', 'vshyi`', 'vshoi`', + 'vshem', 'vshim', 'vshym', 'vshom', + 'emimi', 'emymi', 'emego', 'emogo', + 'ememu', 'emomu', 'emikh', 'emykh', + 'nnimi', 'nnymi', 'nnego', 'nnogo', + 'nnemu', 'nnomu', 'nnikh', 'nnykh', + 'emee', 'emie', 'emye', 'emoe', 'emei`', + 'emii`', 'emyi`', 'emoi`', 'emem', 'emim', + 'emym', 'emom', 'nnee', 'nnie', 'nnye', + 'nnoe', 'nnei`', 'nnii`', 'nnyi`', 'nnoi`', + 'nnem', 'nnim', 'nnym', 'nnom'): + if (rv[-len(suffix) - 3:-len(suffix)] == "i^a" or + rv[-len(suffix) - 1:-len(suffix)] == "a"): + word = word[:-len(suffix)] + r2 = r2[:-len(suffix)] + rv = rv[:-len(suffix)] + adjectival_removed = True + break + else: + word = word[:-len(suffix)] + r2 = r2[:-len(suffix)] + rv = rv[:-len(suffix)] + adjectival_removed = True + break + + if not adjectival_removed: + for suffix in self.__verb_suffixes: + if rv.endswith(suffix): + if suffix in ("la", "na", "ete", "i`te", "li", + "i`", "l", "em", "n", "lo", "no", + "et", "i^ut", "ny", "t'", "esh'", + "nno"): + if (rv[-len(suffix) - 3:-len(suffix)] == "i^a" or + rv[-len(suffix) - 1:-len(suffix)] == "a"): + word = word[:-len(suffix)] + r2 = r2[:-len(suffix)] + rv = rv[:-len(suffix)] + verb_removed = True + break + else: + word = word[:-len(suffix)] + r2 = r2[:-len(suffix)] + rv = rv[:-len(suffix)] + verb_removed = True + break + + if not adjectival_removed and not verb_removed: + for suffix in self.__noun_suffixes: + if rv.endswith(suffix): + word = word[:-len(suffix)] + r2 = r2[:-len(suffix)] + rv = rv[:-len(suffix)] + break + + # Step 2 + if rv.endswith("i"): + word = word[:-1] + r2 = r2[:-1] + + # Step 3 + for suffix in self.__derivational_suffixes: + if r2.endswith(suffix): + word = word[:-len(suffix)] + break + + # Step 4 + if word.endswith("nn"): + word = word[:-1] + undouble_success = True + + if not undouble_success: + for suffix in self.__superlative_suffixes: + if word.endswith(suffix): + word = word[:-len(suffix)] + superlative_removed = True + break + if word.endswith("nn"): + word = word[:-1] + + if not undouble_success and not superlative_removed: + if word.endswith("'"): + word = word[:-1] + + if chr_exceeded: + word = self.__roman_to_cyrillic(word) + return word + + def __regions_russian(self, word): + """ + Return the regions RV and R2 which are used by the Russian stemmer. + + In any word, RV is the region after the first vowel, + or the end of the word if it contains no vowel. + + R2 is the region after the first non-vowel following + a vowel in R1, or the end of the word if there is no such non-vowel. + + R1 is the region after the first non-vowel following a vowel, + or the end of the word if there is no such non-vowel. + + :param word: The Russian word whose regions RV and R2 are determined. + :type word: str or unicode + :return: the regions RV and R2 for the respective Russian word. + :rtype: tuple + :note: This helper method is invoked by the stem method of the subclass + RussianStemmer. It is not to be invoked directly! + + """ + r1 = "" + r2 = "" + rv = "" + + vowels = ("A", "U", "E", "a", "e", "i", "o", "u", "y") + word = (word.replace("i^a", "A") + .replace("i^u", "U") + .replace("e`", "E")) + + for i in range(1, len(word)): + if word[i] not in vowels and word[i - 1] in vowels: + r1 = word[i + 1:] + break + + for i in range(1, len(r1)): + if r1[i] not in vowels and r1[i - 1] in vowels: + r2 = r1[i + 1:] + break + + for i in range(len(word)): + if word[i] in vowels: + rv = word[i + 1:] + break + + r2 = (r2.replace("A", "i^a") + .replace("U", "i^u") + .replace("E", "e`")) + rv = (rv.replace("A", "i^a") + .replace("U", "i^u") + .replace("E", "e`")) + return (rv, r2) + + def __cyrillic_to_roman(self, word): + """ + Transliterate a Russian word into the Roman alphabet. + + A Russian word whose letters consist of the Cyrillic + alphabet are transliterated into the Roman alphabet + in order to ease the forthcoming stemming process. + + :param word: The word that is transliterated. + :type word: unicode + :return: the transliterated word. + :rtype: unicode + :note: This helper method is invoked by the stem method of the subclass + RussianStemmer. It is not to be invoked directly! + + """ + word = (word.replace(u("\u0410"), "a").replace(u("\u0430"), "a") + .replace(u("\u0411"), "b").replace(u("\u0431"), "b") + .replace(u("\u0412"), "v").replace(u("\u0432"), "v") + .replace(u("\u0413"), "g").replace(u("\u0433"), "g") + .replace(u("\u0414"), "d").replace(u("\u0434"), "d") + .replace(u("\u0415"), "e").replace(u("\u0435"), "e") + .replace(u("\u0401"), "e").replace(u("\u0451"), "e") + .replace(u("\u0416"), "zh").replace(u("\u0436"), "zh") + .replace(u("\u0417"), "z").replace(u("\u0437"), "z") + .replace(u("\u0418"), "i").replace(u("\u0438"), "i") + .replace(u("\u0419"), "i`").replace(u("\u0439"), "i`") + .replace(u("\u041A"), "k").replace(u("\u043A"), "k") + .replace(u("\u041B"), "l").replace(u("\u043B"), "l") + .replace(u("\u041C"), "m").replace(u("\u043C"), "m") + .replace(u("\u041D"), "n").replace(u("\u043D"), "n") + .replace(u("\u041E"), "o").replace(u("\u043E"), "o") + .replace(u("\u041F"), "p").replace(u("\u043F"), "p") + .replace(u("\u0420"), "r").replace(u("\u0440"), "r") + .replace(u("\u0421"), "s").replace(u("\u0441"), "s") + .replace(u("\u0422"), "t").replace(u("\u0442"), "t") + .replace(u("\u0423"), "u").replace(u("\u0443"), "u") + .replace(u("\u0424"), "f").replace(u("\u0444"), "f") + .replace(u("\u0425"), "kh").replace(u("\u0445"), "kh") + .replace(u("\u0426"), "t^s").replace(u("\u0446"), "t^s") + .replace(u("\u0427"), "ch").replace(u("\u0447"), "ch") + .replace(u("\u0428"), "sh").replace(u("\u0448"), "sh") + .replace(u("\u0429"), "shch").replace(u("\u0449"), "shch") + .replace(u("\u042A"), "''").replace(u("\u044A"), "''") + .replace(u("\u042B"), "y").replace(u("\u044B"), "y") + .replace(u("\u042C"), "'").replace(u("\u044C"), "'") + .replace(u("\u042D"), "e`").replace(u("\u044D"), "e`") + .replace(u("\u042E"), "i^u").replace(u("\u044E"), "i^u") + .replace(u("\u042F"), "i^a").replace(u("\u044F"), "i^a")) + return word + + def __roman_to_cyrillic(self, word): + """ + Transliterate a Russian word back into the Cyrillic alphabet. + + A Russian word formerly transliterated into the Roman alphabet + in order to ease the stemming process, is transliterated back + into the Cyrillic alphabet, its original form. + + :param word: The word that is transliterated. + :type word: str or unicode + :return: word, the transliterated word. + :rtype: unicode + :note: This helper method is invoked by the stem method of the subclass + RussianStemmer. It is not to be invoked directly! + + """ + word = (word.replace("i^u", u("\u044E")).replace("i^a", u("\u044F")) + .replace("shch", u("\u0449")).replace("kh", u("\u0445")) + .replace("t^s", u("\u0446")).replace("ch", u("\u0447")) + .replace("e`", u("\u044D")).replace("i`", u("\u0439")) + .replace("sh", u("\u0448")).replace("k", u("\u043A")) + .replace("e", u("\u0435")).replace("zh", u("\u0436")) + .replace("a", u("\u0430")).replace("b", u("\u0431")) + .replace("v", u("\u0432")).replace("g", u("\u0433")) + .replace("d", u("\u0434")).replace("e", u("\u0435")) + .replace("z", u("\u0437")).replace("i", u("\u0438")) + .replace("l", u("\u043B")).replace("m", u("\u043C")) + .replace("n", u("\u043D")).replace("o", u("\u043E")) + .replace("p", u("\u043F")).replace("r", u("\u0440")) + .replace("s", u("\u0441")).replace("t", u("\u0442")) + .replace("u", u("\u0443")).replace("f", u("\u0444")) + .replace("''", u("\u044A")).replace("y", u("\u044B")) + .replace("'", u("\u044C"))) + return word diff --git a/nstock/modules/whoosh/lang/snowball/spanish.py b/nstock/modules/whoosh/lang/snowball/spanish.py new file mode 100644 index 0000000..5fbae80 --- /dev/null +++ b/nstock/modules/whoosh/lang/snowball/spanish.py @@ -0,0 +1,248 @@ +from .bases import _StandardStemmer + +from whoosh.compat import u + + +class SpanishStemmer(_StandardStemmer): + + """ + The Spanish Snowball stemmer. + + :cvar __vowels: The Spanish vowels. + :type __vowels: unicode + :cvar __step0_suffixes: Suffixes to be deleted in step 0 of the algorithm. + :type __step0_suffixes: tuple + :cvar __step1_suffixes: Suffixes to be deleted in step 1 of the algorithm. + :type __step1_suffixes: tuple + :cvar __step2a_suffixes: Suffixes to be deleted in step 2a of the algorithm. + :type __step2a_suffixes: tuple + :cvar __step2b_suffixes: Suffixes to be deleted in step 2b of the algorithm. + :type __step2b_suffixes: tuple + :cvar __step3_suffixes: Suffixes to be deleted in step 3 of the algorithm. + :type __step3_suffixes: tuple + :note: A detailed description of the Spanish + stemming algorithm can be found under + http://snowball.tartarus.org/algorithms/spanish/stemmer.html + + """ + + __vowels = u("aeiou\xE1\xE9\xED\xF3\xFA\xFC") + __step0_suffixes = ("selas", "selos", "sela", "selo", "las", + "les", "los", "nos", "me", "se", "la", "le", + "lo") + __step1_suffixes = ('amientos', 'imientos', 'amiento', 'imiento', + 'aciones', 'uciones', 'adoras', 'adores', + 'ancias', u('log\xEDas'), 'encias', 'amente', + 'idades', 'anzas', 'ismos', 'ables', 'ibles', + 'istas', 'adora', u('aci\xF3n'), 'antes', + 'ancia', u('log\xEDa'), u('uci\xf3n'), 'encia', + 'mente', 'anza', 'icos', 'icas', 'ismo', + 'able', 'ible', 'ista', 'osos', 'osas', + 'ador', 'ante', 'idad', 'ivas', 'ivos', + 'ico', + 'ica', 'oso', 'osa', 'iva', 'ivo') + __step2a_suffixes = ('yeron', 'yendo', 'yamos', 'yais', 'yan', + 'yen', 'yas', 'yes', 'ya', 'ye', 'yo', + u('y\xF3')) + __step2b_suffixes = (u('ar\xEDamos'), u('er\xEDamos'), u('ir\xEDamos'), + u('i\xE9ramos'), u('i\xE9semos'), u('ar\xEDais'), + 'aremos', u('er\xEDais'), 'eremos', + u('ir\xEDais'), 'iremos', 'ierais', 'ieseis', + 'asteis', 'isteis', u('\xE1bamos'), + u('\xE1ramos'), u('\xE1semos'), u('ar\xEDan'), + u('ar\xEDas'), u('ar\xE9is'), u('er\xEDan'), + u('er\xEDas'), u('er\xE9is'), u('ir\xEDan'), + u('ir\xEDas'), u('ir\xE9is'), + 'ieran', 'iesen', 'ieron', 'iendo', 'ieras', + 'ieses', 'abais', 'arais', 'aseis', + u('\xE9amos'), u('ar\xE1n'), u('ar\xE1s'), + u('ar\xEDa'), u('er\xE1n'), u('er\xE1s'), + u('er\xEDa'), u('ir\xE1n'), u('ir\xE1s'), + u('ir\xEDa'), 'iera', 'iese', 'aste', 'iste', + 'aban', 'aran', 'asen', 'aron', 'ando', + 'abas', 'adas', 'idas', 'aras', 'ases', + u('\xEDais'), 'ados', 'idos', 'amos', 'imos', + 'emos', u('ar\xE1'), u('ar\xE9'), u('er\xE1'), + u('er\xE9'), u('ir\xE1'), u('ir\xE9'), 'aba', + 'ada', 'ida', 'ara', 'ase', u('\xEDan'), + 'ado', 'ido', u('\xEDas'), u('\xE1is'), + u('\xE9is'), u('\xEDa'), 'ad', 'ed', 'id', + 'an', u('i\xF3'), 'ar', 'er', 'ir', 'as', + u('\xEDs'), 'en', 'es') + __step3_suffixes = ("os", "a", "e", "o", u("\xE1"), + u("\xE9"), u("\xED"), u("\xF3")) + + def stem(self, word): + """ + Stem a Spanish word and return the stemmed form. + + :param word: The word that is stemmed. + :type word: str or unicode + :return: The stemmed form. + :rtype: unicode + + """ + word = word.lower() + + step1_success = False + + r1, r2 = self._r1r2_standard(word, self.__vowels) + rv = self._rv_standard(word, self.__vowels) + + # STEP 0: Attached pronoun + for suffix in self.__step0_suffixes: + if word.endswith(suffix): + if rv.endswith(suffix): + if rv[:-len(suffix)].endswith((u("i\xE9ndo"), + u("\xE1ndo"), + u("\xE1r"), u("\xE9r"), + u("\xEDr"))): + word = (word[:-len(suffix)].replace(u("\xE1"), "a") + .replace(u("\xE9"), "e") + .replace(u("\xED"), "i")) + r1 = (r1[:-len(suffix)].replace(u("\xE1"), "a") + .replace(u("\xE9"), "e") + .replace(u("\xED"), "i")) + r2 = (r2[:-len(suffix)].replace(u("\xE1"), "a") + .replace(u("\xE9"), "e") + .replace(u("\xED"), "i")) + rv = (rv[:-len(suffix)].replace(u("\xE1"), "a") + .replace(u("\xE9"), "e") + .replace(u("\xED"), "i")) + + elif rv[:-len(suffix)].endswith(("ando", "iendo", + "ar", "er", "ir")): + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + r2 = r2[:-len(suffix)] + rv = rv[:-len(suffix)] + + elif (rv[:-len(suffix)].endswith("yendo") and + word[:-len(suffix)].endswith("uyendo")): + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + r2 = r2[:-len(suffix)] + rv = rv[:-len(suffix)] + break + + # STEP 1: Standard suffix removal + for suffix in self.__step1_suffixes: + if word.endswith(suffix): + if suffix == "amente" and r1.endswith(suffix): + step1_success = True + word = word[:-6] + r2 = r2[:-6] + rv = rv[:-6] + + if r2.endswith("iv"): + word = word[:-2] + r2 = r2[:-2] + rv = rv[:-2] + + if r2.endswith("at"): + word = word[:-2] + rv = rv[:-2] + + elif r2.endswith(("os", "ic", "ad")): + word = word[:-2] + rv = rv[:-2] + + elif r2.endswith(suffix): + step1_success = True + if suffix in ("adora", "ador", u("aci\xF3n"), "adoras", + "adores", "aciones", "ante", "antes", + "ancia", "ancias"): + word = word[:-len(suffix)] + r2 = r2[:-len(suffix)] + rv = rv[:-len(suffix)] + + if r2.endswith("ic"): + word = word[:-2] + rv = rv[:-2] + + elif suffix in (u("log\xEDa"), u("log\xEDas")): + word = word.replace(suffix, "log") + rv = rv.replace(suffix, "log") + + elif suffix in (u("uci\xF3n"), "uciones"): + word = word.replace(suffix, "u") + rv = rv.replace(suffix, "u") + + elif suffix in ("encia", "encias"): + word = word.replace(suffix, "ente") + rv = rv.replace(suffix, "ente") + + elif suffix == "mente": + word = word[:-5] + r2 = r2[:-5] + rv = rv[:-5] + + if r2.endswith(("ante", "able", "ible")): + word = word[:-4] + rv = rv[:-4] + + elif suffix in ("idad", "idades"): + word = word[:-len(suffix)] + r2 = r2[:-len(suffix)] + rv = rv[:-len(suffix)] + + for pre_suff in ("abil", "ic", "iv"): + if r2.endswith(pre_suff): + word = word[:-len(pre_suff)] + rv = rv[:-len(pre_suff)] + + elif suffix in ("ivo", "iva", "ivos", "ivas"): + word = word[:-len(suffix)] + r2 = r2[:-len(suffix)] + rv = rv[:-len(suffix)] + if r2.endswith("at"): + word = word[:-2] + rv = rv[:-2] + else: + word = word[:-len(suffix)] + rv = rv[:-len(suffix)] + break + + # STEP 2a: Verb suffixes beginning 'y' + if not step1_success: + for suffix in self.__step2a_suffixes: + if (rv.endswith(suffix) and + word[-len(suffix) - 1:-len(suffix)] == "u"): + word = word[:-len(suffix)] + rv = rv[:-len(suffix)] + break + + # STEP 2b: Other verb suffixes + for suffix in self.__step2b_suffixes: + if rv.endswith(suffix): + if suffix in ("en", "es", u("\xE9is"), "emos"): + word = word[:-len(suffix)] + rv = rv[:-len(suffix)] + + if word.endswith("gu"): + word = word[:-1] + + if rv.endswith("gu"): + rv = rv[:-1] + else: + word = word[:-len(suffix)] + rv = rv[:-len(suffix)] + break + + # STEP 3: Residual suffix + for suffix in self.__step3_suffixes: + if rv.endswith(suffix): + if suffix in ("e", u("\xE9")): + word = word[:-len(suffix)] + rv = rv[:-len(suffix)] + + if len(word) >= 2 and word[-2:] == "gu" and rv[-1] == "u": + word = word[:-1] + else: + word = word[:-len(suffix)] + break + + word = (word.replace(u("\xE1"), "a").replace(u("\xE9"), "e") + .replace(u("\xED"), "i").replace(u("\xF3"), "o") + .replace(u("\xFA"), "u")) + return word diff --git a/nstock/modules/whoosh/lang/snowball/swedish.py b/nstock/modules/whoosh/lang/snowball/swedish.py new file mode 100644 index 0000000..037e273 --- /dev/null +++ b/nstock/modules/whoosh/lang/snowball/swedish.py @@ -0,0 +1,80 @@ +from .bases import _ScandinavianStemmer + +from whoosh.compat import u + + +class SwedishStemmer(_ScandinavianStemmer): + + """ + The Swedish Snowball stemmer. + + :cvar __vowels: The Swedish vowels. + :type __vowels: unicode + :cvar __s_ending: Letters that may directly appear before a word final 's'. + :type __s_ending: unicode + :cvar __step1_suffixes: Suffixes to be deleted in step 1 of the algorithm. + :type __step1_suffixes: tuple + :cvar __step2_suffixes: Suffixes to be deleted in step 2 of the algorithm. + :type __step2_suffixes: tuple + :cvar __step3_suffixes: Suffixes to be deleted in step 3 of the algorithm. + :type __step3_suffixes: tuple + :note: A detailed description of the Swedish + stemming algorithm can be found under + http://snowball.tartarus.org/algorithms/swedish/stemmer.html + """ + + __vowels = u("aeiouy\xE4\xE5\xF6") + __s_ending = "bcdfghjklmnoprtvy" + __step1_suffixes = ("heterna", "hetens", "heter", "heten", + "anden", "arnas", "ernas", "ornas", "andes", + "andet", "arens", "arna", "erna", "orna", + "ande", "arne", "aste", "aren", "ades", + "erns", "ade", "are", "ern", "ens", "het", + "ast", "ad", "en", "ar", "er", "or", "as", + "es", "at", "a", "e", "s") + __step2_suffixes = ("dd", "gd", "nn", "dt", "gt", "kt", "tt") + __step3_suffixes = ("fullt", u("l\xF6st"), "els", "lig", "ig") + + def stem(self, word): + """ + Stem a Swedish word and return the stemmed form. + + :param word: The word that is stemmed. + :type word: str or unicode + :return: The stemmed form. + :rtype: unicode + + """ + word = word.lower() + + r1 = self._r1_scandinavian(word, self.__vowels) + + # STEP 1 + for suffix in self.__step1_suffixes: + if r1.endswith(suffix): + if suffix == "s": + if word[-2] in self.__s_ending: + word = word[:-1] + r1 = r1[:-1] + else: + word = word[:-len(suffix)] + r1 = r1[:-len(suffix)] + break + + # STEP 2 + for suffix in self.__step2_suffixes: + if r1.endswith(suffix): + word = word[:-1] + r1 = r1[:-1] + break + + # STEP 3 + for suffix in self.__step3_suffixes: + if r1.endswith(suffix): + if suffix in ("els", "lig", "ig"): + word = word[:-len(suffix)] + elif suffix in ("fullt", u("l\xF6st")): + word = word[:-1] + break + + return word diff --git a/nstock/modules/whoosh/lang/stopwords.py b/nstock/modules/whoosh/lang/stopwords.py new file mode 100644 index 0000000..8fc1703 --- /dev/null +++ b/nstock/modules/whoosh/lang/stopwords.py @@ -0,0 +1,285 @@ +# coding=utf-8 + +from __future__ import unicode_literals + +# Stopwords Corpus +# +# This module contains lists of stop words for several languages. These +# are high-frequency grammatical words which are usually ignored in text +# retrieval applications. +# +# They were obtained from: +# anoncvs.postgresql.org/cvsweb.cgi/pgsql/src/backend/snowball/stopwords/ + + +# ===== +# This module was generated from the original files using the following script + +#import os.path +#import textwrap +# +#names = os.listdir("stopwords") +#for name in names: +# f = open("stopwords/" + name) +# wordls = [line.strip() for line in f] +# words = " ".join(wordls) +# print '"%s": frozenset(u"""' % name +# print textwrap.fill(words, 72) +# print '""".split())' +# print + + +stoplists = { + "da": frozenset(""" + og i jeg det at en den til er som på de med han af for ikke der var mig + sig men et har om vi min havde ham hun nu over da fra du ud sin dem os + op man hans hvor eller hvad skal selv her alle vil blev kunne ind når + være dog noget ville jo deres efter ned skulle denne end dette mit + også under have dig anden hende mine alt meget sit sine vor mod disse + hvis din nogle hos blive mange ad bliver hendes været thi jer sådan + """.split()), + + "nl": frozenset(""" + de en van ik te dat die in een hij het niet zijn is was op aan met als + voor had er maar om hem dan zou of wat mijn men dit zo door over ze zich + bij ook tot je mij uit der daar haar naar heb hoe heeft hebben deze u + want nog zal me zij nu ge geen omdat iets worden toch al waren veel meer + doen toen moet ben zonder kan hun dus alles onder ja eens hier wie werd + altijd doch wordt wezen kunnen ons zelf tegen na reeds wil kon niets uw + iemand geweest andere + """.split()), + + "en": frozenset(""" + i me my myself we our ours ourselves you your yours yourself yourselves + he him his himself she her hers herself it its itself they them their + theirs themselves what which who whom this that these those am is are + was were be been being have has had having do does did doing a an the + and but if or because as until while of at by for with about against + between into through during before after above below to from up down in + out on off over under again further then once here there when where why + how all any both each few more most other some such no nor not only own + same so than too very s t can will just don should now + """.split()), + + "fi": frozenset(""" + olla olen olet on olemme olette ovat ole oli olisi olisit olisin + olisimme olisitte olisivat olit olin olimme olitte olivat ollut olleet + en et ei emme ette eivät minä minun minut minua minussa minusta minuun + minulla minulta minulle sinä sinun sinut sinua sinussa sinusta sinuun + sinulla sinulta sinulle hän hänen hänet häntä hänessä hänestä + häneen hänellä häneltä hänelle me meidän meidät meitä meissä + meistä meihin meillä meiltä meille te teidän teidät teitä teissä + teistä teihin teillä teiltä teille he heidän heidät heitä heissä + heistä heihin heillä heiltä heille tämä tämän tätä tässä + tästä tähän tallä tältä tälle tänä täksi tuo tuon tuotä + tuossa tuosta tuohon tuolla tuolta tuolle tuona tuoksi se sen sitä + siinä siitä siihen sillä siltä sille sinä siksi nämä näiden + näitä näissä näistä näihin näillä näiltä näille näinä + näiksi nuo noiden noita noissa noista noihin noilla noilta noille noina + noiksi ne niiden niitä niissä niistä niihin niillä niiltä niille + niinä niiksi kuka kenen kenet ketä kenessä kenestä keneen kenellä + keneltä kenelle kenenä keneksi ketkä keiden ketkä keitä keissä + keistä keihin keillä keiltä keille keinä keiksi mikä minkä minkä + mitä missä mistä mihin millä miltä mille minä miksi mitkä joka + jonka jota jossa josta johon jolla jolta jolle jona joksi jotka joiden + joita joissa joista joihin joilla joilta joille joina joiksi että ja + jos koska kuin mutta niin sekä sillä tai vaan vai vaikka kanssa mukaan + noin poikki yli kun niin nyt itse + """.split()), + + "fr": frozenset(""" + au aux avec ce ces dans de des du elle en et eux il je la le leur lui ma + mais me même mes moi mon ne nos notre nous on ou par pas pour qu que + qui sa se ses son sur ta te tes toi ton tu un une vos votre vous c d j l + à m n s t y été étée étées étés étant étante étants étantes + suis es est sommes êtes sont serai seras sera serons serez seront + serais serait serions seriez seraient étais était étions étiez + étaient fus fut fûmes fûtes furent sois soit soyons soyez soient + fusse fusses fût fussions fussiez fussent ayant ayante ayantes ayants + eu eue eues eus ai as avons avez ont aurai auras aura aurons aurez + auront aurais aurait aurions auriez auraient avais avait avions aviez + avaient eut eûmes eûtes eurent aie aies ait ayons ayez aient eusse + eusses eût eussions eussiez eussent + """.split()), + + "de": frozenset(""" + aber alle allem allen aller alles als also am an ander andere anderem + anderen anderer anderes anderm andern anderr anders auch auf aus bei bin + bis bist da damit dann der den des dem die das daß derselbe derselben + denselben desselben demselben dieselbe dieselben dasselbe dazu dein + deine deinem deinen deiner deines denn derer dessen dich dir du dies + diese diesem diesen dieser dieses doch dort durch ein eine einem einen + einer eines einig einige einigem einigen einiger einiges einmal er ihn + ihm es etwas euer eure eurem euren eurer eures für gegen gewesen hab + habe haben hat hatte hatten hier hin hinter ich mich mir ihr ihre ihrem + ihren ihrer ihres euch im in indem ins ist jede jedem jeden jeder jedes + jene jenem jenen jener jenes jetzt kann kein keine keinem keinen keiner + keines können könnte machen man manche manchem manchen mancher manches + mein meine meinem meinen meiner meines mit muss musste nach nicht nichts + noch nun nur ob oder ohne sehr sein seine seinem seinen seiner seines + selbst sich sie ihnen sind so solche solchem solchen solcher solches + soll sollte sondern sonst über um und uns unse unsem unsen unser unses + unter viel vom von vor während war waren warst was weg weil weiter + welche welchem welchen welcher welches wenn werde werden wie wieder will + wir wird wirst wo wollen wollte würde würden zu zum zur zwar zwischen + """.split()), + + "hu": frozenset(""" + a ahogy ahol aki akik akkor alatt által általában amely amelyek + amelyekben amelyeket amelyet amelynek ami amit amolyan amíg amikor át + abban ahhoz annak arra arról az azok azon azt azzal azért aztán + azután azonban bár be belül benne cikk cikkek cikkeket csak de e + eddig egész egy egyes egyetlen egyéb egyik egyre ekkor el elég ellen + elõ elõször elõtt elsõ én éppen ebben ehhez emilyen ennek erre ez + ezt ezek ezen ezzel ezért és fel felé hanem hiszen hogy hogyan igen + így illetve ill. ill ilyen ilyenkor ison ismét itt jó jól jobban + kell kellett keresztül keressünk ki kívül között közül legalább + lehet lehetett legyen lenne lenni lesz lett maga magát majd majd már + más másik meg még mellett mert mely melyek mi mit míg miért milyen + mikor minden mindent mindenki mindig mint mintha mivel most nagy nagyobb + nagyon ne néha nekem neki nem néhány nélkül nincs olyan ott össze + õ õk õket pedig persze rá s saját sem semmi sok sokat sokkal + számára szemben szerint szinte talán tehát teljes tovább továbbá + több úgy ugyanis új újabb újra után utána utolsó vagy vagyis + valaki valami valamint való vagyok van vannak volt voltam voltak + voltunk vissza vele viszont volna + """.split()), + + "it": frozenset(""" + ad al allo ai agli all agl alla alle con col coi da dal dallo dai dagli + dall dagl dalla dalle di del dello dei degli dell degl della delle in + nel nello nei negli nell negl nella nelle su sul sullo sui sugli sull + sugl sulla sulle per tra contro io tu lui lei noi voi loro mio mia miei + mie tuo tua tuoi tue suo sua suoi sue nostro nostra nostri nostre vostro + vostra vostri vostre mi ti ci vi lo la li le gli ne il un uno una ma ed + se perché anche come dov dove che chi cui non più quale quanto quanti + quanta quante quello quelli quella quelle questo questi questa queste si + tutto tutti a c e i l o ho hai ha abbiamo avete hanno abbia abbiate + abbiano avrò avrai avrà avremo avrete avranno avrei avresti avrebbe + avremmo avreste avrebbero avevo avevi aveva avevamo avevate avevano ebbi + avesti ebbe avemmo aveste ebbero avessi avesse avessimo avessero avendo + avuto avuta avuti avute sono sei è siamo siete sia siate siano sarò + sarai sarà saremo sarete saranno sarei saresti sarebbe saremmo sareste + sarebbero ero eri era eravamo eravate erano fui fosti fu fummo foste + furono fossi fosse fossimo fossero essendo faccio fai facciamo fanno + faccia facciate facciano farò farai farà faremo farete faranno farei + faresti farebbe faremmo fareste farebbero facevo facevi faceva facevamo + facevate facevano feci facesti fece facemmo faceste fecero facessi + facesse facessimo facessero facendo sto stai sta stiamo stanno stia + stiate stiano starò starai starà staremo starete staranno starei + staresti starebbe staremmo stareste starebbero stavo stavi stava stavamo + stavate stavano stetti stesti stette stemmo steste stettero stessi + stesse stessimo stessero stando + """.split()), + + "no": frozenset(""" + og i jeg det at en et den til er som på de med han av ikke ikkje der + så var meg seg men ett har om vi min mitt ha hadde hun nå over da ved + fra du ut sin dem oss opp man kan hans hvor eller hva skal selv sjøl + her alle vil bli ble blei blitt kunne inn når være kom noen noe ville + dere som deres kun ja etter ned skulle denne for deg si sine sitt mot å + meget hvorfor dette disse uten hvordan ingen din ditt blir samme hvilken + hvilke sånn inni mellom vår hver hvem vors hvis både bare enn fordi + før mange også slik vært være båe begge siden dykk dykkar dei deira + deires deim di då eg ein eit eitt elles honom hjå ho hoe henne hennar + hennes hoss hossen ikkje ingi inkje korleis korso kva kvar kvarhelst + kven kvi kvifor me medan mi mine mykje no nokon noka nokor noko nokre si + sia sidan so somt somme um upp vere vore verte vort varte vart + """.split()), + + "pt": frozenset(""" + de a o que e do da em um para com não uma os no se na por mais as dos + como mas ao ele das à seu sua ou quando muito nos já eu também só + pelo pela até isso ela entre depois sem mesmo aos seus quem nas me esse + eles você essa num nem suas meu às minha numa pelos elas qual nós lhe + deles essas esses pelas este dele tu te vocês vos lhes meus minhas teu + tua teus tuas nosso nossa nossos nossas dela delas esta estes estas + aquele aquela aqueles aquelas isto aquilo estou está estamos estão + estive esteve estivemos estiveram estava estávamos estavam estivera + estivéramos esteja estejamos estejam estivesse estivéssemos estivessem + estiver estivermos estiverem hei há havemos hão houve houvemos + houveram houvera houvéramos haja hajamos hajam houvesse houvéssemos + houvessem houver houvermos houverem houverei houverá houveremos + houverão houveria houveríamos houveriam sou somos são era éramos + eram fui foi fomos foram fora fôramos seja sejamos sejam fosse + fôssemos fossem for formos forem serei será seremos serão seria + seríamos seriam tenho tem temos tém tinha tínhamos tinham tive teve + tivemos tiveram tivera tivéramos tenha tenhamos tenham tivesse + tivéssemos tivessem tiver tivermos tiverem terei terá teremos terão + teria teríamos teriam + """.split()), + + "ru": frozenset(""" + и в во не что он на я с со как а то все она + так его но да ты к у же вы за бы по только + ее мне было вот от меня еще нет о из ему + теперь когда даже ну вдруг ли если уже + или ни быть был него до вас нибудь опять + уж вам ведь там потом себя ничего ей + может они тут где есть надо ней для мы + тебя их чем была сам чтоб без будто чего + раз тоже себе под будет ж тогда кто этот + того потому этого какой совсем ним + здесь этом один почти мой тем чтобы нее + сейчас были куда зачем всех никогда + можно при наконец два об другой хоть + после над больше тот через эти нас про + всего них какая много разве три эту моя + впрочем хорошо свою этой перед иногда + лучше чуть том нельзя такой им более + всегда конечно всю между + """.split()), + + "es": frozenset(""" + de la que el en y a los del se las por un para con no una su al lo como + más pero sus le ya o este sí porque esta entre cuando muy sin sobre + también me hasta hay donde quien desde todo nos durante todos uno les + ni contra otros ese eso ante ellos e esto mí antes algunos qué unos yo + otro otras otra él tanto esa estos mucho quienes nada muchos cual poco + ella estar estas algunas algo nosotros mi mis tú te ti tu tus ellas + nosotras vosostros vosostras os mío mía míos mías tuyo tuya tuyos + tuyas suyo suya suyos suyas nuestro nuestra nuestros nuestras vuestro + vuestra vuestros vuestras esos esas estoy estás está estamos estáis + están esté estés estemos estéis estén estaré estarás estará + estaremos estaréis estarán estaría estarías estaríamos estaríais + estarían estaba estabas estábamos estabais estaban estuve estuviste + estuvo estuvimos estuvisteis estuvieron estuviera estuvieras + estuviéramos estuvierais estuvieran estuviese estuvieses estuviésemos + estuvieseis estuviesen estando estado estada estados estadas estad he + has ha hemos habéis han haya hayas hayamos hayáis hayan habré habrás + habrá habremos habréis habrán habría habrías habríamos habríais + habrían había habías habíamos habíais habían hube hubiste hubo + hubimos hubisteis hubieron hubiera hubieras hubiéramos hubierais + hubieran hubiese hubieses hubiésemos hubieseis hubiesen habiendo habido + habida habidos habidas soy eres es somos sois son sea seas seamos seáis + sean seré serás será seremos seréis serán sería serías seríamos + seríais serían era eras éramos erais eran fui fuiste fue fuimos + fuisteis fueron fuera fueras fuéramos fuerais fueran fuese fueses + fuésemos fueseis fuesen sintiendo sentido sentida sentidos sentidas + siente sentid tengo tienes tiene tenemos tenéis tienen tenga tengas + tengamos tengáis tengan tendré tendrás tendrá tendremos tendréis + tendrán tendría tendrías tendríamos tendríais tendrían tenía + tenías teníamos teníais tenían tuve tuviste tuvo tuvimos tuvisteis + tuvieron tuviera tuvieras tuviéramos tuvierais tuvieran tuviese + tuvieses tuviésemos tuvieseis tuviesen teniendo tenido tenida tenidos + tenidas tened + """.split()), + + "sv": frozenset(""" + och det att i en jag hon som han på den med var sig för så till är + men ett om hade de av icke mig du henne då sin nu har inte hans honom + skulle hennes där min man ej vid kunde något från ut när efter upp + vi dem vara vad över än dig kan sina här ha mot alla under någon + eller allt mycket sedan ju denna själv detta åt utan varit hur ingen + mitt ni bli blev oss din dessa några deras blir mina samma vilken er + sådan vår blivit dess inom mellan sådant varför varje vilka ditt vem + vilket sitta sådana vart dina vars vårt våra ert era vilkas + """.split()), + + "tr": frozenset(""" + acaba ama aslında az bazı belki biri birkaç birşey biz bu çok + çünkü da daha de defa diye eğer en gibi hem hep hepsi her hiç için + ile ise kez ki kim mı mu mü nasıl ne neden nerde nerede nereye niçin + niye o sanki şey siz şu tüm ve veya ya yani + """.split()), +} diff --git a/nstock/modules/whoosh/lang/wordnet.py b/nstock/modules/whoosh/lang/wordnet.py new file mode 100644 index 0000000..05016e8 --- /dev/null +++ b/nstock/modules/whoosh/lang/wordnet.py @@ -0,0 +1,242 @@ +# Copyright 2009 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +"""This module contains low-level functions and a high-level class for parsing +the prolog file "wn_s.pl" from the WordNet prolog download +into an object suitable for looking up synonyms and performing query expansion. + +http://wordnetcode.princeton.edu/3.0/WNprolog-3.0.tar.gz +""" + +from collections import defaultdict + +from whoosh.compat import iterkeys, text_type +from whoosh.fields import Schema, ID, STORED + + +def parse_file(f): + """Parses the WordNet wn_s.pl prolog file and returns two dictionaries: + word2nums and num2words. + """ + + word2nums = defaultdict(list) + num2words = defaultdict(list) + + for line in f: + if not line.startswith("s("): + continue + + line = line[2:] + num = int(line[:line.find(",")]) + qt = line.find("'") + line = line[qt + 1:] + qt = line.find("'") + word = line[:qt].lower() + + if not word.isalpha(): + continue + + word2nums[word].append(num) + num2words[num].append(word) + + return word2nums, num2words + + +def make_index(storage, indexname, word2nums, num2words): + """Creates a Whoosh index in the given storage object containing + synonyms taken from word2nums and num2words. Returns the Index + object. + """ + + schema = Schema(word=ID, syns=STORED) + ix = storage.create_index(schema, indexname=indexname) + w = ix.writer() + for word in iterkeys(word2nums): + syns = synonyms(word2nums, num2words, word) + w.add_document(word=text_type(word), syns=syns) + w.commit() + return ix + + +def synonyms(word2nums, num2words, word): + """Uses the word2nums and num2words dicts to look up synonyms + for the given word. Returns a list of synonym strings. + """ + + keys = word2nums[word] + syns = set() + for key in keys: + syns = syns.union(num2words[key]) + + if word in syns: + syns.remove(word) + return sorted(syns) + + +class Thesaurus(object): + """Represents the WordNet synonym database, either loaded into memory + from the wn_s.pl Prolog file, or stored on disk in a Whoosh index. + + This class allows you to parse the prolog file "wn_s.pl" from the WordNet prolog + download into an object suitable for looking up synonyms and performing query + expansion. + + http://wordnetcode.princeton.edu/3.0/WNprolog-3.0.tar.gz + + To load a Thesaurus object from the wn_s.pl file... + + >>> t = Thesaurus.from_filename("wn_s.pl") + + To save the in-memory Thesaurus to a Whoosh index... + + >>> from whoosh.filedb.filestore import FileStorage + >>> fs = FileStorage("index") + >>> t.to_storage(fs) + + To load a Thesaurus object from a Whoosh index... + + >>> t = Thesaurus.from_storage(fs) + + The Thesaurus object is thus usable in two ways: + + * Parse the wn_s.pl file into memory (Thesaurus.from_*) and then look up + synonyms in memory. This has a startup cost for parsing the file, and uses + quite a bit of memory to store two large dictionaries, however synonym + look-ups are very fast. + + * Parse the wn_s.pl file into memory (Thesaurus.from_filename) then save it to + an index (to_storage). From then on, open the thesaurus from the saved + index (Thesaurus.from_storage). This has a large cost for storing the index, + but after that it is faster to open the Thesaurus (than re-parsing the file) + but slightly slower to look up synonyms. + + Here are timings for various tasks on my (fast) Windows machine, which might + give an idea of relative costs for in-memory vs. on-disk. + + ================================================ ================ + Task Approx. time (s) + ================================================ ================ + Parsing the wn_s.pl file 1.045 + Saving to an on-disk index 13.084 + Loading from an on-disk index 0.082 + Look up synonyms for "light" (in memory) 0.0011 + Look up synonyms for "light" (loaded from disk) 0.0028 + ================================================ ================ + + Basically, if you can afford spending the memory necessary to parse the + Thesaurus and then cache it, it's faster. Otherwise, use an on-disk index. + """ + + def __init__(self): + self.w2n = None + self.n2w = None + self.searcher = None + + @classmethod + def from_file(cls, fileobj): + """Creates a Thesaurus object from the given file-like object, which should + contain the WordNet wn_s.pl file. + + >>> f = open("wn_s.pl") + >>> t = Thesaurus.from_file(f) + >>> t.synonyms("hail") + ['acclaim', 'come', 'herald'] + """ + + thes = cls() + thes.w2n, thes.n2w = parse_file(fileobj) + return thes + + @classmethod + def from_filename(cls, filename): + """Creates a Thesaurus object from the given filename, which should + contain the WordNet wn_s.pl file. + + >>> t = Thesaurus.from_filename("wn_s.pl") + >>> t.synonyms("hail") + ['acclaim', 'come', 'herald'] + """ + + f = open(filename, "rb") + try: + return cls.from_file(f) + finally: + f.close() + + @classmethod + def from_storage(cls, storage, indexname="THES"): + """Creates a Thesaurus object from the given storage object, + which should contain an index created by Thesaurus.to_storage(). + + >>> from whoosh.filedb.filestore import FileStorage + >>> fs = FileStorage("index") + >>> t = Thesaurus.from_storage(fs) + >>> t.synonyms("hail") + ['acclaim', 'come', 'herald'] + + :param storage: A :class:`whoosh.store.Storage` object from + which to load the index. + :param indexname: A name for the index. This allows you to + store multiple indexes in the same storage object. + """ + + thes = cls() + index = storage.open_index(indexname=indexname) + thes.searcher = index.searcher() + return thes + + def to_storage(self, storage, indexname="THES"): + """Creates am index in the given storage object from the + synonyms loaded from a WordNet file. + + >>> from whoosh.filedb.filestore import FileStorage + >>> fs = FileStorage("index") + >>> t = Thesaurus.from_filename("wn_s.pl") + >>> t.to_storage(fs) + + :param storage: A :class:`whoosh.store.Storage` object in + which to save the index. + :param indexname: A name for the index. This allows you to + store multiple indexes in the same storage object. + """ + + if not self.w2n or not self.n2w: + raise Exception("No synonyms loaded") + make_index(storage, indexname, self.w2n, self.n2w) + + def synonyms(self, word): + """Returns a list of synonyms for the given word. + + >>> thesaurus.synonyms("hail") + ['acclaim', 'come', 'herald'] + """ + + word = word.lower() + if self.searcher: + return self.searcher.document(word=word)["syns"] + else: + return synonyms(self.w2n, self.n2w, word) diff --git a/nstock/modules/whoosh/legacy.py b/nstock/modules/whoosh/legacy.py new file mode 100644 index 0000000..cc7e2e7 --- /dev/null +++ b/nstock/modules/whoosh/legacy.py @@ -0,0 +1,77 @@ +# Copyright 2012 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +""" +This module contains code for maintaining backwards compatibility with old +index formats. +""" + +from whoosh.util.loading import RenamingUnpickler + + +def load_110_toc(stream, gen, schema, version): + # Between version -110 and version -111, I reorganized the modules and + # changed the implementation of the NUMERIC field, so we have to change the + # classes the unpickler tries to load if we need to read an old schema + + # Read the length of the pickled schema + picklen = stream.read_varint() + if schema: + # If the user passed us a schema, use it and skip the one on disk + stream.seek(picklen, 1) + else: + # Remap the old classes and functions to their moved versions as we + # unpickle the schema + scuts = {"wf": "whoosh.fields", + "wsn": "whoosh.support.numeric", + "wcw2": "whoosh.codec.whoosh2"} + objmap = {"%(wf)s.NUMERIC": "%(wcw2)s.OLD_NUMERIC", + "%(wf)s.DATETIME": "%(wcw2)s.OLD_DATETIME", + "%(wsn)s.int_to_text": "%(wcw2)s.int_to_text", + "%(wsn)s.text_to_int": "%(wcw2)s.text_to_int", + "%(wsn)s.long_to_text": "%(wcw2)s.long_to_text", + "%(wsn)s.text_to_long": "%(wcw2)s.text_to_long", + "%(wsn)s.float_to_text": "%(wcw2)s.float_to_text", + "%(wsn)s.text_to_float": "%(wcw2)s.text_to_float", } + ru = RenamingUnpickler(stream, objmap, shortcuts=scuts) + schema = ru.load() + # Read the generation number + index_gen = stream.read_int() + assert gen == index_gen + # Unused number + _ = stream.read_int() + # Unpickle the list of segment objects + segments = stream.read_pickle() + return schema, segments + + +# Map TOC version numbers to functions to load that version +toc_loaders = {-110: load_110_toc} + + +# Map segment class names to functions to load the segment +segment_loaders = {} diff --git a/nstock/modules/whoosh/matching/__init__.py b/nstock/modules/whoosh/matching/__init__.py new file mode 100644 index 0000000..3f826b9 --- /dev/null +++ b/nstock/modules/whoosh/matching/__init__.py @@ -0,0 +1,31 @@ +# Copyright 2012 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from whoosh.matching.mcore import * +from whoosh.matching.binary import * +from whoosh.matching.wrappers import * +from whoosh.matching.combo import * diff --git a/nstock/modules/whoosh/matching/binary.py b/nstock/modules/whoosh/matching/binary.py new file mode 100644 index 0000000..b752295 --- /dev/null +++ b/nstock/modules/whoosh/matching/binary.py @@ -0,0 +1,803 @@ +# Copyright 2010 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from whoosh.matching import mcore + + +class BiMatcher(mcore.Matcher): + """Base class for matchers that combine the results of two sub-matchers in + some way. + """ + + def __init__(self, a, b): + super(BiMatcher, self).__init__() + self.a = a + self.b = b + + def reset(self): + self.a.reset() + self.b.reset() + + def __repr__(self): + return "%s(%r, %r)" % (self.__class__.__name__, self.a, self.b) + + def children(self): + return [self.a, self.b] + + def copy(self): + return self.__class__(self.a.copy(), self.b.copy()) + + def depth(self): + return 1 + max(self.a.depth(), self.b.depth()) + + def skip_to(self, id): + if not self.is_active(): + raise mcore.ReadTooFar + ra = self.a.skip_to(id) + rb = self.b.skip_to(id) + return ra or rb + + def supports_block_quality(self): + return (self.a.supports_block_quality() + and self.b.supports_block_quality()) + + def supports(self, astype): + return self.a.supports(astype) and self.b.supports(astype) + + +class AdditiveBiMatcher(BiMatcher): + """Base class for binary matchers where the scores of the sub-matchers are + added together. + """ + + def max_quality(self): + q = 0.0 + if self.a.is_active(): + q += self.a.max_quality() + if self.b.is_active(): + q += self.b.max_quality() + return q + + def block_quality(self): + bq = 0.0 + if self.a.is_active(): + bq += self.a.block_quality() + if self.b.is_active(): + bq += self.b.block_quality() + return bq + + def weight(self): + return (self.a.weight() + self.b.weight()) + + def score(self): + return (self.a.score() + self.b.score()) + + def __eq__(self, other): + return self.__class__ is type(other) + + def __lt__(self, other): + return type(other) is self.__class__ + + def __ne__(self, other): + return not self.__eq__(other) + + def __gt__(self, other): + return not (self.__lt__(other) or self.__eq__(other)) + + def __le__(self, other): + return self.__eq__(other) or self.__lt__(other) + + def __ge__(self, other): + return self.__eq__(other) or self.__gt__(other) + + +class UnionMatcher(AdditiveBiMatcher): + """Matches the union (OR) of the postings in the two sub-matchers. + """ + + _id = None + + def replace(self, minquality=0): + a = self.a + b = self.b + a_active = a.is_active() + b_active = b.is_active() + + # If neither sub-matcher on its own has a high enough max quality to + # contribute, convert to an intersection matcher + if minquality and a_active and b_active: + a_max = a.max_quality() + b_max = b.max_quality() + if a_max < minquality and b_max < minquality: + return IntersectionMatcher(a, b).replace(minquality) + elif a_max < minquality: + return AndMaybeMatcher(b, a) + elif b_max < minquality: + return AndMaybeMatcher(a, b) + + # If one or both of the sub-matchers are inactive, convert + if not (a_active or b_active): + return mcore.NullMatcher() + elif not a_active: + return b.replace(minquality) + elif not b_active: + return a.replace(minquality) + + a = a.replace(minquality - b.max_quality() if minquality else 0) + b = b.replace(minquality - a.max_quality() if minquality else 0) + # If one of the sub-matchers changed, return a new union + if a is not self.a or b is not self.b: + return self.__class__(a, b) + else: + self._id = None + return self + + def is_active(self): + return self.a.is_active() or self.b.is_active() + + def skip_to(self, id): + self._id = None + ra = rb = False + + if self.a.is_active(): + ra = self.a.skip_to(id) + if self.b.is_active(): + rb = self.b.skip_to(id) + + return ra or rb + + def id(self): + _id = self._id + if _id is not None: + return _id + + a = self.a + b = self.b + if not a.is_active(): + _id = b.id() + elif not b.is_active(): + _id = a.id() + else: + _id = min(a.id(), b.id()) + self._id = _id + return _id + + # Using sets is faster in most cases, but could potentially use a lot of + # memory. Comment out this method override to not use sets. + #def all_ids(self): + # return iter(sorted(set(self.a.all_ids()) | set(self.b.all_ids()))) + + def next(self): + self._id = None + + a = self.a + b = self.b + a_active = a.is_active() + b_active = b.is_active() + + # Shortcut when one matcher is inactive + if not (a_active or b_active): + raise mcore.ReadTooFar + elif not a_active: + return b.next() + elif not b_active: + return a.next() + + a_id = a.id() + b_id = b.id() + ar = br = None + + # After all that, here's the actual implementation + if a_id <= b_id: + ar = a.next() + if b_id <= a_id: + br = b.next() + return ar or br + + def spans(self): + if not self.a.is_active(): + return self.b.spans() + if not self.b.is_active(): + return self.a.spans() + + id_a = self.a.id() + id_b = self.b.id() + if id_a < id_b: + return self.a.spans() + elif id_b < id_a: + return self.b.spans() + else: + return sorted(set(self.a.spans()) | set(self.b.spans())) + + def weight(self): + a = self.a + b = self.b + + if not a.is_active(): + return b.weight() + if not b.is_active(): + return a.weight() + + id_a = a.id() + id_b = b.id() + if id_a < id_b: + return a.weight() + elif id_b < id_a: + return b.weight() + else: + return (a.weight() + b.weight()) + + def score(self): + a = self.a + b = self.b + + if not a.is_active(): + return b.score() + if not b.is_active(): + return a.score() + + id_a = a.id() + id_b = b.id() + if id_a < id_b: + return a.score() + elif id_b < id_a: + return b.score() + else: + return (a.score() + b.score()) + + def skip_to_quality(self, minquality): + self._id = None + + a = self.a + b = self.b + if not (a.is_active() or b.is_active()): + raise mcore.ReadTooFar + + # Short circuit if one matcher is inactive + if not a.is_active(): + return b.skip_to_quality(minquality) + elif not b.is_active(): + return a.skip_to_quality(minquality) + + skipped = 0 + aq = a.block_quality() + bq = b.block_quality() + while a.is_active() and b.is_active() and aq + bq <= minquality: + if aq < bq: + skipped += a.skip_to_quality(minquality - bq) + aq = a.block_quality() + else: + skipped += b.skip_to_quality(minquality - aq) + bq = b.block_quality() + + return skipped + + +class DisjunctionMaxMatcher(UnionMatcher): + """Matches the union (OR) of two sub-matchers. Where both sub-matchers + match the same posting, returns the weight/score of the higher-scoring + posting. + """ + + # TODO: this class inherits from AdditiveBiMatcher (through UnionMatcher) + # but it does not add the scores of the sub-matchers together (it + # overrides all methods that perform addition). Need to clean up the + # inheritance. + + def __init__(self, a, b, tiebreak=0.0): + super(DisjunctionMaxMatcher, self).__init__(a, b) + self.tiebreak = tiebreak + + def copy(self): + return self.__class__(self.a.copy(), self.b.copy(), + tiebreak=self.tiebreak) + + def replace(self, minquality=0): + a = self.a + b = self.b + a_active = a.is_active() + b_active = b.is_active() + + # DisMax takes the max of the sub-matcher qualities instead of adding + # them, so we need special logic here + if minquality and a_active and b_active: + a_max = a.max_quality() + b_max = b.max_quality() + + if a_max < minquality and b_max < minquality: + # If neither sub-matcher has a high enough max quality to + # contribute, return an inactive matcher + return mcore.NullMatcher() + elif b_max < minquality: + # If the b matcher can't contribute, return a + return a.replace(minquality) + elif a_max < minquality: + # If the a matcher can't contribute, return b + return b.replace(minquality) + + if not (a_active or b_active): + return mcore.NullMatcher() + elif not a_active: + return b.replace(minquality) + elif not b_active: + return a.replace(minquality) + + # We CAN pass the minquality down here, since we don't add the two + # scores together + a = a.replace(minquality) + b = b.replace(minquality) + a_active = a.is_active() + b_active = b.is_active() + # It's kind of tedious to check for inactive sub-matchers all over + # again here after we replace them, but it's probably better than + # returning a replacement with an inactive sub-matcher + if not (a_active and b_active): + return mcore.NullMatcher() + elif not a_active: + return b + elif not b_active: + return a + elif a is not self.a or b is not self.b: + # If one of the sub-matchers changed, return a new DisMax + return self.__class__(a, b) + else: + return self + + def score(self): + if not self.a.is_active(): + return self.b.score() + elif not self.b.is_active(): + return self.a.score() + else: + return max(self.a.score(), self.b.score()) + + def max_quality(self): + return max(self.a.max_quality(), self.b.max_quality()) + + def block_quality(self): + return max(self.a.block_quality(), self.b.block_quality()) + + def skip_to_quality(self, minquality): + a = self.a + b = self.b + + # Short circuit if one matcher is inactive + if not a.is_active(): + sk = b.skip_to_quality(minquality) + return sk + elif not b.is_active(): + return a.skip_to_quality(minquality) + + skipped = 0 + aq = a.block_quality() + bq = b.block_quality() + while a.is_active() and b.is_active() and max(aq, bq) <= minquality: + if aq <= minquality: + skipped += a.skip_to_quality(minquality) + aq = a.block_quality() + if bq <= minquality: + skipped += b.skip_to_quality(minquality) + bq = b.block_quality() + return skipped + + +class IntersectionMatcher(AdditiveBiMatcher): + """Matches the intersection (AND) of the postings in the two sub-matchers. + """ + + def __init__(self, a, b): + super(IntersectionMatcher, self).__init__(a, b) + self._find_first() + + def reset(self): + self.a.reset() + self.b.reset() + self._find_first() + + def _find_first(self): + if (self.a.is_active() + and self.b.is_active() + and self.a.id() != self.b.id()): + self._find_next() + + def replace(self, minquality=0): + a = self.a + b = self.b + a_active = a.is_active() + b_active = b.is_active() + + if not (a_active and b_active): + # Intersection matcher requires that both sub-matchers be active + return mcore.NullMatcher() + + if minquality: + a_max = a.max_quality() + b_max = b.max_quality() + if a_max + b_max < minquality: + # If the combined quality of the sub-matchers can't contribute, + # return an inactive matcher + return mcore.NullMatcher() + # Require that the replacements be able to contribute results + # higher than the minquality + a_min = minquality - b_max + b_min = minquality - a_max + else: + a_min = b_min = 0 + + a = a.replace(a_min) + b = b.replace(b_min) + a_active = a.is_active() + b_active = b.is_active() + if not (a_active or b_active): + return mcore.NullMatcher() + elif not a_active: + return b + elif not b_active: + return a + elif a is not self.a or b is not self.b: + return self.__class__(a, b) + else: + return self + + def is_active(self): + return self.a.is_active() and self.b.is_active() + + def _find_next(self): + a = self.a + b = self.b + a_id = a.id() + b_id = b.id() + assert a_id != b_id + r = False + + while a.is_active() and b.is_active() and a_id != b_id: + if a_id < b_id: + ra = a.skip_to(b_id) + if not a.is_active(): + return + r = r or ra + a_id = a.id() + else: + rb = b.skip_to(a_id) + if not b.is_active(): + return + r = r or rb + b_id = b.id() + return r + + def id(self): + return self.a.id() + + # Using sets is faster in some cases, but could potentially use a lot of + # memory + def all_ids(self): + return iter(sorted(set(self.a.all_ids()) & set(self.b.all_ids()))) + + def skip_to(self, id): + if not self.is_active(): + raise mcore.ReadTooFar + ra = self.a.skip_to(id) + rb = self.b.skip_to(id) + if self.is_active(): + rn = False + if self.a.id() != self.b.id(): + rn = self._find_next() + return ra or rb or rn + + def skip_to_quality(self, minquality): + a = self.a + b = self.b + minquality = minquality + + skipped = 0 + aq = a.block_quality() + bq = b.block_quality() + while a.is_active() and b.is_active() and aq + bq <= minquality: + if aq < bq: + # If the block quality of A is less than B, skip A ahead until + # it can contribute at least the balance of the required min + # quality when added to B + sk = a.skip_to_quality(minquality - bq) + skipped += sk + if not sk and a.is_active(): + # The matcher couldn't skip ahead for some reason, so just + # advance and try again + a.next() + else: + # And vice-versa + sk = b.skip_to_quality(minquality - aq) + skipped += sk + if not sk and b.is_active(): + b.next() + + if not a.is_active() or not b.is_active(): + # One of the matchers is exhausted + break + if a.id() != b.id(): + # We want to always leave in a state where the matchers are at + # the same document, so call _find_next() to sync them + self._find_next() + + # Get the block qualities at the new matcher positions + aq = a.block_quality() + bq = b.block_quality() + return skipped + + def next(self): + if not self.is_active(): + raise mcore.ReadTooFar + + # We must assume that the ids are equal whenever next() is called (they + # should have been made equal by _find_next), so advance them both + ar = self.a.next() + if self.is_active(): + nr = self._find_next() + return ar or nr + + def spans(self): + return sorted(set(self.a.spans()) | set(self.b.spans())) + + +class AndNotMatcher(BiMatcher): + """Matches the postings in the first sub-matcher that are NOT present in + the second sub-matcher. + """ + + def __init__(self, a, b): + super(AndNotMatcher, self).__init__(a, b) + self._find_first() + + def reset(self): + self.a.reset() + self.b.reset() + self._find_first() + + def _find_first(self): + if (self.a.is_active() + and self.b.is_active() + and self.a.id() == self.b.id()): + self._find_next() + + def is_active(self): + return self.a.is_active() + + def _find_next(self): + pos = self.a + neg = self.b + if not neg.is_active(): + return + pos_id = pos.id() + r = False + + if neg.id() < pos_id: + neg.skip_to(pos_id) + + while pos.is_active() and neg.is_active() and pos_id == neg.id(): + nr = pos.next() + if not pos.is_active(): + break + + r = r or nr + pos_id = pos.id() + neg.skip_to(pos_id) + + return r + + def supports_block_quality(self): + return self.a.supports_block_quality() + + def replace(self, minquality=0): + if not self.a.is_active(): + # The a matcher is required, so if it's inactive, return an + # inactive matcher + return mcore.NullMatcher() + elif (minquality + and self.a.max_quality() < minquality): + # If the quality of the required matcher isn't high enough to + # contribute, return an inactive matcher + return mcore.NullMatcher() + elif not self.b.is_active(): + # If the prohibited matcher is inactive, convert to just the + # required matcher + return self.a.replace(minquality) + + a = self.a.replace(minquality) + b = self.b.replace() + if a is not self.a or b is not self.b: + # If one of the sub-matchers was replaced, return a new AndNot + return self.__class__(a, b) + else: + return self + + def max_quality(self): + return self.a.max_quality() + + def block_quality(self): + return self.a.block_quality() + + def skip_to_quality(self, minquality): + skipped = self.a.skip_to_quality(minquality) + self._find_next() + return skipped + + def id(self): + return self.a.id() + + def next(self): + if not self.a.is_active(): + raise mcore.ReadTooFar + ar = self.a.next() + nr = False + if self.a.is_active() and self.b.is_active(): + nr = self._find_next() + return ar or nr + + def skip_to(self, id): + if not self.a.is_active(): + raise mcore.ReadTooFar + if id < self.a.id(): + return + + self.a.skip_to(id) + if self.b.is_active(): + self.b.skip_to(id) + self._find_next() + + def weight(self): + return self.a.weight() + + def score(self): + return self.a.score() + + def supports(self, astype): + return self.a.supports(astype) + + def value(self): + return self.a.value() + + def value_as(self, astype): + return self.a.value_as(astype) + + +class AndMaybeMatcher(AdditiveBiMatcher): + """Matches postings in the first sub-matcher, and if the same posting is + in the second sub-matcher, adds their scores. + """ + + def __init__(self, a, b): + AdditiveBiMatcher.__init__(self, a, b) + self._first_b() + + def reset(self): + self.a.reset() + self.b.reset() + self._first_b() + + def _first_b(self): + a = self.a + b = self.b + if a.is_active() and b.is_active() and a.id() != b.id(): + b.skip_to(a.id()) + + def is_active(self): + return self.a.is_active() + + def id(self): + return self.a.id() + + def next(self): + if not self.a.is_active(): + raise mcore.ReadTooFar + + ar = self.a.next() + br = False + if self.a.is_active() and self.b.is_active(): + br = self.b.skip_to(self.a.id()) + return ar or br + + def skip_to(self, id): + if not self.a.is_active(): + raise mcore.ReadTooFar + + ra = self.a.skip_to(id) + rb = False + if self.a.is_active() and self.b.is_active(): + rb = self.b.skip_to(id) + return ra or rb + + def replace(self, minquality=0): + a = self.a + b = self.b + a_active = a.is_active() + b_active = b.is_active() + + if not a_active: + return mcore.NullMatcher() + elif minquality and b_active: + if a.max_quality() + b.max_quality() < minquality: + # If the combined max quality of the sub-matchers isn't high + # enough to possibly contribute, return an inactive matcher + return mcore.NullMatcher() + elif a.max_quality() < minquality: + # If the max quality of the main sub-matcher isn't high enough + # to ever contribute without the optional sub- matcher, change + # into an IntersectionMatcher + return IntersectionMatcher(self.a, self.b) + elif not b_active: + return a.replace(minquality) + + new_a = a.replace(minquality - b.max_quality()) + new_b = b.replace(minquality - a.max_quality()) + if new_a is not a or new_b is not b: + # If one of the sub-matchers changed, return a new AndMaybe + return self.__class__(new_a, new_b) + else: + return self + + def skip_to_quality(self, minquality): + a = self.a + b = self.b + minquality = minquality + + if not a.is_active(): + raise mcore.ReadTooFar + if not b.is_active(): + return a.skip_to_quality(minquality) + + skipped = 0 + aq = a.block_quality() + bq = b.block_quality() + while a.is_active() and b.is_active() and aq + bq <= minquality: + if aq < bq: + skipped += a.skip_to_quality(minquality - bq) + aq = a.block_quality() + else: + skipped += b.skip_to_quality(minquality - aq) + bq = b.block_quality() + + return skipped + + def weight(self): + if self.a.id() == self.b.id(): + return self.a.weight() + self.b.weight() + else: + return self.a.weight() + + def score(self): + if self.b.is_active() and self.a.id() == self.b.id(): + return self.a.score() + self.b.score() + else: + return self.a.score() + + def supports(self, astype): + return self.a.supports(astype) + + def value(self): + return self.a.value() + + def value_as(self, astype): + return self.a.value_as(astype) diff --git a/nstock/modules/whoosh/matching/combo.py b/nstock/modules/whoosh/matching/combo.py new file mode 100644 index 0000000..7c47df9 --- /dev/null +++ b/nstock/modules/whoosh/matching/combo.py @@ -0,0 +1,312 @@ +# Copyright 2010 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from __future__ import division +from array import array + +from whoosh.compat import xrange +from whoosh.matching import mcore + + +class CombinationMatcher(mcore.Matcher): + def __init__(self, submatchers, boost=1.0): + self._submatchers = submatchers + self._boost = boost + + def supports_block_quality(self): + return all(m.supports_block_quality() for m in self._submatchers) + + def max_quality(self): + return max(m.max_quality() for m in self._submatchers + if m.is_active()) * self._boost + + def supports(self, astype): + return all(m.supports(astype) for m in self._submatchers) + + def children(self): + return iter(self._submatchers) + + def score(self): + return sum(m.score() for m in self._submatchers) * self._boost + + +class PreloadedUnionMatcher(CombinationMatcher): + """Instead of marching the sub-matchers along in parallel, this + matcher pre-reads the scores for EVERY MATCHING DOCUMENT, trading memory + for speed. + + This is faster than the implementation using a binary tree of + :class:`~whoosh.matching.binary.UnionMatcher` objects (possibly just + because of less overhead), but it doesn't allow getting information about + the "current" document other than the score, because there isn't really a + current document, just an array of scores. + """ + + def __init__(self, submatchers, doccount, boost=1.0, scored=True): + CombinationMatcher.__init__(self, submatchers, boost=boost) + + self._doccount = doccount + + a = array("d") + active = [subm for subm in self._submatchers if subm.is_active()] + if active: + offset = self._docnum = min(m.id() for m in active) + for m in active: + while m.is_active(): + if scored: + score = m.score() * boost + else: + score = boost + + docnum = m.id() + place = docnum - offset + if len(a) <= place: + a.extend(0 for _ in xrange(place - len(a) + 1)) + a[place] += score + m.next() + self._a = a + self._offset = offset + else: + self._docnum = 0 + self._offset = 0 + self._a = a + + def is_active(self): + return self._docnum - self._offset < len(self._a) + + def id(self): + return self._docnum + + def score(self): + return self._a[self._docnum - self._offset] + + def next(self): + a = self._a + offset = self._offset + place = self._docnum - offset + + place += 1 + while place < len(a) and a[place] == 0: + place += 1 + self._docnum = place + offset + + def max_quality(self): + return max(self._a[self._docnum - self._offset:]) + + def block_quality(self): + return self.max_quality() + + def skip_to(self, docnum): + if docnum < self._docnum: + return + + self._docnum = docnum + i = docnum - self._offset + if i < len(self._a) and self._a[i] == 0: + self.next() + + def skip_to_quality(self, minquality): + a = self._a + offset = self._offset + place = self._docnum - offset + + skipped = 0 + while place < len(a) and a[place] <= minquality: + place += 1 + skipped = 1 + + self._docnum = place + offset + return skipped + + def supports(self, astype): + # This matcher doesn't support any posting values + return False + + def all_ids(self): + a = self._a + offset = self._offset + place = self._docnum - offset + + while place < len(a): + if a[place] > 0: + yield place + offset + place += 1 + + +class ArrayUnionMatcher(CombinationMatcher): + """Instead of marching the sub-matchers along in parallel, this matcher + pre-reads the scores for a large block of documents at a time from each + matcher, accumulating the scores in an array. + + This is faster than the implementation using a binary tree of + :class:`~whoosh.matching.binary.UnionMatcher` objects (possibly just + because of less overhead), but it doesn't allow getting information about + the "current" document other than the score, because there isn't really a + current document, just an array of scores. + """ + + def __init__(self, submatchers, doccount, boost=1.0, scored=True, + partsize=2048): + CombinationMatcher.__init__(self, submatchers, boost=boost) + self._scored = scored + self._doccount = doccount + + if not partsize: + partsize = doccount + self._partsize = partsize + + self._a = array("d", (0 for _ in xrange(self._partsize))) + self._docnum = self._min_id() + self._read_part() + + def __repr__(self): + return ("%s(%r, boost=%f, scored=%r, partsize=%d)" + % (self.__class__.__name__, self._submatchers, self._boost, + self._scored, self._partsize)) + + def _min_id(self): + active = [subm for subm in self._submatchers if subm.is_active()] + if active: + return min(subm.id() for subm in active) + else: + return self._doccount + + def _read_part(self): + scored = self._scored + boost = self._boost + limit = min(self._docnum + self._partsize, self._doccount) + offset = self._docnum + a = self._a + + # Clear the array + for i in xrange(self._partsize): + a[i] = 0 + + # Add the scores from the submatchers into the array + for m in self._submatchers: + while m.is_active() and m.id() < limit: + i = m.id() - offset + if scored: + a[i] += m.score() * boost + else: + a[i] = 1 + m.next() + + self._offset = offset + self._limit = limit + + def _find_next(self): + a = self._a + docnum = self._docnum + offset = self._offset + limit = self._limit + + while docnum < limit: + if a[docnum - offset] > 0: + break + docnum += 1 + + if docnum == limit: + self._docnum = self._min_id() + self._read_part() + else: + self._docnum = docnum + + def supports(self, astype): + # This matcher doesn't support any posting values + return False + + def is_active(self): + return self._docnum < self._doccount + + def max_quality(self): + return max(m.max_quality() for m in self._submatchers) + + def block_quality(self): + return max(self._a) + + def skip_to(self, docnum): + if docnum < self._offset: + # We've already passed it + return + elif docnum < self._limit: + # It's in the current part + self._docnum = docnum + self._find_next() + return + + # Advance all active submatchers + submatchers = self._submatchers + active = False + for subm in submatchers: + if subm.is_active(): + subm.skip_to(docnum) + + if any(subm.is_active() for subm in submatchers): + # Rebuffer + self._docnum = self._min_id() + self._read_part() + else: + self._docnum = self._doccount + + def skip_to_quality(self, minquality): + skipped = 0 + while self.is_active() and self.block_quality() <= minquality: + skipped += 1 + self._docnum = self._limit + self._read_part() + if self.is_active(): + self._find_next() + return skipped + + def id(self): + return self._docnum + + def all_ids(self): + doccount = self._doccount + docnum = self._docnum + offset = self._offset + limit = self._limit + + a = self._a + while docnum < doccount: + if a[docnum - offset] > 0: + yield docnum + + docnum += 1 + if docnum == limit: + self._docnum = docnum + self._read_part() + offset = self._offset + limit = self._limit + + def next(self): + self._docnum += 1 + return self._find_next() + + def score(self): + return self._a[self._docnum - self._offset] diff --git a/nstock/modules/whoosh/matching/mcore.py b/nstock/modules/whoosh/matching/mcore.py new file mode 100644 index 0000000..0b61c7d --- /dev/null +++ b/nstock/modules/whoosh/matching/mcore.py @@ -0,0 +1,622 @@ +# Copyright 2010 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +""" +This module contains "matcher" classes. Matchers deal with posting lists. The +most basic matcher, which reads the list of postings for a term, will be +provided by the backend implementation (for example, +:class:`whoosh.filedb.filepostings.FilePostingReader`). The classes in this +module provide additional functionality, such as combining the results of two +matchers, or modifying the results of a matcher. + +You do not need to deal with the classes in this module unless you need to +write your own Matcher implementation to provide some new functionality. These +classes are not instantiated by the user. They are usually created by a +:class:`~whoosh.query.Query` object's :meth:`~whoosh.query.Query.matcher()` +method, which returns the appropriate matcher to implement the query (for +example, the :class:`~whoosh.query.Or` query's +:meth:`~whoosh.query.Or.matcher()` method returns a +:py:class:`~whoosh.matching.UnionMatcher` object). + +Certain backends support "quality" optimizations. These backends have the +ability to skip ahead if it knows the current block of postings can't +contribute to the top N documents. If the matcher tree and backend support +these optimizations, the matcher's :meth:`Matcher.supports_block_quality()` +method will return ``True``. +""" + +import sys +from itertools import repeat + +from whoosh.compat import izip, xrange +from whoosh.compat import abstractmethod + + +# Exceptions + +class ReadTooFar(Exception): + """Raised when :meth:`~whoosh.matching.Matcher.next()` or + :meth:`~whoosh.matching.Matcher.skip_to()` are called on an inactive + matcher. + """ + + +class NoQualityAvailable(Exception): + """Raised when quality methods are called on a matcher that does not + support block quality optimizations. + """ + + +# Classes + +class Matcher(object): + """Base class for all matchers. + """ + + @abstractmethod + def is_active(self): + """Returns True if this matcher is still "active", that is, it has not + yet reached the end of the posting list. + """ + + raise NotImplementedError + + @abstractmethod + def reset(self): + """Returns to the start of the posting list. + + Note that reset() may not do what you expect after you call + :meth:`Matcher.replace()`, since this can mean calling reset() not on + the original matcher, but on an optimized replacement. + """ + + raise NotImplementedError + + def term(self): + """Returns a ``("fieldname", "termtext")`` tuple for the term this + matcher matches, or None if this matcher is not a term matcher. + """ + + return None + + def term_matchers(self): + """Returns an iterator of term matchers in this tree. + """ + + if self.term() is not None: + yield self + else: + for cm in self.children(): + for m in cm.term_matchers(): + yield m + + def matching_terms(self, id=None): + """Returns an iterator of ``("fieldname", "termtext")`` tuples for the + **currently matching** term matchers in this tree. + """ + + if not self.is_active(): + return + + if id is None: + id = self.id() + elif id != self.id(): + return + + t = self.term() + if t is None: + for c in self.children(): + for t in c.matching_terms(id): + yield t + else: + yield t + + def is_leaf(self): + return not bool(self.children()) + + def children(self): + """Returns an (possibly empty) list of the submatchers of this + matcher. + """ + + return [] + + def replace(self, minquality=0): + """Returns a possibly-simplified version of this matcher. For example, + if one of the children of a UnionMatcher is no longer active, calling + this method on the UnionMatcher will return the other child. + """ + + return self + + @abstractmethod + def copy(self): + """Returns a copy of this matcher. + """ + + raise NotImplementedError + + def depth(self): + """Returns the depth of the tree under this matcher, or 0 if this + matcher does not have any children. + """ + + return 0 + + def supports_block_quality(self): + """Returns True if this matcher supports the use of ``quality`` and + ``block_quality``. + """ + + return False + + def max_quality(self): + """Returns the maximum possible quality measurement for this matcher, + according to the current weighting algorithm. Raises + ``NoQualityAvailable`` if the matcher or weighting do not support + quality measurements. + """ + + raise NoQualityAvailable(self.__class__) + + def block_quality(self): + """Returns a quality measurement of the current block of postings, + according to the current weighting algorithm. Raises + ``NoQualityAvailable`` if the matcher or weighting do not support + quality measurements. + """ + + raise NoQualityAvailable(self.__class__) + + @abstractmethod + def id(self): + """Returns the ID of the current posting. + """ + + raise NotImplementedError + + def all_ids(self): + """Returns a generator of all IDs in the matcher. + + What this method returns for a matcher that has already read some + postings (whether it only yields the remaining postings or all postings + from the beginning) is undefined, so it's best to only use this method + on fresh matchers. + """ + + i = 0 + m = self + while m.is_active(): + yield m.id() + m.next() + i += 1 + if i == 10: + m = m.replace() + i = 0 + + def all_items(self): + """Returns a generator of all (ID, encoded value) pairs in the matcher. + + What this method returns for a matcher that has already read some + postings (whether it only yields the remaining postings or all postings + from the beginning) is undefined, so it's best to only use this method + on fresh matchers. + """ + + i = 0 + m = self + while self.is_active(): + yield (m.id(), m.value()) + m.next() + i += 1 + if i == 10: + m = m.replace() + i = 0 + + def items_as(self, astype): + """Returns a generator of all (ID, decoded value) pairs in the matcher. + + What this method returns for a matcher that has already read some + postings (whether it only yields the remaining postings or all postings + from the beginning) is undefined, so it's best to only use this method + on fresh matchers. + """ + + while self.is_active(): + yield (self.id(), self.value_as(astype)) + self.next() + + @abstractmethod + def value(self): + """Returns the encoded value of the current posting. + """ + + raise NotImplementedError + + @abstractmethod + def supports(self, astype): + """Returns True if the field's format supports the named data type, + for example 'frequency' or 'characters'. + """ + + raise NotImplementedError("supports not implemented in %s" + % self.__class__) + + @abstractmethod + def value_as(self, astype): + """Returns the value(s) of the current posting as the given type. + """ + + raise NotImplementedError("value_as not implemented in %s" + % self.__class__) + + def spans(self): + """Returns a list of :class:`~whoosh.query.spans.Span` objects for the + matches in this document. Raises an exception if the field being + searched does not store positions. + """ + + from whoosh.query.spans import Span + + if self.supports("characters"): + return [Span(pos, startchar=startchar, endchar=endchar) + for pos, startchar, endchar in self.value_as("characters")] + elif self.supports("positions"): + return [Span(pos) for pos in self.value_as("positions")] + else: + raise Exception("Field does not support spans") + + def skip_to(self, id): + """Moves this matcher to the first posting with an ID equal to or + greater than the given ID. + """ + + while self.is_active() and self.id() < id: + self.next() + + def skip_to_quality(self, minquality): + """Moves this matcher to the next block with greater than the given + minimum quality value. + """ + + raise NotImplementedError(self.__class__.__name__) + + @abstractmethod + def next(self): + """Moves this matcher to the next posting. + """ + + raise NotImplementedError(self.__class__.__name__) + + def weight(self): + """Returns the weight of the current posting. + """ + + return self.value_as("weight") + + @abstractmethod + def score(self): + """Returns the score of the current posting. + """ + + raise NotImplementedError(self.__class__.__name__) + + def __eq__(self, other): + return self.__class__ is type(other) + + def __lt__(self, other): + return type(other) is self.__class__ + + def __ne__(self, other): + return not self.__eq__(other) + + def __gt__(self, other): + return not (self.__lt__(other) or self.__eq__(other)) + + def __le__(self, other): + return self.__eq__(other) or self.__lt__(other) + + def __ge__(self, other): + return self.__eq__(other) or self.__gt__(other) + + +# Simple intermediate classes + +class ConstantScoreMatcher(Matcher): + def __init__(self, score=1.0): + self._score = score + + def supports_block_quality(self): + return True + + def max_quality(self): + return self._score + + def block_quality(self): + return self._score + + def skip_to_quality(self, minquality): + if minquality >= self._score: + self.go_inactive() + + def score(self): + return self._score + + +# Null matcher + +class NullMatcherClass(Matcher): + """Matcher with no postings which is never active. + """ + + def __call__(self): + return self + + def __repr__(self): + return "" + + def supports_block_quality(self): + return True + + def max_quality(self): + return 0 + + def block_quality(self): + return 0 + + def skip_to_quality(self, minquality): + return 0 + + def is_active(self): + return False + + def reset(self): + pass + + def all_ids(self): + return [] + + def copy(self): + return self + + +# Singleton instance +NullMatcher = NullMatcherClass() + + +class ListMatcher(Matcher): + """Synthetic matcher backed by a list of IDs. + """ + + def __init__(self, ids, weights=None, values=None, format=None, + scorer=None, position=0, all_weights=None, term=None, + terminfo=None): + """ + :param ids: a list of doc IDs. + :param weights: a list of weights corresponding to the list of IDs. + If this argument is not supplied, a list of 1.0 values is used. + :param values: a list of encoded values corresponding to the list of + IDs. + :param format: a :class:`whoosh.formats.Format` object representing the + format of the field. + :param scorer: a :class:`whoosh.scoring.BaseScorer` object for scoring + the postings. + :param term: a ``("fieldname", "text")`` tuple, or None if this is not + a term matcher. + """ + + self._ids = ids + self._weights = weights + self._all_weights = all_weights + self._values = values + self._i = position + self._format = format + self._scorer = scorer + self._term = term + self._terminfo = terminfo + + def __repr__(self): + return "<%s>" % self.__class__.__name__ + + def is_active(self): + return self._i < len(self._ids) + + def reset(self): + self._i = 0 + + def skip_to(self, id): + if not self.is_active(): + raise ReadTooFar + if id < self.id(): + return + + while self._i < len(self._ids) and self._ids[self._i] < id: + self._i += 1 + + def term(self): + return self._term + + def copy(self): + return self.__class__(self._ids, self._weights, self._values, + self._format, self._scorer, self._i, + self._all_weights) + + def replace(self, minquality=0): + if not self.is_active(): + return NullMatcher() + elif minquality and self.max_quality() < minquality: + return NullMatcher() + else: + return self + + def supports_block_quality(self): + return (self._scorer is not None + and self._scorer.supports_block_quality()) + + def max_quality(self): + # This matcher treats all postings in the list as one "block", so the + # block quality is the same as the quality of the entire list + if self._scorer: + return self._scorer.block_quality(self) + else: + return self.block_max_weight() + + def block_quality(self): + return self._scorer.block_quality(self) + + def skip_to_quality(self, minquality): + while self._i < len(self._ids) and self.block_quality() <= minquality: + self._i += 1 + return 0 + + def id(self): + return self._ids[self._i] + + def all_ids(self): + return iter(self._ids) + + def all_items(self): + values = self._values + if values is None: + values = repeat('') + + return izip(self._ids, values) + + def value(self): + if self._values: + v = self._values[self._i] + + if isinstance(v, list): + # This object supports "values" that are actually lists of + # value strings. This is to support combining the results of + # several different matchers into a single ListMatcher (see the + # TOO_MANY_CLAUSES functionality of MultiTerm). We combine the + # values here instead of combining them first and then making + # the ListMatcher to avoid wasting time combining values if the + # consumer never asks for them. + assert len(v) > 0 + if len(v) == 1: + v = v[0] + else: + v = self._format.combine(v) + # Replace the list with the computed value string + self._values[self._i] = v + + return v + else: + return '' + + def value_as(self, astype): + decoder = self._format.decoder(astype) + return decoder(self.value()) + + def supports(self, astype): + return self._format.supports(astype) + + def next(self): + self._i += 1 + + def weight(self): + if self._all_weights: + return self._all_weights + elif self._weights: + return self._weights[self._i] + else: + return 1.0 + + def block_min_length(self): + return self._terminfo.min_length() + + def block_max_length(self): + return self._terminfo.max_length() + + def block_max_weight(self): + if self._all_weights: + return self._all_weights + elif self._weights: + return max(self._weights) + elif self._terminfo is not None: + return self._terminfo.max_weight() + else: + return 1.0 + + def score(self): + if self._scorer: + return self._scorer.score(self) + else: + return self.weight() + + +# Term/vector leaf posting matcher middleware + +class LeafMatcher(Matcher): + # Subclasses need to set + # self.scorer -- a Scorer object or None + # self.format -- Format object for the posting values + + def __repr__(self): + return "%s(%r, %s)" % (self.__class__.__name__, self.term(), + self.is_active()) + + def term(self): + return self._term + + def items_as(self, astype): + decoder = self.format.decoder(astype) + for id, value in self.all_items(): + yield (id, decoder(value)) + + def supports(self, astype): + return self.format.supports(astype) + + def value_as(self, astype): + decoder = self.format.decoder(astype) + return decoder(self.value()) + + def spans(self): + from whoosh.query.spans import Span + + if self.supports("characters"): + return [Span(pos, startchar=startchar, endchar=endchar) + for pos, startchar, endchar in self.value_as("characters")] + elif self.supports("positions"): + return [Span(pos) for pos in self.value_as("positions")] + else: + raise Exception("Field does not support positions (%r)" + % self.term()) + + def supports_block_quality(self): + return self.scorer and self.scorer.supports_block_quality() + + def max_quality(self): + return self.scorer.max_quality() + + def block_quality(self): + return self.scorer.block_quality(self) + + def score(self): + return self.scorer.score(self) diff --git a/nstock/modules/whoosh/matching/wrappers.py b/nstock/modules/whoosh/matching/wrappers.py new file mode 100644 index 0000000..0fadf08 --- /dev/null +++ b/nstock/modules/whoosh/matching/wrappers.py @@ -0,0 +1,572 @@ +# Copyright 2010 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from __future__ import division + +from whoosh.compat import xrange +from whoosh.matching import mcore + + +class WrappingMatcher(mcore.Matcher): + """Base class for matchers that wrap sub-matchers. + """ + + def __init__(self, child, boost=1.0): + self.child = child + self.boost = boost + + def __repr__(self): + return "%s(%r, boost=%s)" % (self.__class__.__name__, self.child, + self.boost) + + def copy(self): + kwargs = {} + if hasattr(self, "boost"): + kwargs["boost"] = self.boost + return self.__class__(self.child.copy(), **kwargs) + + def depth(self): + return 1 + self.child.depth() + + def _replacement(self, newchild): + return self.__class__(newchild, boost=self.boost) + + def replace(self, minquality=0): + # Replace the child matcher + r = self.child.replace(minquality) + if r is not self.child: + # If the child changed, return a new wrapper on the new child + return self._replacement(r) + else: + return self + + def id(self): + return self.child.id() + + def all_ids(self): + return self.child.all_ids() + + def is_active(self): + return self.child.is_active() + + def reset(self): + self.child.reset() + + def children(self): + return [self.child] + + def supports(self, astype): + return self.child.supports(astype) + + def value(self): + return self.child.value() + + def value_as(self, astype): + return self.child.value_as(astype) + + def spans(self): + return self.child.spans() + + def skip_to(self, id): + return self.child.skip_to(id) + + def next(self): + self.child.next() + + def supports_block_quality(self): + return self.child.supports_block_quality() + + def skip_to_quality(self, minquality): + return self.child.skip_to_quality(minquality / self.boost) + + def max_quality(self): + return self.child.max_quality() * self.boost + + def block_quality(self): + return self.child.block_quality() * self.boost + + def weight(self): + return self.child.weight() * self.boost + + def score(self): + return self.child.score() * self.boost + + +class MultiMatcher(mcore.Matcher): + """Serializes the results of a list of sub-matchers. + """ + + def __init__(self, matchers, idoffsets, scorer=None, current=0): + """ + :param matchers: a list of Matcher objects. + :param idoffsets: a list of offsets corresponding to items in the + ``matchers`` list. + """ + + self.matchers = matchers + self.offsets = idoffsets + self.scorer = scorer + self.current = current + self._next_matcher() + + def __repr__(self): + return "%s(%r, %r, current=%s)" % (self.__class__.__name__, + self.matchers, self.offsets, + self.current) + + def is_active(self): + return self.current < len(self.matchers) + + def reset(self): + for mr in self.matchers: + mr.reset() + self.current = 0 + + def children(self): + return [self.matchers[self.current]] + + def _next_matcher(self): + matchers = self.matchers + while (self.current < len(matchers) + and not matchers[self.current].is_active()): + self.current += 1 + + def copy(self): + return self.__class__([mr.copy() for mr in self.matchers], + self.offsets, current=self.current) + + def depth(self): + if self.is_active(): + return 1 + max(mr.depth() for mr in self.matchers[self.current:]) + else: + return 0 + + def replace(self, minquality=0): + m = self + if minquality: + # Skip sub-matchers that don't have a high enough max quality to + # contribute + while (m.is_active() + and m.matchers[m.current].max_quality() < minquality): + m = self.__class__(self.matchers, self.offsets, self.scorer, + m.current + 1) + m._next_matcher() + + if not m.is_active(): + return mcore.NullMatcher() + + # TODO: Possible optimization: if the last matcher is current, replace + # this with the last matcher, but wrap it with a matcher that adds the + # offset. Have to check whether that's actually faster, though. + return m + + def id(self): + current = self.current + return self.matchers[current].id() + self.offsets[current] + + def all_ids(self): + offsets = self.offsets + for i, mr in enumerate(self.matchers): + for id in mr.all_ids(): + yield id + offsets[i] + + def spans(self): + return self.matchers[self.current].spans() + + def supports(self, astype): + return self.matchers[self.current].supports(astype) + + def value(self): + return self.matchers[self.current].value() + + def value_as(self, astype): + return self.matchers[self.current].value_as(astype) + + def next(self): + if not self.is_active(): + raise mcore.ReadTooFar + + self.matchers[self.current].next() + if not self.matchers[self.current].is_active(): + self._next_matcher() + + def skip_to(self, id): + if not self.is_active(): + raise mcore.ReadTooFar + if id <= self.id(): + return + + matchers = self.matchers + offsets = self.offsets + r = False + + while self.current < len(matchers) and id > self.id(): + mr = matchers[self.current] + sr = mr.skip_to(id - offsets[self.current]) + r = sr or r + if mr.is_active(): + break + + self._next_matcher() + + return r + + def supports_block_quality(self): + return all(mr.supports_block_quality() for mr + in self.matchers[self.current:]) + + def max_quality(self): + return max(m.max_quality() for m in self.matchers[self.current:]) + + def block_quality(self): + return self.matchers[self.current].block_quality() + + def weight(self): + return self.matchers[self.current].weight() + + def score(self): + return self.scorer.score(self) + + +def ExcludeMatcher(child, excluded, boost=1.0): + return FilterMatcher(child, excluded, exclude=True, boost=boost) + + +class FilterMatcher(WrappingMatcher): + """Filters the postings from the wrapped based on whether the IDs are + present in or absent from a set. + """ + + def __init__(self, child, ids, exclude=False, boost=1.0): + """ + :param child: the child matcher. + :param ids: a set of IDs to filter by. + :param exclude: by default, only IDs from the wrapped matcher that are + **in** the set are used. If this argument is True, only IDs from + the wrapped matcher that are **not in** the set are used. + """ + + super(FilterMatcher, self).__init__(child) + self._ids = ids + self._exclude = exclude + self.boost = boost + self._find_next() + + def __repr__(self): + return "%s(%r, %r, %r, boost=%s)" % (self.__class__.__name__, + self.child, self._ids, + self._exclude, self.boost) + + def reset(self): + self.child.reset() + self._find_next() + + def copy(self): + return self.__class__(self.child.copy(), self._ids, self._exclude, + boost=self.boost) + + def _replacement(self, newchild): + return self.__class__(newchild, self._ids, exclude=self._exclude, + boost=self.boost) + + def _find_next(self): + child = self.child + ids = self._ids + r = False + + if self._exclude: + while child.is_active() and child.id() in ids: + r = child.next() or r + else: + while child.is_active() and child.id() not in ids: + r = child.next() or r + return r + + def next(self): + self.child.next() + self._find_next() + + def skip_to(self, id): + self.child.skip_to(id) + self._find_next() + + def all_ids(self): + ids = self._ids + if self._exclude: + return (id for id in self.child.all_ids() if id not in ids) + else: + return (id for id in self.child.all_ids() if id in ids) + + def all_items(self): + ids = self._ids + if self._exclude: + return (item for item in self.child.all_items() + if item[0] not in ids) + else: + return (item for item in self.child.all_items() if item[0] in ids) + + +class InverseMatcher(WrappingMatcher): + """Synthetic matcher, generates postings that are NOT present in the + wrapped matcher. + """ + + def __init__(self, child, limit, missing=None, weight=1.0, id=0): + super(InverseMatcher, self).__init__(child) + self.limit = limit + self._weight = weight + self.missing = missing or (lambda id: False) + self._id = id + self._find_next() + + def copy(self): + return self.__class__(self.child.copy(), self.limit, + weight=self._weight, missing=self.missing, + id=self._id) + + def _replacement(self, newchild): + return self.__class__(newchild, self.limit, missing=self.missing, + weight=self._weight, id=self._id) + + def is_active(self): + return self._id < self.limit + + def reset(self): + self.child.reset() + self._id = 0 + self._find_next() + + def supports_block_quality(self): + return False + + def _find_next(self): + child = self.child + missing = self.missing + + # If the current docnum isn't missing and the child matcher is + # exhausted (so we don't have to worry about skipping its matches), we + # don't have to do anything + if not child.is_active() and not missing(self._id): + return + + # Skip missing documents + while self._id < self.limit and missing(self._id): + self._id += 1 + + # Catch the child matcher up to where this matcher is + if child.is_active() and child.id() < self._id: + child.skip_to(self._id) + + # While self._id is missing or is in the child matcher, increase it + while child.is_active() and self._id < self.limit: + if missing(self._id): + self._id += 1 + continue + + if self._id == child.id(): + self._id += 1 + child.next() + continue + + break + + def id(self): + return self._id + + def all_ids(self): + return mcore.Matcher.all_ids(self) + + def next(self): + if self._id >= self.limit: + raise mcore.ReadTooFar + self._id += 1 + self._find_next() + + def skip_to(self, id): + if self._id >= self.limit: + raise mcore.ReadTooFar + if id < self._id: + return + self._id = id + self._find_next() + + def weight(self): + return self._weight + + def score(self): + return self._weight + + +class RequireMatcher(WrappingMatcher): + """Matches postings that are in both sub-matchers, but only uses scores + from the first. + """ + + def __init__(self, a, b): + from whoosh.matching.binary import IntersectionMatcher + + self.a = a + self.b = b + WrappingMatcher.__init__(self, IntersectionMatcher(a, b)) + + def copy(self): + return self.__class__(self.a.copy(), self.b.copy()) + + def supports_block_quality(self): + return self.a.supports_block_quality() + + def replace(self, minquality=0): + if not self.child.is_active(): + # If one of the sub-matchers is inactive, go inactive + return mcore.NullMatcher() + elif minquality and self.a.max_quality() < minquality: + # If the required matcher doesn't have a high enough max quality + # to possibly contribute, return an inactive matcher + return mcore.NullMatcher() + + new_a = self.a.replace(minquality) + new_b = self.b.replace() + if not new_a.is_active(): + return mcore.NullMatcher() + elif new_a is not self.a or new_b is not self.b: + # If one of the sub-matchers changed, return a new Require + return self.__class__(new_a, self.b) + else: + return self + + def max_quality(self): + return self.a.max_quality() + + def block_quality(self): + return self.a.block_quality() + + def skip_to_quality(self, minquality): + skipped = self.a.skip_to_quality(minquality) + self.child._find_next() + return skipped + + def weight(self): + return self.a.weight() + + def score(self): + return self.a.score() + + def supports(self, astype): + return self.a.supports(astype) + + def value(self): + return self.a.value() + + def value_as(self, astype): + return self.a.value_as(astype) + + +class ConstantScoreWrapperMatcher(WrappingMatcher): + def __init__(self, child, score=1.0): + WrappingMatcher.__init__(self, child) + self._score = score + + def copy(self): + return self.__class__(self.child.copy(), score=self._score) + + def _replacement(self, newchild): + return self.__class__(newchild, score=self._score) + + def max_quality(self): + return self._score + + def block_quality(self): + return self._score + + def score(self): + return self._score + + +class SingleTermMatcher(WrappingMatcher): + """Makes a tree of matchers act as if they were a matcher for a single + term for the purposes of "what terms are matching?" questions. + """ + + def __init__(self, child, term): + WrappingMatcher.__init__(self, child) + self._term = term + + def term(self): + return self._term + + def replace(self, minquality=0): + return self + + +class CoordMatcher(WrappingMatcher): + """Modifies the computed score to penalize documents that don't match all + terms in the matcher tree. + + Because this matcher modifies the score, it may give unexpected results + when compared to another matcher returning the unmodified score. + """ + + def __init__(self, child, scale=1.0): + WrappingMatcher.__init__(self, child) + self._termcount = len(list(child.term_matchers())) + self._maxqual = child.max_quality() + self._scale = scale + + def _replacement(self, newchild): + return self.__class__(newchild, scale=self._scale) + + def _sqr(self, score, matching): + # This is the "SQR" (Short Query Ranking) function used by Apple's old + # V-twin search library, described in the paper "V-Twin: A Lightweight + # Engine for Interactive Use". + # + # http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.56.1916 + + # score - document score using the current weighting function + # matching - number of matching terms in the current document + termcount = self._termcount # Number of terms in this tree + scale = self._scale # Scaling factor + + sqr = ((score + ((matching - 1) / (termcount - scale) ** 2)) + * ((termcount - 1) / termcount)) + return sqr + + def max_quality(self): + return self._sqr(self.child.max_quality(), self._termcount) + + def block_quality(self): + return self._sqr(self.child.block_quality(), self._termcount) + + def score(self): + child = self.child + + score = child.score() + matching = 0 + for _ in child.matching_terms(child.id()): + matching += 1 + + return self._sqr(score, matching) diff --git a/nstock/modules/whoosh/multiproc.py b/nstock/modules/whoosh/multiproc.py new file mode 100644 index 0000000..de2d1c4 --- /dev/null +++ b/nstock/modules/whoosh/multiproc.py @@ -0,0 +1,385 @@ +# Copyright 2011 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from __future__ import with_statement +import os +from multiprocessing import Process, Queue, cpu_count + +from whoosh.compat import queue, xrange, iteritems, pickle +from whoosh.codec import base +from whoosh.writing import PostingPool, SegmentWriter +from whoosh.externalsort import imerge +from whoosh.util import random_name + + +def finish_subsegment(writer, k=64): + # Tell the pool to finish up the current file + writer.pool.save() + # Tell the pool to merge any and all runs in the pool until there + # is only one run remaining. "k" is an optional parameter passed + # from the parent which sets the maximum number of files to open + # while reducing. + writer.pool.reduce_to(1, k) + + # The filename of the single remaining run + runname = writer.pool.runs[0] + # The indexed field names + fieldnames = writer.pool.fieldnames + # The segment object (parent can use this to re-open the files created + # by the sub-writer) + segment = writer._partial_segment() + + return runname, fieldnames, segment + + +# Multiprocessing Writer + +class SubWriterTask(Process): + # This is a Process object that takes "jobs" off a job Queue, processes + # them, and when it's done, puts a summary of its work on a results Queue + + def __init__(self, storage, indexname, jobqueue, resultqueue, kwargs, + multisegment): + Process.__init__(self) + self.storage = storage + self.indexname = indexname + self.jobqueue = jobqueue + self.resultqueue = resultqueue + self.kwargs = kwargs + self.multisegment = multisegment + self.running = True + + def run(self): + # This is the main loop of the process. OK, so the way this works is + # kind of brittle and stupid, but I had to figure out how to use the + # multiprocessing module, work around bugs, and address performance + # issues, so there is at least some reasoning behind some of this + + # The "parent" task farms individual documents out to the subtasks for + # indexing. You could pickle the actual documents and put them in the + # queue, but that is not very performant. Instead, we assume the tasks + # share a filesystem and use that to pass the information around. The + # parent task writes a certain number of documents to a file, then puts + # the filename on the "job queue". A subtask gets the filename off the + # queue and reads through the file processing the documents. + + jobqueue = self.jobqueue + resultqueue = self.resultqueue + multisegment = self.multisegment + + # Open a placeholder object representing the index + ix = self.storage.open_index(self.indexname) + # Open a writer for the index. The _lk=False parameter means to not try + # to lock the index (the parent object that started me takes care of + # locking the index) + writer = self.writer = SegmentWriter(ix, _lk=False, **self.kwargs) + + # If the parent task calls cancel() on me, it will set self.running to + # False, so I'll notice the next time through the loop + while self.running: + # Take an object off the job queue + jobinfo = jobqueue.get() + # If the object is None, it means the parent task wants me to + # finish up + if jobinfo is None: + break + # The object from the queue is a tuple of (filename, + # number_of_docs_in_file). Pass those two pieces of information as + # arguments to _process_file(). + self._process_file(*jobinfo) + # jobqueue.task_done() + + if not self.running: + # I was cancelled, so I'll cancel my underlying writer + writer.cancel() + else: + if multisegment: + # Actually finish the segment and return it with no run + runname = None + fieldnames = writer.pool.fieldnames + segment = writer._finalize_segment() + else: + # Merge all runs in the writer's pool into one run, close the + # segment, and return the run name and the segment + k = self.kwargs.get("k", 64) + runname, fieldnames, segment = finish_subsegment(writer, k) + + # Put the results (the run filename and the segment object) on the + # result queue + resultqueue.put((runname, fieldnames, segment), timeout=5) + + def _process_file(self, filename, doc_count): + # This method processes a "job file" written out by the parent task. A + # job file is a series of pickled (code, arguments) tuples. Currently + # the only command codes is 0=add_document + + writer = self.writer + tempstorage = writer.temp_storage() + + load = pickle.load + with tempstorage.open_file(filename).raw_file() as f: + for _ in xrange(doc_count): + # Load the next pickled tuple from the file + code, args = load(f) + assert code == 0 + writer.add_document(**args) + # Remove the job file + tempstorage.delete_file(filename) + + def cancel(self): + self.running = False + + +class MpWriter(SegmentWriter): + def __init__(self, ix, procs=None, batchsize=100, subargs=None, + multisegment=False, **kwargs): + # This is the "main" writer that will aggregate the results created by + # the sub-tasks + SegmentWriter.__init__(self, ix, **kwargs) + + self.procs = procs or cpu_count() + # The maximum number of documents in each job file submitted to the + # sub-tasks + self.batchsize = batchsize + # You can use keyword arguments or the "subargs" argument to pass + # keyword arguments to the sub-writers + self.subargs = subargs if subargs else kwargs + # If multisegment is True, don't merge the segments created by the + # sub-writers, just add them directly to the TOC + self.multisegment = multisegment + + # A list to hold the sub-task Process objects + self.tasks = [] + # A queue to pass the filenames of job files to the sub-tasks + self.jobqueue = Queue(self.procs * 4) + # A queue to get back the final results of the sub-tasks + self.resultqueue = Queue() + # A buffer for documents before they are flushed to a job file + self.docbuffer = [] + + self._grouping = 0 + self._added_sub = False + + def _new_task(self): + task = SubWriterTask(self.storage, self.indexname, + self.jobqueue, self.resultqueue, self.subargs, + self.multisegment) + self.tasks.append(task) + task.start() + return task + + def _enqueue(self): + # Flush the documents stored in self.docbuffer to a file and put the + # filename on the job queue + docbuffer = self.docbuffer + dump = pickle.dump + length = len(docbuffer) + + filename = "%s.doclist" % random_name() + with self.temp_storage().create_file(filename).raw_file() as f: + for item in docbuffer: + dump(item, f, 2) + + if len(self.tasks) < self.procs: + self._new_task() + jobinfo = (filename, length) + self.jobqueue.put(jobinfo) + self.docbuffer = [] + + def cancel(self): + try: + for task in self.tasks: + task.cancel() + finally: + SegmentWriter.cancel(self) + + def start_group(self): + self._grouping += 1 + + def end_group(self): + if not self._grouping: + raise Exception("Unbalanced end_group") + self._grouping -= 1 + + def add_document(self, **fields): + # Add the document to the docbuffer + self.docbuffer.append((0, fields)) + # If the buffer is full, flush it to the job queue + if not self._grouping and len(self.docbuffer) >= self.batchsize: + self._enqueue() + self._added_sub = True + + def _read_and_renumber_run(self, path, offset): + # Note that SortingPool._read_run() automatically deletes the run file + # when it's finished + + gen = self.pool._read_run(path) + # If offset is 0, just return the items unchanged + if not offset: + return gen + else: + # Otherwise, add the offset to each docnum + return ((fname, text, docnum + offset, weight, value) + for fname, text, docnum, weight, value in gen) + + def commit(self, mergetype=None, optimize=None, merge=None): + if self._added_sub: + # If documents have been added to sub-writers, use the parallel + # merge commit code + self._commit(mergetype, optimize, merge) + else: + # Otherwise, just do a regular-old commit + SegmentWriter.commit(self, mergetype=mergetype, optimize=optimize, + merge=merge) + + def _commit(self, mergetype, optimize, merge): + # Index the remaining documents in the doc buffer + if self.docbuffer: + self._enqueue() + # Tell the tasks to finish + for task in self.tasks: + self.jobqueue.put(None) + + # Merge existing segments + finalsegments = self._merge_segments(mergetype, optimize, merge) + + # Wait for the subtasks to finish + for task in self.tasks: + task.join() + + # Pull a (run_file_name, fieldnames, segment) tuple off the result + # queue for each sub-task, representing the final results of the task + results = [] + for _ in self.tasks: + try: + results.append(self.resultqueue.get(timeout=1)) + except queue.Empty: + pass + + if self.multisegment: + # If we're not merging the segments, we don't care about the runname + # and fieldnames in the results... just pull out the segments and + # add them to the list of final segments + finalsegments += [s for _, _, s in results] + if self._added: + finalsegments.append(self._finalize_segment()) + else: + self._close_segment() + assert self.perdocwriter.is_closed + else: + # Merge the posting sources from the sub-writers and my + # postings into this writer + self._merge_subsegments(results, mergetype) + self._close_segment() + self._assemble_segment() + finalsegments.append(self.get_segment()) + assert self.perdocwriter.is_closed + + self._commit_toc(finalsegments) + self._finish() + + def _merge_subsegments(self, results, mergetype): + schema = self.schema + schemanames = set(schema.names()) + storage = self.storage + codec = self.codec + sources = [] + + # If information was added to this writer the conventional (e.g. + # through add_reader or merging segments), add it as an extra source + if self._added: + sources.append(self.pool.iter_postings()) + + pdrs = [] + for runname, fieldnames, segment in results: + fieldnames = set(fieldnames) | schemanames + pdr = codec.per_document_reader(storage, segment) + pdrs.append(pdr) + basedoc = self.docnum + docmap = self.write_per_doc(fieldnames, pdr) + assert docmap is None + + items = self._read_and_renumber_run(runname, basedoc) + sources.append(items) + + # Create a MultiLengths object combining the length files from the + # subtask segments + self.perdocwriter.close() + pdrs.insert(0, self.per_document_reader()) + mpdr = base.MultiPerDocumentReader(pdrs) + + try: + # Merge the iterators into the field writer + self.fieldwriter.add_postings(schema, mpdr, imerge(sources)) + finally: + mpdr.close() + self._added = True + + +class SerialMpWriter(MpWriter): + # A non-parallel version of the MpWriter for testing purposes + + def __init__(self, ix, procs=None, batchsize=100, subargs=None, **kwargs): + SegmentWriter.__init__(self, ix, **kwargs) + + self.procs = procs or cpu_count() + self.batchsize = batchsize + self.subargs = subargs if subargs else kwargs + self.tasks = [SegmentWriter(ix, _lk=False, **self.subargs) + for _ in xrange(self.procs)] + self.pointer = 0 + self._added_sub = False + + def add_document(self, **fields): + self.tasks[self.pointer].add_document(**fields) + self.pointer = (self.pointer + 1) % len(self.tasks) + self._added_sub = True + + def _commit(self, mergetype, optimize, merge): + # Pull a (run_file_name, segment) tuple off the result queue for each + # sub-task, representing the final results of the task + + # Merge existing segments + finalsegments = self._merge_segments(mergetype, optimize, merge) + results = [] + for writer in self.tasks: + results.append(finish_subsegment(writer)) + + self._merge_subsegments(results, mergetype) + self._close_segment() + self._assemble_segment() + finalsegments.append(self.get_segment()) + + self._commit_toc(finalsegments) + self._finish() + + +# For compatibility with old multiproc module +class MultiSegmentWriter(MpWriter): + def __init__(self, *args, **kwargs): + MpWriter.__init__(self, *args, **kwargs) + self.multisegment = True diff --git a/nstock/modules/whoosh/qparser/__init__.py b/nstock/modules/whoosh/qparser/__init__.py new file mode 100644 index 0000000..a61f905 --- /dev/null +++ b/nstock/modules/whoosh/qparser/__init__.py @@ -0,0 +1,30 @@ +# Copyright 2010 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from whoosh.qparser.default import * +from whoosh.qparser.plugins import * +from whoosh.qparser.syntax import * diff --git a/nstock/modules/whoosh/qparser/common.py b/nstock/modules/whoosh/qparser/common.py new file mode 100644 index 0000000..39e7087 --- /dev/null +++ b/nstock/modules/whoosh/qparser/common.py @@ -0,0 +1,65 @@ +# Copyright 2010 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +""" +This module contains common utility objects/functions for the other query +parser modules. +""" + +import sys + +from whoosh.compat import string_type + + +class QueryParserError(Exception): + def __init__(self, cause, msg=None): + super(QueryParserError, self).__init__(str(cause)) + self.cause = cause + + +def get_single_text(field, text, **kwargs): + """Returns the first token from an analyzer's output. + """ + + for t in field.process_text(text, mode="query", **kwargs): + return t + + +def attach(q, stxnode): + if q: + try: + q.startchar = stxnode.startchar + q.endchar = stxnode.endchar + except AttributeError: + raise AttributeError("Can't set attribute on %s" + % q.__class__.__name__) + return q + + +def print_debug(level, msg, out=sys.stderr): + if level: + out.write("%s%s\n" % (" " * (level - 1), msg)) diff --git a/nstock/modules/whoosh/qparser/dateparse.py b/nstock/modules/whoosh/qparser/dateparse.py new file mode 100644 index 0000000..1c4d511 --- /dev/null +++ b/nstock/modules/whoosh/qparser/dateparse.py @@ -0,0 +1,922 @@ +# Copyright 2010 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +import re +import sys +from datetime import datetime, timedelta + +from whoosh.compat import string_type, iteritems +from whoosh.qparser import plugins, syntax +from whoosh.qparser.taggers import Tagger +from whoosh.support.relativedelta import relativedelta +from whoosh.util.text import rcompile +from whoosh.util.times import adatetime, timespan +from whoosh.util.times import fill_in, is_void, relative_days +from whoosh.util.times import TimeError + + +class DateParseError(Exception): + "Represents an error in parsing date text." + + +# Utility functions + +def print_debug(level, msg, *args): + if level > 0: + print((" " * (level - 1)) + (msg % args)) + + +# Parser element objects + +class Props(object): + """A dumb little object that just puts copies a dictionary into attibutes + so I can use dot syntax instead of square bracket string item lookup and + save a little bit of typing. Used by :class:`Regex`. + """ + + def __init__(self, **args): + self.__dict__ = args + + def __repr__(self): + return repr(self.__dict__) + + def get(self, key, default=None): + return self.__dict__.get(key, default) + + +class ParserBase(object): + """Base class for date parser elements. + """ + + def to_parser(self, e): + if isinstance(e, string_type): + return Regex(e) + else: + return e + + def parse(self, text, dt, pos=0, debug=-9999): + raise NotImplementedError + + def date_from(self, text, dt=None, pos=0, debug=-9999): + if dt is None: + dt = datetime.now() + + d, pos = self.parse(text, dt, pos, debug + 1) + return d + + +class MultiBase(ParserBase): + """Base class for date parser elements such as Sequence and Bag that + have sub-elements. + """ + + def __init__(self, elements, name=None): + """ + :param elements: the sub-elements to match. + :param name: a name for this element (for debugging purposes only). + """ + + self.elements = [self.to_parser(e) for e in elements] + self.name = name + + def __repr__(self): + return "%s<%s>%r" % (self.__class__.__name__, self.name or '', + self.elements) + + +class Sequence(MultiBase): + """Merges the dates parsed by a sequence of sub-elements. + """ + + def __init__(self, elements, sep="(\\s+|\\s*,\\s*)", name=None, + progressive=False): + """ + :param elements: the sequence of sub-elements to parse. + :param sep: a separator regular expression to match between elements, + or None to not have separators. + :param name: a name for this element (for debugging purposes only). + :param progressive: if True, elements after the first do not need to + match. That is, for elements (a, b, c) and progressive=True, the + sequence matches like ``a[b[c]]``. + """ + + super(Sequence, self).__init__(elements, name) + self.sep_pattern = sep + if sep: + self.sep_expr = rcompile(sep, re.IGNORECASE) + else: + self.sep_expr = None + self.progressive = progressive + + def parse(self, text, dt, pos=0, debug=-9999): + d = adatetime() + first = True + foundall = False + failed = False + + print_debug(debug, "Seq %s sep=%r text=%r", self.name, + self.sep_pattern, text[pos:]) + for e in self.elements: + print_debug(debug, "Seq %s text=%r", self.name, text[pos:]) + if self.sep_expr and not first: + print_debug(debug, "Seq %s looking for sep", self.name) + m = self.sep_expr.match(text, pos) + if m: + pos = m.end() + else: + print_debug(debug, "Seq %s didn't find sep", self.name) + break + + print_debug(debug, "Seq %s trying=%r at=%s", self.name, e, pos) + + try: + at, newpos = e.parse(text, dt, pos=pos, debug=debug + 1) + except TimeError: + failed = True + break + + print_debug(debug, "Seq %s result=%r", self.name, at) + if not at: + break + pos = newpos + + print_debug(debug, "Seq %s adding=%r to=%r", self.name, at, d) + try: + d = fill_in(d, at) + except TimeError: + print_debug(debug, "Seq %s Error in fill_in", self.name) + failed = True + break + print_debug(debug, "Seq %s filled date=%r", self.name, d) + + first = False + else: + foundall = True + + if not failed and (foundall or (not first and self.progressive)): + print_debug(debug, "Seq %s final=%r", self.name, d) + return (d, pos) + else: + print_debug(debug, "Seq %s failed", self.name) + return (None, None) + + +class Combo(Sequence): + """Parses a sequence of elements in order and combines the dates parsed + by the sub-elements somehow. The default behavior is to accept two dates + from the sub-elements and turn them into a range. + """ + + def __init__(self, elements, fn=None, sep="(\\s+|\\s*,\\s*)", min=2, max=2, + name=None): + """ + :param elements: the sequence of sub-elements to parse. + :param fn: a function to run on all dates found. It should return a + datetime, adatetime, or timespan object. If this argument is None, + the default behavior accepts two dates and returns a timespan. + :param sep: a separator regular expression to match between elements, + or None to not have separators. + :param min: the minimum number of dates required from the sub-elements. + :param max: the maximum number of dates allowed from the sub-elements. + :param name: a name for this element (for debugging purposes only). + """ + + super(Combo, self).__init__(elements, sep=sep, name=name) + self.fn = fn + self.min = min + self.max = max + + def parse(self, text, dt, pos=0, debug=-9999): + dates = [] + first = True + + print_debug(debug, "Combo %s sep=%r text=%r", self.name, + self.sep_pattern, text[pos:]) + for e in self.elements: + if self.sep_expr and not first: + print_debug(debug, "Combo %s looking for sep at %r", + self.name, text[pos:]) + m = self.sep_expr.match(text, pos) + if m: + pos = m.end() + else: + print_debug(debug, "Combo %s didn't find sep", self.name) + return (None, None) + + print_debug(debug, "Combo %s trying=%r", self.name, e) + try: + at, pos = e.parse(text, dt, pos, debug + 1) + except TimeError: + at, pos = None, None + + print_debug(debug, "Combo %s result=%r", self.name, at) + if at is None: + return (None, None) + + first = False + if is_void(at): + continue + if len(dates) == self.max: + print_debug(debug, "Combo %s length > %s", self.name, self.max) + return (None, None) + dates.append(at) + + print_debug(debug, "Combo %s dates=%r", self.name, dates) + if len(dates) < self.min: + print_debug(debug, "Combo %s length < %s", self.name, self.min) + return (None, None) + + return (self.dates_to_timespan(dates), pos) + + def dates_to_timespan(self, dates): + if self.fn: + return self.fn(dates) + elif len(dates) == 2: + return timespan(dates[0], dates[1]) + else: + raise DateParseError("Don't know what to do with %r" % (dates,)) + + +class Choice(MultiBase): + """Returns the date from the first of its sub-elements that matches. + """ + + def parse(self, text, dt, pos=0, debug=-9999): + print_debug(debug, "Choice %s text=%r", self.name, text[pos:]) + for e in self.elements: + print_debug(debug, "Choice %s trying=%r", self.name, e) + + try: + d, newpos = e.parse(text, dt, pos, debug + 1) + except TimeError: + d, newpos = None, None + if d: + print_debug(debug, "Choice %s matched", self.name) + return (d, newpos) + print_debug(debug, "Choice %s no match", self.name) + return (None, None) + + +class Bag(MultiBase): + """Parses its sub-elements in any order and merges the dates. + """ + + def __init__(self, elements, sep="(\\s+|\\s*,\\s*)", onceper=True, + requireall=False, allof=None, anyof=None, name=None): + """ + :param elements: the sub-elements to parse. + :param sep: a separator regular expression to match between elements, + or None to not have separators. + :param onceper: only allow each element to match once. + :param requireall: if True, the sub-elements can match in any order, + but they must all match. + :param allof: a list of indexes into the list of elements. When this + argument is not None, this element matches only if all the + indicated sub-elements match. + :param allof: a list of indexes into the list of elements. When this + argument is not None, this element matches only if any of the + indicated sub-elements match. + :param name: a name for this element (for debugging purposes only). + """ + + super(Bag, self).__init__(elements, name) + self.sep_expr = rcompile(sep, re.IGNORECASE) + self.onceper = onceper + self.requireall = requireall + self.allof = allof + self.anyof = anyof + + def parse(self, text, dt, pos=0, debug=-9999): + first = True + d = adatetime() + seen = [False] * len(self.elements) + + while True: + newpos = pos + print_debug(debug, "Bag %s text=%r", self.name, text[pos:]) + if not first: + print_debug(debug, "Bag %s looking for sep", self.name) + m = self.sep_expr.match(text, pos) + if m: + newpos = m.end() + else: + print_debug(debug, "Bag %s didn't find sep", self.name) + break + + for i, e in enumerate(self.elements): + print_debug(debug, "Bag %s trying=%r", self.name, e) + + try: + at, xpos = e.parse(text, dt, newpos, debug + 1) + except TimeError: + at, xpos = None, None + + print_debug(debug, "Bag %s result=%r", self.name, at) + if at: + if self.onceper and seen[i]: + return (None, None) + + d = fill_in(d, at) + newpos = xpos + seen[i] = True + break + else: + break + + pos = newpos + if self.onceper and all(seen): + break + + first = False + + if (not any(seen) + or (self.allof and not all(seen[pos] for pos in self.allof)) + or (self.anyof and not any(seen[pos] for pos in self.anyof)) + or (self.requireall and not all(seen))): + return (None, None) + + print_debug(debug, "Bag %s final=%r", self.name, d) + return (d, pos) + + +class Optional(ParserBase): + """Wraps a sub-element to indicate that the sub-element is optional. + """ + + def __init__(self, element): + self.element = self.to_parser(element) + + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self.element) + + def parse(self, text, dt, pos=0, debug=-9999): + try: + d, pos = self.element.parse(text, dt, pos, debug + 1) + except TimeError: + d, pos = None, None + + if d: + return (d, pos) + else: + return (adatetime(), pos) + + +class ToEnd(ParserBase): + """Wraps a sub-element and requires that the end of the sub-element's match + be the end of the text. + """ + + def __init__(self, element): + self.element = element + + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self.element) + + def parse(self, text, dt, pos=0, debug=-9999): + try: + d, pos = self.element.parse(text, dt, pos, debug + 1) + except TimeError: + d, pos = None, None + + if d and pos == len(text): + return (d, pos) + else: + return (None, None) + + +class Regex(ParserBase): + """Matches a regular expression and maps named groups in the pattern to + datetime attributes using a function or overridden method. + + There are two points at which you can customize the behavior of this class, + either by supplying functions to the initializer or overriding methods. + + * The ``modify`` function or ``modify_props`` method takes a ``Props`` + object containing the named groups and modifies its values (in place). + * The ``fn`` function or ``props_to_date`` method takes a ``Props`` object + and the base datetime and returns an adatetime/datetime. + """ + + fn = None + modify = None + + def __init__(self, pattern, fn=None, modify=None): + self.pattern = pattern + self.expr = rcompile(pattern, re.IGNORECASE) + self.fn = fn + self.modify = modify + + def __repr__(self): + return "<%r>" % (self.pattern,) + + def parse(self, text, dt, pos=0, debug=-9999): + m = self.expr.match(text, pos) + if not m: + return (None, None) + + props = self.extract(m) + self.modify_props(props) + + try: + d = self.props_to_date(props, dt) + except TimeError: + d = None + + if d: + return (d, m.end()) + else: + return (None, None) + + def extract(self, match): + d = match.groupdict() + for key, value in iteritems(d): + try: + value = int(value) + d[key] = value + except (ValueError, TypeError): + pass + return Props(**d) + + def modify_props(self, props): + if self.modify: + self.modify(props) + + def props_to_date(self, props, dt): + if self.fn: + return self.fn(props, dt) + else: + args = {} + for key in adatetime.units: + args[key] = props.get(key) + return adatetime(**args) + + +class Month(Regex): + def __init__(self, *patterns): + self.patterns = patterns + self.exprs = [rcompile(pat, re.IGNORECASE) for pat in self.patterns] + + self.pattern = ("(?P" + + "|".join("(%s)" % pat for pat in self.patterns) + + ")") + self.expr = rcompile(self.pattern, re.IGNORECASE) + + def modify_props(self, p): + text = p.month + for i, expr in enumerate(self.exprs): + m = expr.match(text) + if m: + p.month = i + 1 + break + + +class PlusMinus(Regex): + def __init__(self, years, months, weeks, days, hours, minutes, seconds): + rel_years = "((?P[0-9]+) *(%s))?" % years + rel_months = "((?P[0-9]+) *(%s))?" % months + rel_weeks = "((?P[0-9]+) *(%s))?" % weeks + rel_days = "((?P[0-9]+) *(%s))?" % days + rel_hours = "((?P[0-9]+) *(%s))?" % hours + rel_mins = "((?P[0-9]+) *(%s))?" % minutes + rel_secs = "((?P[0-9]+) *(%s))?" % seconds + + self.pattern = ("(?P[+-]) *%s *%s *%s *%s *%s *%s *%s(?=(\\W|$))" + % (rel_years, rel_months, rel_weeks, rel_days, + rel_hours, rel_mins, rel_secs)) + self.expr = rcompile(self.pattern, re.IGNORECASE) + + def props_to_date(self, p, dt): + if p.dir == "-": + dir = -1 + else: + dir = 1 + + delta = relativedelta(years=(p.get("years") or 0) * dir, + months=(p.get("months") or 0) * dir, + weeks=(p.get("weeks") or 0) * dir, + days=(p.get("days") or 0) * dir, + hours=(p.get("hours") or 0) * dir, + minutes=(p.get("mins") or 0) * dir, + seconds=(p.get("secs") or 0) * dir) + return dt + delta + + +class Daynames(Regex): + def __init__(self, next, last, daynames): + self.next_pattern = next + self.last_pattern = last + self._dayname_exprs = tuple(rcompile(pat, re.IGNORECASE) + for pat in daynames) + dn_pattern = "|".join(daynames) + self.pattern = ("(?P%s|%s) +(?P%s)(?=(\\W|$))" + % (next, last, dn_pattern)) + self.expr = rcompile(self.pattern, re.IGNORECASE) + + def props_to_date(self, p, dt): + if re.match(p.dir, self.last_pattern): + dir = -1 + else: + dir = 1 + + for daynum, expr in enumerate(self._dayname_exprs): + m = expr.match(p.day) + if m: + break + current_daynum = dt.weekday() + days_delta = relative_days(current_daynum, daynum, dir) + + d = dt.date() + timedelta(days=days_delta) + return adatetime(year=d.year, month=d.month, day=d.day) + + +class Time12(Regex): + def __init__(self): + self.pattern = ("(?P[1-9]|10|11|12)(:(?P[0-5][0-9])" + "(:(?P[0-5][0-9])(\\.(?P[0-9]{1,5}))?)?)?" + "\\s*(?Pam|pm)(?=(\\W|$))") + self.expr = rcompile(self.pattern, re.IGNORECASE) + + def props_to_date(self, p, dt): + isam = p.ampm.lower().startswith("a") + + if p.hour == 12: + if isam: + hr = 0 + else: + hr = 12 + else: + hr = p.hour + if not isam: + hr += 12 + + return adatetime(hour=hr, minute=p.mins, second=p.secs, microsecond=p.usecs) + + +# Top-level parser classes + +class DateParser(object): + """Base class for locale-specific parser classes. + """ + + day = Regex("(?P([123][0-9])|[1-9])(?=(\\W|$))(?!=:)", + lambda p, dt: adatetime(day=p.day)) + year = Regex("(?P[0-9]{4})(?=(\\W|$))", + lambda p, dt: adatetime(year=p.year)) + time24 = Regex("(?P([0-1][0-9])|(2[0-3])):(?P[0-5][0-9])" + "(:(?P[0-5][0-9])(\\.(?P[0-9]{1,5}))?)?" + "(?=(\\W|$))", + lambda p, dt: adatetime(hour=p.hour, minute=p.mins, + second=p.secs, microsecond=p.usecs)) + time12 = Time12() + + def __init__(self): + simple_year = "(?P[0-9]{4})" + simple_month = "(?P[0-1][0-9])" + simple_day = "(?P[0-3][0-9])" + simple_hour = "(?P([0-1][0-9])|(2[0-3]))" + simple_minute = "(?P[0-5][0-9])" + simple_second = "(?P[0-5][0-9])" + simple_usec = "(?P[0-9]{6})" + + tup = (simple_year, simple_month, simple_day, simple_hour, + simple_minute, simple_second, simple_usec) + simple_seq = Sequence(tup, sep="[- .:/]*", name="simple", + progressive=True) + self.simple = Sequence((simple_seq, "(?=(\\s|$))"), sep='') + + self.setup() + + def setup(self): + raise NotImplementedError + + # + + def get_parser(self): + return self.all + + def parse(self, text, dt, pos=0, debug=-9999): + parser = self.get_parser() + + d, newpos = parser.parse(text, dt, pos=pos, debug=debug) + if isinstance(d, (adatetime, timespan)): + d = d.disambiguated(dt) + + return (d, newpos) + + def date_from(self, text, basedate=None, pos=0, debug=-9999, toend=True): + if basedate is None: + basedate = datetime.utcnow() + + parser = self.get_parser() + if toend: + parser = ToEnd(parser) + + d = parser.date_from(text, basedate, pos=pos, debug=debug) + if isinstance(d, (adatetime, timespan)): + d = d.disambiguated(basedate) + return d + + +class English(DateParser): + day = Regex("(?P([123][0-9])|[1-9])(st|nd|rd|th)?(?=(\\W|$))", + lambda p, dt: adatetime(day=p.day)) + + def setup(self): + self.plusdate = PlusMinus("years|year|yrs|yr|ys|y", + "months|month|mons|mon|mos|mo", + "weeks|week|wks|wk|ws|w", + "days|day|dys|dy|ds|d", + "hours|hour|hrs|hr|hs|h", + "minutes|minute|mins|min|ms|m", + "seconds|second|secs|sec|s") + + self.dayname = Daynames("next", "last", + ("monday|mon|mo", "tuesday|tues|tue|tu", + "wednesday|wed|we", "thursday|thur|thu|th", + "friday|fri|fr", "saturday|sat|sa", + "sunday|sun|su")) + + midnight_l = lambda p, dt: adatetime(hour=0, minute=0, second=0, + microsecond=0) + midnight = Regex("midnight", midnight_l) + + noon_l = lambda p, dt: adatetime(hour=12, minute=0, second=0, + microsecond=0) + noon = Regex("noon", noon_l) + + now = Regex("now", lambda p, dt: dt) + + self.time = Choice((self.time12, self.time24, midnight, noon, now), + name="time") + + def tomorrow_to_date(p, dt): + d = dt.date() + timedelta(days=+1) + return adatetime(year=d.year, month=d.month, day=d.day) + tomorrow = Regex("tomorrow", tomorrow_to_date) + + def yesterday_to_date(p, dt): + d = dt.date() + timedelta(days=-1) + return adatetime(year=d.year, month=d.month, day=d.day) + yesterday = Regex("yesterday", yesterday_to_date) + + thisyear = Regex("this year", lambda p, dt: adatetime(year=dt.year)) + thismonth = Regex("this month", + lambda p, dt: adatetime(year=dt.year, + month=dt.month)) + today = Regex("today", + lambda p, dt: adatetime(year=dt.year, month=dt.month, + day=dt.day)) + + self.month = Month("january|jan", "february|febuary|feb", "march|mar", + "april|apr", "may", "june|jun", "july|jul", + "august|aug", "september|sept|sep", "october|oct", + "november|nov", "december|dec") + + # If you specify a day number you must also specify a month... this + # Choice captures that constraint + + self.dmy = Choice((Sequence((self.day, self.month, self.year), + name="dmy"), + Sequence((self.month, self.day, self.year), + name="mdy"), + Sequence((self.year, self.month, self.day), + name="ymd"), + Sequence((self.year, self.day, self.month), + name="ydm"), + Sequence((self.day, self.month), name="dm"), + Sequence((self.month, self.day), name="md"), + Sequence((self.month, self.year), name="my"), + self.month, self.year, self.dayname, tomorrow, + yesterday, thisyear, thismonth, today, now, + ), name="date") + + self.datetime = Bag((self.time, self.dmy), name="datetime") + self.bundle = Choice((self.plusdate, self.datetime, self.simple), + name="bundle") + self.torange = Combo((self.bundle, "to", self.bundle), name="torange") + + self.all = Choice((self.torange, self.bundle), name="all") + + +# QueryParser plugin + +class DateParserPlugin(plugins.Plugin): + """Adds more powerful parsing of DATETIME fields. + + >>> parser.add_plugin(DateParserPlugin()) + >>> parser.parse(u"date:'last tuesday'") + """ + + def __init__(self, basedate=None, dateparser=None, callback=None, + free=False, free_expr="([A-Za-z][A-Za-z_0-9]*):([^^]+)"): + """ + :param basedate: a datetime object representing the current time + against which to measure relative dates. If you do not supply this + argument, the plugin uses ``datetime.utcnow()``. + :param dateparser: an instance of + :class:`whoosh.qparser.dateparse.DateParser`. If you do not supply + this argument, the plugin automatically uses + :class:`whoosh.qparser.dateparse.English`. + :param callback: a callback function for parsing errors. This allows + you to provide feedback to the user about problems parsing dates. + :param remove: if True, unparseable dates are removed from the token + stream instead of being replaced with ErrorToken. + :param free: if True, this plugin will install a filter early in the + parsing process and try to find undelimited dates such as + ``date:last tuesday``. Note that allowing this could result in + normal query words accidentally being parsed as dates sometimes. + """ + + self.basedate = basedate + if dateparser is None: + dateparser = English() + self.dateparser = dateparser + self.callback = callback + self.free = free + self.freeexpr = free_expr + + def taggers(self, parser): + if self.free: + # If we're tokenizing, we have to go before the FieldsPlugin + return [(DateTagger(self, self.freeexpr), -1)] + else: + return () + + def filters(self, parser): + # Run the filter after the FieldsPlugin assigns field names + return [(self.do_dates, 110)] + + def errorize(self, message, node): + if self.callback: + self.callback(message) + return syntax.ErrorNode(message, node) + + def text_to_dt(self, node): + text = node.text + try: + dt = self.dateparser.date_from(text, self.basedate) + if dt is None: + return self.errorize(text, node) + else: + n = DateTimeNode(node.fieldname, dt, node.boost) + except DateParseError: + e = sys.exc_info()[1] + n = self.errorize(e, node) + n.startchar = node.startchar + n.endchar = node.endchar + return n + + def range_to_dt(self, node): + start = end = None + dp = self.dateparser.get_parser() + + if node.start: + start = dp.date_from(node.start, self.basedate) + if start is None: + return self.errorize(node.start, node) + if node.end: + end = dp.date_from(node.end, self.basedate) + if end is None: + return self.errorize(node.end, node) + + if start and end: + ts = timespan(start, end).disambiguated(self.basedate) + start, end = ts.start, ts.end + elif start: + start = start.disambiguated(self.basedate) + if isinstance(start, timespan): + start = start.start + elif end: + end = end.disambiguated(self.basedate) + if isinstance(end, timespan): + end = end.end + drn = DateRangeNode(node.fieldname, start, end, boost=node.boost) + drn.startchar = node.startchar + drn.endchar = node.endchar + return drn + + def do_dates(self, parser, group): + schema = parser.schema + if not schema: + return group + + from whoosh.fields import DATETIME + datefields = frozenset(fieldname for fieldname, field + in parser.schema.items() + if isinstance(field, DATETIME)) + + for i, node in enumerate(group): + if node.has_fieldname: + fname = node.fieldname or parser.fieldname + else: + fname = None + + if isinstance(node, syntax.GroupNode): + group[i] = self.do_dates(parser, node) + elif fname in datefields: + if node.has_text: + group[i] = self.text_to_dt(node) + elif isinstance(node, syntax.RangeNode): + group[i] = self.range_to_dt(node) + return group + + +class DateTimeNode(syntax.SyntaxNode): + has_fieldname = True + has_boost = True + + def __init__(self, fieldname, dt, boost=1.0): + self.fieldname = fieldname + self.dt = dt + self.boost = 1.0 + + def r(self): + return repr(self.dt) + + def query(self, parser): + from whoosh import query + + fieldname = self.fieldname or parser.fieldname + field = parser.schema[fieldname] + dt = self.dt + if isinstance(self.dt, datetime): + btext = field.to_bytes(dt) + return query.Term(fieldname, btext, boost=self.boost) + elif isinstance(self.dt, timespan): + return query.DateRange(fieldname, dt.start, dt.end, + boost=self.boost) + else: + raise Exception("Unknown time object: %r" % dt) + + +class DateRangeNode(syntax.SyntaxNode): + has_fieldname = True + has_boost = True + + def __init__(self, fieldname, start, end, boost=1.0): + self.fieldname = fieldname + self.start = start + self.end = end + self.boost = 1.0 + + def r(self): + return "%r-%r" % (self.start, self.end) + + def query(self, parser): + from whoosh import query + + fieldname = self.fieldname or parser.fieldname + return query.DateRange(fieldname, self.start, self.end, + boost=self.boost) + + +class DateTagger(Tagger): + def __init__(self, plugin, expr): + self.plugin = plugin + self.expr = rcompile(expr, re.IGNORECASE) + + def match(self, parser, text, pos): + from whoosh.fields import DATETIME + + match = self.expr.match(text, pos) + if match: + fieldname = match.group(1) + dtext = match.group(2) + + if parser.schema and fieldname in parser.schema: + field = parser.schema[fieldname] + if isinstance(field, DATETIME): + plugin = self.plugin + dateparser = plugin.dateparser + basedate = plugin.basedate + + d, newpos = dateparser.parse(dtext, basedate) + if d: + node = DateTimeNode(fieldname, d) + node.startchar = match.start() + node.endchar = newpos + match.start(2) + return node diff --git a/nstock/modules/whoosh/qparser/default.py b/nstock/modules/whoosh/qparser/default.py new file mode 100644 index 0000000..7b4dfee --- /dev/null +++ b/nstock/modules/whoosh/qparser/default.py @@ -0,0 +1,439 @@ +# Copyright 2011 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +import sys + +from whoosh import query +from whoosh.compat import text_type +from whoosh.qparser import syntax +from whoosh.qparser.common import print_debug, QueryParserError + + +# Query parser object + +class QueryParser(object): + """A hand-written query parser built on modular plug-ins. The default + configuration implements a powerful fielded query language similar to + Lucene's. + + You can use the ``plugins`` argument when creating the object to override + the default list of plug-ins, and/or use ``add_plugin()`` and/or + ``remove_plugin_class()`` to change the plug-ins included in the parser. + + >>> from whoosh import qparser + >>> parser = qparser.QueryParser("content", schema) + >>> parser.remove_plugin_class(qparser.WildcardPlugin) + >>> parser.add_plugin(qparser.PrefixPlugin()) + >>> parser.parse(u"hello there") + And([Term("content", u"hello"), Term("content", u"there")]) + """ + + def __init__(self, fieldname, schema, plugins=None, termclass=query.Term, + phraseclass=query.Phrase, group=syntax.AndGroup): + """ + :param fieldname: the default field -- the parser uses this as the + field for any terms without an explicit field. + :param schema: a :class:`whoosh.fields.Schema` object to use when + parsing. The appropriate fields in the schema will be used to + tokenize terms/phrases before they are turned into query objects. + You can specify None for the schema to create a parser that does + not analyze the text of the query, usually for testing purposes. + :param plugins: a list of plugins to use. WhitespacePlugin is + automatically included, do not put it in this list. This overrides + the default list of plugins. Classes in the list will be + automatically instantiated. + :param termclass: the query class to use for individual search terms. + The default is :class:`whoosh.query.Term`. + :param phraseclass: the query class to use for phrases. The default + is :class:`whoosh.query.Phrase`. + :param group: the default grouping. ``AndGroup`` makes terms required + by default. ``OrGroup`` makes terms optional by default. + """ + + self.fieldname = fieldname + self.schema = schema + self.termclass = termclass + self.phraseclass = phraseclass + self.group = group + self.plugins = [] + + if plugins is None: + plugins = self.default_set() + self._add_ws_plugin() + self.add_plugins(plugins) + + def default_set(self): + """Returns the default list of plugins to use. + """ + + from whoosh.qparser import plugins + + return [plugins.WhitespacePlugin(), + plugins.SingleQuotePlugin(), + plugins.FieldsPlugin(), + plugins.WildcardPlugin(), + plugins.PhrasePlugin(), + plugins.RangePlugin(), + plugins.GroupPlugin(), + plugins.OperatorsPlugin(), + plugins.BoostPlugin(), + plugins.EveryPlugin(), + ] + + def add_plugins(self, pins): + """Adds the given list of plugins to the list of plugins in this + parser. + """ + + for pin in pins: + self.add_plugin(pin) + + def add_plugin(self, pin): + """Adds the given plugin to the list of plugins in this parser. + """ + + if isinstance(pin, type): + pin = pin() + self.plugins.append(pin) + + def _add_ws_plugin(self): + from whoosh.qparser.plugins import WhitespacePlugin + self.add_plugin(WhitespacePlugin()) + + def remove_plugin(self, pi): + """Removes the given plugin object from the list of plugins in this + parser. + """ + + self.plugins.remove(pi) + + def remove_plugin_class(self, cls): + """Removes any plugins of the given class from this parser. + """ + + self.plugins = [pi for pi in self.plugins if not isinstance(pi, cls)] + + def replace_plugin(self, plugin): + """Removes any plugins of the class of the given plugin and then adds + it. This is a convenience method to keep from having to call + ``remove_plugin_class`` followed by ``add_plugin`` each time you want + to reconfigure a default plugin. + + >>> qp = qparser.QueryParser("content", schema) + >>> qp.replace_plugin(qparser.NotPlugin("(^| )-")) + """ + + self.remove_plugin_class(plugin.__class__) + self.add_plugin(plugin) + + def _priorized(self, methodname): + # methodname is "taggers" or "filters". Returns a priorized list of + # tagger objects or filter functions. + items_and_priorities = [] + for plugin in self.plugins: + # Call either .taggers() or .filters() on the plugin + method = getattr(plugin, methodname) + for item in method(self): + items_and_priorities.append(item) + # Sort the list by priority (lower priority runs first) + items_and_priorities.sort(key=lambda x: x[1]) + # Return the sorted list without the priorities + return [item for item, _ in items_and_priorities] + + def multitoken_query(self, spec, texts, fieldname, termclass, boost): + """Returns a query for multiple texts. This method implements the + intention specified in the field's ``multitoken_query`` attribute, + which specifies what to do when strings that look like single terms + to the parser turn out to yield multiple tokens when analyzed. + + :param spec: a string describing how to join the text strings into a + query. This is usually the value of the field's + ``multitoken_query`` attribute. + :param texts: a list of token strings. + :param fieldname: the name of the field. + :param termclass: the query class to use for single terms. + :param boost: the original term's boost in the query string, should be + applied to the returned query object. + """ + + spec = spec.lower() + if spec == "first": + # Throw away all but the first token + return termclass(fieldname, texts[0], boost=boost) + elif spec == "phrase": + # Turn the token into a phrase + return self.phraseclass(fieldname, texts, boost=boost) + else: + if spec == "default": + qclass = self.group.qclass + elif spec == "and": + qclass = query.And + elif spec == "or": + qclass = query.Or + else: + raise QueryParserError("Unknown multitoken_query value %r" + % spec) + return qclass([termclass(fieldname, t, boost=boost) + for t in texts]) + + def term_query(self, fieldname, text, termclass, boost=1.0, tokenize=True, + removestops=True): + """Returns the appropriate query object for a single term in the query + string. + """ + + if self.schema and fieldname in self.schema: + field = self.schema[fieldname] + + # If this field type wants to parse queries itself, let it do so + # and return early + if field.self_parsing(): + try: + q = field.parse_query(fieldname, text, boost=boost) + return q + except: + e = sys.exc_info()[1] + return query.error_query(e) + + # Otherwise, ask the field to process the text into a list of + # tokenized strings + texts = list(field.process_text(text, mode="query", + tokenize=tokenize, + removestops=removestops)) + + # If the analyzer returned more than one token, use the field's + # multitoken_query attribute to decide what query class, if any, to + # use to put the tokens together + if len(texts) > 1: + return self.multitoken_query(field.multitoken_query, texts, + fieldname, termclass, boost) + + # It's possible field.process_text() will return an empty list (for + # example, on a stop word) + if not texts: + return None + text = texts[0] + + return termclass(fieldname, text, boost=boost) + + def taggers(self): + """Returns a priorized list of tagger objects provided by the parser's + currently configured plugins. + """ + + return self._priorized("taggers") + + def filters(self): + """Returns a priorized list of filter functions provided by the + parser's currently configured plugins. + """ + + return self._priorized("filters") + + def tag(self, text, pos=0, debug=False): + """Returns a group of syntax nodes corresponding to the given text, + created by matching the Taggers provided by the parser's plugins. + + :param text: the text to tag. + :param pos: the position in the text to start tagging at. + """ + + # The list out output tags + stack = [] + # End position of the previous match + prev = pos + # Priorized list of taggers provided by the parser's plugins + taggers = self.taggers() + if debug: + print_debug(debug, "Taggers: %r" % taggers) + + # Define a function that will make a WordNode from the "interstitial" + # text between matches + def inter(startchar, endchar): + n = syntax.WordNode(text[startchar:endchar]) + n.startchar = startchar + n.endchar = endchar + return n + + while pos < len(text): + node = None + # Try each tagger to see if it matches at the current position + for tagger in taggers: + node = tagger.match(self, text, pos) + if node is not None: + if node.endchar <= pos: + raise Exception("Token %r did not move cursor forward." + " (%r, %s)" % (tagger, text, pos)) + if prev < pos: + tween = inter(prev, pos) + if debug: + print_debug(debug, "Tween: %r" % tween) + stack.append(tween) + + if debug: + print_debug(debug, "Tagger: %r at %s: %r" + % (tagger, pos, node)) + stack.append(node) + prev = pos = node.endchar + break + + if not node: + # No taggers matched, move forward + pos += 1 + + # If there's unmatched text left over on the end, put it in a WordNode + if prev < len(text): + stack.append(inter(prev, len(text))) + + # Wrap the list of nodes in a group node + group = self.group(stack) + if debug: + print_debug(debug, "Tagged group: %r" % group) + return group + + def filterize(self, nodes, debug=False): + """Takes a group of nodes and runs the filters provided by the parser's + plugins. + """ + + # Call each filter in the priorized list of plugin filters + if debug: + print_debug(debug, "Pre-filtered group: %r" % nodes) + for f in self.filters(): + if debug: + print_debug(debug, "..Applying: %r" % f) + nodes = f(self, nodes) + if debug: + print_debug(debug, "..Result: %r" % nodes) + if nodes is None: + raise Exception("Filter %r did not return anything" % f) + return nodes + + def process(self, text, pos=0, debug=False): + """Returns a group of syntax nodes corresponding to the given text, + tagged by the plugin Taggers and filtered by the plugin filters. + + :param text: the text to tag. + :param pos: the position in the text to start tagging at. + """ + + nodes = self.tag(text, pos=pos, debug=debug) + nodes = self.filterize(nodes, debug=debug) + return nodes + + def parse(self, text, normalize=True, debug=False): + """Parses the input string and returns a :class:`whoosh.query.Query` + object/tree. + + :param text: the unicode string to parse. + :param normalize: whether to call normalize() on the query object/tree + before returning it. This should be left on unless you're trying to + debug the parser output. + :rtype: :class:`whoosh.query.Query` + """ + + if not isinstance(text, text_type): + text = text.decode("latin1") + + nodes = self.process(text, debug=debug) + if debug: + print_debug(debug, "Syntax tree: %r" % nodes) + + q = nodes.query(self) + if not q: + q = query.NullQuery + if debug: + print_debug(debug, "Pre-normalized query: %r" % q) + + if normalize: + q = q.normalize() + if debug: + print_debug(debug, "Normalized query: %r" % q) + return q + + def parse_(self, text, normalize=True): + pass + + +# Premade parser configurations + +def MultifieldParser(fieldnames, schema, fieldboosts=None, **kwargs): + """Returns a QueryParser configured to search in multiple fields. + + Instead of assigning unfielded clauses to a default field, this parser + transforms them into an OR clause that searches a list of fields. For + example, if the list of multi-fields is "f1", "f2" and the query string is + "hello there", the class will parse "(f1:hello OR f2:hello) (f1:there OR + f2:there)". This is very useful when you have two textual fields (e.g. + "title" and "content") you want to search by default. + + :param fieldnames: a list of field names to search. + :param fieldboosts: an optional dictionary mapping field names to boosts. + """ + + from whoosh.qparser.plugins import MultifieldPlugin + + p = QueryParser(None, schema, **kwargs) + mfp = MultifieldPlugin(fieldnames, fieldboosts=fieldboosts) + p.add_plugin(mfp) + return p + + +def SimpleParser(fieldname, schema, **kwargs): + """Returns a QueryParser configured to support only +, -, and phrase + syntax. + """ + + from whoosh.qparser import plugins, syntax + + pins = [plugins.WhitespacePlugin, + plugins.PlusMinusPlugin, + plugins.PhrasePlugin] + orgroup = syntax.OrGroup + return QueryParser(fieldname, schema, plugins=pins, group=orgroup, + **kwargs) + + +def DisMaxParser(fieldboosts, schema, tiebreak=0.0, **kwargs): + """Returns a QueryParser configured to support only +, -, and phrase + syntax, and which converts individual terms into DisjunctionMax queries + across a set of fields. + + :param fieldboosts: a dictionary mapping field names to boosts. + """ + + from whoosh.qparser import plugins, syntax + + mfp = plugins.MultifieldPlugin(list(fieldboosts.keys()), + fieldboosts=fieldboosts, + group=syntax.DisMaxGroup) + pins = [plugins.WhitespacePlugin, + plugins.PlusMinusPlugin, + plugins.PhrasePlugin, + mfp] + orgroup = syntax.OrGroup + return QueryParser(None, schema, plugins=pins, group=orgroup, **kwargs) diff --git a/nstock/modules/whoosh/qparser/plugins.py b/nstock/modules/whoosh/qparser/plugins.py new file mode 100644 index 0000000..9f1a7fa --- /dev/null +++ b/nstock/modules/whoosh/qparser/plugins.py @@ -0,0 +1,1413 @@ +# Copyright 2011 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +import copy + +from whoosh import query +from whoosh.compat import u +from whoosh.compat import iteritems, xrange +from whoosh.qparser import syntax +from whoosh.qparser.common import attach +from whoosh.qparser.taggers import RegexTagger, FnTagger +from whoosh.util.text import rcompile + + +class Plugin(object): + """Base class for parser plugins. + """ + + def taggers(self, parser): + """Should return a list of ``(Tagger, priority)`` tuples to add to the + syntax the parser understands. Lower priorities run first. + """ + + return () + + def filters(self, parser): + """Should return a list of ``(filter_function, priority)`` tuples to + add to parser. Lower priority numbers run first. + + Filter functions will be called with ``(parser, groupnode)`` and should + return a group node. + """ + + return () + + +class TaggingPlugin(RegexTagger): + """A plugin that also acts as a Tagger, to avoid having an extra Tagger + class for simple cases. + + A TaggingPlugin object should have a ``priority`` attribute and either a + ``nodetype`` attribute or a ``create()`` method. If the subclass doesn't + override ``create()``, the base class will call ``self.nodetype`` with the + Match object's named groups as keyword arguments. + """ + + priority = 0 + + def __init__(self, expr=None): + self.expr = rcompile(expr or self.expr) + + def taggers(self, parser): + return [(self, self.priority)] + + def filters(self, parser): + return () + + def create(self, parser, match): + # Groupdict keys can be unicode sometimes apparently? Convert them to + # str for use as keyword arguments. This should be Py3-safe. + kwargs = dict((str(k), v) for k, v in iteritems(match.groupdict())) + return self.nodetype(**kwargs) + + +class WhitespacePlugin(TaggingPlugin): + """Tags whitespace and removes it at priority 500. Depending on whether + your plugin's filter wants to see where whitespace was in the original + query, it should run with priority lower than 500 (before removal of + whitespace) or higher than 500 (after removal of whitespace). + """ + + nodetype = syntax.Whitespace + priority = 100 + + def __init__(self, expr=r"\s+"): + TaggingPlugin.__init__(self, expr) + + def filters(self, parser): + return [(self.remove_whitespace, 500)] + + def remove_whitespace(self, parser, group): + newgroup = group.empty_copy() + for node in group: + if isinstance(node, syntax.GroupNode): + newgroup.append(self.remove_whitespace(parser, node)) + elif not node.is_ws(): + newgroup.append(node) + return newgroup + + +class SingleQuotePlugin(TaggingPlugin): + """Adds the ability to specify single "terms" containing spaces by + enclosing them in single quotes. + """ + + expr = r"(^|(?<=\W))'(?P.*?)'(?=\s|\]|[)}]|$)" + nodetype = syntax.WordNode + + +class PrefixPlugin(TaggingPlugin): + """Adds the ability to specify prefix queries by ending a term with an + asterisk. + + This plugin is useful if you want the user to be able to create prefix but + not wildcard queries (for performance reasons). If you are including the + wildcard plugin, you should not include this plugin as well. + + >>> qp = qparser.QueryParser("content", myschema) + >>> qp.remove_plugin_class(qparser.WildcardPlugin) + >>> qp.add_plugin(qparser.PrefixPlugin()) + >>> q = qp.parse("pre*") + """ + + class PrefixNode(syntax.TextNode): + qclass = query.Prefix + + def r(self): + return "%r*" % self.text + + expr = "(?P[^ \t\r\n*]+)[*](?= |$|\\))" + nodetype = PrefixNode + + +class WildcardPlugin(TaggingPlugin): + # \u055E = Armenian question mark + # \u061F = Arabic question mark + # \u1367 = Ethiopic question mark + qmarks = u("?\u055E\u061F\u1367") + expr = "(?P[*%s])" % qmarks + + def filters(self, parser): + # Run early, but definitely before multifield plugin + return [(self.do_wildcards, 50)] + + def do_wildcards(self, parser, group): + i = 0 + while i < len(group): + node = group[i] + if isinstance(node, self.WildcardNode): + if i < len(group) - 1 and group[i + 1].is_text(): + nextnode = group.pop(i + 1) + node.text += nextnode.text + if i > 0 and group[i - 1].is_text(): + prevnode = group.pop(i - 1) + node.text = prevnode.text + node.text + else: + i += 1 + else: + if isinstance(node, syntax.GroupNode): + self.do_wildcards(parser, node) + i += 1 + + for i in xrange(len(group)): + node = group[i] + if isinstance(node, self.WildcardNode): + text = node.text + if len(text) > 1 and not any(qm in text for qm in self.qmarks): + if text.find("*") == len(text) - 1: + newnode = PrefixPlugin.PrefixNode(text[:-1]) + newnode.startchar = node.startchar + newnode.endchar = node.endchar + group[i] = newnode + return group + + class WildcardNode(syntax.TextNode): + # Note that this node inherits tokenize = False from TextNode, + # so the text in this node will not be analyzed... just passed + # straight to the query + + qclass = query.Wildcard + + def r(self): + return "Wild %r" % self.text + + nodetype = WildcardNode + + +class RegexPlugin(TaggingPlugin): + """Adds the ability to specify regular expression term queries. + + The default syntax for a regular expression term is ``r"termexpr"``. + + >>> qp = qparser.QueryParser("content", myschema) + >>> qp.add_plugin(qparser.RegexPlugin()) + >>> q = qp.parse('foo title:r"bar+"') + """ + + class RegexNode(syntax.TextNode): + qclass = query.Regex + + def r(self): + return "Regex %r" % self.text + + expr = 'r"(?P[^"]*)"' + nodetype = RegexNode + + +class BoostPlugin(TaggingPlugin): + """Adds the ability to boost clauses of the query using the circumflex. + + >>> qp = qparser.QueryParser("content", myschema) + >>> q = qp.parse("hello there^2") + """ + + expr = "\\^(?P[0-9]*(\\.[0-9]+)?)($|(?=[ \t\r\n)]))" + + class BoostNode(syntax.SyntaxNode): + def __init__(self, original, boost): + self.original = original + self.boost = boost + + def r(self): + return "^ %s" % self.boost + + def create(self, parser, match): + # Override create so we can grab group 0 + original = match.group(0) + try: + boost = float(match.group("boost")) + except ValueError: + # The text after the ^ wasn't a valid number, so turn it into a + # word + node = syntax.WordNode(original) + else: + node = self.BoostNode(original, boost) + + return node + + def filters(self, parser): + return [(self.clean_boost, 0), (self.do_boost, 510)] + + def clean_boost(self, parser, group): + """This filter finds any BoostNodes in positions where they can't boost + the previous node (e.g. at the very beginning, after whitespace, or + after another BoostNode) and turns them into WordNodes. + """ + + bnode = self.BoostNode + for i, node in enumerate(group): + if isinstance(node, bnode): + if (not i or not group[i - 1].has_boost): + group[i] = syntax.to_word(node) + return group + + def do_boost(self, parser, group): + """This filter finds BoostNodes and applies the boost to the previous + node. + """ + + newgroup = group.empty_copy() + for node in group: + if isinstance(node, syntax.GroupNode): + node = self.do_boost(parser, node) + elif isinstance(node, self.BoostNode): + if (newgroup and newgroup[-1].has_boost): + # Apply the BoostNode's boost to the previous node + newgroup[-1].set_boost(node.boost) + # Skip adding the BoostNode to the new group + continue + else: + node = syntax.to_word(node) + newgroup.append(node) + return newgroup + + +class GroupPlugin(Plugin): + """Adds the ability to group clauses using parentheses. + """ + + # Marker nodes for open and close bracket + + class OpenBracket(syntax.SyntaxNode): + def r(self): + return "(" + + class CloseBracket(syntax.SyntaxNode): + def r(self): + return ")" + + def __init__(self, openexpr="[(]", closeexpr="[)]"): + self.openexpr = openexpr + self.closeexpr = closeexpr + + def taggers(self, parser): + return [(FnTagger(self.openexpr, self.OpenBracket, "openB"), 0), + (FnTagger(self.closeexpr, self.CloseBracket, "closeB"), 0)] + + def filters(self, parser): + return [(self.do_groups, 0)] + + def do_groups(self, parser, group): + """This filter finds open and close bracket markers in a flat group + and uses them to organize the nodes into a hierarchy. + """ + + ob, cb = self.OpenBracket, self.CloseBracket + # Group hierarchy stack + stack = [parser.group()] + for node in group: + if isinstance(node, ob): + # Open bracket: push a new level of hierarchy on the stack + stack.append(parser.group()) + elif isinstance(node, cb): + # Close bracket: pop the current level of hierarchy and append + # it to the previous level + if len(stack) > 1: + last = stack.pop() + stack[-1].append(last) + else: + # Anything else: add it to the current level of hierarchy + stack[-1].append(node) + + top = stack[0] + # If the parens were unbalanced (more opens than closes), just take + # whatever levels of hierarchy were left on the stack and tack them on + # the end of the top-level + if len(stack) > 1: + for ls in stack[1:]: + top.extend(ls) + + if len(top) == 1 and isinstance(top[0], syntax.GroupNode): + boost = top.boost + top = top[0] + top.boost = boost + + return top + + +class EveryPlugin(TaggingPlugin): + expr = "[*]:[*]" + priority = -1 + + def create(self, parser, match): + return self.EveryNode() + + class EveryNode(syntax.SyntaxNode): + def r(self): + return "*:*" + + def query(self, parser): + return query.Every() + + +class FieldsPlugin(TaggingPlugin): + """Adds the ability to specify the field of a clause. + """ + + class FieldnameTagger(RegexTagger): + def create(self, parser, match): + return syntax.FieldnameNode(match.group("text"), match.group(0)) + + def __init__(self, expr=r"(?P\w+|[*]):", remove_unknown=True): + """ + :param expr: the regular expression to use for tagging fields. + :param remove_unknown: if True, converts field specifications for + fields that aren't in the schema into regular text. + """ + + self.expr = expr + self.removeunknown = remove_unknown + + def taggers(self, parser): + return [(self.FieldnameTagger(self.expr), 0)] + + def filters(self, parser): + return [(self.do_fieldnames, 100)] + + def do_fieldnames(self, parser, group): + """This filter finds FieldnameNodes in the tree and applies their + fieldname to the next node. + """ + + fnclass = syntax.FieldnameNode + + if self.removeunknown and parser.schema: + # Look for field nodes that aren't in the schema and convert them + # to text + schema = parser.schema + newgroup = group.empty_copy() + prev_field_node = None + + for node in group: + if isinstance(node, fnclass) and node.fieldname not in schema: + prev_field_node = node + continue + elif prev_field_node: + # If prev_field_node is not None, it contains a field node + # that appeared before this node but isn't in the schema, + # so we'll convert it to text here + if node.has_text: + node.text = prev_field_node.original + node.text + else: + newgroup.append(syntax.to_word(prev_field_node)) + prev_field_node = None + newgroup.append(node) + if prev_field_node: + newgroup.append(syntax.to_word(prev_field_node)) + group = newgroup + + newgroup = group.empty_copy() + # Iterate backwards through the stream, looking for field-able objects + # with field nodes in front of them + i = len(group) + while i > 0: + i -= 1 + node = group[i] + if isinstance(node, fnclass): + # If we see a fieldname node, it must not have been in front + # of something fieldable, since we would have already removed + # it (since we're iterating backwards), so convert it to text + node = syntax.to_word(node) + elif isinstance(node, syntax.GroupNode): + node = self.do_fieldnames(parser, node) + + if i > 0 and not node.is_ws() and isinstance(group[i - 1], + fnclass): + node.set_fieldname(group[i - 1].fieldname, override=False) + i -= 1 + + newgroup.append(node) + newgroup.reverse() + return newgroup + + +class FuzzyTermPlugin(TaggingPlugin): + """Adds syntax to the query parser to create "fuzzy" term queries, which + match any term within a certain "edit distance" (number of inserted, + deleted, or transposed characters) by appending a tilde (``~``) and an + optional maximum edit distance to a term. If you don't specify an explicit + maximum edit distance, the default is 1. + + >>> qp = qparser.QueryParser("content", myschema) + >>> qp.add_plugin(qparser.FuzzyTermPlugin()) + >>> q = qp.parse("Stephen~2 Colbert") + + For example, the following query creates a :class:`whoosh.query.FuzzyTerm` + query with a maximum edit distance of 1:: + + bob~ + + The following creates a fuzzy term query with a maximum edit distance of + 2:: + + bob~2 + + The maximum edit distance can only be a single digit. Note that edit + distances greater than 2 can take an extremely long time and are generally + not useful. + + You can specify a prefix length using ``~n/m``. For example, to allow a + maximum edit distance of 2 and require a prefix match of 3 characters:: + + johannson~2/3 + + To specify a prefix with the default edit distance:: + + johannson~/3 + """ + + expr = rcompile(""" + (?<=\\S) # Only match right after non-space + ~ # Initial tilde + (?P[0-9])? # Optional maxdist + (/ # Optional prefix slash + (?P[1-9][0-9]*) # prefix + )? # (end prefix group) + """, verbose=True) + + class FuzzinessNode(syntax.SyntaxNode): + def __init__(self, maxdist, prefixlength, original): + self.maxdist = maxdist + self.prefixlength = prefixlength + self.original = original + + def __repr__(self): + return "<~%d/%d>" % (self.maxdist, self.prefixlength) + + class FuzzyTermNode(syntax.TextNode): + qclass = query.FuzzyTerm + + def __init__(self, wordnode, maxdist, prefixlength): + self.fieldname = wordnode.fieldname + self.text = wordnode.text + self.boost = wordnode.boost + self.startchar = wordnode.startchar + self.endchar = wordnode.endchar + self.maxdist = maxdist + self.prefixlength = prefixlength + + def r(self): + return "%r ~%d/%d" % (self.text, self.maxdist, self.prefixlength) + + def query(self, parser): + # Use the superclass's query() method to create a FuzzyTerm query + # (it looks at self.qclass), just because it takes care of some + # extra checks and attributes + q = syntax.TextNode.query(self, parser) + # Set FuzzyTerm-specific attributes + q.maxdist = self.maxdist + q.prefixlength = self.prefixlength + return q + + def create(self, parser, match): + mdstr = match.group("maxdist") + maxdist = int(mdstr) if mdstr else 1 + + pstr = match.group("prefix") + prefixlength = int(pstr) if pstr else 0 + + return self.FuzzinessNode(maxdist, prefixlength, match.group(0)) + + def filters(self, parser): + return [(self.do_fuzzyterms, 0)] + + def do_fuzzyterms(self, parser, group): + newgroup = group.empty_copy() + i = 0 + while i < len(group): + node = group[i] + if i < len(group) - 1 and isinstance(node, syntax.WordNode): + nextnode = group[i + 1] + if isinstance(nextnode, self.FuzzinessNode): + node = self.FuzzyTermNode(node, nextnode.maxdist, + nextnode.prefixlength) + i += 1 + if isinstance(node, self.FuzzinessNode): + node = syntax.to_word(node) + if isinstance(node, syntax.GroupNode): + node = self.do_fuzzyterms(parser, node) + + newgroup.append(node) + i += 1 + return newgroup + + +class FunctionPlugin(TaggingPlugin): + """Adds an abitrary "function call" syntax to the query parser to allow + advanced and extensible query functionality. + + This is unfinished and experimental. + """ + + expr = rcompile(""" + [#](?P[A-Za-z_][A-Za-z0-9._]*) # function name + ( # optional args + \\[ # inside square brackets + (?P.*?) + \\] + )? + """, verbose=True) + + class FunctionNode(syntax.SyntaxNode): + has_fieldname = False + has_boost = True + merging = False + + def __init__(self, name, fn, args, kwargs): + self.name = name + self.fn = fn + self.args = args + self.kwargs = kwargs + self.nodes = [] + self.boost = None + + def __repr__(self): + return "#%s<%r>(%r)" % (self.name, self.args, self.nodes) + + def query(self, parser): + qs = [n.query(parser) for n in self.nodes] + kwargs = self.kwargs + if "boost" not in kwargs and self.boost is not None: + kwargs["boost"] = self.boost + # TODO: If this call raises an exception, return an error query + return self.fn(qs, *self.args, **self.kwargs) + + def __init__(self, fns): + """ + :param fns: a dictionary mapping names to functions that return a + query. + """ + + self.fns = fns + + def create(self, parser, match): + name = match.group("name") + if name in self.fns: + fn = self.fns[name] + argstring = match.group("args") + if argstring: + args, kwargs = self._parse_args(argstring) + else: + args = () + kwargs = {} + return self.FunctionNode(name, fn, args, kwargs) + + def _parse_args(self, argstring): + args = [] + kwargs = {} + + parts = argstring.split(",") + for part in parts: + if "=" in part: + name, value = part.split("=", 1) + # Wrap with str() because Python 2.5 can't handle unicode kws + name = str(name.strip()) + else: + name = None + value = part + + value = value.strip() + if value.startswith("'") and value.endswith("'"): + value = value[1:-1] + + if name: + kwargs[name] = value + else: + args.append(value) + + return args, kwargs + + def filters(self, parser): + return [(self.do_functions, 600)] + + def do_functions(self, parser, group): + newgroup = group.empty_copy() + i = 0 + while i < len(group): + node = group[i] + if (isinstance(node, self.FunctionNode) + and i < len(group) - 1 + and isinstance(group[i + 1], syntax.GroupNode)): + nextnode = group[i + 1] + node.nodes = list(self.do_functions(parser, nextnode)) + + if nextnode.boost != 1: + node.set_boost(nextnode.boost) + + i += 1 + elif isinstance(node, syntax.GroupNode): + node = self.do_functions(parser, node) + + newgroup.append(node) + i += 1 + return newgroup + + +class PhrasePlugin(Plugin): + """Adds the ability to specify phrase queries inside double quotes. + """ + + # Didn't use TaggingPlugin because I need to add slop parsing at some + # point + + # Expression used to find words if a schema isn't available + wordexpr = rcompile(r'\S+') + + class PhraseNode(syntax.TextNode): + def __init__(self, text, textstartchar, slop=1): + syntax.TextNode.__init__(self, text) + self.textstartchar = textstartchar + self.slop = slop + + def r(self): + return "%s %r~%s" % (self.__class__.__name__, self.text, self.slop) + + def apply(self, fn): + return self.__class__(self.type, [fn(node) for node in self.nodes], + slop=self.slop, boost=self.boost) + + def query(self, parser): + text = self.text + fieldname = self.fieldname or parser.fieldname + + # We want to process the text of the phrase into "words" (tokens), + # and also record the startchar and endchar of each word + + sc = self.textstartchar + if parser.schema and fieldname in parser.schema: + field = parser.schema[fieldname] + if field.analyzer: + # We have a field with an analyzer, so use it to parse + # the phrase into tokens + tokens = field.tokenize(text, mode="query", chars=True) + words = [] + char_ranges = [] + for t in tokens: + words.append(t.text) + char_ranges.append((sc + t.startchar, sc + t.endchar)) + else: + # We have a field but it doesn't have a format object, + # for some reason (it's self-parsing?), so use process_text + # to get the texts (we won't know the start/end chars) + words = list(field.process_text(text, mode="query")) + char_ranges = [(None, None)] * len(words) + else: + # We're parsing without a schema, so just use the default + # regular expression to break the text into words + words = [] + char_ranges = [] + for match in PhrasePlugin.wordexpr.finditer(text): + words.append(match.group(0)) + char_ranges.append((sc + match.start(), sc + match.end())) + + qclass = parser.phraseclass + q = qclass(fieldname, words, slop=self.slop, boost=self.boost, + char_ranges=char_ranges) + return attach(q, self) + + class PhraseTagger(RegexTagger): + def create(self, parser, match): + text = match.group("text") + textstartchar = match.start("text") + slopstr = match.group("slop") + slop = int(slopstr) if slopstr else 1 + return PhrasePlugin.PhraseNode(text, textstartchar, slop) + + def __init__(self, expr='"(?P.*?)"(~(?P[1-9][0-9]*))?'): + self.expr = expr + + def taggers(self, parser): + return [(self.PhraseTagger(self.expr), 0)] + + +class SequencePlugin(Plugin): + """Adds the ability to group arbitrary queries inside double quotes to + produce a query matching the individual sub-queries in sequence. + + To enable this plugin, first remove the default PhrasePlugin, then add + this plugin:: + + qp = qparser.QueryParser("field", my_schema) + qp.remove_plugin_class(qparser.PhrasePlugin) + qp.add_plugin(qparser.SequencePlugin()) + + This enables parsing "phrases" such as:: + + "(jon OR john OR jonathan~1) smith*" + """ + + def __init__(self, expr='["](~(?P[1-9][0-9]*))?'): + """ + :param expr: a regular expression for the marker at the start and end + of a phrase. The default is the double-quotes character. + """ + + self.expr = expr + + class SequenceNode(syntax.GroupNode): + qclass = query.Sequence + + class QuoteNode(syntax.MarkerNode): + def __init__(self, slop=None): + self.slop = int(slop) if slop else 1 + + def taggers(self, parser): + return [(FnTagger(self.expr, self.QuoteNode, "quote"), 0)] + + def filters(self, parser): + return [(self.do_quotes, 550)] + + def do_quotes(self, parser, group): + # New group to copy nodes into + newgroup = group.empty_copy() + # Buffer for sequence nodes; when it's None, it means we're not in + # a sequence + seq = None + + # Start copying nodes from group to newgroup. When we find a quote + # node, start copying nodes into the buffer instead. When we find + # the next (end) quote, put the buffered nodes into a SequenceNode + # and add it to newgroup. + for node in group: + if isinstance(node, syntax.GroupNode): + # Recurse + node = self.do_quotes(parser, node) + + if isinstance(node, self.QuoteNode): + if seq is None: + # Start a new sequence + seq = [] + else: + # End the current sequence + sn = self.SequenceNode(seq, slop=node.slop) + newgroup.append(sn) + seq = None + elif seq is None: + # Not in a sequence, add directly + newgroup.append(node) + else: + # In a sequence, add it to the buffer + seq.append(node) + + # We can end up with buffered nodes if there was an unbalanced quote; + # just add the buffered nodes directly to newgroup + if seq is not None: + newgroup.extend(seq) + + return newgroup + + +class RangePlugin(Plugin): + """Adds the ability to specify term ranges. + """ + + expr = rcompile(r""" + (?P\{|\[) # Open paren + (?P + ('[^']*?'\s+) # single-quoted + | # or + ([^\]}]+?(?=[Tt][Oo])) # everything until "to" + )? + [Tt][Oo] # "to" + (?P + (\s+'[^']*?') # single-quoted + | # or + ([^\]}]+?) # everything until "]" or "}" + )? + (?P}|]) # Close paren + """, verbose=True) + + class RangeTagger(RegexTagger): + def __init__(self, expr, excl_start, excl_end): + self.expr = expr + self.excl_start = excl_start + self.excl_end = excl_end + + def create(self, parser, match): + start = match.group("start") + end = match.group("end") + if start: + # Strip the space before the "to" + start = start.rstrip() + # Strip single quotes + if start.startswith("'") and start.endswith("'"): + start = start[1:-1] + if end: + # Strip the space before the "to" + end = end.lstrip() + # Strip single quotes + if end.startswith("'") and end.endswith("'"): + end = end[1:-1] + # What kind of open and close brackets were used? + startexcl = match.group("open") == self.excl_start + endexcl = match.group("close") == self.excl_end + + rn = syntax.RangeNode(start, end, startexcl, endexcl) + return rn + + def __init__(self, expr=None, excl_start="{", excl_end="}"): + self.expr = expr or self.expr + self.excl_start = excl_start + self.excl_end = excl_end + + def taggers(self, parser): + tagger = self.RangeTagger(self.expr, self.excl_start, self.excl_end) + return [(tagger, 1)] + + +class OperatorsPlugin(Plugin): + """By default, adds the AND, OR, ANDNOT, ANDMAYBE, and NOT operators to + the parser syntax. This plugin scans the token stream for subclasses of + :class:`Operator` and calls their :meth:`Operator.make_group` methods + to allow them to manipulate the stream. + + There are two levels of configuration available. + + The first level is to change the regular expressions of the default + operators, using the ``And``, ``Or``, ``AndNot``, ``AndMaybe``, and/or + ``Not`` keyword arguments. The keyword value can be a pattern string or + a compiled expression, or None to remove the operator:: + + qp = qparser.QueryParser("content", schema) + cp = qparser.OperatorsPlugin(And="&", Or="\\|", AndNot="&!", + AndMaybe="&~", Not=None) + qp.replace_plugin(cp) + + You can also specify a list of ``(OpTagger, priority)`` pairs as the first + argument to the initializer to use custom operators. See :ref:`custom-op` + for more information on this. + """ + + class OpTagger(RegexTagger): + def __init__(self, expr, grouptype, optype=syntax.InfixOperator, + leftassoc=True, memo=""): + RegexTagger.__init__(self, expr) + self.grouptype = grouptype + self.optype = optype + self.leftassoc = leftassoc + self.memo = memo + + def __repr__(self): + return "<%s %r (%s)>" % (self.__class__.__name__, + self.expr.pattern, self.memo) + + def create(self, parser, match): + return self.optype(match.group(0), self.grouptype, self.leftassoc) + + def __init__(self, ops=None, clean=False, + And=r"(?<=\s)AND(?=\s)", + Or=r"(?<=\s)OR(?=\s)", + AndNot=r"(?<=\s)ANDNOT(?=\s)", + AndMaybe=r"(?<=\s)ANDMAYBE(?=\s)", + Not=r"(^|(?<=(\s|[()])))NOT(?=\s)", + Require=r"(^|(?<=\s))REQUIRE(?=\s)"): + if ops: + ops = list(ops) + else: + ops = [] + + if not clean: + ot = self.OpTagger + if Not: + ops.append((ot(Not, syntax.NotGroup, syntax.PrefixOperator, + memo="not"), 0)) + if And: + ops.append((ot(And, syntax.AndGroup, memo="and"), 0)) + if Or: + ops.append((ot(Or, syntax.OrGroup, memo="or"), 0)) + if AndNot: + ops.append((ot(AndNot, syntax.AndNotGroup, + memo="anot"), -5)) + if AndMaybe: + ops.append((ot(AndMaybe, syntax.AndMaybeGroup, + memo="amaybe"), -5)) + if Require: + ops.append((ot(Require, syntax.RequireGroup, + memo="req"), 0)) + + self.ops = ops + + def taggers(self, parser): + return self.ops + + def filters(self, parser): + return [(self.do_operators, 600)] + + def do_operators(self, parser, group): + """This filter finds PrefixOperator, PostfixOperator, and InfixOperator + nodes in the tree and calls their logic to rearrange the nodes. + """ + + for tagger, _ in self.ops: + # Get the operators created by the configured taggers + optype = tagger.optype + gtype = tagger.grouptype + + # Left-associative infix operators are replaced left-to-right, and + # right-associative infix operators are replaced right-to-left. + # Most of the work is done in the different implementations of + # Operator.replace_self(). + if tagger.leftassoc: + i = 0 + while i < len(group): + t = group[i] + if isinstance(t, optype) and t.grouptype is gtype: + i = t.replace_self(parser, group, i) + else: + i += 1 + else: + i = len(group) - 1 + while i >= 0: + t = group[i] + if isinstance(t, optype): + i = t.replace_self(parser, group, i) + i -= 1 + + # Descend into the groups and recursively call do_operators + for i, t in enumerate(group): + if isinstance(t, syntax.GroupNode): + group[i] = self.do_operators(parser, t) + + return group + + +# + +class PlusMinusPlugin(Plugin): + """Adds the ability to use + and - in a flat OR query to specify required + and prohibited terms. + + This is the basis for the parser configuration returned by + ``SimpleParser()``. + """ + + # Marker nodes for + and - + + class Plus(syntax.MarkerNode): + pass + + class Minus(syntax.MarkerNode): + pass + + def __init__(self, plusexpr="\\+", minusexpr="-"): + self.plusexpr = plusexpr + self.minusexpr = minusexpr + + def taggers(self, parser): + return [(FnTagger(self.plusexpr, self.Plus, "plus"), 0), + (FnTagger(self.minusexpr, self.Minus, "minus"), 0)] + + def filters(self, parser): + return [(self.do_plusminus, 510)] + + def do_plusminus(self, parser, group): + """This filter sorts nodes in a flat group into "required", "optional", + and "banned" subgroups based on the presence of plus and minus nodes. + """ + + required = syntax.AndGroup() + optional = syntax.OrGroup() + banned = syntax.OrGroup() + + # If the top-level group is an AndGroup we make everything "required" by default + if isinstance(group, syntax.AndGroup): + optional = syntax.AndGroup() + + # Which group to put the next node we see into + next = optional + for node in group: + if isinstance(node, self.Plus): + # +: put the next node in the required group + next = required + elif isinstance(node, self.Minus): + # -: put the next node in the banned group + next = banned + else: + # Anything else: put it in the appropriate group + next.append(node) + # Reset to putting things in the optional group by default + next = optional + + group = optional + if required: + group = syntax.AndMaybeGroup([required, group]) + if banned: + group = syntax.AndNotGroup([group, banned]) + return group + + +class GtLtPlugin(TaggingPlugin): + """Allows the user to use greater than/less than symbols to create range + queries:: + + a:>100 b:<=z c:>=-1.4 d:``, ``<``, ``>=``, ``<=``, ``=>``, and ``=<`` + after a field specifier. The field specifier is required. You cannot do the + following:: + + >100 + + This plugin requires the FieldsPlugin and RangePlugin to work. + """ + + class GtLtNode(syntax.SyntaxNode): + def __init__(self, rel): + self.rel = rel + + def __repr__(self): + return "(%s)" % self.rel + + expr = r"(?P(<=|>=|<|>|=<|=>))" + nodetype = GtLtNode + + def filters(self, parser): + # Run before the fields filter removes FilenameNodes at priority 100. + return [(self.do_gtlt, 99)] + + def do_gtlt(self, parser, group): + """This filter translate FieldnameNode/GtLtNode pairs into RangeNodes. + """ + + fname = syntax.FieldnameNode + newgroup = group.empty_copy() + i = 0 + lasti = len(group) - 1 + while i < len(group): + node = group[i] + # If this is a GtLtNode... + if isinstance(node, self.GtLtNode): + # If it's not the last node in the group... + if i < lasti: + prevnode = newgroup[-1] + nextnode = group[i + 1] + # If previous was a fieldname and next node has text + if isinstance(prevnode, fname) and nextnode.has_text: + # Make the next node into a range based on the symbol + newgroup.append(self.make_range(nextnode, node.rel)) + # Skip the next node + i += 1 + else: + # If it's not a GtLtNode, add it to the filtered group + newgroup.append(node) + i += 1 + + return newgroup + + def make_range(self, node, rel): + text = node.text + if rel == "<": + n = syntax.RangeNode(None, text, False, True) + elif rel == ">": + n = syntax.RangeNode(text, None, True, False) + elif rel == "<=" or rel == "=<": + n = syntax.RangeNode(None, text, False, False) + elif rel == ">=" or rel == "=>": + n = syntax.RangeNode(text, None, False, False) + return n.set_range(node.startchar, node.endchar) + + +class MultifieldPlugin(Plugin): + """Converts any unfielded terms into OR clauses that search for the + term in a specified list of fields. + + >>> qp = qparser.QueryParser(None, myschema) + >>> qp.add_plugin(qparser.MultifieldPlugin(["a", "b"]) + >>> qp.parse("alfa c:bravo") + And([Or([Term("a", "alfa"), Term("b", "alfa")]), Term("c", "bravo")]) + + This plugin is the basis for the ``MultifieldParser``. + """ + + def __init__(self, fieldnames, fieldboosts=None, group=syntax.OrGroup): + """ + :param fieldnames: a list of fields to search. + :param fieldboosts: an optional dictionary mapping field names to + a boost to use for that field. + :param group: the group to use to relate the fielded terms to each + other. + """ + + self.fieldnames = fieldnames + self.boosts = fieldboosts or {} + self.group = group + + def filters(self, parser): + # Run after the fields filter applies explicit fieldnames (at priority + # 100) + return [(self.do_multifield, 110)] + + def do_multifield(self, parser, group): + for i, node in enumerate(group): + if isinstance(node, syntax.GroupNode): + # Recurse inside groups + group[i] = self.do_multifield(parser, node) + elif node.has_fieldname and node.fieldname is None: + # For an unfielded node, create a new group containing fielded + # versions of the node for each configured "multi" field. + newnodes = [] + for fname in self.fieldnames: + newnode = copy.copy(node) + newnode.set_fieldname(fname) + newnode.set_boost(self.boosts.get(fname, 1.0)) + newnodes.append(newnode) + group[i] = self.group(newnodes) + return group + + +class FieldAliasPlugin(Plugin): + """Adds the ability to use "aliases" of fields in the query string. + + This plugin is useful for allowing users of languages that can't be + represented in ASCII to use field names in their own language, and + translate them into the "real" field names, which must be valid Python + identifiers. + + >>> # Allow users to use 'body' or 'text' to refer to the 'content' field + >>> parser.add_plugin(FieldAliasPlugin({"content": ["body", "text"]})) + >>> parser.parse("text:hello") + Term("content", "hello") + """ + + def __init__(self, fieldmap): + self.fieldmap = fieldmap + self.reverse = {} + for key, values in iteritems(fieldmap): + for value in values: + self.reverse[value] = key + + def filters(self, parser): + # Run before fields plugin at 100 + return [(self.do_aliases, 90)] + + def do_aliases(self, parser, group): + for i, node in enumerate(group): + if isinstance(node, syntax.GroupNode): + group[i] = self.do_aliases(parser, node) + elif node.has_fieldname and node.fieldname is not None: + fname = node.fieldname + if fname in self.reverse: + node.set_fieldname(self.reverse[fname], override=True) + return group + + +class CopyFieldPlugin(Plugin): + """Looks for basic syntax nodes (terms, prefixes, wildcards, phrases, etc.) + occurring in a certain field and replaces it with a group (by default OR) + containing the original token and the token copied to a new field. + + For example, the query:: + + hello name:matt + + could be automatically converted by ``CopyFieldPlugin({"name", "author"})`` + to:: + + hello (name:matt OR author:matt) + + This is useful where one field was indexed with a differently-analyzed copy + of another, and you want the query to search both fields. + + You can specify a different group type with the ``group`` keyword. You can + also specify ``group=None``, in which case the copied node is inserted + "inline" next to the original, instead of in a new group:: + + hello name:matt author:matt + """ + + def __init__(self, map, group=syntax.OrGroup, mirror=False): + """ + :param map: a dictionary mapping names of fields to copy to the + names of the destination fields. + :param group: the type of group to create in place of the original + token. You can specify ``group=None`` to put the copied node + "inline" next to the original node instead of in a new group. + :param two_way: if True, the plugin copies both ways, so if the user + specifies a query in the 'toname' field, it will be copied to + the 'fromname' field. + """ + + self.map = map + self.group = group + if mirror: + # Add in reversed mappings + map.update(dict((v, k) for k, v in iteritems(map))) + + def filters(self, parser): + # Run after the fieldname filter (100) but before multifield (110) + return [(self.do_copyfield, 109)] + + def do_copyfield(self, parser, group): + map = self.map + newgroup = group.empty_copy() + for node in group: + if isinstance(node, syntax.GroupNode): + # Recurse into groups + node = self.do_copyfield(parser, node) + elif node.has_fieldname: + fname = node.fieldname or parser.fieldname + if fname in map: + newnode = copy.copy(node) + newnode.set_fieldname(map[fname], override=True) + if self.group is None: + newgroup.append(node) + newgroup.append(newnode) + else: + newgroup.append(self.group([node, newnode])) + continue + newgroup.append(node) + return newgroup + + +class PseudoFieldPlugin(Plugin): + """This is an advanced plugin that lets you define "pseudo-fields" the user + can use in their queries. When the parser encounters one of these fields, + it runs a given function on the following node in the abstract syntax tree. + + Unfortunately writing the transform function(s) requires knowledge of the + parser's abstract syntax tree classes. A transform function takes a + :class:`whoosh.qparser.SyntaxNode` and returns a + :class:`~whoosh.qparser.SyntaxNode` (or None if the node should be removed + instead of transformed). + + Some things you can do in the transform function:: + + from whoosh import qparser + + def my_xform_fn(node): + # Is this a text node? + if node.has_text: + # Change the node's text + node.text = node.text + "foo" + + # Change the node into a prefix query + node = qparser.PrefixPlugin.PrefixNode(node.text) + + # Set the field the node should search in + node.set_fieldname("title") + + return node + else: + # If the pseudo-field wasn't applied to a text node (e.g. + # it preceded a group, as in ``pfield:(a OR b)`` ), remove the + # node. Alternatively you could just ``return node`` here to + # leave the non-text node intact. + return None + + In the following example, if the user types ``regex:foo.bar``, the function + transforms the text in the pseudo-field "regex" into a regular expression + query in the "content" field:: + + from whoosh import qparser + + def regex_maker(node): + if node.has_text: + node = qparser.RegexPlugin.RegexNode(node.text) + node.set_fieldname("content") + return node + + qp = qparser.QueryParser("content", myindex.schema) + qp.add_plugin(qparser.PseudoFieldPlugin({"regex": regex_maker})) + q = qp.parse("alfa regex:br.vo") + + The name of the "pseudo" field can be the same as an actual field. Imagine + the schema has a field named ``reverse``, and you want the user to be able + to type ``reverse:foo`` and transform it to ``reverse:(foo OR oof)``:: + + def rev_text(node): + if node.has_text: + # Create a word node for the reversed text + revtext = node.text[::-1] # Reverse the text + rnode = qparser.WordNode(revtext) + + # Put the original node and the reversed node in an OrGroup + group = qparser.OrGroup([node, rnode]) + + # Need to set the fieldname here because the PseudoFieldPlugin + # removes the field name syntax + group.set_fieldname("reverse") + + return group + + qp = qparser.QueryParser("content", myindex.schema) + qp.add_plugin(qparser.PseudoFieldPlugin({"reverse": rev_text})) + q = qp.parse("alfa reverse:bravo") + + Note that transforming the query like this can potentially really confuse + the spell checker! + + This plugin works as a filter, so it can only operate on the query after it + has been parsed into an abstract syntax tree. For parsing control (i.e. to + give a pseudo-field its own special syntax), you would need to write your + own parsing plugin. + """ + + def __init__(self, xform_map): + """ + :param xform_map: a dictionary mapping psuedo-field names to transform + functions. The function should take a + :class:`whoosh.qparser.SyntaxNode` as an argument, and return a + :class:`~whoosh.qparser.SyntaxNode`. If the function returns None, + the node will be removed from the query. + """ + + self.xform_map = xform_map + + def filters(self, parser): + # Run before the fieldname filter (100) + return [(self.do_pseudofield, 99)] + + def do_pseudofield(self, parser, group): + xform_map = self.xform_map + + newgroup = group.empty_copy() + xform_next = None + for node in group: + if isinstance(node, syntax.GroupNode): + node = self.do_pseudofield(parser, node) + elif (isinstance(node, syntax.FieldnameNode) + and node.fieldname in xform_map): + xform_next = xform_map[node.fieldname] + continue + + if xform_next: + newnode = xform_next(node) + xform_next = None + if newnode is None: + continue + else: + newnode.set_range(node.startchar, node.endchar) + node = newnode + + newgroup.append(node) + + return newgroup diff --git a/nstock/modules/whoosh/qparser/syntax.py b/nstock/modules/whoosh/qparser/syntax.py new file mode 100644 index 0000000..8e0fb47 --- /dev/null +++ b/nstock/modules/whoosh/qparser/syntax.py @@ -0,0 +1,645 @@ +# Copyright 2011 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +import sys, weakref + +from whoosh import query +from whoosh.qparser.common import get_single_text, QueryParserError, attach + + +class SyntaxNode(object): + """Base class for nodes that make up the abstract syntax tree (AST) of a + parsed user query string. The AST is an intermediate step, generated + from the query string, then converted into a :class:`whoosh.query.Query` + tree by calling the ``query()`` method on the nodes. + + Instances have the following required attributes: + + ``has_fieldname`` + True if this node has a ``fieldname`` attribute. + ``has_text`` + True if this node has a ``text`` attribute + ``has_boost`` + True if this node has a ``boost`` attribute. + ``startchar`` + The character position in the original text at which this node started. + ``endchar`` + The character position in the original text at which this node ended. + """ + + has_fieldname = False + has_text = False + has_boost = False + _parent = None + + def __repr__(self): + r = "<" + if self.has_fieldname: + r += "%r:" % self.fieldname + r += self.r() + if self.has_boost and self.boost != 1.0: + r += " ^%s" % self.boost + r += ">" + return r + + def r(self): + """Returns a basic representation of this node. The base class's + ``__repr__`` method calls this, then does the extra busy work of adding + fieldname and boost where appropriate. + """ + + return "%s %r" % (self.__class__.__name__, self.__dict__) + + def apply(self, fn): + return self + + def accept(self, fn): + def fn_wrapper(n): + return fn(n.apply(fn_wrapper)) + + return fn_wrapper(self) + + def query(self, parser): + """Returns a :class:`whoosh.query.Query` instance corresponding to this + syntax tree node. + """ + + raise NotImplementedError(self.__class__.__name__) + + def is_ws(self): + """Returns True if this node is ignorable whitespace. + """ + + return False + + def is_text(self): + return False + + def set_fieldname(self, name, override=False): + """Sets the fieldname associated with this node. If ``override`` is + False (the default), the fieldname will only be replaced if this node + does not already have a fieldname set. + + For nodes that don't have a fieldname, this is a no-op. + """ + + if not self.has_fieldname: + return + + if self.fieldname is None or override: + self.fieldname = name + return self + + def set_boost(self, boost): + """Sets the boost associated with this node. + + For nodes that don't have a boost, this is a no-op. + """ + + if not self.has_boost: + return + self.boost = boost + return self + + def set_range(self, startchar, endchar): + """Sets the character range associated with this node. + """ + + self.startchar = startchar + self.endchar = endchar + return self + + # Navigation methods + + def parent(self): + if self._parent: + return self._parent() + + def next_sibling(self): + p = self.parent() + if p: + return p.node_after(self) + + def prev_sibling(self): + p = self.parent() + if p: + return p.node_before(self) + + def bake(self, parent): + self._parent = weakref.ref(parent) + + +class MarkerNode(SyntaxNode): + """Base class for nodes that only exist to mark places in the tree. + """ + + def r(self): + return self.__class__.__name__ + + +class Whitespace(MarkerNode): + """Abstract syntax tree node for ignorable whitespace. + """ + + def r(self): + return " " + + def is_ws(self): + return True + + +class FieldnameNode(SyntaxNode): + """Abstract syntax tree node for field name assignments. + """ + + has_fieldname = True + + def __init__(self, fieldname, original): + self.fieldname = fieldname + self.original = original + + def __repr__(self): + return "<%r:>" % self.fieldname + + +class GroupNode(SyntaxNode): + """Base class for abstract syntax tree node types that group together + sub-nodes. + + Instances have the following attributes: + + ``merging`` + True if side-by-side instances of this group can be merged into a + single group. + ``qclass`` + If a subclass doesn't override ``query()``, the base class will simply + wrap this class around the queries returned by the subnodes. + + This class implements a number of list methods for operating on the + subnodes. + """ + + has_boost = True + merging = True + qclass = None + + def __init__(self, nodes=None, boost=1.0, **kwargs): + self.nodes = nodes or [] + self.boost = boost + self.kwargs = kwargs + + def r(self): + return "%s %s" % (self.__class__.__name__, + ", ".join(repr(n) for n in self.nodes)) + + @property + def startchar(self): + if not self.nodes: + return None + return self.nodes[0].startchar + + @property + def endchar(self): + if not self.nodes: + return None + return self.nodes[-1].endchar + + def apply(self, fn): + return self.__class__(self.type, [fn(node) for node in self.nodes], + boost=self.boost, **self.kwargs) + + def query(self, parser): + subs = [] + for node in self.nodes: + subq = node.query(parser) + if subq is not None: + subs.append(subq) + + q = self.qclass(subs, boost=self.boost, **self.kwargs) + return attach(q, self) + + def empty_copy(self): + """Returns an empty copy of this group. + + This is used in the common pattern where a filter creates an new + group and then adds nodes from the input group to it if they meet + certain criteria, then returns the new group:: + + def remove_whitespace(parser, group): + newgroup = group.empty_copy() + for node in group: + if not node.is_ws(): + newgroup.append(node) + return newgroup + """ + + c = self.__class__(**self.kwargs) + if self.has_boost: + c.boost = self.boost + if self.has_fieldname: + c.fieldname = self.fieldname + if self.has_text: + c.text = self.text + return c + + def set_fieldname(self, name, override=False): + SyntaxNode.set_fieldname(self, name, override=override) + for node in self.nodes: + node.set_fieldname(name, override=override) + + def set_range(self, startchar, endchar): + for node in self.nodes: + node.set_range(startchar, endchar) + return self + + # List-like methods + + def __nonzero__(self): + return bool(self.nodes) + + __bool__ = __nonzero__ + + def __iter__(self): + return iter(self.nodes) + + def __len__(self): + return len(self.nodes) + + def __getitem__(self, n): + return self.nodes.__getitem__(n) + + def __setitem__(self, n, v): + self.nodes.__setitem__(n, v) + + def __delitem__(self, n): + self.nodes.__delitem__(n) + + def insert(self, n, v): + self.nodes.insert(n, v) + + def append(self, v): + self.nodes.append(v) + + def extend(self, vs): + self.nodes.extend(vs) + + def pop(self, *args, **kwargs): + return self.nodes.pop(*args, **kwargs) + + def reverse(self): + self.nodes.reverse() + + def index(self, v): + return self.nodes.index(v) + + # Navigation methods + + def bake(self, parent): + SyntaxNode.bake(self, parent) + for node in self.nodes: + node.bake(self) + + def node_before(self, n): + try: + i = self.nodes.index(n) + except ValueError: + return + if i > 0: + return self.nodes[i - 1] + + def node_after(self, n): + try: + i = self.nodes.index(n) + except ValueError: + return + if i < len(self.nodes) - 2: + return self.nodes[i + 1] + + +class BinaryGroup(GroupNode): + """Intermediate base class for group nodes that have two subnodes and + whose ``qclass`` initializer takes two arguments instead of a list. + """ + + merging = False + has_boost = False + + def query(self, parser): + assert len(self.nodes) == 2 + + qa = self.nodes[0].query(parser) + qb = self.nodes[1].query(parser) + if qa is None and qb is None: + q = query.NullQuery + elif qa is None: + q = qb + elif qb is None: + q = qa + else: + q = self.qclass(self.nodes[0].query(parser), + self.nodes[1].query(parser)) + + return attach(q, self) + + +class Wrapper(GroupNode): + """Intermediate base class for nodes that wrap a single sub-node. + """ + + merging = False + + def query(self, parser): + q = self.nodes[0].query(parser) + if q: + return attach(self.qclass(q), self) + + +class ErrorNode(SyntaxNode): + def __init__(self, message, node=None): + self.message = message + self.node = node + + def r(self): + return "ERR %r %r" % (self.node, self.message) + + @property + def startchar(self): + return self.node.startchar + + @property + def endchar(self): + return self.node.endchar + + def query(self, parser): + if self.node: + q = self.node.query(parser) + else: + q = query.NullQuery + + return attach(query.error_query(self.message, q), self) + + +class AndGroup(GroupNode): + qclass = query.And + + +class OrGroup(GroupNode): + qclass = query.Or + + @classmethod + def factory(cls, scale=1.0): + class ScaledOrGroup(OrGroup): + def __init__(self, nodes=None, **kwargs): + if "scale" in kwargs: + del kwargs["scale"] + super(ScaledOrGroup, self).__init__(nodes=nodes, scale=scale, + **kwargs) + return ScaledOrGroup + + +class DisMaxGroup(GroupNode): + qclass = query.DisjunctionMax + + +class OrderedGroup(GroupNode): + qclass = query.Ordered + + +class AndNotGroup(BinaryGroup): + qclass = query.AndNot + + +class AndMaybeGroup(BinaryGroup): + qclass = query.AndMaybe + + +class RequireGroup(BinaryGroup): + qclass = query.Require + + +class NotGroup(Wrapper): + qclass = query.Not + + +class RangeNode(SyntaxNode): + """Syntax node for range queries. + """ + + has_fieldname = True + + def __init__(self, start, end, startexcl, endexcl): + self.start = start + self.end = end + self.startexcl = startexcl + self.endexcl = endexcl + self.boost = 1.0 + self.fieldname = None + self.kwargs = {} + + def r(self): + b1 = "{" if self.startexcl else "[" + b2 = "}" if self.endexcl else "]" + return "%s%r %r%s" % (b1, self.start, self.end, b2) + + def query(self, parser): + fieldname = self.fieldname or parser.fieldname + start = self.start + end = self.end + + if parser.schema and fieldname in parser.schema: + field = parser.schema[fieldname] + if field.self_parsing(): + try: + q = field.parse_range(fieldname, start, end, + self.startexcl, self.endexcl, + boost=self.boost) + if q is not None: + return attach(q, self) + except QueryParserError: + e = sys.exc_info()[1] + return attach(query.error_query(e), self) + + if start: + start = get_single_text(field, start, tokenize=False, + removestops=False) + if end: + end = get_single_text(field, end, tokenize=False, + removestops=False) + + q = query.TermRange(fieldname, start, end, self.startexcl, + self.endexcl, boost=self.boost) + return attach(q, self) + + +class TextNode(SyntaxNode): + """Intermediate base class for basic nodes that search for text, such as + term queries, wildcards, prefixes, etc. + + Instances have the following attributes: + + ``qclass`` + If a subclass does not override ``query()``, the base class will use + this class to construct the query. + ``tokenize`` + If True and the subclass does not override ``query()``, the node's text + will be tokenized before constructing the query + ``removestops`` + If True and the subclass does not override ``query()``, and the field's + analyzer has a stop word filter, stop words will be removed from the + text before constructing the query. + """ + + has_fieldname = True + has_text = True + has_boost = True + qclass = None + tokenize = False + removestops = False + + def __init__(self, text): + self.fieldname = None + self.text = text + self.boost = 1.0 + + def r(self): + return "%s %r" % (self.__class__.__name__, self.text) + + def is_text(self): + return True + + def query(self, parser): + fieldname = self.fieldname or parser.fieldname + termclass = self.qclass or parser.termclass + q = parser.term_query(fieldname, self.text, termclass, + boost=self.boost, tokenize=self.tokenize, + removestops=self.removestops) + return attach(q, self) + + +class WordNode(TextNode): + """Syntax node for term queries. + """ + + tokenize = True + removestops = True + + def r(self): + return repr(self.text) + + +# Operators + +class Operator(SyntaxNode): + """Base class for PrefixOperator, PostfixOperator, and InfixOperator. + + Operators work by moving the nodes they apply to (e.g. for prefix operator, + the previous node, for infix operator, the nodes on either side, etc.) into + a group node. The group provides the code for what to do with the nodes. + """ + + def __init__(self, text, grouptype, leftassoc=True): + """ + :param text: the text of the operator in the query string. + :param grouptype: the type of group to create in place of the operator + and the node(s) it operates on. + :param leftassoc: for infix opeators, whether the operator is left + associative. use ``leftassoc=False`` for right-associative infix + operators. + """ + + self.text = text + self.grouptype = grouptype + self.leftassoc = leftassoc + + def r(self): + return "OP %r" % self.text + + def replace_self(self, parser, group, position): + """Called with the parser, a group, and the position at which the + operator occurs in that group. Should return a group with the operator + replaced by whatever effect the operator has (e.g. for an infix op, + replace the op and the nodes on either side with a sub-group). + """ + + raise NotImplementedError + + +class PrefixOperator(Operator): + def replace_self(self, parser, group, position): + length = len(group) + del group[position] + if position < length - 1: + group[position] = self.grouptype([group[position]]) + return position + + +class PostfixOperator(Operator): + def replace_self(self, parser, group, position): + del group[position] + if position > 0: + group[position - 1] = self.grouptype([group[position - 1]]) + return position + + +class InfixOperator(Operator): + def replace_self(self, parser, group, position): + la = self.leftassoc + gtype = self.grouptype + merging = gtype.merging + + if position > 0 and position < len(group) - 1: + left = group[position - 1] + right = group[position + 1] + + # The first two clauses check whether the "strong" side is already + # a group of the type we are going to create. If it is, we just + # append the "weak" side to the "strong" side instead of creating + # a new group inside the existing one. This is necessary because + # we can quickly run into Python's recursion limit otherwise. + if merging and la and isinstance(left, gtype): + left.append(right) + del group[position:position + 2] + elif merging and not la and isinstance(right, gtype): + right.insert(0, left) + del group[position - 1:position + 1] + return position - 1 + else: + # Replace the operator and the two surrounding objects + group[position - 1:position + 2] = [gtype([left, right])] + else: + del group[position] + + return position + + +# Functions + +def to_word(n): + node = WordNode(n.original) + node.startchar = n.startchar + node.endchar = n.endchar + return node diff --git a/nstock/modules/whoosh/qparser/taggers.py b/nstock/modules/whoosh/qparser/taggers.py new file mode 100644 index 0000000..e3b5bb5 --- /dev/null +++ b/nstock/modules/whoosh/qparser/taggers.py @@ -0,0 +1,93 @@ +# Copyright 2011 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from whoosh.util.text import rcompile + + +# Tagger objects + +class Tagger(object): + """Base class for taggers, objects which match syntax in the query string + and translate it into a :class:`whoosh.qparser.syntax.SyntaxNode` object. + """ + + def match(self, parser, text, pos): + """This method should see if this tagger matches the query string at + the given position. If it matches, it should return + + :param parser: the :class:`whoosh.qparser.default.QueryParser` object. + :param text: the text being parsed. + :param pos: the position in the text at which the tagger should try to + match. + """ + + raise NotImplementedError + + +class RegexTagger(Tagger): + """Tagger class that uses regular expressions to match the query string. + Subclasses should override ``create()`` instead of ``match()``. + """ + + def __init__(self, expr): + self.expr = rcompile(expr) + + def match(self, parser, text, pos): + match = self.expr.match(text, pos) + if match: + node = self.create(parser, match) + if node is not None: + node = node.set_range(match.start(), match.end()) + return node + + def create(self, parser, match): + """When the regular expression matches, this method is called to + translate the regex match object into a syntax node. + + :param parser: the :class:`whoosh.qparser.default.QueryParser` object. + :param match: the regex match object. + """ + + raise NotImplementedError + + +class FnTagger(RegexTagger): + """Tagger that takes a regular expression and a class or function, and for + matches calls the class/function with the regex match's named groups as + keyword arguments. + """ + + def __init__(self, expr, fn, memo=""): + RegexTagger.__init__(self, expr) + self.fn = fn + self.memo = memo + + def __repr__(self): + return "<%s %r (%s)>" % (self.__class__.__name__, self.expr, self.memo) + + def create(self, parser, match): + return self.fn(**match.groupdict()) diff --git a/nstock/modules/whoosh/query/__init__.py b/nstock/modules/whoosh/query/__init__.py new file mode 100644 index 0000000..97e34a4 --- /dev/null +++ b/nstock/modules/whoosh/query/__init__.py @@ -0,0 +1,36 @@ +# Copyright 2012 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from whoosh.query.qcore import * +from whoosh.query.terms import * +from whoosh.query.compound import * +from whoosh.query.positional import * +from whoosh.query.ranges import * +from whoosh.query.wrappers import * +from whoosh.query.nested import * +from whoosh.query.qcolumns import * +from whoosh.query.spans import * diff --git a/nstock/modules/whoosh/query/compound.py b/nstock/modules/whoosh/query/compound.py new file mode 100644 index 0000000..b458cbc --- /dev/null +++ b/nstock/modules/whoosh/query/compound.py @@ -0,0 +1,660 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from __future__ import division + +from whoosh import matching +from whoosh.compat import text_type, u +from whoosh.compat import xrange +from whoosh.query import qcore +from whoosh.util import make_binary_tree, make_weighted_tree + + +class CompoundQuery(qcore.Query): + """Abstract base class for queries that combine or manipulate the results + of multiple sub-queries . + """ + + def __init__(self, subqueries, boost=1.0): + for subq in subqueries: + if not isinstance(subq, qcore.Query): + raise qcore.QueryError("%r is not a query" % subq) + self.subqueries = subqueries + self.boost = boost + + def __repr__(self): + r = "%s(%r" % (self.__class__.__name__, self.subqueries) + if hasattr(self, "boost") and self.boost != 1: + r += ", boost=%s" % self.boost + r += ")" + return r + + def __unicode__(self): + r = u("(") + r += self.JOINT.join([text_type(s) for s in self.subqueries]) + r += u(")") + return r + + __str__ = __unicode__ + + def __eq__(self, other): + return (other + and self.__class__ is other.__class__ + and self.subqueries == other.subqueries + and self.boost == other.boost) + + def __getitem__(self, i): + return self.subqueries.__getitem__(i) + + def __len__(self): + return len(self.subqueries) + + def __iter__(self): + return iter(self.subqueries) + + def __hash__(self): + h = hash(self.__class__.__name__) ^ hash(self.boost) + for q in self.subqueries: + h ^= hash(q) + return h + + def is_leaf(self): + return False + + def children(self): + return iter(self.subqueries) + + def apply(self, fn): + return self.__class__([fn(q) for q in self.subqueries], + boost=self.boost) + + def field(self): + if self.subqueries: + f = self.subqueries[0].field() + if all(q.field() == f for q in self.subqueries[1:]): + return f + + def estimate_size(self, ixreader): + est = sum(q.estimate_size(ixreader) for q in self.subqueries) + return min(est, ixreader.doc_count()) + + def estimate_min_size(self, ixreader): + from whoosh.query import Not + + subs = self.subqueries + qs = [(q, q.estimate_min_size(ixreader)) for q in subs + if not isinstance(q, Not)] + pos = [minsize for q, minsize in qs if minsize > 0] + if pos: + neg = [q.estimate_size(ixreader) for q in subs + if isinstance(q, Not)] + size = min(pos) - sum(neg) + if size > 0: + return size + return 0 + + def normalize(self): + from whoosh.query import Every, TermRange, NumericRange + + # Normalize subqueries and merge nested instances of this class + subqueries = [] + for s in self.subqueries: + s = s.normalize() + if isinstance(s, self.__class__): + subqueries += [ss.with_boost(ss.boost * s.boost) for ss in s] + else: + subqueries.append(s) + + # If every subquery is Null, this query is Null + if all(q is qcore.NullQuery for q in subqueries): + return qcore.NullQuery + + # If there's an unfielded Every inside, then this query is Every + if any((isinstance(q, Every) and q.fieldname is None) + for q in subqueries): + return Every() + + # Merge ranges and Everys + everyfields = set() + i = 0 + while i < len(subqueries): + q = subqueries[i] + f = q.field() + if f in everyfields: + subqueries.pop(i) + continue + + if isinstance(q, (TermRange, NumericRange)): + j = i + 1 + while j < len(subqueries): + if q.overlaps(subqueries[j]): + qq = subqueries.pop(j) + q = q.merge(qq, intersect=self.intersect_merge) + else: + j += 1 + q = subqueries[i] = q.normalize() + + if isinstance(q, Every): + everyfields.add(q.fieldname) + i += 1 + + # Eliminate duplicate queries + subqs = [] + seenqs = set() + for s in subqueries: + if not isinstance(s, Every) and s.field() in everyfields: + continue + if s in seenqs: + continue + seenqs.add(s) + subqs.append(s) + + # Remove NullQuerys + subqs = [q for q in subqs if q is not qcore.NullQuery] + + if not subqs: + return qcore.NullQuery + + if len(subqs) == 1: + sub = subqs[0] + sub_boost = getattr(sub, "boost", 1.0) + if not (self.boost == 1.0 and sub_boost == 1.0): + sub = sub.with_boost(sub_boost * self.boost) + return sub + + return self.__class__(subqs, boost=self.boost) + + def simplify(self, ixreader): + subs = self.subqueries + if subs: + q = self.__class__([subq.simplify(ixreader) for subq in subs], + boost=self.boost).normalize() + else: + q = qcore.NullQuery + return q + + def matcher(self, searcher, context=None): + # This method does a little sanity checking and then passes the info + # down to the _matcher() method which subclasses must implement + + subs = self.subqueries + if not subs: + return matching.NullMatcher() + + if len(subs) == 1: + m = subs[0].matcher(searcher, context) + else: + m = self._matcher(subs, searcher, context) + return m + + def _matcher(self, subs, searcher, context): + # Subclasses must implement this method + + raise NotImplementedError + + def _tree_matcher(self, subs, mcls, searcher, context, q_weight_fn, + **kwargs): + # q_weight_fn is a function which is called on each query and returns a + # "weight" value which is used to build a huffman-like matcher tree. If + # q_weight_fn is None, an order-preserving binary tree is used instead. + + # Create a matcher from the list of subqueries + subms = [q.matcher(searcher, context) for q in subs] + + if len(subms) == 1: + m = subms[0] + elif q_weight_fn is None: + m = make_binary_tree(mcls, subms, **kwargs) + else: + w_subms = [(q_weight_fn(q), m) for q, m in zip(subs, subms)] + m = make_weighted_tree(mcls, w_subms, **kwargs) + + # If this query had a boost, add a wrapping matcher to apply the boost + if self.boost != 1.0: + m = matching.WrappingMatcher(m, self.boost) + + return m + + +class And(CompoundQuery): + """Matches documents that match ALL of the subqueries. + + >>> And([Term("content", u"render"), + ... Term("content", u"shade"), + ... Not(Term("content", u"texture"))]) + >>> # You can also do this + >>> Term("content", u"render") & Term("content", u"shade") + """ + + # This is used by the superclass's __unicode__ method. + JOINT = " AND " + intersect_merge = True + + def requires(self): + s = set() + for q in self.subqueries: + s |= q.requires() + return s + + def estimate_size(self, ixreader): + return min(q.estimate_size(ixreader) for q in self.subqueries) + + def _matcher(self, subs, searcher, context): + r = searcher.reader() + q_weight_fn = lambda q: 0 - q.estimate_size(r) + return self._tree_matcher(subs, matching.IntersectionMatcher, searcher, + context, q_weight_fn) + + +class Or(CompoundQuery): + """Matches documents that match ANY of the subqueries. + + >>> Or([Term("content", u"render"), + ... And([Term("content", u"shade"), Term("content", u"texture")]), + ... Not(Term("content", u"network"))]) + >>> # You can also do this + >>> Term("content", u"render") | Term("content", u"shade") + """ + + # This is used by the superclass's __unicode__ method. + JOINT = " OR " + intersect_merge = False + TOO_MANY_CLAUSES = 1024 + + # For debugging: set the array_type property to control matcher selection + AUTO_MATCHER = 0 # Use automatic heuristics to choose matcher + DEFAULT_MATCHER = 1 # Use a binary tree of UnionMatchers + SPLIT_MATCHER = 2 # Use a different strategy for short and long queries + ARRAY_MATCHER = 3 # Use a matcher that pre-loads docnums and scores + matcher_type = AUTO_MATCHER + + def __init__(self, subqueries, boost=1.0, minmatch=0, scale=None): + """ + :param subqueries: a list of :class:`Query` objects to search for. + :param boost: a boost factor to apply to the scores of all matching + documents. + :param minmatch: not yet implemented. + :param scale: a scaling factor for a "coordination bonus". If this + value is not None, it should be a floating point number greater + than 0 and less than 1. The scores of the matching documents are + boosted/penalized based on the number of query terms that matched + in the document. This number scales the effect of the bonuses. + """ + + CompoundQuery.__init__(self, subqueries, boost=boost) + self.minmatch = minmatch + self.scale = scale + + def __unicode__(self): + r = u("(") + r += (self.JOINT).join([text_type(s) for s in self.subqueries]) + r += u(")") + if self.minmatch: + r += u(">%s") % self.minmatch + return r + + __str__ = __unicode__ + + def normalize(self): + norm = CompoundQuery.normalize(self) + if norm.__class__ is self.__class__: + norm.minmatch = self.minmatch + norm.scale = self.scale + return norm + + def requires(self): + if len(self.subqueries) == 1: + return self.subqueries[0].requires() + else: + return set() + + def _matcher(self, subs, searcher, context): + needs_current = context.needs_current if context else True + weighting = context.weighting if context else None + matcher_type = self.matcher_type + + if matcher_type == self.AUTO_MATCHER: + dc = searcher.doc_count_all() + if (len(subs) < self.TOO_MANY_CLAUSES + and (needs_current + or self.scale + or len(subs) == 2 + or dc > 5000)): + # If the parent matcher needs the current match, or there's just + # two sub-matchers, use the standard binary tree of Unions + matcher_type = self.DEFAULT_MATCHER + else: + # For small indexes, or too many clauses, just preload all + # matches + matcher_type = self.ARRAY_MATCHER + + if matcher_type == self.DEFAULT_MATCHER: + # Implementation of Or that creates a binary tree of Union matchers + cls = DefaultOr + elif matcher_type == self.SPLIT_MATCHER: + # Hybrid of pre-loading small queries and a binary tree of union + # matchers for big queries + cls = SplitOr + elif matcher_type == self.ARRAY_MATCHER: + # Implementation that pre-loads docnums and scores into an array + cls = PreloadedOr + else: + raise ValueError("Unknown matcher_type %r" % self.matcher_type) + + return cls(subs, boost=self.boost, minmatch=self.minmatch, + scale=self.scale).matcher(searcher, context) + + +class DefaultOr(Or): + JOINT = " dOR " + + def _matcher(self, subs, searcher, context): + reader = searcher.reader() + q_weight_fn = lambda q: q.estimate_size(reader) + m = self._tree_matcher(subs, matching.UnionMatcher, searcher, context, + q_weight_fn) + + # If a scaling factor was given, wrap the matcher in a CoordMatcher to + # alter scores based on term coordination + if self.scale and any(m.term_matchers()): + m = matching.CoordMatcher(m, scale=self.scale) + + return m + + +class SplitOr(Or): + JOINT = " sOr " + SPLIT_DOC_LIMIT = 8000 + + def matcher(self, searcher, context=None): + from whoosh import collectors + + # Get the subqueries + subs = self.subqueries + if not subs: + return matching.NullMatcher() + elif len(subs) == 1: + return subs[0].matcher(searcher, context) + + # Sort the subqueries into "small" and "big" queries based on their + # estimated size. This works best for term queries. + reader = searcher.reader() + smallqs = [] + bigqs = [] + for q in subs: + size = q.estimate_size(reader) + if size <= self.SPLIT_DOC_LIMIT: + smallqs.append(q) + else: + bigqs.append(q) + + # Build a pre-scored matcher for the small queries + minscore = 0 + smallmatcher = None + if smallqs: + smallmatcher = DefaultOr(smallqs).matcher(searcher, context) + smallmatcher = matching.ArrayMatcher(smallmatcher, context.limit) + minscore = smallmatcher.limit_quality() + if bigqs: + # Get a matcher for the big queries + m = DefaultOr(bigqs).matcher(searcher, context) + # Add the prescored matcher for the small queries + if smallmatcher: + m = matching.UnionMatcher(m, smallmatcher) + # Set the minimum score based on the prescored matcher + m.set_min_quality(minscore) + elif smallmatcher: + # If there are no big queries, just return the prescored matcher + m = smallmatcher + else: + m = matching.NullMatcher() + + return m + + +class PreloadedOr(Or): + JOINT = " pOR " + + def _matcher(self, subs, searcher, context): + if context: + scored = context.weighting is not None + else: + scored = True + + ms = [sub.matcher(searcher, context) for sub in subs] + doccount = searcher.doc_count_all() + am = matching.ArrayUnionMatcher(ms, doccount, boost=self.boost, + scored=scored) + return am + + +class DisjunctionMax(CompoundQuery): + """Matches all documents that match any of the subqueries, but scores each + document using the maximum score from the subqueries. + """ + + def __init__(self, subqueries, boost=1.0, tiebreak=0.0): + CompoundQuery.__init__(self, subqueries, boost=boost) + self.tiebreak = tiebreak + + def __unicode__(self): + r = u("DisMax(") + r += " ".join(sorted(text_type(s) for s in self.subqueries)) + r += u(")") + if self.tiebreak: + r += u("~") + text_type(self.tiebreak) + return r + + __str__ = __unicode__ + + def normalize(self): + norm = CompoundQuery.normalize(self) + if norm.__class__ is self.__class__: + norm.tiebreak = self.tiebreak + return norm + + def requires(self): + if len(self.subqueries) == 1: + return self.subqueries[0].requires() + else: + return set() + + def _matcher(self, subs, searcher, context): + r = searcher.reader() + q_weight_fn = lambda q: q.estimate_size(r) + return self._tree_matcher(subs, matching.DisjunctionMaxMatcher, + searcher, context, q_weight_fn, + tiebreak=self.tiebreak) + + +# Boolean queries + +class BinaryQuery(CompoundQuery): + """Base class for binary queries (queries which are composed of two + sub-queries). Subclasses should set the ``matcherclass`` attribute or + override ``matcher()``, and may also need to override ``normalize()``, + ``estimate_size()``, and/or ``estimate_min_size()``. + """ + + boost = 1.0 + + def __init__(self, a, b): + self.a = a + self.b = b + self.subqueries = (a, b) + + def __eq__(self, other): + return (other and self.__class__ is other.__class__ + and self.a == other.a and self.b == other.b) + + def __hash__(self): + return (hash(self.__class__.__name__) ^ hash(self.a) ^ hash(self.b)) + + def needs_spans(self): + return self.a.needs_spans() or self.b.needs_spans() + + def apply(self, fn): + return self.__class__(fn(self.a), fn(self.b)) + + def field(self): + f = self.a.field() + if self.b.field() == f: + return f + + def with_boost(self, boost): + return self.__class__(self.a.with_boost(boost), + self.b.with_boost(boost)) + + def normalize(self): + a = self.a.normalize() + b = self.b.normalize() + if a is qcore.NullQuery and b is qcore.NullQuery: + return qcore.NullQuery + elif a is qcore.NullQuery: + return b + elif b is qcore.NullQuery: + return a + + return self.__class__(a, b) + + def matcher(self, searcher, context=None): + return self.matcherclass(self.a.matcher(searcher, context), + self.b.matcher(searcher, context)) + + +class AndNot(BinaryQuery): + """Binary boolean query of the form 'a ANDNOT b', where documents that + match b are removed from the matches for a. + """ + + JOINT = " ANDNOT " + + def with_boost(self, boost): + return self.__class__(self.a.with_boost(boost), self.b) + + def normalize(self): + a = self.a.normalize() + b = self.b.normalize() + + if a is qcore.NullQuery: + return qcore.NullQuery + elif b is qcore.NullQuery: + return a + + return self.__class__(a, b) + + def requires(self): + return self.a.requires() + + def matcher(self, searcher, context=None): + scoredm = self.a.matcher(searcher, context) + notm = self.b.matcher(searcher, searcher.boolean_context()) + return matching.AndNotMatcher(scoredm, notm) + + +class Otherwise(BinaryQuery): + """A binary query that only matches the second clause if the first clause + doesn't match any documents. + """ + + JOINT = " OTHERWISE " + + def matcher(self, searcher, context=None): + m = self.a.matcher(searcher, context) + if not m.is_active(): + m = self.b.matcher(searcher, context) + return m + + +class Require(BinaryQuery): + """Binary query returns results from the first query that also appear in + the second query, but only uses the scores from the first query. This lets + you filter results without affecting scores. + """ + + JOINT = " REQUIRE " + matcherclass = matching.RequireMatcher + + def requires(self): + return self.a.requires() | self.b.requires() + + def estimate_size(self, ixreader): + return self.b.estimate_size(ixreader) + + def estimate_min_size(self, ixreader): + return self.b.estimate_min_size(ixreader) + + def with_boost(self, boost): + return self.__class__(self.a.with_boost(boost), self.b) + + def normalize(self): + a = self.a.normalize() + b = self.b.normalize() + if a is qcore.NullQuery or b is qcore.NullQuery: + return qcore.NullQuery + return self.__class__(a, b) + + def docs(self, searcher): + return And(self.subqueries).docs(searcher) + + def matcher(self, searcher, context=None): + scoredm = self.a.matcher(searcher, context) + requiredm = self.b.matcher(searcher, searcher.boolean_context()) + return matching.AndNotMatcher(scoredm, requiredm) + + +class AndMaybe(BinaryQuery): + """Binary query takes results from the first query. If and only if the + same document also appears in the results from the second query, the score + from the second query will be added to the score from the first query. + """ + + JOINT = " ANDMAYBE " + matcherclass = matching.AndMaybeMatcher + + def normalize(self): + a = self.a.normalize() + b = self.b.normalize() + if a is qcore.NullQuery: + return qcore.NullQuery + if b is qcore.NullQuery: + return a + return self.__class__(a, b) + + def requires(self): + return self.a.requires() + + def estimate_min_size(self, ixreader): + return self.subqueries[0].estimate_min_size(ixreader) + + def docs(self, searcher): + return self.subqueries[0].docs(searcher) + + +def BooleanQuery(required, should, prohibited): + return AndNot(AndMaybe(And(required), Or(should)), + Or(prohibited)).normalize() diff --git a/nstock/modules/whoosh/query/nested.py b/nstock/modules/whoosh/query/nested.py new file mode 100644 index 0000000..2678839 --- /dev/null +++ b/nstock/modules/whoosh/query/nested.py @@ -0,0 +1,415 @@ +# Copyright 2012 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from whoosh import matching +from whoosh.compat import text_type, u, xrange +from whoosh.query import qcore +from whoosh.query.wrappers import WrappingQuery + + +class NestedParent(WrappingQuery): + """A query that allows you to search for "nested" documents, where you can + index (possibly multiple levels of) "parent" and "child" documents using + the :meth:`~whoosh.writing.IndexWriter.group` and/or + :meth:`~whoosh.writing.IndexWriter.start_group` methods of a + :class:`whoosh.writing.IndexWriter` to indicate that hierarchically related + documents should be kept together:: + + schema = fields.Schema(type=fields.ID, text=fields.TEXT(stored=True)) + + with ix.writer() as w: + # Say we're indexing chapters (type=chap) and each chapter has a + # number of paragraphs (type=p) + with w.group(): + w.add_document(type="chap", text="Chapter 1") + w.add_document(type="p", text="Able baker") + w.add_document(type="p", text="Bright morning") + with w.group(): + w.add_document(type="chap", text="Chapter 2") + w.add_document(type="p", text="Car trip") + w.add_document(type="p", text="Dog eared") + w.add_document(type="p", text="Every day") + with w.group(): + w.add_document(type="chap", text="Chapter 3") + w.add_document(type="p", text="Fine day") + + The ``NestedParent`` query wraps two sub-queries: the "parent query" + matches a class of "parent documents". The "sub query" matches nested + documents you want to find. For each "sub document" the "sub query" finds, + this query acts as if it found the corresponding "parent document". + + >>> with ix.searcher() as s: + ... r = s.search(query.Term("text", "day")) + ... for hit in r: + ... print(hit["text"]) + ... + Chapter 2 + Chapter 3 + """ + + def __init__(self, parents, subq, per_parent_limit=None, score_fn=sum): + """ + :param parents: a query, DocIdSet object, or Results object + representing the documents you want to use as the "parent" + documents. Where the sub-query matches, the corresponding document + in these results will be returned as the match. + :param subq: a query matching the information you want to find. + :param per_parent_limit: a maximum number of "sub documents" to search + per parent. The default is None, meaning no limit. + :param score_fn: a function to use to combine the scores of matching + sub-documents to calculate the score returned for the parent + document. The default is ``sum``, that is, add up the scores of the + sub-documents. + """ + + self.parents = parents + self.child = subq + self.per_parent_limit = per_parent_limit + self.score_fn = score_fn + + def normalize(self): + p = self.parents + if isinstance(p, qcore.Query): + p = p.normalize() + q = self.child.normalize() + + if p is qcore.NullQuery or q is qcore.NullQuery: + return qcore.NullQuery + + return self.__class__(p, q) + + def requires(self): + return self.child.requires() + + def matcher(self, searcher, context=None): + bits = searcher._filter_to_comb(self.parents) + if not bits: + return matching.NullMatcher + m = self.child.matcher(searcher, context) + if not m.is_active(): + return matching.NullMatcher + + return self.NestedParentMatcher(bits, m, self.per_parent_limit, + searcher.doc_count_all(), + self.score_fn) + + def deletion_docs(self, searcher): + bits = searcher._filter_to_comb(self.parents) + if not bits: + return + + m = self.child.matcher(searcher, searcher.boolean_context()) + maxdoc = searcher.doc_count_all() + while m.is_active(): + docnum = m.id() + parentdoc = bits.before(docnum + 1) + nextparent = bits.after(docnum) or maxdoc + for i in xrange(parentdoc, nextparent): + yield i + m.skip_to(nextparent) + + class NestedParentMatcher(matching.Matcher): + def __init__(self, comb, child, per_parent_limit, maxdoc, score_fn): + self.comb = comb + self.child = child + self.per_parent_limit = per_parent_limit + self.maxdoc = maxdoc + self.score_fn = score_fn + + self._nextdoc = None + if self.child.is_active(): + self._gather() + + def is_active(self): + return self._nextdoc is not None + + def supports_block_quality(self): + return False + + def _gather(self): + # This is where the magic happens ;) + child = self.child + pplimit = self.per_parent_limit + + # The next document returned by this matcher is the parent of the + # child's current document. We don't have to worry about whether + # the parent is deleted, because the query that gave us the parents + # wouldn't return deleted documents. + self._nextdoc = self.comb.before(child.id() + 1) + # The next parent after the child matcher's current document + nextparent = self.comb.after(child.id()) or self.maxdoc + + # Sum the scores of all matching documents under the parent + count = 1 + scores = [] + while child.is_active() and child.id() < nextparent: + if pplimit and count > pplimit: + child.skip_to(nextparent) + break + + scores.append(child.score()) + child.next() + count += 1 + + score = self.score_fn(scores) if scores else 0 + self._nextscore = score + + def id(self): + return self._nextdoc + + def score(self): + return self._nextscore + + def reset(self): + self.child.reset() + self._gather() + + def next(self): + if self.child.is_active(): + self._gather() + else: + if self._nextdoc is None: + raise matching.ReadTooFar + else: + self._nextdoc = None + + def skip_to(self, id): + self.child.skip_to(id) + self._gather() + + def value(self): + raise NotImplementedError(self.__class__) + + def spans(self): + return [] + + +class NestedChildren(WrappingQuery): + """This is the reverse of a :class:`NestedParent` query: instead of taking + a query that matches children but returns the parent, this query matches + parents but returns the children. + + This is useful, for example, to search for an album title and return the + songs in the album:: + + schema = fields.Schema(type=fields.ID(stored=True), + album_name=fields.TEXT(stored=True), + track_num=fields.NUMERIC(stored=True), + track_name=fields.TEXT(stored=True), + lyrics=fields.TEXT) + ix = RamStorage().create_index(schema) + + # Indexing + with ix.writer() as w: + # For each album, index a "group" of a parent "album" document and + # multiple child "track" documents. + with w.group(): + w.add_document(type="album", + artist="The Cure", album_name="Disintegration") + w.add_document(type="track", track_num=1, + track_name="Plainsong") + w.add_document(type="track", track_num=2, + track_name="Pictures of You") + # ... + # ... + + + # Find songs where the song name has "heaven" in the title and the + # album the song is on has "hell" in the title + qp = QueryParser("lyrics", ix.schema) + with ix.searcher() as s: + # A query that matches all parents + all_albums = qp.parse("type:album") + + # A query that matches the parents we want + albums_with_hell = qp.parse("album_name:hell") + + # A query that matches the desired albums but returns the tracks + songs_on_hell_albums = NestedChildren(all_albums, albums_with_hell) + + # A query that matches tracks with heaven in the title + songs_with_heaven = qp.parse("track_name:heaven") + + # A query that finds tracks with heaven in the title on albums + # with hell in the title + q = query.And([songs_on_hell_albums, songs_with_heaven]) + + """ + + def __init__(self, parents, subq, boost=1.0): + self.parents = parents + self.child = subq + self.boost = boost + + def matcher(self, searcher, context=None): + bits = searcher._filter_to_comb(self.parents) + if not bits: + return matching.NullMatcher + + m = self.child.matcher(searcher, context) + if not m.is_active(): + return matching.NullMatcher + + return self.NestedChildMatcher(bits, m, searcher.doc_count_all(), + searcher.reader().is_deleted, + boost=self.boost) + + class NestedChildMatcher(matching.WrappingMatcher): + def __init__(self, parent_comb, wanted_parent_matcher, limit, + is_deleted, boost=1.0): + self.parent_comb = parent_comb + self.child = wanted_parent_matcher + self.limit = limit + self.is_deleted = is_deleted + self.boost = boost + self._nextchild = -1 + self._nextparent = -1 + self._find_next_children() + + def __repr__(self): + return "%s(%r, %r)" % (self.__class__.__name__, + self.parent_comb, + self.child) + + def reset(self): + self.child.reset() + self._reset() + + def _reset(self): + self._nextchild = -1 + self._nextparent = -1 + self._find_next_children() + + def is_active(self): + return self._nextchild < self._nextparent + + def replace(self, minquality=0): + return self + + def _find_next_children(self): + # "comb" contains the doc IDs of all parent documents + comb = self.parent_comb + # "m" is the matcher for "wanted" parents + m = self.child + # Last doc ID + 1 + limit = self.limit + # A function that returns True if a doc ID is deleted + is_deleted = self.is_deleted + nextchild = self._nextchild + nextparent = self._nextparent + + while m.is_active(): + # Move the "child id" to the document after the current match + nextchild = m.id() + 1 + # Move the parent matcher to the next match + m.next() + + # Find the next parent document (matching or not) after this + nextparent = comb.after(nextchild) + if nextparent is None: + nextparent = limit + + # Skip any deleted child documents + while is_deleted(nextchild): + nextchild += 1 + + # If skipping deleted documents put us to or past the next + # parent doc, go again + if nextchild >= nextparent: + continue + else: + # Otherwise, we're done + break + + self._nextchild = nextchild + self._nextparent = nextparent + + def id(self): + return self._nextchild + + def all_ids(self): + while self.is_active(): + yield self.id() + self.next() + + def next(self): + is_deleted = self.is_deleted + limit = self.limit + nextparent = self._nextparent + + # Go to the next document + nextchild = self._nextchild + nextchild += 1 + + # Skip over any deleted child documents + while nextchild < nextparent and is_deleted(nextchild): + nextchild += 1 + + self._nextchild = nextchild + # If we're at or past the next parent doc, go to the next set of + # children + if nextchild >= limit: + return + elif nextchild >= nextparent: + self._find_next_children() + + def skip_to(self, docid): + comb = self.parent_comb + wanted = self.child + + # self._nextchild is the "current" matching child ID + if docid <= self._nextchild: + return + + # self._nextparent is the next parent ID (matching or not) + if docid < self._nextparent: + # Just iterate + while self.is_active() and self.id() < docid: + self.next() + elif wanted.is_active(): + # Find the parent before the target ID + pid = comb.before(docid) + # Skip the parent matcher to that ID + wanted.skip_to(pid) + # If that made the matcher inactive, then we're done + if not wanted.is_active(): + self._nextchild = self._nextparent = self.limit + else: + # Reestablish for the next child after the next matching + # parent + self._find_next_children() + else: + self._nextchild = self._nextparent = self.limit + + def value(self): + raise NotImplementedError(self.__class__) + + def score(self): + return self.boost + + def spans(self): + return [] diff --git a/nstock/modules/whoosh/query/positional.py b/nstock/modules/whoosh/query/positional.py new file mode 100644 index 0000000..4ad9320 --- /dev/null +++ b/nstock/modules/whoosh/query/positional.py @@ -0,0 +1,249 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from __future__ import division +import copy + +from whoosh import matching +from whoosh.analysis import Token +from whoosh.compat import u +from whoosh.query import qcore, terms, compound + + +class Sequence(compound.CompoundQuery): + """Matches documents containing a list of sub-queries in adjacent + positions. + + This object has no sanity check to prevent you from using queries in + different fields. + """ + + JOINT = " NEAR " + intersect_merge = True + + def __init__(self, subqueries, slop=1, ordered=True, boost=1.0): + """ + :param subqueries: a list of :class:`whoosh.query.Query` objects to + match in sequence. + :param slop: the maximum difference in position allowed between the + subqueries. + :param ordered: if True, the position differences between subqueries + must be positive (that is, each subquery in the list must appear + after the previous subquery in the document). + :param boost: a boost factor to add to the score of documents matching + this query. + """ + + compound.CompoundQuery.__init__(self, subqueries, boost=boost) + self.slop = slop + self.ordered = ordered + + def __eq__(self, other): + return (other and type(self) is type(other) + and self.subqueries == other.subqueries + and self.boost == other.boost) + + def __repr__(self): + return "%s(%r, slop=%d, boost=%f)" % (self.__class__.__name__, + self.subqueries, self.slop, + self.boost) + + def __hash__(self): + h = hash(self.slop) ^ hash(self.boost) + for q in self.subqueries: + h ^= hash(q) + return h + + def normalize(self): + # Because the subqueries are in sequence, we can't do the fancy merging + # that CompoundQuery does + return self.__class__([q.normalize() for q in self.subqueries], + self.slop, self.ordered, self.boost) + + def _and_query(self): + return compound.And(self.subqueries) + + def estimate_size(self, ixreader): + return self._and_query().estimate_size(ixreader) + + def estimate_min_size(self, ixreader): + return self._and_query().estimate_min_size(ixreader) + + def _matcher(self, subs, searcher, context): + from whoosh.query.spans import SpanNear + + # Tell the sub-queries this matcher will need the current match to get + # spans + context = context.set(needs_current=True) + m = self._tree_matcher(subs, SpanNear.SpanNearMatcher, searcher, + context, None, slop=self.slop, + ordered=self.ordered) + return m + + +class Ordered(Sequence): + """Matches documents containing a list of sub-queries in the given order. + """ + + JOINT = " BEFORE " + + def _matcher(self, subs, searcher, context): + from whoosh.query.spans import SpanBefore + + return self._tree_matcher(subs, SpanBefore._Matcher, searcher, + context, None) + + +class Phrase(qcore.Query): + """Matches documents containing a given phrase.""" + + def __init__(self, fieldname, words, slop=1, boost=1.0, char_ranges=None): + """ + :param fieldname: the field to search. + :param words: a list of words (unicode strings) in the phrase. + :param slop: the number of words allowed between each "word" in the + phrase; the default of 1 means the phrase must match exactly. + :param boost: a boost factor that to apply to the raw score of + documents matched by this query. + :param char_ranges: if a Phrase object is created by the query parser, + it will set this attribute to a list of (startchar, endchar) pairs + corresponding to the words in the phrase + """ + + self.fieldname = fieldname + self.words = words + self.slop = slop + self.boost = boost + self.char_ranges = char_ranges + + def __eq__(self, other): + return (other and self.__class__ is other.__class__ + and self.fieldname == other.fieldname + and self.words == other.words + and self.slop == other.slop + and self.boost == other.boost) + + def __repr__(self): + return "%s(%r, %r, slop=%s, boost=%f)" % (self.__class__.__name__, + self.fieldname, self.words, + self.slop, self.boost) + + def __unicode__(self): + return u('%s:"%s"') % (self.fieldname, u(" ").join(self.words)) + + __str__ = __unicode__ + + def __hash__(self): + h = hash(self.fieldname) ^ hash(self.slop) ^ hash(self.boost) + for w in self.words: + h ^= hash(w) + return h + + def has_terms(self): + return True + + def terms(self, phrases=False): + if phrases and self.field(): + for word in self.words: + yield (self.field(), word) + + def tokens(self, boost=1.0): + char_ranges = self.char_ranges + startchar = endchar = None + for i, word in enumerate(self.words): + if char_ranges: + startchar, endchar = char_ranges[i] + + yield Token(fieldname=self.fieldname, text=word, + boost=boost * self.boost, startchar=startchar, + endchar=endchar, chars=True) + + def normalize(self): + if not self.words: + return qcore.NullQuery + if len(self.words) == 1: + t = terms.Term(self.fieldname, self.words[0]) + if self.char_ranges: + t.startchar, t.endchar = self.char_ranges[0] + return t + + words = [w for w in self.words if w is not None] + return self.__class__(self.fieldname, words, slop=self.slop, + boost=self.boost, char_ranges=self.char_ranges) + + def replace(self, fieldname, oldtext, newtext): + q = copy.copy(self) + if q.fieldname == fieldname: + for i, word in enumerate(q.words): + if word == oldtext: + q.words[i] = newtext + return q + + def _and_query(self): + return compound.And([terms.Term(self.fieldname, word) + for word in self.words]) + + def estimate_size(self, ixreader): + return self._and_query().estimate_size(ixreader) + + def estimate_min_size(self, ixreader): + return self._and_query().estimate_min_size(ixreader) + + def matcher(self, searcher, context=None): + from whoosh.query import Term, SpanNear2 + + fieldname = self.fieldname + if fieldname not in searcher.schema: + return matching.NullMatcher() + + field = searcher.schema[fieldname] + if not field.format or not field.format.supports("positions"): + raise qcore.QueryError("Phrase search: %r field has no positions" + % self.fieldname) + + terms = [] + # Build a list of Term queries from the words in the phrase + reader = searcher.reader() + for word in self.words: + try: + word = field.to_bytes(word) + except ValueError: + return matching.NullMatcher() + + if (fieldname, word) not in reader: + # Shortcut the query if one of the words doesn't exist. + return matching.NullMatcher() + terms.append(Term(fieldname, word)) + + # Create the equivalent SpanNear2 query from the terms + q = SpanNear2(terms, slop=self.slop, ordered=True, mindist=1) + # Get the matcher + m = q.matcher(searcher, context) + + if self.boost != 1.0: + m = matching.WrappingMatcher(m, boost=self.boost) + return m diff --git a/nstock/modules/whoosh/query/qcolumns.py b/nstock/modules/whoosh/query/qcolumns.py new file mode 100644 index 0000000..d2dd6af --- /dev/null +++ b/nstock/modules/whoosh/query/qcolumns.py @@ -0,0 +1,117 @@ +# Copyright 2012 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from whoosh.matching import ConstantScoreMatcher, NullMatcher, ReadTooFar +from whoosh.query import Query + + +class ColumnQuery(Query): + """A query that matches per-document values stored in a column rather than + terms in the inverted index. + + This may be useful in special circumstances, but note that this is MUCH + SLOWER than searching an indexed field. + """ + + def __init__(self, fieldname, condition): + """ + :param fieldname: the name of the field to look in. If the field does + not have a column, this query will not match anything. + :param condition: if this is a callable, it is called on each value + in the column, and for documents where callable(docvalue) returns + True are returned as matching documents. If this is not a callable, + the document values are compared to it (using ``==``). + """ + + self.fieldname = fieldname + self.condition = condition + + def is_leaf(self): + return True + + def matcher(self, searcher, context=None): + fieldname = self.fieldname + condition = self.condition + if callable(condition): + comp = condition + else: + def comp(v): + # Made this a function instead of a lambda so I could put + # debug prints here if necessary ;) + return v == condition + + reader = searcher.reader() + if not reader.has_column(fieldname): + return NullMatcher() + + creader = reader.column_reader(fieldname) + return ColumnMatcher(creader, comp) + + +class ColumnMatcher(ConstantScoreMatcher): + def __init__(self, creader, condition): + self.creader = creader + self.condition = condition + self._i = 0 + self._find_next() + + def _find_next(self): + condition = self.condition + creader = self.creader + + while self._i < len(creader) and not condition(creader[self._i]): + self._i += 1 + + def is_active(self): + return self._i < len(self.creader) + + def next(self): + if not self.is_active(): + raise ReadTooFar + self._i += 1 + self._find_next() + + def reset(self): + self._i = 0 + self._find_next() + + def id(self): + return self._i + + def all_ids(self): + condition = self.condition + for docnum, v in enumerate(self.creader): + if condition(v): + yield docnum + + def supports(self, astype): + return False + + def skip_to_quality(self, minquality): + if self._score <= minquality: + self._i = len(self.creader) + return True diff --git a/nstock/modules/whoosh/query/qcore.py b/nstock/modules/whoosh/query/qcore.py new file mode 100644 index 0000000..883a90b --- /dev/null +++ b/nstock/modules/whoosh/query/qcore.py @@ -0,0 +1,715 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from __future__ import division +import copy +from array import array + +from whoosh import matching +from whoosh.compat import u +from whoosh.reading import TermNotFound +from whoosh.compat import methodcaller + + +# Exceptions + +class QueryError(Exception): + """Error encountered while running a query. + """ + pass + + +# Functions + +def error_query(msg, q=None): + """Returns the query in the second argument (or a :class:`NullQuery` if the + second argument is not given) with its ``error`` attribute set to + ``msg``. + """ + + if q is None: + q = _NullQuery() + q.error = msg + return q + + +def token_lists(q, phrases=True): + """Returns the terms in the query tree, with the query hierarchy + represented as nested lists. + """ + + if q.is_leaf(): + from whoosh.query import Phrase + if phrases or not isinstance(q, Phrase): + return list(q.tokens()) + else: + ls = [] + for qq in q.children(): + t = token_lists(qq, phrases=phrases) + if len(t) == 1: + t = t[0] + if t: + ls.append(t) + return ls + + +# Utility classes + +class Lowest(object): + """A value that is always compares lower than any other object except + itself. + """ + + def __cmp__(self, other): + if other.__class__ is Lowest: + return 0 + return -1 + + def __eq__(self, other): + return self.__class__ is type(other) + + def __lt__(self, other): + return type(other) is not self.__class__ + + def __ne__(self, other): + return not self.__eq__(other) + + def __gt__(self, other): + return not (self.__lt__(other) or self.__eq__(other)) + + def __le__(self, other): + return self.__eq__(other) or self.__lt__(other) + + def __ge__(self, other): + return self.__eq__(other) or self.__gt__(other) + + +class Highest(object): + """A value that is always compares higher than any other object except + itself. + """ + + def __cmp__(self, other): + if other.__class__ is Highest: + return 0 + return 1 + + def __eq__(self, other): + return self.__class__ is type(other) + + def __lt__(self, other): + return type(other) is self.__class__ + + def __ne__(self, other): + return not self.__eq__(other) + + def __gt__(self, other): + return not (self.__lt__(other) or self.__eq__(other)) + + def __le__(self, other): + return self.__eq__(other) or self.__lt__(other) + + def __ge__(self, other): + return self.__eq__(other) or self.__gt__(other) + + +Lowest = Lowest() +Highest = Highest() + + +# Base classes + +class Query(object): + """Abstract base class for all queries. + + Note that this base class implements __or__, __and__, and __sub__ to allow + slightly more convenient composition of query objects:: + + >>> Term("content", u"a") | Term("content", u"b") + Or([Term("content", u"a"), Term("content", u"b")]) + + >>> Term("content", u"a") & Term("content", u"b") + And([Term("content", u"a"), Term("content", u"b")]) + + >>> Term("content", u"a") - Term("content", u"b") + And([Term("content", u"a"), Not(Term("content", u"b"))]) + """ + + # For queries produced by the query parser, record where in the user + # query this object originated + startchar = endchar = None + # For queries produced by the query parser, records an error that resulted + # in this query + error = None + + def __unicode__(self): + raise NotImplementedError(self.__class__.__name__) + + def __getitem__(self, item): + raise NotImplementedError + + def __or__(self, query): + """Allows you to use | between query objects to wrap them in an Or + query. + """ + + from whoosh.query import Or + return Or([self, query]).normalize() + + def __and__(self, query): + """Allows you to use & between query objects to wrap them in an And + query. + """ + + from whoosh.query import And + return And([self, query]).normalize() + + def __sub__(self, query): + """Allows you to use - between query objects to add the right-hand + query as a "NOT" query. + """ + + from whoosh.query import And, Not + return And([self, Not(query)]).normalize() + + def __hash__(self): + raise NotImplementedError + + def __ne__(self, other): + return not self.__eq__(other) + + def is_leaf(self): + """Returns True if this is a leaf node in the query tree, or False if + this query has sub-queries. + """ + + return True + + def children(self): + """Returns an iterator of the subqueries of this object. + """ + + return iter([]) + + def is_range(self): + """Returns True if this object searches for values within a range. + """ + + return False + + def has_terms(self): + """Returns True if this specific object represents a search for a + specific term (as opposed to a pattern, as in Wildcard and Prefix) or + terms (i.e., whether the ``replace()`` method does something + meaningful on this instance). + """ + + return False + + def needs_spans(self): + for child in self.children(): + if child.needs_spans(): + return True + return False + + def apply(self, fn): + """If this query has children, calls the given function on each child + and returns a new copy of this node with the new children returned by + the function. If this is a leaf node, simply returns this object. + + This is useful for writing functions that transform a query tree. For + example, this function changes all Term objects in a query tree into + Variations objects:: + + def term2var(q): + if isinstance(q, Term): + return Variations(q.fieldname, q.text) + else: + return q.apply(term2var) + + q = And([Term("f", "alfa"), + Or([Term("f", "bravo"), + Not(Term("f", "charlie"))])]) + q = term2var(q) + + Note that this method does not automatically create copies of nodes. + To avoid modifying the original tree, your function should call the + :meth:`Query.copy` method on nodes before changing their attributes. + """ + + return self + + def accept(self, fn): + """Applies the given function to this query's subqueries (if any) and + then to this query itself:: + + def boost_phrases(q): + if isintance(q, Phrase): + q.boost *= 2.0 + return q + + myquery = myquery.accept(boost_phrases) + + This method automatically creates copies of the nodes in the original + tree before passing them to your function, so your function can change + attributes on nodes without altering the original tree. + + This method is less flexible than using :meth:`Query.apply` (in fact + it's implemented using that method) but is often more straightforward. + """ + + def fn_wrapper(q): + q = q.apply(fn_wrapper) + return fn(q) + + return fn_wrapper(self) + + def replace(self, fieldname, oldtext, newtext): + """Returns a copy of this query with oldtext replaced by newtext (if + oldtext was anywhere in this query). + + Note that this returns a *new* query with the given text replaced. It + *does not* modify the original query "in place". + """ + + # The default implementation uses the apply method to "pass down" the + # replace() method call + if self.is_leaf(): + return copy.copy(self) + else: + return self.apply(methodcaller("replace", fieldname, oldtext, + newtext)) + + def copy(self): + """Deprecated, just use ``copy.deepcopy``. + """ + + return copy.deepcopy(self) + + def all_terms(self, phrases=True): + """Returns a set of all terms in this query tree. + + This method exists for backwards-compatibility. Use iter_all_terms() + instead. + + :param phrases: Whether to add words found in Phrase queries. + :rtype: set + """ + + return set(self.iter_all_terms(phrases=phrases)) + + def terms(self, phrases=False): + """Yields zero or more (fieldname, text) pairs queried by this object. + You can check whether a query object targets specific terms before you + call this method using :meth:`Query.has_terms`. + + To get all terms in a query tree, use :meth:`Query.iter_all_terms`. + """ + + return iter(()) + + def expanded_terms(self, ixreader, phrases=True): + return self.terms(phrases=phrases) + + def existing_terms(self, ixreader, phrases=True, expand=False, fieldname=None): + """Returns a set of all byteterms in this query tree that exist in + the given ixreader. + + :param ixreader: A :class:`whoosh.reading.IndexReader` object. + :param phrases: Whether to add words found in Phrase queries. + :param expand: If True, queries that match multiple terms + will return all matching expansions. + :rtype: set + """ + + schema = ixreader.schema + termset = set() + + for q in self.leaves(): + if fieldname and fieldname != q.field(): + continue + + if expand: + terms = q.expanded_terms(ixreader, phrases=phrases) + else: + terms = q.terms(phrases=phrases) + + for fieldname, text in terms: + if (fieldname, text) in termset: + continue + + if fieldname in schema: + field = schema[fieldname] + + try: + btext = field.to_bytes(text) + except ValueError: + continue + + if (fieldname, btext) in ixreader: + termset.add((fieldname, btext)) + return termset + + def leaves(self): + """Returns an iterator of all the leaf queries in this query tree as a + flat series. + """ + + if self.is_leaf(): + yield self + else: + for q in self.children(): + for qq in q.leaves(): + yield qq + + def iter_all_terms(self, phrases=True): + """Returns an iterator of (fieldname, text) pairs for all terms in + this query tree. + + >>> qp = qparser.QueryParser("text", myindex.schema) + >>> q = myparser.parse("alfa bravo title:charlie") + >>> # List the terms in a query + >>> list(q.iter_all_terms()) + [("text", "alfa"), ("text", "bravo"), ("title", "charlie")] + >>> # Get a set of all terms in the query that don't exist in the index + >>> r = myindex.reader() + >>> missing = set(t for t in q.iter_all_terms() if t not in r) + set([("text", "alfa"), ("title", "charlie")]) + >>> # All terms in the query that occur in fewer than 5 documents in + >>> # the index + >>> [t for t in q.iter_all_terms() if r.doc_frequency(t[0], t[1]) < 5] + [("title", "charlie")] + + :param phrases: Whether to add words found in Phrase queries. + """ + + for q in self.leaves(): + if q.has_terms(): + for t in q.terms(phrases=phrases): + yield t + + def all_tokens(self, boost=1.0): + """Returns an iterator of :class:`analysis.Token` objects corresponding + to all terms in this query tree. The Token objects will have the + ``fieldname``, ``text``, and ``boost`` attributes set. If the query + was built by the query parser, they Token objects will also have + ``startchar`` and ``endchar`` attributes indexing into the original + user query. + """ + + if self.is_leaf(): + for token in self.tokens(boost): + yield token + else: + boost *= self.boost if hasattr(self, "boost") else 1.0 + for child in self.children(): + for token in child.all_tokens(boost): + yield token + + def tokens(self, boost=1.0, exreader=None): + """Yields zero or more :class:`analysis.Token` objects corresponding to + the terms searched for by this query object. You can check whether a + query object targets specific terms before you call this method using + :meth:`Query.has_terms`. + + The Token objects will have the ``fieldname``, ``text``, and ``boost`` + attributes set. If the query was built by the query parser, they Token + objects will also have ``startchar`` and ``endchar`` attributes + indexing into the original user query. + + To get all tokens for a query tree, use :meth:`Query.all_tokens`. + + :param exreader: a reader to use to expand multiterm queries such as + prefixes and wildcards. The default is None meaning do not expand. + """ + + return iter(()) + + def requires(self): + """Returns a set of queries that are *known* to be required to match + for the entire query to match. Note that other queries might also turn + out to be required but not be determinable by examining the static + query. + + >>> a = Term("f", u"a") + >>> b = Term("f", u"b") + >>> And([a, b]).requires() + set([Term("f", u"a"), Term("f", u"b")]) + >>> Or([a, b]).requires() + set([]) + >>> AndMaybe(a, b).requires() + set([Term("f", u"a")]) + >>> a.requires() + set([Term("f", u"a")]) + """ + + # Subclasses should implement the _add_required_to(qset) method + + return set([self]) + + def field(self): + """Returns the field this query matches in, or None if this query does + not match in a single field. + """ + + return self.fieldname + + def with_boost(self, boost): + """Returns a COPY of this query with the boost set to the given value. + + If a query type does not accept a boost itself, it will try to pass the + boost on to its children, if any. + """ + + q = self.copy() + q.boost = boost + return q + + def estimate_size(self, ixreader): + """Returns an estimate of how many documents this query could + potentially match (for example, the estimated size of a simple term + query is the document frequency of the term). It is permissible to + overestimate, but not to underestimate. + """ + raise NotImplementedError + + def estimate_min_size(self, ixreader): + """Returns an estimate of the minimum number of documents this query + could potentially match. + """ + + return self.estimate_size(ixreader) + + def matcher(self, searcher, context=None): + """Returns a :class:`~whoosh.matching.Matcher` object you can use to + retrieve documents and scores matching this query. + + :rtype: :class:`whoosh.matching.Matcher` + """ + + raise NotImplementedError + + def docs(self, searcher): + """Returns an iterator of docnums matching this query. + + >>> with my_index.searcher() as searcher: + ... list(my_query.docs(searcher)) + [10, 34, 78, 103] + + :param searcher: A :class:`whoosh.searching.Searcher` object. + """ + + try: + context = searcher.boolean_context() + return self.matcher(searcher, context).all_ids() + except TermNotFound: + return iter([]) + + def deletion_docs(self, searcher): + """Returns an iterator of docnums matching this query for the purpose + of deletion. The :meth:`~whoosh.writing.IndexWriter.delete_by_query` + method will use this method when deciding what documents to delete, + allowing special queries (e.g. nested queries) to override what + documents are deleted. The default implementation just forwards to + :meth:`Query.docs`. + """ + + return self.docs(searcher) + + def normalize(self): + """Returns a recursively "normalized" form of this query. The + normalized form removes redundancy and empty queries. This is called + automatically on query trees created by the query parser, but you may + want to call it yourself if you're writing your own parser or building + your own queries. + + >>> q = And([And([Term("f", u"a"), + ... Term("f", u"b")]), + ... Term("f", u"c"), Or([])]) + >>> q.normalize() + And([Term("f", u"a"), Term("f", u"b"), Term("f", u"c")]) + + Note that this returns a *new, normalized* query. It *does not* modify + the original query "in place". + """ + return self + + def simplify(self, ixreader): + """Returns a recursively simplified form of this query, where + "second-order" queries (such as Prefix and Variations) are re-written + into lower-level queries (such as Term and Or). + """ + return self + + +# Null query + +class _NullQuery(Query): + "Represents a query that won't match anything." + + boost = 1.0 + + def __init__(self): + self.error = None + + def __unicode__(self): + return u("<_NullQuery>") + + def __call__(self): + return self + + def __repr__(self): + return "<%s>" % (self.__class__.__name__) + + def __eq__(self, other): + return isinstance(other, _NullQuery) + + def __ne__(self, other): + return not self.__eq__(other) + + def __hash__(self): + return id(self) + + def __copy__(self): + return self + + def __deepcopy__(self, memo): + return self + + def field(self): + return None + + def estimate_size(self, ixreader): + return 0 + + def normalize(self): + return self + + def simplify(self, ixreader): + return self + + def docs(self, searcher): + return [] + + def matcher(self, searcher, context=None): + return matching.NullMatcher() + + +NullQuery = _NullQuery() + + +# Every + +class Every(Query): + """A query that matches every document containing any term in a given + field. If you don't specify a field, the query matches every document. + + >>> # Match any documents with something in the "path" field + >>> q = Every("path") + >>> # Matcher every document + >>> q = Every() + + The unfielded form (matching every document) is efficient. + + The fielded is more efficient than a prefix query with an empty prefix or a + '*' wildcard, but it can still be very slow on large indexes. It requires + the searcher to read the full posting list of every term in the given + field. + + Instead of using this query it is much more efficient when you create the + index to include a single term that appears in all documents that have the + field you want to match. + + For example, instead of this:: + + # Match all documents that have something in the "path" field + q = Every("path") + + Do this when indexing:: + + # Add an extra field that indicates whether a document has a path + schema = fields.Schema(path=fields.ID, has_path=fields.ID) + + # When indexing, set the "has_path" field based on whether the document + # has anything in the "path" field + writer.add_document(text=text_value1) + writer.add_document(text=text_value2, path=path_value2, has_path="t") + + Then to find all documents with a path:: + + q = Term("has_path", "t") + """ + + def __init__(self, fieldname=None, boost=1.0): + """ + :param fieldname: the name of the field to match, or ``None`` or ``*`` + to match all documents. + """ + + if not fieldname or fieldname == "*": + fieldname = None + self.fieldname = fieldname + self.boost = boost + + def __repr__(self): + return "%s(%r, boost=%s)" % (self.__class__.__name__, self.fieldname, + self.boost) + + def __eq__(self, other): + return (other and self.__class__ is other.__class__ + and self.fieldname == other.fieldname + and self.boost == other.boost) + + def __unicode__(self): + return u("%s:*") % self.fieldname + + __str__ = __unicode__ + + def __hash__(self): + return hash(self.fieldname) + + def estimate_size(self, ixreader): + return ixreader.doc_count() + + def matcher(self, searcher, context=None): + fieldname = self.fieldname + reader = searcher.reader() + + if fieldname in (None, "", "*"): + # This takes into account deletions + doclist = array("I", reader.all_doc_ids()) + else: + # This is a hacky hack, but just create an in-memory set of all the + # document numbers of every term in the field. This is SLOOOW for + # large indexes + doclist = set() + for text in searcher.lexicon(fieldname): + pr = searcher.postings(fieldname, text) + doclist.update(pr.all_ids()) + doclist = sorted(doclist) + + return matching.ListMatcher(doclist, all_weights=self.boost) diff --git a/nstock/modules/whoosh/query/ranges.py b/nstock/modules/whoosh/query/ranges.py new file mode 100644 index 0000000..b2b03d0 --- /dev/null +++ b/nstock/modules/whoosh/query/ranges.py @@ -0,0 +1,347 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from __future__ import division + +from whoosh.compat import b, u +from whoosh.query import qcore, terms, compound, wrappers +from whoosh.util.times import datetime_to_long + + +class RangeMixin(object): + # Contains methods shared by TermRange and NumericRange + + def __repr__(self): + return ('%s(%r, %r, %r, %s, %s, boost=%s, constantscore=%s)' + % (self.__class__.__name__, self.fieldname, self.start, + self.end, self.startexcl, self.endexcl, self.boost, + self.constantscore)) + + def __unicode__(self): + startchar = "{" if self.startexcl else "[" + endchar = "}" if self.endexcl else "]" + start = '' if self.start is None else self.start + end = '' if self.end is None else self.end + return u("%s:%s%s TO %s%s") % (self.fieldname, startchar, start, end, + endchar) + + __str__ = __unicode__ + + def __eq__(self, other): + return (other and self.__class__ is other.__class__ + and self.fieldname == other.fieldname + and self.start == other.start and self.end == other.end + and self.startexcl == other.startexcl + and self.endexcl == other.endexcl + and self.boost == other.boost + and self.constantscore == other.constantscore) + + def __hash__(self): + return (hash(self.fieldname) ^ hash(self.start) ^ hash(self.startexcl) + ^ hash(self.end) ^ hash(self.endexcl) ^ hash(self.boost)) + + def is_range(self): + return True + + def _comparable_start(self): + if self.start is None: + return (qcore.Lowest, 0) + else: + second = 1 if self.startexcl else 0 + return (self.start, second) + + def _comparable_end(self): + if self.end is None: + return (qcore.Highest, 0) + else: + second = -1 if self.endexcl else 0 + return (self.end, second) + + def overlaps(self, other): + if not isinstance(other, TermRange): + return False + if self.fieldname != other.fieldname: + return False + + start1 = self._comparable_start() + start2 = other._comparable_start() + end1 = self._comparable_end() + end2 = other._comparable_end() + + return ((start1 >= start2 and start1 <= end2) + or (end1 >= start2 and end1 <= end2) + or (start2 >= start1 and start2 <= end1) + or (end2 >= start1 and end2 <= end1)) + + def merge(self, other, intersect=True): + assert self.fieldname == other.fieldname + + start1 = self._comparable_start() + start2 = other._comparable_start() + end1 = self._comparable_end() + end2 = other._comparable_end() + + if start1 >= start2 and end1 <= end2: + start = start2 + end = end2 + elif start2 >= start1 and end2 <= end1: + start = start1 + end = end1 + elif intersect: + start = max(start1, start2) + end = min(end1, end2) + else: + start = min(start1, start2) + end = max(end1, end2) + + startval = None if start[0] is qcore.Lowest else start[0] + startexcl = start[1] == 1 + endval = None if end[0] is qcore.Highest else end[0] + endexcl = end[1] == -1 + + boost = max(self.boost, other.boost) + constantscore = self.constantscore or other.constantscore + + return self.__class__(self.fieldname, startval, endval, startexcl, + endexcl, boost=boost, + constantscore=constantscore) + + +class TermRange(RangeMixin, terms.MultiTerm): + """Matches documents containing any terms in a given range. + + >>> # Match documents where the indexed "id" field is greater than or equal + >>> # to 'apple' and less than or equal to 'pear'. + >>> TermRange("id", u"apple", u"pear") + """ + + def __init__(self, fieldname, start, end, startexcl=False, endexcl=False, + boost=1.0, constantscore=True): + """ + :param fieldname: The name of the field to search. + :param start: Match terms equal to or greater than this. + :param end: Match terms equal to or less than this. + :param startexcl: If True, the range start is exclusive. If False, the + range start is inclusive. + :param endexcl: If True, the range end is exclusive. If False, the + range end is inclusive. + :param boost: Boost factor that should be applied to the raw score of + results matched by this query. + """ + + self.fieldname = fieldname + self.start = start + self.end = end + self.startexcl = startexcl + self.endexcl = endexcl + self.boost = boost + self.constantscore = constantscore + + def normalize(self): + if self.start in ('', None) and self.end in (u('\uffff'), None): + from whoosh.query import Every + return Every(self.fieldname, boost=self.boost) + elif self.start == self.end: + if self.startexcl or self.endexcl: + return qcore.NullQuery + return terms.Term(self.fieldname, self.start, boost=self.boost) + else: + return TermRange(self.fieldname, self.start, self.end, + self.startexcl, self.endexcl, + boost=self.boost) + + #def replace(self, fieldname, oldtext, newtext): + # q = self.copy() + # if q.fieldname == fieldname: + # if q.start == oldtext: + # q.start = newtext + # if q.end == oldtext: + # q.end = newtext + # return q + + def _btexts(self, ixreader): + fieldname = self.fieldname + field = ixreader.schema[fieldname] + startexcl = self.startexcl + endexcl = self.endexcl + + if self.start is None: + start = b("") + else: + try: + start = field.to_bytes(self.start) + except ValueError: + return + + if self.end is None: + end = b("\xFF\xFF\xFF\xFF") + else: + try: + end = field.to_bytes(self.end) + except ValueError: + return + + for fname, t in ixreader.terms_from(fieldname, start): + if fname != fieldname: + break + if t == start and startexcl: + continue + if t == end and endexcl: + break + if t > end: + break + yield t + + +class NumericRange(RangeMixin, qcore.Query): + """A range query for NUMERIC fields. Takes advantage of tiered indexing + to speed up large ranges by matching at a high resolution at the edges of + the range and a low resolution in the middle. + + >>> # Match numbers from 10 to 5925 in the "number" field. + >>> nr = NumericRange("number", 10, 5925) + """ + + def __init__(self, fieldname, start, end, startexcl=False, endexcl=False, + boost=1.0, constantscore=True): + """ + :param fieldname: The name of the field to search. + :param start: Match terms equal to or greater than this number. This + should be a number type, not a string. + :param end: Match terms equal to or less than this number. This should + be a number type, not a string. + :param startexcl: If True, the range start is exclusive. If False, the + range start is inclusive. + :param endexcl: If True, the range end is exclusive. If False, the + range end is inclusive. + :param boost: Boost factor that should be applied to the raw score of + results matched by this query. + :param constantscore: If True, the compiled query returns a constant + score (the value of the ``boost`` keyword argument) instead of + actually scoring the matched terms. This gives a nice speed boost + and won't affect the results in most cases since numeric ranges + will almost always be used as a filter. + """ + + self.fieldname = fieldname + self.start = start + self.end = end + self.startexcl = startexcl + self.endexcl = endexcl + self.boost = boost + self.constantscore = constantscore + + def simplify(self, ixreader): + return self._compile_query(ixreader).simplify(ixreader) + + def estimate_size(self, ixreader): + return self._compile_query(ixreader).estimate_size(ixreader) + + def estimate_min_size(self, ixreader): + return self._compile_query(ixreader).estimate_min_size(ixreader) + + def docs(self, searcher): + q = self._compile_query(searcher.reader()) + return q.docs(searcher) + + def _compile_query(self, ixreader): + from whoosh.fields import NUMERIC + from whoosh.util.numeric import tiered_ranges + + field = ixreader.schema[self.fieldname] + if not isinstance(field, NUMERIC): + raise Exception("NumericRange: field %r is not numeric" + % self.fieldname) + + start = self.start + if start is not None: + start = field.prepare_number(start) + end = self.end + if end is not None: + end = field.prepare_number(end) + + subqueries = [] + stb = field.sortable_to_bytes + # Get the term ranges for the different resolutions + ranges = tiered_ranges(field.numtype, field.bits, field.signed, + start, end, field.shift_step, + self.startexcl, self.endexcl) + for startnum, endnum, shift in ranges: + if startnum == endnum: + subq = terms.Term(self.fieldname, stb(startnum, shift)) + else: + startbytes = stb(startnum, shift) + endbytes = stb(endnum, shift) + subq = TermRange(self.fieldname, startbytes, endbytes) + subqueries.append(subq) + + if len(subqueries) == 1: + q = subqueries[0] + elif subqueries: + q = compound.Or(subqueries, boost=self.boost) + else: + return qcore.NullQuery + + if self.constantscore: + q = wrappers.ConstantScoreQuery(q, self.boost) + return q + + def matcher(self, searcher, context=None): + q = self._compile_query(searcher.reader()) + return q.matcher(searcher, context) + + +class DateRange(NumericRange): + """This is a very thin subclass of :class:`NumericRange` that only + overrides the initializer and ``__repr__()`` methods to work with datetime + objects instead of numbers. Internally this object converts the datetime + objects it's created with to numbers and otherwise acts like a + ``NumericRange`` query. + + >>> DateRange("date", datetime(2010, 11, 3, 3, 0), + ... datetime(2010, 11, 3, 17, 59)) + """ + + def __init__(self, fieldname, start, end, startexcl=False, endexcl=False, + boost=1.0, constantscore=True): + self.startdate = start + self.enddate = end + if start: + start = datetime_to_long(start) + if end: + end = datetime_to_long(end) + super(DateRange, self).__init__(fieldname, start, end, + startexcl=startexcl, endexcl=endexcl, + boost=boost, + constantscore=constantscore) + + def __repr__(self): + return '%s(%r, %r, %r, %s, %s, boost=%s)' % (self.__class__.__name__, + self.fieldname, + self.startdate, self.enddate, + self.startexcl, self.endexcl, + self.boost) diff --git a/nstock/modules/whoosh/query/spans.py b/nstock/modules/whoosh/query/spans.py new file mode 100644 index 0000000..b4d1c69 --- /dev/null +++ b/nstock/modules/whoosh/query/spans.py @@ -0,0 +1,881 @@ +# Copyright 2010 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +""" +This module contains Query objects that deal with "spans". + +Span queries allow for positional constraints on matching documents. For +example, the :class:`whoosh.spans.SpanNear` query matches documents where one +term occurs near another. Because you can nest span queries, and wrap them +around almost any non-span query, you can create very complex constraints. + +For example, to find documents containing "whoosh" at most 5 positions before +"library" in the "text" field:: + + from whoosh import query, spans + t1 = query.Term("text", "whoosh") + t2 = query.Term("text", "library") + q = spans.SpanNear(t1, t2, slop=5) + +""" + +from whoosh.matching import mcore, wrappers, binary +from whoosh.query import Query, And, AndMaybe, Or, Term +from whoosh.util import make_binary_tree + + +# Span class + +class Span(object): + __slots__ = ("start", "end", "startchar", "endchar", "boost") + + def __init__(self, start, end=None, startchar=None, endchar=None, + boost=1.0): + if end is None: + end = start + assert start <= end + self.start = start + self.end = end + self.startchar = startchar + self.endchar = endchar + self.boost = boost + + def __repr__(self): + if self.startchar is not None or self.endchar is not None: + return "<%d-%d %d:%d>" % (self.start, self.end, self.startchar, + self.endchar) + else: + return "<%d-%d>" % (self.start, self.end) + + def __eq__(self, span): + return (self.start == span.start + and self.end == span.end + and self.startchar == span.startchar + and self.endchar == span.endchar) + + def __ne__(self, span): + return self.start != span.start or self.end != span.end + + def __lt__(self, span): + return self.start < span.start + + def __gt__(self, span): + return self.start > span.start + + def __hash__(self): + return hash((self.start, self.end)) + + @classmethod + def merge(cls, spans): + """Merges overlapping and touches spans in the given list of spans. + + Note that this modifies the original list. + + >>> spans = [Span(1,2), Span(3)] + >>> Span.merge(spans) + >>> spans + [<1-3>] + """ + + i = 0 + while i < len(spans) - 1: + here = spans[i] + j = i + 1 + while j < len(spans): + there = spans[j] + if there.start > here.end + 1: + break + if here.touches(there) or here.overlaps(there): + here = here.to(there) + spans[i] = here + del spans[j] + else: + j += 1 + i += 1 + return spans + + def to(self, span): + if self.startchar is None: + minchar = span.startchar + elif span.startchar is None: + minchar = self.startchar + else: + minchar = min(self.startchar, span.startchar) + if self.endchar is None: + maxchar = span.endchar + elif span.endchar is None: + maxchar = self.endchar + else: + maxchar = max(self.endchar, span.endchar) + + minpos = min(self.start, span.start) + maxpos = max(self.end, span.end) + return self.__class__(minpos, maxpos, minchar, maxchar) + + def overlaps(self, span): + return ((self.start >= span.start and self.start <= span.end) + or (self.end >= span.start and self.end <= span.end) + or (span.start >= self.start and span.start <= self.end) + or (span.end >= self.start and span.end <= self.end)) + + def surrounds(self, span): + return self.start < span.start and self.end > span.end + + def is_within(self, span): + return self.start >= span.start and self.end <= span.end + + def is_before(self, span): + return self.end < span.start + + def is_after(self, span): + return self.start > span.end + + def touches(self, span): + return self.start == span.end + 1 or self.end == span.start - 1 + + def distance_to(self, span): + if self.overlaps(span): + return 0 + elif self.is_before(span): + return span.start - self.end + else: + return self.start - span.end + + +def bisect_spans(spans, start): + lo = 0 + hi = len(spans) + while lo < hi: + mid = (lo + hi) // 2 + if spans[mid].start < start: + lo = mid + 1 + else: + hi = mid + return lo + + +# Base matchers + +class SpanWrappingMatcher(wrappers.WrappingMatcher): + """An abstract matcher class that wraps a "regular" matcher. This matcher + uses the sub-matcher's matching logic, but only matches documents that have + matching spans, i.e. where ``_get_spans()`` returns a non-empty list. + + Subclasses must implement the ``_get_spans()`` method, which returns a list + of valid spans for the current document. + """ + + def __init__(self, child): + super(SpanWrappingMatcher, self).__init__(child) + self._spans = None + if self.is_active(): + self._find_next() + + def copy(self): + m = self.__class__(self.child.copy()) + m._spans = self._spans + return m + + def _replacement(self, newchild): + return self.__class__(newchild) + + def _find_next(self): + if not self.is_active(): + return + + child = self.child + r = False + + spans = self._get_spans() + while child.is_active() and not spans: + r = child.next() or r + if not child.is_active(): + return True + spans = self._get_spans() + self._spans = spans + + return r + + def spans(self): + return self._spans + + def next(self): + self.child.next() + self._find_next() + + def skip_to(self, id): + self.child.skip_to(id) + self._find_next() + + def all_ids(self): + while self.is_active(): + if self.spans(): + yield self.id() + self.next() + + +class SpanBiMatcher(SpanWrappingMatcher): + def copy(self): + return self.__class__(self.a.copy(), self.b.copy()) + + def depth(self): + return 1 + max(self.a.depth(), self.b.depth()) + + def replace(self, minquality=0): + # TODO: fix this + if not self.is_active(): + return mcore.NullMatcher() + return self + + +# Queries + +class SpanQuery(Query): + """Abstract base class for span-based queries. Each span query type wraps + a "regular" query that implements the basic document-matching functionality + (for example, SpanNear wraps an And query, because SpanNear requires that + the two sub-queries occur in the same documents. The wrapped query is + stored in the ``q`` attribute. + + Subclasses usually only need to implement the initializer to set the + wrapped query, and ``matcher()`` to return a span-aware matcher object. + """ + + def _subm(self, s, context=None): + return self.q.matcher(s, context) + + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self.q) + + def __eq__(self, other): + return (other and self.__class__ is other.__class__ + and self.q == other.q) + + def __hash__(self): + return hash(self.__class__.__name__) ^ hash(self.q) + + def field(self): + return None + + def needs_spans(self): + return True + + +class WrappingSpan(SpanQuery): + def is_leaf(self): + return False + + def apply(self, fn): + return self.__class__(fn(self.q), limit=self.limit) + + def field(self): + return self.q.field() + + +class SpanFirst(WrappingSpan): + """Matches spans that end within the first N positions. This lets you + for example only match terms near the beginning of the document. + """ + + def __init__(self, q, limit=0): + """ + :param q: the query to match. + :param limit: the query must match within this position at the start + of a document. The default is ``0``, which means the query must + match at the first position. + """ + + self.q = q + self.limit = limit + + def __eq__(self, other): + return (other and self.__class__ is other.__class__ + and self.q == other.q and self.limit == other.limit) + + def __hash__(self): + return hash(self.q) ^ hash(self.limit) + + def matcher(self, searcher, context=None): + m = self._subm(searcher, context) + return SpanFirst.SpanFirstMatcher(m, limit=self.limit) + + class SpanFirstMatcher(SpanWrappingMatcher): + def __init__(self, child, limit=0): + self.limit = limit + super(SpanFirst.SpanFirstMatcher, self).__init__(child) + + def copy(self): + return self.__class__(self.child.copy(), limit=self.limit) + + def _replacement(self, newchild): + return self.__class__(newchild, limit=self.limit) + + def _get_spans(self): + return [span for span in self.child.spans() + if span.end <= self.limit] + + +class SpanNear(SpanQuery): + """ + Note: for new code, use :class:`SpanNear2` instead of this class. SpanNear2 + takes a list of sub-queries instead of requiring you to create a binary + tree of query objects. + + Matches queries that occur near each other. By default, only matches + queries that occur right next to each other (slop=1) and in order + (ordered=True). + + For example, to find documents where "whoosh" occurs next to "library" + in the "text" field:: + + from whoosh import query, spans + t1 = query.Term("text", "whoosh") + t2 = query.Term("text", "library") + q = spans.SpanNear(t1, t2) + + To find documents where "whoosh" occurs at most 5 positions before + "library":: + + q = spans.SpanNear(t1, t2, slop=5) + + To find documents where "whoosh" occurs at most 5 positions before or after + "library":: + + q = spans.SpanNear(t1, t2, slop=5, ordered=False) + + You can use the ``phrase()`` class method to create a tree of SpanNear + queries to match a list of terms:: + + q = spans.SpanNear.phrase("text", ["whoosh", "search", "library"], + slop=2) + """ + + def __init__(self, a, b, slop=1, ordered=True, mindist=1): + """ + :param a: the first query to match. + :param b: the second query that must occur within "slop" positions of + the first query. + :param slop: the number of positions within which the queries must + occur. Default is 1, meaning the queries must occur right next + to each other. + :param ordered: whether a must occur before b. Default is True. + :pram mindist: the minimum distance allowed between the queries. + """ + + self.q = And([a, b]) + self.a = a + self.b = b + self.slop = slop + self.ordered = ordered + self.mindist = mindist + + def __repr__(self): + return ("%s(%r, slop=%d, ordered=%s, mindist=%d)" + % (self.__class__.__name__, self.q, self.slop, self.ordered, + self.mindist)) + + def __eq__(self, other): + return (other and self.__class__ == other.__class__ + and self.q == other.q and self.slop == other.slop + and self.ordered == other.ordered + and self.mindist == other.mindist) + + def __hash__(self): + return (hash(self.a) ^ hash(self.b) ^ hash(self.slop) + ^ hash(self.ordered) ^ hash(self.mindist)) + + def is_leaf(self): + return False + + def apply(self, fn): + return self.__class__(fn(self.a), fn(self.b), slop=self.slop, + ordered=self.ordered, mindist=self.mindist) + + def matcher(self, searcher, context=None): + ma = self.a.matcher(searcher, context) + mb = self.b.matcher(searcher, context) + return SpanNear.SpanNearMatcher(ma, mb, slop=self.slop, + ordered=self.ordered, + mindist=self.mindist) + + @classmethod + def phrase(cls, fieldname, words, slop=1, ordered=True): + """Returns a tree of SpanNear queries to match a list of terms. + + This class method is a convenience for constructing a phrase query + using a binary tree of SpanNear queries:: + + SpanNear.phrase("content", ["alfa", "bravo", "charlie", "delta"]) + + :param fieldname: the name of the field to search in. + :param words: a sequence of texts to search for. + :param slop: the number of positions within which the terms must + occur. Default is 1, meaning the terms must occur right next + to each other. + :param ordered: whether the terms must occur in order. Default is True. + """ + + terms = [Term(fieldname, word) for word in words] + return make_binary_tree(cls, terms, slop=slop, ordered=ordered) + + class SpanNearMatcher(SpanWrappingMatcher): + def __init__(self, a, b, slop=1, ordered=True, mindist=1): + self.a = a + self.b = b + self.slop = slop + self.ordered = ordered + self.mindist = mindist + isect = binary.IntersectionMatcher(a, b) + super(SpanNear.SpanNearMatcher, self).__init__(isect) + + def copy(self): + return self.__class__(self.a.copy(), self.b.copy(), slop=self.slop, + ordered=self.ordered, mindist=self.mindist) + + def replace(self, minquality=0): + # TODO: fix this + if not self.is_active(): + return mcore.NullMatcher() + return self + + def _get_spans(self): + slop = self.slop + mindist = self.mindist + ordered = self.ordered + spans = set() + + bspans = self.b.spans() + for aspan in self.a.spans(): + for bspan in bspans: + if (bspan.end < aspan.start - slop + or (ordered and aspan.start > bspan.start)): + # B is too far in front of A, or B is in front of A + # *at all* when ordered is True + continue + if bspan.start > aspan.end + slop: + # B is too far from A. Since spans are listed in + # start position order, we know that all spans after + # this one will also be too far. + break + + # Check the distance between the spans + dist = aspan.distance_to(bspan) + if mindist <= dist <= slop: + spans.add(aspan.to(bspan)) + + return sorted(spans) + + +class SpanNear2(SpanQuery): + """ + Matches queries that occur near each other. By default, only matches + queries that occur right next to each other (slop=1) and in order + (ordered=True). + + New code should use this query type instead of :class:`SpanNear`. + + (Unlike :class:`SpanNear`, this query takes a list of subqueries instead of + requiring you to build a binary tree of query objects. This query should + also be slightly faster due to less overhead.) + + For example, to find documents where "whoosh" occurs next to "library" + in the "text" field:: + + from whoosh import query, spans + t1 = query.Term("text", "whoosh") + t2 = query.Term("text", "library") + q = spans.SpanNear2([t1, t2]) + + To find documents where "whoosh" occurs at most 5 positions before + "library":: + + q = spans.SpanNear2([t1, t2], slop=5) + + To find documents where "whoosh" occurs at most 5 positions before or after + "library":: + + q = spans.SpanNear2(t1, t2, slop=5, ordered=False) + """ + + def __init__(self, qs, slop=1, ordered=True, mindist=1): + """ + :param qs: a sequence of sub-queries to match. + :param slop: the number of positions within which the queries must + occur. Default is 1, meaning the queries must occur right next + to each other. + :param ordered: whether a must occur before b. Default is True. + :pram mindist: the minimum distance allowed between the queries. + """ + + self.qs = qs + self.slop = slop + self.ordered = ordered + self.mindist = mindist + + def __repr__(self): + return ("%s(%r, slop=%d, ordered=%s, mindist=%d)" + % (self.__class__.__name__, self.qs, self.slop, self.ordered, + self.mindist)) + + def __eq__(self, other): + return (other and self.__class__ == other.__class__ + and self.qs == other.qs and self.slop == other.slop + and self.ordered == other.ordered + and self.mindist == other.mindist) + + def __hash__(self): + h = hash(self.slop) ^ hash(self.ordered) ^ hash(self.mindist) + for q in self.qs: + h ^= hash(q) + return h + + def _and_query(self): + return q.And(self.qs) + + def estimate_size(self, ixreader): + return self._and_query().estimate_size(ixreader) + + def estimate_min_size(self, ixreader): + return self._and_query().estimate_min_size(ixreader) + + def is_leaf(self): + return False + + def children(self): + return self.qs + + def apply(self, fn): + return self.__class__([fn(q) for q in self.qs], slop=self.slop, + ordered=self.ordered, mindist=self.mindist) + + def matcher(self, searcher, context=None): + ms = [q.matcher(searcher, context) for q in self.qs] + return self.SpanNear2Matcher(ms, slop=self.slop, ordered=self.ordered, + mindist=self.mindist) + + class SpanNear2Matcher(SpanWrappingMatcher): + def __init__(self, ms, slop=1, ordered=True, mindist=1): + self.ms = ms + self.slop = slop + self.ordered = ordered + self.mindist = mindist + isect = make_binary_tree(binary.IntersectionMatcher, ms) + super(SpanNear2.SpanNear2Matcher, self).__init__(isect) + + def copy(self): + return self.__class__([m.copy() for m in self.ms], slop=self.slop, + ordered=self.ordered, mindist=self.mindist) + + def replace(self, minquality=0): + # TODO: fix this + if not self.is_active(): + return mcore.NullMatcher() + return self + + def _get_spans(self): + slop = self.slop + mindist = self.mindist + ordered = self.ordered + ms = self.ms + + aspans = ms[0].spans() + i = 1 + while i < len(ms) and aspans: + bspans = ms[i].spans() + spans = set() + for aspan in aspans: + # Use a binary search to find the first position we should + # start looking for possible matches + if ordered: + start = aspan.start + else: + start = max(0, aspan.start - slop) + j = bisect_spans(bspans, start) + + while j < len(bspans): + bspan = bspans[j] + j += 1 + + if (bspan.end < aspan.start - slop + or (ordered and aspan.start > bspan.start)): + # B is too far in front of A, or B is in front of A + # *at all* when ordered is True + continue + if bspan.start > aspan.end + slop: + # B is too far from A. Since spans are listed in + # start position order, we know that all spans after + # this one will also be too far. + break + + # Check the distance between the spans + dist = aspan.distance_to(bspan) + if mindist <= dist <= slop: + spans.add(aspan.to(bspan)) + aspans = sorted(spans) + i += 1 + + if i == len(ms): + return aspans + else: + return [] + + +class SpanOr(SpanQuery): + """Matches documents that match any of a list of sub-queries. Unlike + query.Or, this class merges together matching spans from the different + sub-queries when they overlap. + """ + + def __init__(self, subqs): + """ + :param subqs: a list of queries to match. + """ + + self.q = Or(subqs) + self.subqs = subqs + + def is_leaf(self): + return False + + def apply(self, fn): + return self.__class__([fn(sq) for sq in self.subqs]) + + def matcher(self, searcher, context=None): + matchers = [q.matcher(searcher, context) for q in self.subqs] + return make_binary_tree(SpanOr.SpanOrMatcher, matchers) + + class SpanOrMatcher(SpanBiMatcher): + def __init__(self, a, b): + self.a = a + self.b = b + um = binary.UnionMatcher(a, b) + super(SpanOr.SpanOrMatcher, self).__init__(um) + + def _get_spans(self): + a_active = self.a.is_active() + b_active = self.b.is_active() + + if a_active: + a_id = self.a.id() + if b_active: + b_id = self.b.id() + if a_id == b_id: + spans = sorted(set(self.a.spans()) + | set(self.b.spans())) + elif a_id < b_id: + spans = self.a.spans() + else: + spans = self.b.spans() + else: + spans = self.a.spans() + else: + spans = self.b.spans() + + Span.merge(spans) + return spans + + +class SpanBiQuery(SpanQuery): + # Intermediate base class for methods common to "a/b" span query types + + def is_leaf(self): + return False + + def apply(self, fn): + return self.__class__(fn(self.a), fn(self.b)) + + def matcher(self, searcher, context=None): + ma = self.a.matcher(searcher, context) + mb = self.b.matcher(searcher, context) + return self._Matcher(ma, mb) + + +class SpanNot(SpanBiQuery): + """Matches spans from the first query only if they don't overlap with + spans from the second query. If there are no non-overlapping spans, the + document does not match. + + For example, to match documents that contain "bear" at most 2 places after + "apple" in the "text" field but don't have "cute" between them:: + + from whoosh import query, spans + t1 = query.Term("text", "apple") + t2 = query.Term("text", "bear") + near = spans.SpanNear(t1, t2, slop=2) + q = spans.SpanNot(near, query.Term("text", "cute")) + """ + + def __init__(self, a, b): + """ + :param a: the query to match. + :param b: do not match any spans that overlap with spans from this + query. + """ + + self.q = AndMaybe(a, b) + self.a = a + self.b = b + + class _Matcher(SpanBiMatcher): + def __init__(self, a, b): + self.a = a + self.b = b + amm = binary.AndMaybeMatcher(a, b) + super(SpanNot._Matcher, self).__init__(amm) + + def _get_spans(self): + if self.a.id() == self.b.id(): + spans = [] + bspans = self.b.spans() + for aspan in self.a.spans(): + overlapped = False + for bspan in bspans: + if aspan.overlaps(bspan): + overlapped = True + break + if not overlapped: + spans.append(aspan) + return spans + else: + return self.a.spans() + + +class SpanContains(SpanBiQuery): + """Matches documents where the spans of the first query contain any spans + of the second query. + + For example, to match documents where "apple" occurs at most 10 places + before "bear" in the "text" field and "cute" is between them:: + + from whoosh import query, spans + t1 = query.Term("text", "apple") + t2 = query.Term("text", "bear") + near = spans.SpanNear(t1, t2, slop=10) + q = spans.SpanContains(near, query.Term("text", "cute")) + """ + + def __init__(self, a, b): + """ + :param a: the query to match. + :param b: the query whose spans must occur within the matching spans + of the first query. + """ + + self.q = And([a, b]) + self.a = a + self.b = b + + class _Matcher(SpanBiMatcher): + def __init__(self, a, b): + self.a = a + self.b = b + im = binary.IntersectionMatcher(a, b) + super(SpanContains._Matcher, self).__init__(im) + + def _get_spans(self): + spans = [] + bspans = self.b.spans() + for aspan in self.a.spans(): + for bspan in bspans: + if aspan.start > bspan.end: + continue + if aspan.end < bspan.start: + break + + if bspan.is_within(aspan): + spans.append(aspan) + break + return spans + + +class SpanBefore(SpanBiQuery): + """Matches documents where the spans of the first query occur before any + spans of the second query. + + For example, to match documents where "apple" occurs anywhere before + "bear":: + + from whoosh import query, spans + t1 = query.Term("text", "apple") + t2 = query.Term("text", "bear") + q = spans.SpanBefore(t1, t2) + """ + + def __init__(self, a, b): + """ + :param a: the query that must occur before the second. + :param b: the query that must occur after the first. + """ + + self.a = a + self.b = b + self.q = And([a, b]) + + class _Matcher(SpanBiMatcher): + def __init__(self, a, b): + self.a = a + self.b = b + im = binary.IntersectionMatcher(a, b) + super(SpanBefore._Matcher, self).__init__(im) + + def _get_spans(self): + bminstart = min(bspan.start for bspan in self.b.spans()) + return [aspan for aspan in self.a.spans() if aspan.end < bminstart] + + +class SpanCondition(SpanBiQuery): + """Matches documents that satisfy both subqueries, but only uses the spans + from the first subquery. + + This is useful when you want to place conditions on matches but not have + those conditions affect the spans returned. + + For example, to get spans for the term ``alfa`` in documents that also + must contain the term ``bravo``:: + + SpanCondition(Term("text", u"alfa"), Term("text", u"bravo")) + + """ + + def __init__(self, a, b): + self.a = a + self.b = b + self.q = And([a, b]) + + class _Matcher(SpanBiMatcher): + def __init__(self, a, b): + self.a = a + im = binary.IntersectionMatcher(a, b) + super(SpanCondition._Matcher, self).__init__(im) + + def _get_spans(self): + return self.a.spans() + + + + + diff --git a/nstock/modules/whoosh/query/terms.py b/nstock/modules/whoosh/query/terms.py new file mode 100644 index 0000000..d123d97 --- /dev/null +++ b/nstock/modules/whoosh/query/terms.py @@ -0,0 +1,535 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from __future__ import division +import copy +import fnmatch +import re +from collections import defaultdict + +from whoosh import matching +from whoosh.analysis import Token +from whoosh.compat import bytes_type, text_type, u +from whoosh.lang.morph_en import variations +from whoosh.query import qcore + + +class Term(qcore.Query): + """Matches documents containing the given term (fieldname+text pair). + + >>> Term("content", u"render") + """ + + __inittypes__ = dict(fieldname=str, text=text_type, boost=float) + + def __init__(self, fieldname, text, boost=1.0, minquality=None): + self.fieldname = fieldname + self.text = text + self.boost = boost + self.minquality = minquality + + def __eq__(self, other): + return (other + and self.__class__ is other.__class__ + and self.fieldname == other.fieldname + and self.text == other.text + and self.boost == other.boost) + + def __repr__(self): + r = "%s(%r, %r" % (self.__class__.__name__, self.fieldname, self.text) + if self.boost != 1.0: + r += ", boost=%s" % self.boost + r += ")" + return r + + def __unicode__(self): + text = self.text + if isinstance(text, bytes_type): + try: + text = text.decode("ascii") + except UnicodeDecodeError: + text = repr(text) + + t = u("%s:%s") % (self.fieldname, text) + if self.boost != 1: + t += u("^") + text_type(self.boost) + return t + + __str__ = __unicode__ + + def __hash__(self): + return hash(self.fieldname) ^ hash(self.text) ^ hash(self.boost) + + def has_terms(self): + return True + + def tokens(self, boost=1.0): + yield Token(fieldname=self.fieldname, text=self.text, + boost=boost * self.boost, startchar=self.startchar, + endchar=self.endchar, chars=True) + + def terms(self, phrases=False): + if self.field(): + yield (self.field(), self.text) + + def replace(self, fieldname, oldtext, newtext): + q = copy.copy(self) + if q.fieldname == fieldname and q.text == oldtext: + q.text = newtext + return q + + def estimate_size(self, ixreader): + fieldname = self.fieldname + if fieldname not in ixreader.schema: + return 0 + + field = ixreader.schema[fieldname] + try: + text = field.to_bytes(self.text) + except ValueError: + return 0 + + return ixreader.doc_frequency(fieldname, text) + + def matcher(self, searcher, context=None): + fieldname = self.fieldname + text = self.text + if fieldname not in searcher.schema: + return matching.NullMatcher() + + field = searcher.schema[fieldname] + try: + text = field.to_bytes(text) + except ValueError: + return matching.NullMatcher() + + if (self.fieldname, text) in searcher.reader(): + if context is None: + w = searcher.weighting + else: + w = context.weighting + + m = searcher.postings(self.fieldname, text, weighting=w) + if self.minquality: + m.set_min_quality(self.minquality) + if self.boost != 1.0: + m = matching.WrappingMatcher(m, boost=self.boost) + return m + else: + return matching.NullMatcher() + + +class MultiTerm(qcore.Query): + """Abstract base class for queries that operate on multiple terms in the + same field. + """ + + constantscore = False + + def _btexts(self, ixreader): + raise NotImplementedError(self.__class__.__name__) + + def expanded_terms(self, ixreader, phrases=False): + fieldname = self.field() + if fieldname: + for btext in self._btexts(ixreader): + yield (fieldname, btext) + + def tokens(self, boost=1.0, exreader=None): + fieldname = self.field() + if exreader is None: + btexts = [self.text] + else: + btexts = self._btexts(exreader) + + for btext in btexts: + yield Token(fieldname=fieldname, text=btext, + boost=boost * self.boost, startchar=self.startchar, + endchar=self.endchar, chars=True) + + def simplify(self, ixreader): + fieldname = self.field() + + if fieldname not in ixreader.schema: + return qcore.NullQuery() + field = ixreader.schema[fieldname] + + existing = [] + for btext in sorted(set(self._btexts(ixreader))): + text = field.from_bytes(btext) + existing.append(Term(fieldname, text, boost=self.boost)) + + if len(existing) == 1: + return existing[0] + elif existing: + from whoosh.query import Or + return Or(existing) + else: + return qcore.NullQuery + + def estimate_size(self, ixreader): + fieldname = self.field() + return sum(ixreader.doc_frequency(fieldname, btext) + for btext in self._btexts(ixreader)) + + def estimate_min_size(self, ixreader): + fieldname = self.field() + return min(ixreader.doc_frequency(fieldname, text) + for text in self._btexts(ixreader)) + + def matcher(self, searcher, context=None): + from whoosh.query import Or + + fieldname = self.field() + constantscore = self.constantscore + + reader = searcher.reader() + qs = [Term(fieldname, word) for word in self._btexts(reader) + if word] + if not qs: + return matching.NullMatcher() + + if len(qs) == 1: + # If there's only one term, just use it + m = qs[0].matcher(searcher, context) + else: + if constantscore: + # To tell the sub-query that score doesn't matter, set weighting + # to None + if context: + context = context.set(weighting=None) + else: + from whoosh.searching import SearchContext + context = SearchContext(weighting=None) + # Or the terms together + m = Or(qs, boost=self.boost).matcher(searcher, context) + return m + + +class PatternQuery(MultiTerm): + """An intermediate base class for common methods of Prefix and Wildcard. + """ + + __inittypes__ = dict(fieldname=str, text=text_type, boost=float) + + def __init__(self, fieldname, text, boost=1.0, constantscore=True): + self.fieldname = fieldname + self.text = text + self.boost = boost + self.constantscore = constantscore + + def __eq__(self, other): + return (other and self.__class__ is other.__class__ + and self.fieldname == other.fieldname + and self.text == other.text and self.boost == other.boost + and self.constantscore == other.constantscore) + + def __repr__(self): + r = "%s(%r, %r" % (self.__class__.__name__, self.fieldname, self.text) + if self.boost != 1: + r += ", boost=%s" % self.boost + r += ")" + return r + + def __hash__(self): + return (hash(self.fieldname) ^ hash(self.text) ^ hash(self.boost) + ^ hash(self.constantscore)) + + def _get_pattern(self): + raise NotImplementedError + + def _find_prefix(self, text): + # Subclasses/instances should set the SPECIAL_CHARS attribute to a set + # of characters that mark the end of the literal prefix + specialchars = self.SPECIAL_CHARS + i = 0 + for i, char in enumerate(text): + if char in specialchars: + break + return text[:i] + + def _btexts(self, ixreader): + field = ixreader.schema[self.fieldname] + + exp = re.compile(self._get_pattern()) + prefix = self._find_prefix(self.text) + if prefix: + candidates = ixreader.expand_prefix(self.fieldname, prefix) + else: + candidates = ixreader.lexicon(self.fieldname) + + from_bytes = field.from_bytes + for btext in candidates: + text = from_bytes(btext) + if exp.match(text): + yield btext + + +class Prefix(PatternQuery): + """Matches documents that contain any terms that start with the given text. + + >>> # Match documents containing words starting with 'comp' + >>> Prefix("content", u"comp") + """ + + def __unicode__(self): + return "%s:%s*" % (self.fieldname, self.text) + + __str__ = __unicode__ + + def _btexts(self, ixreader): + return ixreader.expand_prefix(self.fieldname, self.text) + + def matcher(self, searcher, context=None): + if self.text == "": + from whoosh.query import Every + eq = Every(self.fieldname, boost=self.boost) + return eq.matcher(searcher, context) + else: + return PatternQuery.matcher(self, searcher, context) + + +class Wildcard(PatternQuery): + """Matches documents that contain any terms that match a "glob" pattern. + See the Python ``fnmatch`` module for information about globs. + + >>> Wildcard("content", u"in*f?x") + """ + + SPECIAL_CHARS = frozenset("*?[") + + def __unicode__(self): + return "%s:%s" % (self.fieldname, self.text) + + __str__ = __unicode__ + + def _get_pattern(self): + return fnmatch.translate(self.text) + + def normalize(self): + # If there are no wildcard characters in this "wildcard", turn it into + # a simple Term + text = self.text + if text == "*": + from whoosh.query import Every + return Every(self.fieldname, boost=self.boost) + if "*" not in text and "?" not in text: + # If no wildcard chars, convert to a normal term. + return Term(self.fieldname, self.text, boost=self.boost) + elif ("?" not in text and text.endswith("*") + and text.find("*") == len(text) - 1): + # If the only wildcard char is an asterisk at the end, convert to a + # Prefix query. + return Prefix(self.fieldname, self.text[:-1], boost=self.boost) + else: + return self + + def matcher(self, searcher, context=None): + if self.text == "*": + from whoosh.query import Every + eq = Every(self.fieldname, boost=self.boost) + return eq.matcher(searcher, context) + else: + return PatternQuery.matcher(self, searcher, context) + + # _btexts() implemented in PatternQuery + + +class Regex(PatternQuery): + """Matches documents that contain any terms that match a regular + expression. See the Python ``re`` module for information about regular + expressions. + """ + + SPECIAL_CHARS = frozenset("{}()[].?*+^$\\") + + def __unicode__(self): + return '%s:r"%s"' % (self.fieldname, self.text) + + __str__ = __unicode__ + + def _get_pattern(self): + return self.text + + def _find_prefix(self, text): + if "|" in text: + return "" + if text.startswith("^"): + text = text[1:] + elif text.startswith("\\A"): + text = text[2:] + + prefix = PatternQuery._find_prefix(self, text) + + lp = len(prefix) + if lp < len(text) and text[lp] in "*?": + # we stripped something starting from * or ? - they both MAY mean + # "0 times". As we had stripped starting from FIRST special char, + # that implies there were only ordinary chars left of it. Thus, + # the very last of them is not part of the real prefix: + prefix = prefix[:-1] + return prefix + + def matcher(self, searcher, context=None): + if self.text == ".*": + from whoosh.query import Every + eq = Every(self.fieldname, boost=self.boost) + return eq.matcher(searcher, context) + else: + return PatternQuery.matcher(self, searcher, context) + + # _btexts() implemented in PatternQuery + + +class ExpandingTerm(MultiTerm): + """Intermediate base class for queries such as FuzzyTerm and Variations + that expand into multiple queries, but come from a single term. + """ + + def has_terms(self): + return True + + def terms(self, phrases=False): + if self.field(): + yield (self.field(), self.text) + + +class FuzzyTerm(ExpandingTerm): + """Matches documents containing words similar to the given term. + """ + + __inittypes__ = dict(fieldname=str, text=text_type, boost=float, + maxdist=float, prefixlength=int) + + def __init__(self, fieldname, text, boost=1.0, maxdist=1, + prefixlength=1, constantscore=True): + """ + :param fieldname: The name of the field to search. + :param text: The text to search for. + :param boost: A boost factor to apply to scores of documents matching + this query. + :param maxdist: The maximum edit distance from the given text. + :param prefixlength: The matched terms must share this many initial + characters with 'text'. For example, if text is "light" and + prefixlength is 2, then only terms starting with "li" are checked + for similarity. + """ + + self.fieldname = fieldname + self.text = text + self.boost = boost + self.maxdist = maxdist + self.prefixlength = prefixlength + self.constantscore = constantscore + + def __eq__(self, other): + return (other and self.__class__ is other.__class__ + and self.fieldname == other.fieldname + and self.text == other.text + and self.maxdist == other.maxdist + and self.prefixlength == other.prefixlength + and self.boost == other.boost + and self.constantscore == other.constantscore) + + def __repr__(self): + r = "%s(%r, %r, boost=%f, maxdist=%d, prefixlength=%d)" + return r % (self.__class__.__name__, self.fieldname, self.text, + self.boost, self.maxdist, self.prefixlength) + + def __unicode__(self): + r = u("%s:%s") % (self.fieldname, self.text) + u("~") + if self.maxdist > 1: + r += u("%d") % self.maxdist + if self.boost != 1.0: + r += u("^%f") % self.boost + return r + + __str__ = __unicode__ + + def __hash__(self): + return (hash(self.fieldname) ^ hash(self.text) ^ hash(self.boost) + ^ hash(self.maxdist) ^ hash(self.prefixlength) + ^ hash(self.constantscore)) + + def _btexts(self, ixreader): + return ixreader.terms_within(self.fieldname, self.text, self.maxdist, + prefix=self.prefixlength) + + def replace(self, fieldname, oldtext, newtext): + q = copy.copy(self) + if q.fieldname == fieldname and q.text == oldtext: + q.text = newtext + return q + + +class Variations(ExpandingTerm): + """Query that automatically searches for morphological variations of the + given word in the same field. + """ + + def __init__(self, fieldname, text, boost=1.0): + self.fieldname = fieldname + self.text = text + self.boost = boost + + def __repr__(self): + r = "%s(%r, %r" % (self.__class__.__name__, self.fieldname, self.text) + if self.boost != 1: + r += ", boost=%s" % self.boost + r += ")" + return r + + def __eq__(self, other): + return (other and self.__class__ is other.__class__ + and self.fieldname == other.fieldname + and self.text == other.text and self.boost == other.boost) + + def __hash__(self): + return hash(self.fieldname) ^ hash(self.text) ^ hash(self.boost) + + def _btexts(self, ixreader): + fieldname = self.fieldname + to_bytes = ixreader.schema[fieldname].to_bytes + for word in variations(self.text): + try: + btext = to_bytes(word) + except ValueError: + continue + + if (fieldname, btext) in ixreader: + yield btext + + def __unicode__(self): + return u("%s:<%s>") % (self.fieldname, self.text) + + __str__ = __unicode__ + + def replace(self, fieldname, oldtext, newtext): + q = copy.copy(self) + if q.fieldname == fieldname and q.text == oldtext: + q.text = newtext + return q diff --git a/nstock/modules/whoosh/query/wrappers.py b/nstock/modules/whoosh/query/wrappers.py new file mode 100644 index 0000000..db59798 --- /dev/null +++ b/nstock/modules/whoosh/query/wrappers.py @@ -0,0 +1,198 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from __future__ import division +from array import array + +from whoosh import matching +from whoosh.compat import text_type, u, xrange +from whoosh.query import qcore + + +class WrappingQuery(qcore.Query): + def __init__(self, child): + self.child = child + + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self.child) + + def __hash__(self): + return hash(self.__class__.__name__) ^ hash(self.child) + + def _rewrap(self, child): + return self.__class__(child) + + def is_leaf(self): + return False + + def children(self): + yield self.child + + def apply(self, fn): + return self._rewrap(fn(self.child)) + + def requires(self): + return self.child.requires() + + def field(self): + return self.child.field() + + def with_boost(self, boost): + return self._rewrap(self.child.with_boost(boost)) + + def estimate_size(self, ixreader): + return self.child.estimate_size(ixreader) + + def estimate_min_size(self, ixreader): + return self.child.estimate_min_size(ixreader) + + def matcher(self, searcher, context=None): + return self.child.matcher(searcher, context) + + +class Not(qcore.Query): + """Excludes any documents that match the subquery. + + >>> # Match documents that contain 'render' but not 'texture' + >>> And([Term("content", u"render"), + ... Not(Term("content", u"texture"))]) + >>> # You can also do this + >>> Term("content", u"render") - Term("content", u"texture") + """ + + __inittypes__ = dict(query=qcore.Query) + + def __init__(self, query, boost=1.0): + """ + :param query: A :class:`Query` object. The results of this query + are *excluded* from the parent query. + :param boost: Boost is meaningless for excluded documents but this + keyword argument is accepted for the sake of a consistent + interface. + """ + + self.query = query + self.boost = boost + + def __eq__(self, other): + return other and self.__class__ is other.__class__ and\ + self.query == other.query + + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, repr(self.query)) + + def __unicode__(self): + return u("NOT ") + text_type(self.query) + + __str__ = __unicode__ + + def __hash__(self): + return (hash(self.__class__.__name__) + ^ hash(self.query) + ^ hash(self.boost)) + + def is_leaf(self): + return False + + def children(self): + yield self.query + + def apply(self, fn): + return self.__class__(fn(self.query)) + + def normalize(self): + q = self.query.normalize() + if q is qcore.NullQuery: + return q + else: + return self.__class__(q, boost=self.boost) + + def field(self): + return None + + def estimate_size(self, ixreader): + return ixreader.doc_count() + + def estimate_min_size(self, ixreader): + return 1 if ixreader.doc_count() else 0 + + def matcher(self, searcher, context=None): + # Usually only called if Not is the root query. Otherwise, queries such + # as And and Or do special handling of Not subqueries. + reader = searcher.reader() + child = self.query.matcher(searcher, searcher.boolean_context()) + return matching.InverseMatcher(child, reader.doc_count_all(), + missing=reader.is_deleted) + + +class ConstantScoreQuery(WrappingQuery): + """Wraps a query and uses a matcher that always gives a constant score + to all matching documents. This is a useful optimization when you don't + care about scores from a certain branch of the query tree because it is + simply acting as a filter. See also the :class:`AndMaybe` query. + """ + + def __init__(self, child, score=1.0): + WrappingQuery.__init__(self, child) + self.score = score + + def __eq__(self, other): + return (other and self.__class__ is other.__class__ + and self.child == other.child and self.score == other.score) + + def __hash__(self): + return hash(self.child) ^ hash(self.score) + + def _rewrap(self, child): + return self.__class__(child, self.score) + + def matcher(self, searcher, context=None): + from whoosh.searching import SearchContext + + context = context or SearchContext() + m = self.child.matcher(searcher, context) + if context.needs_current or isinstance(m, matching.NullMatcherClass): + return m + else: + ids = array("I", m.all_ids()) + return matching.ListMatcher(ids, all_weights=self.score, + term=m.term()) + + +class WeightingQuery(WrappingQuery): + """Wraps a query and uses a specific :class:`whoosh.sorting.WeightingModel` + to score documents that match the wrapped query. + """ + + def __init__(self, child, weighting): + WrappingQuery.__init__(self, child) + self.weighting = weighting + + def matcher(self, searcher, context=None): + # Replace the passed-in weighting with the one configured on this query + context.set(weighting=self.weighting) + return self.child.matcher(searcher, context) diff --git a/nstock/modules/whoosh/reading.py b/nstock/modules/whoosh/reading.py new file mode 100644 index 0000000..f79d6dd --- /dev/null +++ b/nstock/modules/whoosh/reading.py @@ -0,0 +1,1296 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +"""This module contains classes that allow reading from an index. +""" + +from math import log +from bisect import bisect_right +from heapq import heapify, heapreplace, heappop, nlargest + +from whoosh import columns +from whoosh.compat import abstractmethod +from whoosh.compat import xrange, zip_, next, iteritems +from whoosh.filedb.filestore import OverlayStorage +from whoosh.matching import MultiMatcher +from whoosh.support.levenshtein import distance +from whoosh.system import emptybytes + + +# Exceptions + +class ReaderClosed(Exception): + """Exception raised when you try to do some operation on a closed searcher + (or a Results object derived from a searcher that has since been closed). + """ + + message = "Operation on a closed reader" + + +class TermNotFound(Exception): + pass + + +# Term Info base class + +class TermInfo(object): + """Represents a set of statistics about a term. This object is returned by + :meth:`IndexReader.term_info`. These statistics may be useful for + optimizations and scoring algorithms. + """ + + def __init__(self, weight=0, df=0, minlength=None, + maxlength=0, maxweight=0, minid=None, maxid=0): + self._weight = weight + self._df = df + self._minlength = minlength + self._maxlength = maxlength + self._maxweight = maxweight + self._minid = minid + self._maxid = maxid + + def add_posting(self, docnum, weight, length=None): + if self._minid is None: + self._minid = docnum + self._maxid = docnum + self._weight += weight + self._df += 1 + self._maxweight = max(self._maxweight, weight) + + if length is not None: + if self._minlength is None: + self._minlength = length + else: + self._minlength = min(self._minlength, length) + self._maxlength = max(self._maxlength, length) + + def weight(self): + """Returns the total frequency of the term across all documents. + """ + + return self._weight + + def doc_frequency(self): + """Returns the number of documents the term appears in. + """ + + return self._df + + def min_length(self): + """Returns the length of the shortest field value the term appears + in. + """ + + return self._minlength + + def max_length(self): + """Returns the length of the longest field value the term appears + in. + """ + + return self._maxlength + + def max_weight(self): + """Returns the number of times the term appears in the document in + which it appears the most. + """ + + return self._maxweight + + def min_id(self): + """Returns the lowest document ID this term appears in. + """ + + return self._minid + + def max_id(self): + """Returns the highest document ID this term appears in. + """ + + return self._maxid + + +# Reader base class + +class IndexReader(object): + """Do not instantiate this object directly. Instead use Index.reader(). + """ + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + @abstractmethod + def __contains__(self, term): + """Returns True if the given term tuple (fieldname, text) is + in this reader. + """ + raise NotImplementedError + + def codec(self): + """Returns the :class:`whoosh.codec.base.Codec` object used to read + this reader's segment. If this reader is not atomic + (``reader.is_atomic() == True``), returns None. + """ + + return None + + def segment(self): + """Returns the :class:`whoosh.index.Segment` object used by this reader. + If this reader is not atomic (``reader.is_atomic() == True``), returns + None. + """ + + return None + + def storage(self): + """Returns the :class:`whoosh.filedb.filestore.Storage` object used by + this reader to read its files. If the reader is not atomic, + (``reader.is_atomic() == True``), returns None. + """ + + return None + + def is_atomic(self): + return True + + def _text_to_bytes(self, fieldname, text): + if fieldname not in self.schema: + raise TermNotFound((fieldname, text)) + return self.schema[fieldname].to_bytes(text) + + def close(self): + """Closes the open files associated with this reader. + """ + + pass + + def generation(self): + """Returns the generation of the index being read, or -1 if the backend + is not versioned. + """ + + return None + + @abstractmethod + def indexed_field_names(self): + """Returns an iterable of strings representing the names of the indexed + fields. This may include additional names not explicitly listed in the + Schema if you use "glob" fields. + """ + + raise NotImplementedError + + @abstractmethod + def all_terms(self): + """Yields (fieldname, text) tuples for every term in the index. + """ + + raise NotImplementedError + + def terms_from(self, fieldname, prefix): + """Yields (fieldname, text) tuples for every term in the index starting + at the given prefix. + """ + + # The default implementation just scans the whole list of terms + for fname, text in self.all_terms(): + if fname < fieldname or text < prefix: + continue + yield (fname, text) + + @abstractmethod + def term_info(self, fieldname, text): + """Returns a :class:`TermInfo` object allowing access to various + statistics about the given term. + """ + + raise NotImplementedError + + def expand_prefix(self, fieldname, prefix): + """Yields terms in the given field that start with the given prefix. + """ + + prefix = self._text_to_bytes(fieldname, prefix) + for fn, text in self.terms_from(fieldname, prefix): + if fn != fieldname or not text.startswith(prefix): + return + yield text + + def lexicon(self, fieldname): + """Yields all bytestrings in the given field. + """ + + for fn, btext in self.terms_from(fieldname, emptybytes): + if fn != fieldname: + return + yield btext + + def field_terms(self, fieldname): + """Yields all term values (converted from on-disk bytes) in the given + field. + """ + + from_bytes = self.schema[fieldname].from_bytes + for btext in self.lexicon(fieldname): + yield from_bytes(btext) + + def __iter__(self): + """Yields ((fieldname, text), terminfo) tuples for each term in the + reader, in lexical order. + """ + + term_info = self.term_info + for term in self.all_terms(): + yield (term, term_info(*term)) + + def iter_from(self, fieldname, text): + """Yields ((fieldname, text), terminfo) tuples for all terms in the + reader, starting at the given term. + """ + + term_info = self.term_info + text = self._text_to_bytes(fieldname, text) + for term in self.terms_from(fieldname, text): + yield (term, term_info(*term)) + + def iter_field(self, fieldname, prefix=''): + """Yields (text, terminfo) tuples for all terms in the given field. + """ + + prefix = self._text_to_bytes(fieldname, prefix) + for (fn, text), terminfo in self.iter_from(fieldname, prefix): + if fn != fieldname: + return + yield text, terminfo + + def iter_prefix(self, fieldname, prefix): + """Yields (text, terminfo) tuples for all terms in the given field with + a certain prefix. + """ + + prefix = self._text_to_bytes(fieldname, prefix) + for text, terminfo in self.iter_field(fieldname, prefix): + if not text.startswith(prefix): + return + yield (text, terminfo) + + @abstractmethod + def has_deletions(self): + """Returns True if the underlying index/segment has deleted + documents. + """ + + raise NotImplementedError + + def all_doc_ids(self): + """Returns an iterator of all (undeleted) document IDs in the reader. + """ + + is_deleted = self.is_deleted + return (docnum for docnum in xrange(self.doc_count_all()) + if not is_deleted(docnum)) + + def iter_docs(self): + """Yields a series of ``(docnum, stored_fields_dict)`` + tuples for the undeleted documents in the reader. + """ + + for docnum in self.all_doc_ids(): + yield docnum, self.stored_fields(docnum) + + @abstractmethod + def is_deleted(self, docnum): + """Returns True if the given document number is marked deleted. + """ + + raise NotImplementedError + + @abstractmethod + def stored_fields(self, docnum): + """Returns the stored fields for the given document number. + + :param numerickeys: use field numbers as the dictionary keys instead of + field names. + """ + + raise NotImplementedError + + def all_stored_fields(self): + """Yields the stored fields for all non-deleted documents. + """ + + is_deleted = self.is_deleted + for docnum in xrange(self.doc_count_all()): + if not is_deleted(docnum): + yield self.stored_fields(docnum) + + @abstractmethod + def doc_count_all(self): + """Returns the total number of documents, DELETED OR UNDELETED, + in this reader. + """ + + raise NotImplementedError + + @abstractmethod + def doc_count(self): + """Returns the total number of UNDELETED documents in this reader. + """ + + return self.doc_count_all() - self.deleted_count() + + @abstractmethod + def frequency(self, fieldname, text): + """Returns the total number of instances of the given term in the + collection. + """ + raise NotImplementedError + + @abstractmethod + def doc_frequency(self, fieldname, text): + """Returns how many documents the given term appears in. + """ + raise NotImplementedError + + @abstractmethod + def field_length(self, fieldname): + """Returns the total number of terms in the given field. This is used + by some scoring algorithms. + """ + raise NotImplementedError + + @abstractmethod + def min_field_length(self, fieldname): + """Returns the minimum length of the field across all documents. This + is used by some scoring algorithms. + """ + raise NotImplementedError + + @abstractmethod + def max_field_length(self, fieldname): + """Returns the minimum length of the field across all documents. This + is used by some scoring algorithms. + """ + raise NotImplementedError + + @abstractmethod + def doc_field_length(self, docnum, fieldname, default=0): + """Returns the number of terms in the given field in the given + document. This is used by some scoring algorithms. + """ + raise NotImplementedError + + def first_id(self, fieldname, text): + """Returns the first ID in the posting list for the given term. This + may be optimized in certain backends. + """ + + text = self._text_to_bytes(fieldname, text) + p = self.postings(fieldname, text) + if p.is_active(): + return p.id() + raise TermNotFound((fieldname, text)) + + def iter_postings(self): + """Low-level method, yields all postings in the reader as + ``(fieldname, text, docnum, weight, valuestring)`` tuples. + """ + + for fieldname, btext in self.all_terms(): + m = self.postings(fieldname, btext) + while m.is_active(): + yield (fieldname, btext, m.id(), m.weight(), m.value()) + m.next() + + @abstractmethod + def postings(self, fieldname, text): + """Returns a :class:`~whoosh.matching.Matcher` for the postings of the + given term. + + >>> pr = reader.postings("content", "render") + >>> pr.skip_to(10) + >>> pr.id + 12 + + :param fieldname: the field name or field number of the term. + :param text: the text of the term. + :rtype: :class:`whoosh.matching.Matcher` + """ + + raise NotImplementedError + + @abstractmethod + def has_vector(self, docnum, fieldname): + """Returns True if the given document has a term vector for the given + field. + """ + raise NotImplementedError + + @abstractmethod + def vector(self, docnum, fieldname, format_=None): + """Returns a :class:`~whoosh.matching.Matcher` object for the + given term vector. + + >>> docnum = searcher.document_number(path=u'/a/b/c') + >>> v = searcher.vector(docnum, "content") + >>> v.all_as("frequency") + [(u"apple", 3), (u"bear", 2), (u"cab", 2)] + + :param docnum: the document number of the document for which you want + the term vector. + :param fieldname: the field name or field number of the field for which + you want the term vector. + :rtype: :class:`whoosh.matching.Matcher` + """ + raise NotImplementedError + + def vector_as(self, astype, docnum, fieldname): + """Returns an iterator of (termtext, value) pairs for the terms in the + given term vector. This is a convenient shortcut to calling vector() + and using the Matcher object when all you want are the terms and/or + values. + + >>> docnum = searcher.document_number(path=u'/a/b/c') + >>> searcher.vector_as("frequency", docnum, "content") + [(u"apple", 3), (u"bear", 2), (u"cab", 2)] + + :param docnum: the document number of the document for which you want + the term vector. + :param fieldname: the field name or field number of the field for which + you want the term vector. + :param astype: a string containing the name of the format you want the + term vector's data in, for example "weights". + """ + + vec = self.vector(docnum, fieldname) + if astype == "weight": + while vec.is_active(): + yield (vec.id(), vec.weight()) + vec.next() + else: + format_ = self.schema[fieldname].format + decoder = format_.decoder(astype) + while vec.is_active(): + yield (vec.id(), decoder(vec.value())) + vec.next() + + def corrector(self, fieldname): + """Returns a :class:`whoosh.spelling.Corrector` object that suggests + corrections based on the terms in the given field. + """ + + from whoosh.spelling import ReaderCorrector + + fieldobj = self.schema[fieldname] + return ReaderCorrector(self, fieldname, fieldobj) + + def terms_within(self, fieldname, text, maxdist, prefix=0): + """ + Returns a generator of words in the given field within ``maxdist`` + Damerau-Levenshtein edit distance of the given text. + + Important: the terms are returned in **no particular order**. The only + criterion is that they are within ``maxdist`` edits of ``text``. You + may want to run this method multiple times with increasing ``maxdist`` + values to ensure you get the closest matches first. You may also have + additional information (such as term frequency or an acoustic matching + algorithm) you can use to rank terms with the same edit distance. + + :param maxdist: the maximum edit distance. + :param prefix: require suggestions to share a prefix of this length + with the given word. This is often justifiable since most + misspellings do not involve the first letter of the word. + Using a prefix dramatically decreases the time it takes to generate + the list of words. + :param seen: an optional set object. Words that appear in the set will + not be yielded. + """ + + fieldobj = self.schema[fieldname] + for btext in self.expand_prefix(fieldname, text[:prefix]): + word = fieldobj.from_bytes(btext) + k = distance(word, text, limit=maxdist) + if k <= maxdist: + yield word + + def most_frequent_terms(self, fieldname, number=5, prefix=''): + """Returns the top 'number' most frequent terms in the given field as a + list of (frequency, text) tuples. + """ + + gen = ((terminfo.weight(), text) for text, terminfo + in self.iter_prefix(fieldname, prefix)) + return nlargest(number, gen) + + def most_distinctive_terms(self, fieldname, number=5, prefix=''): + """Returns the top 'number' terms with the highest `tf*idf` scores as + a list of (score, text) tuples. + """ + + N = float(self.doc_count()) + gen = ((terminfo.weight() * log(N / terminfo.doc_frequency()), text) + for text, terminfo in self.iter_prefix(fieldname, prefix)) + return nlargest(number, gen) + + def leaf_readers(self): + """Returns a list of (IndexReader, docbase) pairs for the child readers + of this reader if it is a composite reader. If this is not a composite + reader, it returns `[(self, 0)]`. + """ + + return [(self, 0)] + + def supports_caches(self): + return False + + def has_column(self, fieldname): + return False + + def column_reader(self, fieldname, column=None, reverse=False, + translate=False): + """ + + :param fieldname: the name of the field for which to get a reader. + :param column: if passed, use this Column object instead of the one + associated with the field in the Schema. + :param reverse: if passed, reverses the order of keys returned by the + reader's ``sort_key()`` method. If the column type is not + reversible, this will raise a ``NotImplementedError``. + :param translate: if True, wrap the reader to call the field's + ``from_bytes()`` method on the returned values. + :return: a :class:`whoosh.columns.ColumnReader` object. + """ + + raise NotImplementedError + + +# Segment-based reader + +class SegmentReader(IndexReader): + def __init__(self, storage, schema, segment, generation=None, codec=None): + self.schema = schema + self.is_closed = False + + self._segment = segment + self._segid = self._segment.segment_id() + self._gen = generation + + # self.files is a storage object from which to load the segment files. + # This is different from the general storage (which will be used for + # caches) if the segment is in a compound file. + if segment.is_compound(): + # Open the compound file as a storage object + files = segment.open_compound_file(storage) + # Use an overlay here instead of just the compound storage, in rare + # circumstances a segment file may be added after the segment is + # written + self._storage = OverlayStorage(files, storage) + else: + self._storage = storage + + # Get subreaders from codec + self._codec = codec if codec else segment.codec() + self._terms = self._codec.terms_reader(self._storage, segment) + self._perdoc = self._codec.per_document_reader(self._storage, segment) + + def codec(self): + return self._codec + + def segment(self): + return self._segment + + def storage(self): + return self._storage + + def has_deletions(self): + if self.is_closed: + raise ReaderClosed + return self._perdoc.has_deletions() + + def doc_count(self): + if self.is_closed: + raise ReaderClosed + return self._perdoc.doc_count() + + def doc_count_all(self): + if self.is_closed: + raise ReaderClosed + return self._perdoc.doc_count_all() + + def is_deleted(self, docnum): + if self.is_closed: + raise ReaderClosed + return self._perdoc.is_deleted(docnum) + + def generation(self): + return self._gen + + def __repr__(self): + return "%s(%r, %r)" % (self.__class__.__name__, self._storage, + self._segment) + + def __contains__(self, term): + if self.is_closed: + raise ReaderClosed + fieldname, text = term + if fieldname not in self.schema: + return False + text = self._text_to_bytes(fieldname, text) + return (fieldname, text) in self._terms + + def close(self): + if self.is_closed: + raise ReaderClosed("Reader already closed") + self._terms.close() + self._perdoc.close() + + # It's possible some weird codec that doesn't use storage might have + # passed None instead of a storage object + if self._storage: + self._storage.close() + + self.is_closed = True + + def stored_fields(self, docnum): + if self.is_closed: + raise ReaderClosed + assert docnum >= 0 + schema = self.schema + sfs = self._perdoc.stored_fields(docnum) + # Double-check with schema to filter out removed fields + return dict(item for item in iteritems(sfs) if item[0] in schema) + + # Delegate doc methods to the per-doc reader + + def all_doc_ids(self): + if self.is_closed: + raise ReaderClosed + return self._perdoc.all_doc_ids() + + def iter_docs(self): + if self.is_closed: + raise ReaderClosed + return self._perdoc.iter_docs() + + def all_stored_fields(self): + if self.is_closed: + raise ReaderClosed + return self._perdoc.all_stored_fields() + + def field_length(self, fieldname): + if self.is_closed: + raise ReaderClosed + return self._perdoc.field_length(fieldname) + + def min_field_length(self, fieldname): + if self.is_closed: + raise ReaderClosed + return self._perdoc.min_field_length(fieldname) + + def max_field_length(self, fieldname): + if self.is_closed: + raise ReaderClosed + return self._perdoc.max_field_length(fieldname) + + def doc_field_length(self, docnum, fieldname, default=0): + if self.is_closed: + raise ReaderClosed + return self._perdoc.doc_field_length(docnum, fieldname, default) + + def has_vector(self, docnum, fieldname): + if self.is_closed: + raise ReaderClosed + return self._perdoc.has_vector(docnum, fieldname) + + # + + def _test_field(self, fieldname): + if self.is_closed: + raise ReaderClosed + if fieldname not in self.schema: + raise TermNotFound("No field %r" % fieldname) + if self.schema[fieldname].format is None: + raise TermNotFound("Field %r is not indexed" % fieldname) + + def indexed_field_names(self): + return self._terms.indexed_field_names() + + def all_terms(self): + if self.is_closed: + raise ReaderClosed + schema = self.schema + return ((fieldname, text) for fieldname, text in self._terms.terms() + if fieldname in schema) + + def terms_from(self, fieldname, prefix): + self._test_field(fieldname) + prefix = self._text_to_bytes(fieldname, prefix) + schema = self.schema + return ((fname, text) for fname, text + in self._terms.terms_from(fieldname, prefix) + if fname in schema) + + def term_info(self, fieldname, text): + self._test_field(fieldname) + text = self._text_to_bytes(fieldname, text) + try: + return self._terms.term_info(fieldname, text) + except KeyError: + raise TermNotFound("%s:%r" % (fieldname, text)) + + def expand_prefix(self, fieldname, prefix): + self._test_field(fieldname) + prefix = self._text_to_bytes(fieldname, prefix) + return IndexReader.expand_prefix(self, fieldname, prefix) + + def lexicon(self, fieldname): + self._test_field(fieldname) + return IndexReader.lexicon(self, fieldname) + + def __iter__(self): + if self.is_closed: + raise ReaderClosed + schema = self.schema + return ((term, terminfo) for term, terminfo in self._terms.items() + if term[0] in schema) + + def iter_from(self, fieldname, text): + self._test_field(fieldname) + schema = self.schema + text = self._text_to_bytes(fieldname, text) + for term, terminfo in self._terms.items_from(fieldname, text): + if term[0] not in schema: + continue + yield (term, terminfo) + + def frequency(self, fieldname, text): + self._test_field(fieldname) + text = self._text_to_bytes(fieldname, text) + try: + return self._terms.frequency(fieldname, text) + except KeyError: + return 0 + + def doc_frequency(self, fieldname, text): + self._test_field(fieldname) + text = self._text_to_bytes(fieldname, text) + try: + return self._terms.doc_frequency(fieldname, text) + except KeyError: + return 0 + + def postings(self, fieldname, text, scorer=None): + from whoosh.matching.wrappers import FilterMatcher + + if self.is_closed: + raise ReaderClosed + if fieldname not in self.schema: + raise TermNotFound("No field %r" % fieldname) + text = self._text_to_bytes(fieldname, text) + format_ = self.schema[fieldname].format + matcher = self._terms.matcher(fieldname, text, format_, scorer=scorer) + deleted = frozenset(self._perdoc.deleted_docs()) + if deleted: + matcher = FilterMatcher(matcher, deleted, exclude=True) + return matcher + + def vector(self, docnum, fieldname, format_=None): + if self.is_closed: + raise ReaderClosed + if fieldname not in self.schema: + raise TermNotFound("No field %r" % fieldname) + vformat = format_ or self.schema[fieldname].vector + if not vformat: + raise Exception("No vectors are stored for field %r" % fieldname) + return self._perdoc.vector(docnum, fieldname, vformat) + + def cursor(self, fieldname): + if self.is_closed: + raise ReaderClosed + fieldobj = self.schema[fieldname] + return self._terms.cursor(fieldname, fieldobj) + + def terms_within(self, fieldname, text, maxdist, prefix=0): + # Replaces the horribly inefficient base implementation with one based + # on skipping through the word list efficiently using a DFA + + fieldobj = self.schema[fieldname] + spellfield = fieldobj.spelling_fieldname(fieldname) + auto = self._codec.automata(self._storage, self._segment) + fieldcur = self.cursor(spellfield) + return auto.terms_within(fieldcur, text, maxdist, prefix) + + # Column methods + + def has_column(self, fieldname): + if self.is_closed: + raise ReaderClosed + coltype = self.schema[fieldname].column_type + return coltype and self._perdoc.has_column(fieldname) + + def column_reader(self, fieldname, column=None, reverse=False, + translate=True): + if self.is_closed: + raise ReaderClosed + + fieldobj = self.schema[fieldname] + column = column or fieldobj.column_type + if not column: + raise Exception("No column for field %r in %r" + % (fieldname, self)) + + if self._perdoc.has_column(fieldname): + creader = self._perdoc.column_reader(fieldname, column) + if reverse: + creader.set_reverse() + else: + # This segment doesn't have a column file for this field, so create + # a fake column reader that always returns the default value. + default = column.default_value(reverse) + creader = columns.EmptyColumnReader(default, self.doc_count_all()) + + if translate: + # Wrap the column in a Translator to give the caller + # nice values instead of sortable representations + fcv = fieldobj.from_column_value + creader = columns.TranslatingColumnReader(creader, fcv) + + return creader + + +# Fake IndexReader class for empty indexes + +class EmptyReader(IndexReader): + def __init__(self, schema): + self.schema = schema + + def __contains__(self, term): + return False + + def __iter__(self): + return iter([]) + + def cursor(self, fieldname): + from whoosh.codec.base import EmptyCursor + + return EmptyCursor() + + def indexed_field_names(self): + return [] + + def all_terms(self): + return iter([]) + + def term_info(self, fieldname, text): + raise TermNotFound((fieldname, text)) + + def iter_from(self, fieldname, text): + return iter([]) + + def iter_field(self, fieldname, prefix=''): + return iter([]) + + def iter_prefix(self, fieldname, prefix=''): + return iter([]) + + def lexicon(self, fieldname): + return iter([]) + + def has_deletions(self): + return False + + def is_deleted(self, docnum): + return False + + def stored_fields(self, docnum): + raise KeyError("No document number %s" % docnum) + + def all_stored_fields(self): + return iter([]) + + def doc_count_all(self): + return 0 + + def doc_count(self): + return 0 + + def frequency(self, fieldname, text): + return 0 + + def doc_frequency(self, fieldname, text): + return 0 + + def field_length(self, fieldname): + return 0 + + def min_field_length(self, fieldname): + return 0 + + def max_field_length(self, fieldname): + return 0 + + def doc_field_length(self, docnum, fieldname, default=0): + return default + + def postings(self, fieldname, text, scorer=None): + raise TermNotFound("%s:%r" % (fieldname, text)) + + def has_vector(self, docnum, fieldname): + return False + + def vector(self, docnum, fieldname, format_=None): + raise KeyError("No document number %s" % docnum) + + def most_frequent_terms(self, fieldname, number=5, prefix=''): + return iter([]) + + def most_distinctive_terms(self, fieldname, number=5, prefix=None): + return iter([]) + + +# Multisegment reader class + +class MultiReader(IndexReader): + """Do not instantiate this object directly. Instead use Index.reader(). + """ + + def __init__(self, readers, generation=None): + self.readers = readers + self._gen = generation + self.schema = None + if readers: + self.schema = readers[0].schema + + self.doc_offsets = [] + self.base = 0 + for r in self.readers: + self.doc_offsets.append(self.base) + self.base += r.doc_count_all() + + self.is_closed = False + + def _document_segment(self, docnum): + return max(0, bisect_right(self.doc_offsets, docnum) - 1) + + def _segment_and_docnum(self, docnum): + segmentnum = self._document_segment(docnum) + offset = self.doc_offsets[segmentnum] + return segmentnum, docnum - offset + + def cursor(self, fieldname): + return MultiCursor([r.cursor(fieldname) for r in self.readers]) + + def is_atomic(self): + return False + + def leaf_readers(self): + return zip_(self.readers, self.doc_offsets) + + def add_reader(self, reader): + self.readers.append(reader) + self.doc_offsets.append(self.base) + self.base += reader.doc_count_all() + + def close(self): + for d in self.readers: + d.close() + self.is_closed = True + + def generation(self): + return self._gen + + def format(self, fieldname): + for r in self.readers: + fmt = r.format(fieldname) + if fmt is not None: + return fmt + + def vector_format(self, fieldname): + for r in self.readers: + vfmt = r.vector_format(fieldname) + if vfmt is not None: + return vfmt + + # Term methods + + def __contains__(self, term): + return any(r.__contains__(term) for r in self.readers) + + def _merge_terms(self, iterlist): + # Merge-sorts terms coming from a list of term iterators. + + # Create a map so we can look up each iterator by its id() value + itermap = {} + for it in iterlist: + itermap[id(it)] = it + + # Fill in the list with the head term from each iterator. + + current = [] + for it in iterlist: + try: + term = next(it) + except StopIteration: + continue + current.append((term, id(it))) + # Number of active iterators + active = len(current) + + # If only one iterator is active, just yield from it and return + if active == 1: + term, itid = current[0] + it = itermap[itid] + yield term + for term in it: + yield term + return + + # Otherwise, do a streaming heap sort of the terms from the iterators + heapify(current) + while active: + # Peek at the first term in the sorted list + term = current[0][0] + + # Re-iterate on all items in the list that have that term + while active and current[0][0] == term: + it = itermap[current[0][1]] + try: + nextterm = next(it) + heapreplace(current, (nextterm, id(it))) + except StopIteration: + heappop(current) + active -= 1 + + # Yield the term + yield term + + def indexed_field_names(self): + names = set() + for r in self.readers: + names.update(r.indexed_field_names()) + return iter(names) + + def all_terms(self): + return self._merge_terms([r.all_terms() for r in self.readers]) + + def terms_from(self, fieldname, prefix): + return self._merge_terms([r.terms_from(fieldname, prefix) + for r in self.readers]) + + def term_info(self, fieldname, text): + term = (fieldname, text) + + # Get the term infos for the sub-readers containing the term + tis = [(r.term_info(fieldname, text), offset) for r, offset + in zip_(self.readers, self.doc_offsets) if term in r] + + # If only one reader had the term, return its terminfo with the offset + # added + if not tis: + raise TermNotFound(term) + + return combine_terminfos(tis) + + def frequency(self, fieldname, text): + return sum(r.frequency(fieldname, text) for r in self.readers) + + def doc_frequency(self, fieldname, text): + return sum(r.doc_frequency(fieldname, text) for r in self.readers) + + def postings(self, fieldname, text): + # This method does not add a scorer; for that, use Searcher.postings() + + postreaders = [] + docoffsets = [] + term = (fieldname, text) + + for i, r in enumerate(self.readers): + if term in r: + offset = self.doc_offsets[i] + pr = r.postings(fieldname, text) + postreaders.append(pr) + docoffsets.append(offset) + + if not postreaders: + raise TermNotFound(fieldname, text) + + return MultiMatcher(postreaders, docoffsets) + + def first_id(self, fieldname, text): + for i, r in enumerate(self.readers): + try: + id = r.first_id(fieldname, text) + except (KeyError, TermNotFound): + pass + else: + if id is None: + raise TermNotFound((fieldname, text)) + else: + return self.doc_offsets[i] + id + + raise TermNotFound((fieldname, text)) + + # Deletion methods + + def has_deletions(self): + return any(r.has_deletions() for r in self.readers) + + def is_deleted(self, docnum): + segmentnum, segmentdoc = self._segment_and_docnum(docnum) + return self.readers[segmentnum].is_deleted(segmentdoc) + + def stored_fields(self, docnum): + segmentnum, segmentdoc = self._segment_and_docnum(docnum) + return self.readers[segmentnum].stored_fields(segmentdoc) + + # Columns + + def has_column(self, fieldname): + return any(r.has_column(fieldname) for r in self.readers) + + def column_reader(self, fieldname, column=None, reverse=False, + translate=True): + crs = [] + doc_offsets = [] + for i, r in enumerate(self.readers): + if r.has_column(fieldname): + cr = r.column_reader(fieldname, column=column, reverse=reverse, + translate=translate) + crs.append(cr) + doc_offsets.append(self.doc_offsets[i]) + return columns.MultiColumnReader(crs, doc_offsets) + + # Per doc methods + + def all_stored_fields(self): + for reader in self.readers: + for result in reader.all_stored_fields(): + yield result + + def doc_count_all(self): + return sum(dr.doc_count_all() for dr in self.readers) + + def doc_count(self): + return sum(dr.doc_count() for dr in self.readers) + + def field_length(self, fieldname): + return sum(dr.field_length(fieldname) for dr in self.readers) + + def min_field_length(self, fieldname): + return min(r.min_field_length(fieldname) for r in self.readers) + + def max_field_length(self, fieldname): + return max(r.max_field_length(fieldname) for r in self.readers) + + def doc_field_length(self, docnum, fieldname, default=0): + segmentnum, segmentdoc = self._segment_and_docnum(docnum) + reader = self.readers[segmentnum] + return reader.doc_field_length(segmentdoc, fieldname, default=default) + + def has_vector(self, docnum, fieldname): + segmentnum, segmentdoc = self._segment_and_docnum(docnum) + return self.readers[segmentnum].has_vector(segmentdoc, fieldname) + + def vector(self, docnum, fieldname, format_=None): + segmentnum, segmentdoc = self._segment_and_docnum(docnum) + return self.readers[segmentnum].vector(segmentdoc, fieldname) + + def vector_as(self, astype, docnum, fieldname): + segmentnum, segmentdoc = self._segment_and_docnum(docnum) + return self.readers[segmentnum].vector_as(astype, segmentdoc, + fieldname) + + +def combine_terminfos(tis): + if len(tis) == 1: + ti, offset = tis[0] + ti._minid += offset + ti._maxid += offset + return ti + + # Combine the various statistics + w = sum(ti.weight() for ti, _ in tis) + df = sum(ti.doc_frequency() for ti, _ in tis) + ml = min(ti.min_length() for ti, _ in tis) + xl = max(ti.max_length() for ti, _ in tis) + xw = max(ti.max_weight() for ti, _ in tis) + + # For min and max ID, we need to add the doc offsets + mid = min(ti.min_id() + offset for ti, offset in tis) + xid = max(ti.max_id() + offset for ti, offset in tis) + + return TermInfo(w, df, ml, xl, xw, mid, xid) + + +class MultiCursor(object): + def __init__(self, cursors): + self._cursors = [c for c in cursors if c.is_valid()] + self._low = [] + self._text = None + self.next() + + def _find_low(self): + low = [] + lowterm = None + + for c in self._cursors: + if c.is_valid(): + cterm = c.term() + if low and cterm == lowterm: + low.append(c) + elif low and cterm < lowterm: + low = [c] + lowterm = cterm + + self._low = low + self._text = lowterm + return lowterm + + def first(self): + for c in self._cursors: + c.first() + return self._find_low() + + def find(self, term): + for c in self._cursors: + c.find(term) + return self._find_low() + + def next(self): + for c in self._cursors: + c.next() + return self._find_low() + + def term_info(self): + tis = [c.term_info() for c in self._low] + return combine_terminfos(tis) if tis else None + + def is_valid(self): + return any(c.is_valid() for c in self._cursors) diff --git a/nstock/modules/whoosh/scoring.py b/nstock/modules/whoosh/scoring.py new file mode 100644 index 0000000..cd6c2d2 --- /dev/null +++ b/nstock/modules/whoosh/scoring.py @@ -0,0 +1,616 @@ +# Copyright 2008 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +""" +This module contains classes for scoring (and sorting) search results. +""" + +from __future__ import division +from math import log, pi + +from whoosh.compat import iteritems + + +# Base classes + +class WeightingModel(object): + """Abstract base class for scoring models. A WeightingModel object provides + a method, ``scorer``, which returns an instance of + :class:`whoosh.scoring.Scorer`. + + Basically, WeightingModel objects store the configuration information for + the model (for example, the values of B and K1 in the BM25F model), and + then creates a scorer instance based on additional run-time information + (the searcher, the fieldname, and term text) to do the actual scoring. + """ + + use_final = False + + def idf(self, searcher, fieldname, text): + """Returns the inverse document frequency of the given term. + """ + + parent = searcher.get_parent() + n = parent.doc_frequency(fieldname, text) + dc = parent.doc_count_all() + return log(dc / (n + 1)) + 1 + + def scorer(self, searcher, fieldname, text, qf=1): + """Returns an instance of :class:`whoosh.scoring.Scorer` configured + for the given searcher, fieldname, and term text. + """ + + raise NotImplementedError(self.__class__.__name__) + + def final(self, searcher, docnum, score): + """Returns a final score for each document. You can use this method + in subclasses to apply document-level adjustments to the score, for + example using the value of stored field to influence the score + (although that would be slow). + + WeightingModel sub-classes that use ``final()`` should have the + attribute ``use_final`` set to ``True``. + + :param searcher: :class:`whoosh.searching.Searcher` for the index. + :param docnum: the doc number of the document being scored. + :param score: the document's accumulated term score. + + :rtype: float + """ + + return score + + +class BaseScorer(object): + """Base class for "scorer" implementations. A scorer provides a method for + scoring a document, and sometimes methods for rating the "quality" of a + document and a matcher's current "block", to implement quality-based + optimizations. + + Scorer objects are created by WeightingModel objects. Basically, + WeightingModel objects store the configuration information for the model + (for example, the values of B and K1 in the BM25F model), and then creates + a scorer instance. + """ + + def supports_block_quality(self): + """Returns True if this class supports quality optimizations. + """ + + return False + + def score(self, matcher): + """Returns a score for the current document of the matcher. + """ + + raise NotImplementedError(self.__class__.__name__) + + def max_quality(self): + """Returns the *maximum limit* on the possible score the matcher can + give. This can be an estimate and not necessarily the actual maximum + score possible, but it must never be less than the actual maximum + score. + """ + + raise NotImplementedError(self.__class__.__name__) + + def block_quality(self, matcher): + """Returns the *maximum limit* on the possible score the matcher can + give **in its current "block"** (whatever concept of "block" the + backend might use). This can be an estimate and not necessarily the + actual maximum score possible, but it must never be less than the + actual maximum score. + + If this score is less than the minimum score + required to make the "top N" results, then we can tell the matcher to + skip ahead to another block with better "quality". + """ + + raise NotImplementedError(self.__class__.__name__) + + +# Scorer that just returns term weight + +class WeightScorer(BaseScorer): + """A scorer that simply returns the weight as the score. This is useful + for more complex weighting models to return when they are asked for a + scorer for fields that aren't scorable (don't store field lengths). + """ + + def __init__(self, maxweight): + self._maxweight = maxweight + + def supports_block_quality(self): + return True + + def score(self, matcher): + return matcher.weight() + + def max_quality(self): + return self._maxweight + + def block_quality(self, matcher): + return matcher.block_max_weight() + + @classmethod + def for_(cls, searcher, fieldname, text): + ti = searcher.term_info(fieldname, text) + return cls(ti.max_weight()) + + +# Base scorer for models that only use weight and field length + +class WeightLengthScorer(BaseScorer): + """Base class for scorers where the only per-document variables are term + weight and field length. + + Subclasses should override the ``_score(weight, length)`` method to return + the score for a document with the given weight and length, and call the + ``setup()`` method at the end of the initializer to set up common + attributes. + """ + + def setup(self, searcher, fieldname, text): + """Initializes the scorer and then does the busy work of + adding the ``dfl()`` function and maximum quality attribute. + + This method assumes the initializers of WeightLengthScorer subclasses + always take ``searcher, offset, fieldname, text`` as the first three + arguments. Any additional arguments given to this method are passed + through to the initializer. + + Note: this method calls ``self._score()``, so you should only call it + in the initializer after setting up whatever attributes ``_score()`` + depends on:: + + class MyScorer(WeightLengthScorer): + def __init__(self, searcher, fieldname, text, parm=1.0): + self.parm = parm + self.setup(searcher, fieldname, text) + + def _score(self, weight, length): + return (weight / (length + 1)) * self.parm + """ + + ti = searcher.term_info(fieldname, text) + if not searcher.schema[fieldname].scorable: + return WeightScorer(ti.max_weight()) + + self.dfl = lambda docid: searcher.doc_field_length(docid, fieldname, 1) + self._maxquality = self._score(ti.max_weight(), ti.min_length()) + + def supports_block_quality(self): + return True + + def score(self, matcher): + return self._score(matcher.weight(), self.dfl(matcher.id())) + + def max_quality(self): + return self._maxquality + + def block_quality(self, matcher): + return self._score(matcher.block_max_weight(), + matcher.block_min_length()) + + def _score(self, weight, length): + # Override this method with the actual scoring function + raise NotImplementedError(self.__class__.__name__) + + +# WeightingModel implementations + +# Debugging model + +class DebugModel(WeightingModel): + def __init__(self): + self.log = [] + + def scorer(self, searcher, fieldname, text, qf=1): + return DebugScorer(searcher, fieldname, text, self.log) + + +class DebugScorer(BaseScorer): + def __init__(self, searcher, fieldname, text, log): + ti = searcher.term_info(fieldname, text) + self._maxweight = ti.max_weight() + + self.searcher = searcher + self.fieldname = fieldname + self.text = text + self.log = log + + def supports_block_quality(self): + return True + + def score(self, matcher): + fieldname, text = self.fieldname, self.text + docid = matcher.id() + w = matcher.weight() + length = self.searcher.doc_field_length(docid, fieldname) + self.log.append((fieldname, text, docid, w, length)) + return w + + def max_quality(self): + return self._maxweight + + def block_quality(self, matcher): + return matcher.block_max_weight() + + +# BM25F Model + +def bm25(idf, tf, fl, avgfl, B, K1): + # idf - inverse document frequency + # tf - term frequency in the current document + # fl - field length in the current document + # avgfl - average field length across documents in collection + # B, K1 - free paramters + + return idf * ((tf * (K1 + 1)) / (tf + K1 * ((1 - B) + B * fl / avgfl))) + + +class BM25F(WeightingModel): + """Implements the BM25F scoring algorithm. + """ + + def __init__(self, B=0.75, K1=1.2, **kwargs): + """ + + >>> from whoosh import scoring + >>> # Set a custom B value for the "content" field + >>> w = scoring.BM25F(B=0.75, content_B=1.0, K1=1.5) + + :param B: free parameter, see the BM25 literature. Keyword arguments of + the form ``fieldname_B`` (for example, ``body_B``) set field- + specific values for B. + :param K1: free parameter, see the BM25 literature. + """ + + self.B = B + self.K1 = K1 + + self._field_B = {} + for k, v in iteritems(kwargs): + if k.endswith("_B"): + fieldname = k[:-2] + self._field_B[fieldname] = v + + def supports_block_quality(self): + return True + + def scorer(self, searcher, fieldname, text, qf=1): + if not searcher.schema[fieldname].scorable: + return WeightScorer.for_(searcher, fieldname, text) + + if fieldname in self._field_B: + B = self._field_B[fieldname] + else: + B = self.B + + return BM25FScorer(searcher, fieldname, text, B, self.K1, qf=qf) + + +class BM25FScorer(WeightLengthScorer): + def __init__(self, searcher, fieldname, text, B, K1, qf=1): + # IDF and average field length are global statistics, so get them from + # the top-level searcher + parent = searcher.get_parent() # Returns self if no parent + self.idf = parent.idf(fieldname, text) + self.avgfl = parent.avg_field_length(fieldname) or 1 + + self.B = B + self.K1 = K1 + self.qf = qf + self.setup(searcher, fieldname, text) + + def _score(self, weight, length): + s = bm25(self.idf, weight, length, self.avgfl, self.B, self.K1) + return s + + +# DFree model + +def dfree(tf, cf, qf, dl, fl): + # tf - term frequency in current document + # cf - term frequency in collection + # qf - term frequency in query + # dl - field length in current document + # fl - total field length across all documents in collection + prior = tf / dl + post = (tf + 1.0) / (dl + 1.0) + invpriorcol = fl / cf + norm = tf * log(post / prior) + + return qf * norm * (tf * (log(prior * invpriorcol)) + + (tf + 1.0) * (log(post * invpriorcol)) + + 0.5 * log(post / prior)) + + +class DFree(WeightingModel): + """Implements the DFree scoring model from Terrier. + + See http://terrier.org/ + """ + + def supports_block_quality(self): + return True + + def scorer(self, searcher, fieldname, text, qf=1): + if not searcher.schema[fieldname].scorable: + return WeightScorer.for_(searcher, fieldname, text) + + return DFreeScorer(searcher, fieldname, text, qf=qf) + + +class DFreeScorer(WeightLengthScorer): + def __init__(self, searcher, fieldname, text, qf=1): + # Total term weight and total field length are global statistics, so + # get them from the top-level searcher + parent = searcher.get_parent() # Returns self if no parent + self.cf = parent.weight(fieldname, text) + self.fl = parent.field_length(fieldname) + + self.qf = qf + self.setup(searcher, fieldname, text) + + def _score(self, weight, length): + return dfree(weight, self.cf, self.qf, length, self.fl) + + +# PL2 model + +rec_log2_of_e = 1.0 / log(2) + + +def pl2(tf, cf, qf, dc, fl, avgfl, c): + # tf - term frequency in the current document + # cf - term frequency in the collection + # qf - term frequency in the query + # dc - doc count + # fl - field length in the current document + # avgfl - average field length across all documents + # c -free parameter + + TF = tf * log(1.0 + (c * avgfl) / fl) + norm = 1.0 / (TF + 1.0) + f = cf / dc + return norm * qf * (TF * log(1.0 / f) + + f * rec_log2_of_e + + 0.5 * log(2 * pi * TF) + + TF * (log(TF) - rec_log2_of_e)) + + +class PL2(WeightingModel): + """Implements the PL2 scoring model from Terrier. + + See http://terrier.org/ + """ + + def __init__(self, c=1.0): + self.c = c + + def scorer(self, searcher, fieldname, text, qf=1): + if not searcher.schema[fieldname].scorable: + return WeightScorer.for_(searcher, fieldname, text) + + return PL2Scorer(searcher, fieldname, text, self.c, qf=qf) + + +class PL2Scorer(WeightLengthScorer): + def __init__(self, searcher, fieldname, text, c, qf=1): + # Total term weight, document count, and average field length are + # global statistics, so get them from the top-level searcher + parent = searcher.get_parent() # Returns self if no parent + self.cf = parent.frequency(fieldname, text) + self.dc = parent.doc_count_all() + self.avgfl = parent.avg_field_length(fieldname) or 1 + + self.c = c + self.qf = qf + self.setup(searcher, fieldname, text) + + def _score(self, weight, length): + return pl2(weight, self.cf, self.qf, self.dc, length, self.avgfl, + self.c) + + +# Simple models + +class Frequency(WeightingModel): + def scorer(self, searcher, fieldname, text, qf=1): + maxweight = searcher.term_info(fieldname, text).max_weight() + return WeightScorer(maxweight) + + +class TF_IDF(WeightingModel): + def scorer(self, searcher, fieldname, text, qf=1): + # IDF is a global statistic, so get it from the top-level searcher + parent = searcher.get_parent() # Returns self if no parent + idf = parent.idf(fieldname, text) + + maxweight = searcher.term_info(fieldname, text).max_weight() + return TF_IDFScorer(maxweight, idf) + + +class TF_IDFScorer(BaseScorer): + def __init__(self, maxweight, idf): + self._maxquality = maxweight * idf + self.idf = idf + + def supports_block_quality(self): + return True + + def score(self, matcher): + return matcher.weight() * self.idf + + def max_quality(self): + return self._maxquality + + def block_quality(self, matcher): + return matcher.block_max_weight() * self.idf + + +# Utility models + +class Weighting(WeightingModel): + """This class provides backwards-compatibility with the old weighting + class architecture, so any existing custom scorers don't need to be + rewritten. + """ + + def scorer(self, searcher, fieldname, text, qf=1): + return self.CompatibilityScorer(searcher, fieldname, text, self.score) + + def score(self, searcher, fieldname, text, docnum, weight): + raise NotImplementedError + + class CompatibilityScorer(BaseScorer): + def __init__(self, searcher, fieldname, text, scoremethod): + self.searcher = searcher + self.fieldname = fieldname + self.text = text + self.scoremethod = scoremethod + + def score(self, matcher): + return self.scoremethod(self.searcher, self.fieldname, self.text, + matcher.id(), matcher.weight()) + + +class FunctionWeighting(WeightingModel): + """Uses a supplied function to do the scoring. For simple scoring functions + and experiments this may be simpler to use than writing a full weighting + model class and scorer class. + + The function should accept the arguments + ``searcher, fieldname, text, matcher``. + + For example, the following function will score documents based on the + earliest position of the query term in the document:: + + def pos_score_fn(searcher, fieldname, text, matcher): + poses = matcher.value_as("positions") + return 1.0 / (poses[0] + 1) + + pos_weighting = scoring.FunctionWeighting(pos_score_fn) + with myindex.searcher(weighting=pos_weighting) as s: + results = s.search(q) + + Note that the searcher passed to the function may be a per-segment searcher + for performance reasons. If you want to get global statistics inside the + function, you should use ``searcher.get_parent()`` to get the top-level + searcher. (However, if you are using global statistics, you should probably + write a real model/scorer combo so you can cache them on the object.) + """ + + def __init__(self, fn): + self.fn = fn + + def scorer(self, searcher, fieldname, text, qf=1): + return self.FunctionScorer(self.fn, searcher, fieldname, text, qf=qf) + + class FunctionScorer(BaseScorer): + def __init__(self, fn, searcher, fieldname, text, qf=1): + self.fn = fn + self.searcher = searcher + self.fieldname = fieldname + self.text = text + self.qf = qf + + def score(self, matcher): + return self.fn(self.searcher, self.fieldname, self.text, matcher) + + +class MultiWeighting(WeightingModel): + """Chooses from multiple scoring algorithms based on the field. + """ + + def __init__(self, default, **weightings): + """The only non-keyword argument specifies the default + :class:`Weighting` instance to use. Keyword arguments specify + Weighting instances for specific fields. + + For example, to use ``BM25`` for most fields, but ``Frequency`` for + the ``id`` field and ``TF_IDF`` for the ``keys`` field:: + + mw = MultiWeighting(BM25(), id=Frequency(), keys=TF_IDF()) + + :param default: the Weighting instance to use for fields not + specified in the keyword arguments. + """ + + self.default = default + # Store weighting functions by field name + self.weightings = weightings + + def scorer(self, searcher, fieldname, text, qf=1): + w = self.weightings.get(fieldname, self.default) + return w.scorer(searcher, fieldname, text, qf=qf) + + +class ReverseWeighting(WeightingModel): + """Wraps a weighting object and subtracts the wrapped model's scores from + 0, essentially reversing the weighting model. + """ + + def __init__(self, weighting): + self.weighting = weighting + + def scorer(self, searcher, fieldname, text, qf=1): + subscorer = self.weighting.scorer(searcher, fieldname, text, qf=qf) + return ReverseWeighting.ReverseScorer(subscorer) + + class ReverseScorer(BaseScorer): + def __init__(self, subscorer): + self.subscorer = subscorer + + def supports_block_quality(self): + return self.subscorer.supports_block_quality() + + def score(self, matcher): + return 0 - self.subscorer.score(matcher) + + def max_quality(self): + return 0 - self.subscorer.max_quality() + + def block_quality(self, matcher): + return 0 - self.subscorer.block_quality(matcher) + + +#class PositionWeighting(WeightingModel): +# def __init__(self, reversed=False): +# self.reversed = reversed +# +# def scorer(self, searcher, fieldname, text, qf=1): +# return PositionWeighting.PositionScorer() +# +# class PositionScorer(BaseScorer): +# def score(self, matcher): +# p = min(span.pos for span in matcher.spans()) +# if self.reversed: +# return p +# else: +# return 0 - p diff --git a/nstock/modules/whoosh/searching.py b/nstock/modules/whoosh/searching.py new file mode 100644 index 0000000..6fc5c81 --- /dev/null +++ b/nstock/modules/whoosh/searching.py @@ -0,0 +1,1653 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +"""This module contains classes and functions related to searching the index. +""" + + +from __future__ import division +import copy +import weakref +from math import ceil + +from whoosh import classify, highlight, query, scoring +from whoosh.compat import iteritems, itervalues, iterkeys, xrange +from whoosh.idsets import DocIdSet, BitSet +from whoosh.reading import TermNotFound +from whoosh.util.cache import lru_cache + + +class NoTermsException(Exception): + """Exception raised you try to access matched terms on a :class:`Results` + object was created without them. To record which terms matched in which + document, you need to call the :meth:`Searcher.search` method with + ``terms=True``. + """ + + message = "Results were created without recording terms" + + +class TimeLimit(Exception): + """Raised by :class:`TimeLimitedCollector` if the time limit is reached + before the search finishes. If you have a reference to the collector, you + can get partial results by calling :meth:`TimeLimitedCollector.results`. + """ + + pass + + +# Context class + +class SearchContext(object): + """A container for information about the current search that may be used + by the collector or the query objects to change how they operate. + """ + + def __init__(self, needs_current=False, weighting=None, top_query=None, + limit=0): + """ + :param needs_current: if True, the search requires that the matcher + tree be "valid" and able to access information about the current + match. For queries during matcher instantiation, this means they + should not instantiate a matcher that doesn't allow access to the + current match's value, weight, and so on. For collectors, this + means they should advanced the matcher doc-by-doc rather than using + shortcut methods such as all_ids(). + :param weighting: the Weighting object to use for scoring documents. + :param top_query: a reference to the top-level query object. + :param limit: the number of results requested by the user. + """ + + self.needs_current = needs_current + self.weighting = weighting + self.top_query = top_query + self.limit = limit + + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self.__dict__) + + def set(self, **kwargs): + ctx = copy.copy(self) + ctx.__dict__.update(kwargs) + return ctx + + +# Searcher class + +class Searcher(object): + """Wraps an :class:`~whoosh.reading.IndexReader` object and provides + methods for searching the index. + """ + + def __init__(self, reader, weighting=scoring.BM25F, closereader=True, + fromindex=None, parent=None): + """ + :param reader: An :class:`~whoosh.reading.IndexReader` object for + the index to search. + :param weighting: A :class:`whoosh.scoring.Weighting` object to use to + score found documents. + :param closereader: Whether the underlying reader will be closed when + the searcher is closed. + :param fromindex: An optional reference to the index of the underlying + reader. This is required for :meth:`Searcher.up_to_date` and + :meth:`Searcher.refresh` to work. + """ + + self.ixreader = reader + self.is_closed = False + self._closereader = closereader + self._ix = fromindex + self._doccount = self.ixreader.doc_count_all() + # Cache for PostingCategorizer objects (supports fields without columns) + self._field_caches = {} + + if parent: + self.parent = weakref.ref(parent) + self.schema = parent.schema + self._idf_cache = parent._idf_cache + self._filter_cache = parent._filter_cache + else: + self.parent = None + self.schema = self.ixreader.schema + self._idf_cache = {} + self._filter_cache = {} + + if type(weighting) is type: + self.weighting = weighting() + else: + self.weighting = weighting + + self.leafreaders = None + self.subsearchers = None + if not self.ixreader.is_atomic(): + self.leafreaders = self.ixreader.leaf_readers() + self.subsearchers = [(self._subsearcher(r), offset) for r, offset + in self.leafreaders] + + # Copy attributes/methods from wrapped reader + for name in ("stored_fields", "all_stored_fields", "has_vector", + "vector", "vector_as", "lexicon", "field_terms", + "frequency", "doc_frequency", "term_info", + "doc_field_length", "corrector", "iter_docs"): + setattr(self, name, getattr(self.ixreader, name)) + + def __enter__(self): + return self + + def __exit__(self, *exc_info): + self.close() + + def _subsearcher(self, reader): + return self.__class__(reader, fromindex=self._ix, + weighting=self.weighting, parent=self) + + def _offset_for_subsearcher(self, subsearcher): + for ss, offset in self.subsearchers: + if ss is subsearcher: + return offset + + def leaf_searchers(self): + if self.is_atomic(): + return [(self, 0)] + else: + return self.subsearchers + + def is_atomic(self): + return self.reader().is_atomic() + + def has_parent(self): + return self.parent is not None + + def get_parent(self): + """Returns the parent of this searcher (if has_parent() is True), or + else self. + """ + + if self.has_parent(): + # Call the weak reference to get the parent searcher + return self.parent() + else: + return self + + def doc_count(self): + """Returns the number of UNDELETED documents in the index. + """ + + return self.ixreader.doc_count() + + def doc_count_all(self): + """Returns the total number of documents, DELETED OR UNDELETED, in + the index. + """ + + return self._doccount + + def field_length(self, fieldname): + if self.has_parent(): + return self.get_parent().field_length(fieldname) + else: + return self.reader().field_length(fieldname) + + def max_field_length(self, fieldname): + if self.has_parent(): + return self.get_parent().max_field_length(fieldname) + else: + return self.reader().max_field_length(fieldname) + + def up_to_date(self): + """Returns True if this Searcher represents the latest version of the + index, for backends that support versioning. + """ + + if not self._ix: + raise Exception("No reference to index") + return self._ix.latest_generation() == self.ixreader.generation() + + def refresh(self): + """Returns a fresh searcher for the latest version of the index:: + + my_searcher = my_searcher.refresh() + + If the index has not changed since this searcher was created, this + searcher is simply returned. + + This method may CLOSE underlying resources that are no longer needed + by the refreshed searcher, so you CANNOT continue to use the original + searcher after calling ``refresh()`` on it. + """ + + if not self._ix: + raise Exception("No reference to index") + if self._ix.latest_generation() == self.reader().generation(): + return self + + # Get a new reader, re-using resources from the current reader if + # possible + self.is_closed = True + newreader = self._ix.reader(reuse=self.ixreader) + return self.__class__(newreader, fromindex=self._ix, + weighting=self.weighting) + + def close(self): + if self._closereader: + self.ixreader.close() + self.is_closed = True + + def avg_field_length(self, fieldname, default=None): + if not self.schema[fieldname].scorable: + return default + return self.field_length(fieldname) / (self._doccount or 1) + + def reader(self): + """Returns the underlying :class:`~whoosh.reading.IndexReader`. + """ + return self.ixreader + + def context(self, **kwargs): + """Generates a :class:`SearchContext` for this searcher. + """ + + if "weighting" not in kwargs: + kwargs["weighting"] = self.weighting + + return SearchContext(**kwargs) + + def boolean_context(self): + """Shortcut returns a SearchContext set for unscored (boolean) + searching. + """ + + return self.context(needs_current=False, weighting=None) + + def postings(self, fieldname, text, weighting=None, qf=1): + """Returns a :class:`whoosh.matching.Matcher` for the postings of the + given term. Unlike the :func:`whoosh.reading.IndexReader.postings` + method, this method automatically sets the scoring functions on the + matcher from the searcher's weighting object. + """ + + weighting = weighting or self.weighting + globalscorer = weighting.scorer(self, fieldname, text, qf=qf) + + if self.is_atomic(): + return self.ixreader.postings(fieldname, text, scorer=globalscorer) + else: + from whoosh.matching import MultiMatcher + + matchers = [] + docoffsets = [] + term = (fieldname, text) + for subsearcher, offset in self.subsearchers: + r = subsearcher.reader() + if term in r: + # Make a segment-specific scorer; the scorer should call + # searcher.parent() to get global stats + scorer = weighting.scorer(subsearcher, fieldname, text, qf=qf) + m = r.postings(fieldname, text, scorer=scorer) + matchers.append(m) + docoffsets.append(offset) + + if not matchers: + raise TermNotFound(fieldname, text) + + return MultiMatcher(matchers, docoffsets, globalscorer) + + def idf(self, fieldname, text): + """Calculates the Inverse Document Frequency of the current term (calls + idf() on the searcher's Weighting object). + """ + + # This method just calls the Weighting object's idf() method, but + # caches the result. So Weighting objects should call *this* method + # which will then call *their own* idf() methods. + + cache = self._idf_cache + term = (fieldname, text) + if term in cache: + return cache[term] + + idf = self.weighting.idf(self, fieldname, text) + cache[term] = idf + return idf + + def document(self, **kw): + """Convenience method returns the stored fields of a document + matching the given keyword arguments, where the keyword keys are + field names and the values are terms that must appear in the field. + + This method is equivalent to:: + + searcher.stored_fields(searcher.document_number()) + + Where Searcher.documents() returns a generator, this function returns + either a dictionary or None. Use it when you assume the given keyword + arguments either match zero or one documents (i.e. at least one of the + fields is a unique key). + + >>> stored_fields = searcher.document(path=u"/a/b") + >>> if stored_fields: + ... print(stored_fields['title']) + ... else: + ... print("There is no document with the path /a/b") + """ + + for p in self.documents(**kw): + return p + + def documents(self, **kw): + """Convenience method returns the stored fields of a document + matching the given keyword arguments, where the keyword keys are field + names and the values are terms that must appear in the field. + + Returns a generator of dictionaries containing the stored fields of any + documents matching the keyword arguments. If you do not specify any + arguments (``Searcher.documents()``), this method will yield **all** + documents. + + >>> for stored_fields in searcher.documents(emailto=u"matt@whoosh.ca"): + ... print("Email subject:", stored_fields['subject']) + """ + + ixreader = self.ixreader + return (ixreader.stored_fields(docnum) + for docnum in self.document_numbers(**kw)) + + def _kw_to_text(self, kw): + for k, v in iteritems(kw): + field = self.schema[k] + kw[k] = field.to_bytes(v) + + def _query_for_kw(self, kw): + subqueries = [] + for key, value in iteritems(kw): + subqueries.append(query.Term(key, value)) + if subqueries: + q = query.And(subqueries).normalize() + else: + q = query.Every() + return q + + def document_number(self, **kw): + """Returns the document number of the document matching the given + keyword arguments, where the keyword keys are field names and the + values are terms that must appear in the field. + + >>> docnum = searcher.document_number(path=u"/a/b") + + Where Searcher.document_numbers() returns a generator, this function + returns either an int or None. Use it when you assume the given keyword + arguments either match zero or one documents (i.e. at least one of the + fields is a unique key). + + :rtype: int + """ + + # In the common case where only one keyword was given, just use + # first_id() instead of building a query. + + self._kw_to_text(kw) + if len(kw) == 1: + k, v = list(kw.items())[0] + try: + return self.reader().first_id(k, v) + except TermNotFound: + return None + else: + m = self._query_for_kw(kw).matcher(self, self.boolean_context()) + if m.is_active(): + return m.id() + + def document_numbers(self, **kw): + """Returns a generator of the document numbers for documents matching + the given keyword arguments, where the keyword keys are field names and + the values are terms that must appear in the field. If you do not + specify any arguments (``Searcher.document_numbers()``), this method + will yield **all** document numbers. + + >>> docnums = list(searcher.document_numbers(emailto="matt@whoosh.ca")) + """ + + self._kw_to_text(kw) + return self.docs_for_query(self._query_for_kw(kw)) + + def _find_unique(self, uniques): + # uniques is a list of ("unique_field_name", "field_value") tuples + delset = set() + for name, value in uniques: + docnum = self.document_number(**{name: value}) + if docnum is not None: + delset.add(docnum) + return delset + + def _query_to_comb(self, fq): + return BitSet(self.docs_for_query(fq), size=self.doc_count_all()) + + def _filter_to_comb(self, obj): + if obj is None: + return None + if isinstance(obj, (set, DocIdSet)): + c = obj + elif isinstance(obj, Results): + c = obj.docs() + elif isinstance(obj, ResultsPage): + c = obj.results.docs() + elif isinstance(obj, query.Query): + c = self._query_to_comb(obj) + else: + raise Exception("Don't know what to do with filter object %r" + % obj) + + return c + + def suggest(self, fieldname, text, limit=5, maxdist=2, prefix=0): + """Returns a sorted list of suggested corrections for the given + mis-typed word ``text`` based on the contents of the given field:: + + >>> searcher.suggest("content", "specail") + ["special"] + + This is a convenience method. If you are planning to get suggestions + for multiple words in the same field, it is more efficient to get a + :class:`~whoosh.spelling.Corrector` object and use it directly:: + + corrector = searcher.corrector("fieldname") + for word in words: + print(corrector.suggest(word)) + + :param limit: only return up to this many suggestions. If there are not + enough terms in the field within ``maxdist`` of the given word, the + returned list will be shorter than this number. + :param maxdist: the largest edit distance from the given word to look + at. Numbers higher than 2 are not very effective or efficient. + :param prefix: require suggestions to share a prefix of this length + with the given word. This is often justifiable since most + misspellings do not involve the first letter of the word. Using a + prefix dramatically decreases the time it takes to generate the + list of words. + """ + + c = self.reader().corrector(fieldname) + return c.suggest(text, limit=limit, maxdist=maxdist, prefix=prefix) + + def key_terms(self, docnums, fieldname, numterms=5, + model=classify.Bo1Model, normalize=True): + """Returns the 'numterms' most important terms from the documents + listed (by number) in 'docnums'. You can get document numbers for the + documents your interested in with the document_number() and + document_numbers() methods. + + "Most important" is generally defined as terms that occur frequently in + the top hits but relatively infrequently in the collection as a whole. + + >>> docnum = searcher.document_number(path=u"/a/b") + >>> keywords_and_scores = searcher.key_terms([docnum], "content") + + This method returns a list of ("term", score) tuples. The score may be + useful if you want to know the "strength" of the key terms, however to + just get the terms themselves you can just do this: + + >>> kws = [kw for kw, score in searcher.key_terms([docnum], "content")] + + :param fieldname: Look at the terms in this field. This field must + store vectors. + :param docnums: A sequence of document numbers specifying which + documents to extract key terms from. + :param numterms: Return this number of important terms. + :param model: The classify.ExpansionModel to use. See the classify + module. + :param normalize: normalize the scores. + :returns: a list of ("term", score) tuples. + """ + + expander = classify.Expander(self.ixreader, fieldname, model=model) + for docnum in docnums: + expander.add_document(docnum) + return expander.expanded_terms(numterms, normalize=normalize) + + def key_terms_from_text(self, fieldname, text, numterms=5, + model=classify.Bo1Model, normalize=True): + """Return the 'numterms' most important terms from the given text. + + :param numterms: Return this number of important terms. + :param model: The classify.ExpansionModel to use. See the classify + module. + """ + + expander = classify.Expander(self.ixreader, fieldname, model=model) + expander.add_text(text) + return expander.expanded_terms(numterms, normalize=normalize) + + def more_like(self, docnum, fieldname, text=None, top=10, numterms=5, + model=classify.Bo1Model, normalize=False, filter=None): + """Returns a :class:`Results` object containing documents similar to + the given document, based on "key terms" in the given field:: + + # Get the ID for the document you're interested in + docnum = search.document_number(path=u"/a/b/c") + + r = searcher.more_like(docnum) + + print("Documents like", searcher.stored_fields(docnum)["title"]) + for hit in r: + print(hit["title"]) + + :param fieldname: the name of the field to use to test similarity. + :param text: by default, the method will attempt to load the contents + of the field from the stored fields for the document, or from a + term vector. If the field isn't stored or vectored in the index, + but you have access to the text another way (for example, loading + from a file or a database), you can supply it using the ``text`` + parameter. + :param top: the number of results to return. + :param numterms: the number of "key terms" to extract from the hit and + search for. Using more terms is slower but gives potentially more + and more accurate results. + :param model: (expert) a :class:`whoosh.classify.ExpansionModel` to use + to compute "key terms". + :param normalize: whether to normalize term weights. + :param filter: a query, Results object, or set of docnums. The results + will only contain documents that are also in the filter object. + """ + + if text: + kts = self.key_terms_from_text(fieldname, text, numterms=numterms, + model=model, normalize=normalize) + else: + kts = self.key_terms([docnum], fieldname, numterms=numterms, + model=model, normalize=normalize) + # Create an Or query from the key terms + q = query.Or([query.Term(fieldname, word, boost=weight) + for word, weight in kts]) + + return self.search(q, limit=top, filter=filter, mask=set([docnum])) + + def search_page(self, query, pagenum, pagelen=10, **kwargs): + """This method is Like the :meth:`Searcher.search` method, but returns + a :class:`ResultsPage` object. This is a convenience function for + getting a certain "page" of the results for the given query, which is + often useful in web search interfaces. + + For example:: + + querystring = request.get("q") + query = queryparser.parse("content", querystring) + + pagenum = int(request.get("page", 1)) + pagelen = int(request.get("perpage", 10)) + + results = searcher.search_page(query, pagenum, pagelen=pagelen) + print("Page %d of %d" % (results.pagenum, results.pagecount)) + print("Showing results %d-%d of %d" + % (results.offset + 1, results.offset + results.pagelen + 1, + len(results))) + for hit in results: + print("%d: %s" % (hit.rank + 1, hit["title"])) + + (Note that results.pagelen might be less than the pagelen argument if + there aren't enough results to fill a page.) + + Any additional keyword arguments you supply are passed through to + :meth:`Searcher.search`. For example, you can get paged results of a + sorted search:: + + results = searcher.search_page(q, 2, sortedby="date", reverse=True) + + Currently, searching for page 100 with pagelen of 10 takes the same + amount of time as using :meth:`Searcher.search` to find the first 1000 + results. That is, this method does not have any special optimizations + or efficiencies for getting a page from the middle of the full results + list. (A future enhancement may allow using previous page results to + improve the efficiency of finding the next page.) + + This method will raise a ``ValueError`` if you ask for a page number + higher than the number of pages in the resulting query. + + :param query: the :class:`whoosh.query.Query` object to match. + :param pagenum: the page number to retrieve, starting at ``1`` for the + first page. + :param pagelen: the number of results per page. + :returns: :class:`ResultsPage` + """ + + if pagenum < 1: + raise ValueError("pagenum must be >= 1") + + results = self.search(query, limit=pagenum * pagelen, **kwargs) + return ResultsPage(results, pagenum, pagelen) + + def find(self, defaultfield, querystring, **kwargs): + from whoosh.qparser import QueryParser + qp = QueryParser(defaultfield, schema=self.ixreader.schema) + q = qp.parse(querystring) + return self.search(q, **kwargs) + + def docs_for_query(self, q, for_deletion=False): + """Returns an iterator of document numbers for documents matching the + given :class:`whoosh.query.Query` object. + """ + + # If we're getting the document numbers so we can delete them, use the + # deletion_docs method instead of docs; this lets special queries + # (e.g. nested queries) override what gets deleted + if for_deletion: + method = q.deletion_docs + else: + method = q.docs + + if self.subsearchers: + for s, offset in self.subsearchers: + for docnum in method(s): + yield docnum + offset + else: + for docnum in method(self): + yield docnum + + def collector(self, limit=10, sortedby=None, reverse=False, groupedby=None, + collapse=None, collapse_limit=1, collapse_order=None, + optimize=True, filter=None, mask=None, terms=False, + maptype=None, scored=True): + """Low-level method: returns a configured + :class:`whoosh.collectors.Collector` object based on the given + arguments. You can use this object with + :meth:`Searcher.search_with_collector` to search. + + See the documentation for the :meth:`Searcher.search` method for a + description of the parameters. + + This method may be useful to get a basic collector object and then wrap + it with another collector from ``whoosh.collectors`` or with a custom + collector of your own:: + + # Equivalent of + # results = mysearcher.search(myquery, limit=10) + # but with a time limt... + + # Create a TopCollector + c = mysearcher.collector(limit=10) + + # Wrap it with a TimeLimitedCollector with a time limit of + # 10.5 seconds + from whoosh.collectors import TimeLimitedCollector + c = TimeLimitCollector(c, 10.5) + + # Search using the custom collector + results = mysearcher.search_with_collector(myquery, c) + """ + + from whoosh import collectors + + if limit is not None and limit < 1: + raise ValueError("limit must be >= 1") + + if not scored and not sortedby: + c = collectors.UnsortedCollector() + elif sortedby: + c = collectors.SortingCollector(sortedby, limit=limit, + reverse=reverse) + elif groupedby or reverse or not limit or limit >= self.doc_count(): + # A collector that gathers every matching document + c = collectors.UnlimitedCollector(reverse=reverse) + else: + # A collector that uses block quality optimizations and a heap + # queue to only collect the top N documents + c = collectors.TopCollector(limit, usequality=optimize) + + if groupedby: + c = collectors.FacetCollector(c, groupedby, maptype=maptype) + if terms: + c = collectors.TermsCollector(c) + if collapse: + c = collectors.CollapseCollector(c, collapse, limit=collapse_limit, + order=collapse_order) + + # Filtering wraps last so it sees the docs first + if filter or mask: + c = collectors.FilterCollector(c, filter, mask) + return c + + def search(self, q, **kwargs): + """Runs a :class:`whoosh.query.Query` object on this searcher and + returns a :class:`Results` object. See :doc:`/searching` for more + information. + + This method takes many keyword arguments (documented below). + + See :doc:`/facets` for information on using ``sortedby`` and/or + ``groupedby``. See :ref:`collapsing` for more information on using + ``collapse``, ``collapse_limit``, and ``collapse_order``. + + :param query: a :class:`whoosh.query.Query` object to use to match + documents. + :param limit: the maximum number of documents to score. If you're only + interested in the top N documents, you can set limit=N to limit the + scoring for a faster search. Default is 10. + :param scored: whether to score the results. Overriden by ``sortedby``. + If both ``scored=False`` and ``sortedby=None``, the results will be + in arbitrary order, but will usually be computed faster than + scored or sorted results. + :param sortedby: see :doc:`/facets`. + :param reverse: Reverses the direction of the sort. Default is False. + :param groupedby: see :doc:`/facets`. + :param optimize: use optimizations to get faster results when possible. + Default is True. + :param filter: a query, Results object, or set of docnums. The results + will only contain documents that are also in the filter object. + :param mask: a query, Results object, or set of docnums. The results + will not contain any documents that are in the mask object. + :param terms: if True, record which terms were found in each matching + document. See :doc:`/searching` for more information. Default is + False. + :param maptype: by default, the results of faceting with ``groupedby`` + is a dictionary mapping group names to ordered lists of document + numbers in the group. You can pass a + :class:`whoosh.sorting.FacetMap` subclass to this keyword argument + to specify a different (usually faster) method for grouping. For + example, ``maptype=sorting.Count`` would store only the count of + documents in each group, instead of the full list of document IDs. + :param collapse: a :doc:`facet ` to use to collapse the + results. See :ref:`collapsing` for more information. + :param collapse_limit: the maximum number of documents to allow with + the same collapse key. See :ref:`collapsing` for more information. + :param collapse_order: an optional ordering :doc:`facet ` + to control which documents are kept when collapsing. The default + (``collapse_order=None``) uses the results order (e.g. the highest + scoring documents in a scored search). + :rtype: :class:`Results` + """ + + # Call the collector() method to build a collector based on the + # parameters passed to this method + c = self.collector(**kwargs) + # Call the lower-level method to run the collector + self.search_with_collector(q, c) + # Return the results object from the collector + return c.results() + + def search_with_collector(self, q, collector, context=None): + """Low-level method: runs a :class:`whoosh.query.Query` object on this + searcher using the given :class:`whoosh.collectors.Collector` object + to collect the results:: + + myquery = query.Term("content", "cabbage") + + uc = collectors.UnlimitedCollector() + tc = TermsCollector(uc) + + mysearcher.search_with_collector(myquery, tc) + print(tc.docterms) + print(tc.results()) + + Note that this method does not return a :class:`Results` object. You + need to access the collector to get a results object or other + information the collector might hold after the search. + + :param q: a :class:`whoosh.query.Query` object to use to match + documents. + :param collector: a :class:`whoosh.collectors.Collector` object to feed + the results into. + """ + + # Get the search context object from the searcher + context = context or self.context() + # Allow collector to set up based on the top-level information + collector.prepare(self, q, context) + + collector.run() + + def correct_query(self, q, qstring, correctors=None, terms=None, maxdist=2, + prefix=0, aliases=None): + """ + Returns a corrected version of the given user query using a default + :class:`whoosh.spelling.ReaderCorrector`. + + The default: + + * Corrects any words that don't appear in the index. + + * Takes suggestions from the words in the index. To make certain fields + use custom correctors, use the ``correctors`` argument to pass a + dictionary mapping field names to :class:`whoosh.spelling.Corrector` + objects. + + Expert users who want more sophisticated correction behavior can create + a custom :class:`whoosh.spelling.QueryCorrector` and use that instead + of this method. + + Returns a :class:`whoosh.spelling.Correction` object with a ``query`` + attribute containing the corrected :class:`whoosh.query.Query` object + and a ``string`` attributes containing the corrected query string. + + >>> from whoosh import qparser, highlight + >>> qtext = 'mary "litle lamb"' + >>> q = qparser.QueryParser("text", myindex.schema) + >>> mysearcher = myindex.searcher() + >>> correction = mysearcher().correct_query(q, qtext) + >>> correction.query + + >>> correction.string + 'mary "little lamb"' + >>> mysearcher.close() + + You can use the ``Correction`` object's ``format_string`` method to + format the corrected query string using a + :class:`whoosh.highlight.Formatter` object. For example, you can format + the corrected string as HTML, emphasizing the changed words. + + >>> hf = highlight.HtmlFormatter(classname="change") + >>> correction.format_string(hf) + 'mary "little lamb"' + + :param q: the :class:`whoosh.query.Query` object to correct. + :param qstring: the original user query from which the query object was + created. You can pass None instead of a string, in which the + second item in the returned tuple will also be None. + :param correctors: an optional dictionary mapping fieldnames to + :class:`whoosh.spelling.Corrector` objects. By default, this method + uses the contents of the index to spell check the terms in the + query. You can use this argument to "override" some fields with a + different correct, for example a + :class:`whoosh.spelling.GraphCorrector`. + :param terms: a sequence of ``("fieldname", "text")`` tuples to correct + in the query. By default, this method corrects terms that don't + appear in the index. You can use this argument to override that + behavior and explicitly specify the terms that should be corrected. + :param maxdist: the maximum number of "edits" (insertions, deletions, + subsitutions, or transpositions of letters) allowed between the + original word and any suggestion. Values higher than ``2`` may be + slow. + :param prefix: suggested replacement words must share this number of + initial characters with the original word. Increasing this even to + just ``1`` can dramatically speed up suggestions, and may be + justifiable since spellling mistakes rarely involve the first + letter of a word. + :param aliases: an optional dictionary mapping field names in the query + to different field names to use as the source of spelling + suggestions. The mappings in ``correctors`` are applied after this. + :rtype: :class:`whoosh.spelling.Correction` + """ + + reader = self.reader() + + # Dictionary of field name alias mappings + if aliases is None: + aliases = {} + # Dictionary of custom per-field correctors + if correctors is None: + correctors = {} + + # Remap correctors dict according to aliases + d = {} + for fieldname, corr in iteritems(correctors): + fieldname = aliases.get(fieldname, fieldname) + d[fieldname] = corr + correctors = d + + # Fill in default corrector objects for fields that don't have a custom + # one in the "correctors" dictionary + fieldnames = self.schema.names() + for fieldname in fieldnames: + fieldname = aliases.get(fieldname, fieldname) + if fieldname not in correctors: + correctors[fieldname] = self.reader().corrector(fieldname) + + # Get any missing terms in the query in the fields we're correcting + if terms is None: + terms = [] + for token in q.all_tokens(): + aname = aliases.get(token.fieldname, token.fieldname) + text = token.text + if aname in correctors and (aname, text) not in reader: + # Note that we use the original, not aliases fieldname here + # so if we correct the query we know what it was + terms.append((token.fieldname, token.text)) + + # Make q query corrector + from whoosh import spelling + sqc = spelling.SimpleQueryCorrector(correctors, terms, aliases) + return sqc.correct_query(q, qstring) + + +class Results(object): + """This object is returned by a Searcher. This object represents the + results of a search query. You can mostly use it as if it was a list of + dictionaries, where each dictionary is the stored fields of the document at + that position in the results. + + Note that a Results object keeps a reference to the Searcher that created + it, so keeping a reference to a Results object keeps the Searcher alive and + so keeps all files used by it open. + """ + + def __init__(self, searcher, q, top_n, docset=None, facetmaps=None, + runtime=0, highlighter=None): + """ + :param searcher: the :class:`Searcher` object that produced these + results. + :param query: the original query that created these results. + :param top_n: a list of (score, docnum) tuples representing the top + N search results. + """ + + self.searcher = searcher + self.q = q + self.top_n = top_n + self.docset = docset + self._facetmaps = facetmaps or {} + self.runtime = runtime + self.highlighter = highlighter or highlight.Highlighter() + self.collector = None + self._total = None + self._char_cache = {} + + def __repr__(self): + return "" % (len(self.top_n), + self.q, + self.runtime) + + def __len__(self): + """Returns the total number of documents that matched the query. Note + this may be more than the number of scored documents, given the value + of the ``limit`` keyword argument to :meth:`Searcher.search`. + + If this Results object was created by searching with a ``limit`` + keyword, then computing the exact length of the result set may be + expensive for large indexes or large result sets. You may consider + using :meth:`Results.has_exact_length`, + :meth:`Results.estimated_length`, and + :meth:`Results.estimated_min_length` to display an estimated size of + the result set instead of an exact number. + """ + + if self._total is None: + self._total = self.collector.count() + return self._total + + def __getitem__(self, n): + if isinstance(n, slice): + start, stop, step = n.indices(len(self.top_n)) + return [Hit(self, self.top_n[i][1], i, self.top_n[i][0]) + for i in xrange(start, stop, step)] + else: + if n >= len(self.top_n): + raise IndexError("results[%r]: Results only has %s hits" + % (n, len(self.top_n))) + return Hit(self, self.top_n[n][1], n, self.top_n[n][0]) + + def __iter__(self): + """Yields a :class:`Hit` object for each result in ranked order. + """ + + for i in xrange(len(self.top_n)): + yield Hit(self, self.top_n[i][1], i, self.top_n[i][0]) + + def __contains__(self, docnum): + """Returns True if the given document number matched the query. + """ + + return docnum in self.docs() + + def __nonzero__(self): + return not self.is_empty() + + __bool__ = __nonzero__ + + def is_empty(self): + """Returns True if not documents matched the query. + """ + + return self.scored_length() == 0 + + def items(self): + """Returns an iterator of (docnum, score) pairs for the scored + documents in the results. + """ + + return ((docnum, score) for score, docnum in self.top_n) + + def fields(self, n): + """Returns the stored fields for the document at the ``n`` th position + in the results. Use :meth:`Results.docnum` if you want the raw + document number instead of the stored fields. + """ + + return self.searcher.stored_fields(self.top_n[n][1]) + + def facet_names(self): + """Returns the available facet names, for use with the ``groups()`` + method. + """ + + return self._facetmaps.keys() + + def groups(self, name=None): + """If you generated facet groupings for the results using the + `groupedby` keyword argument to the ``search()`` method, you can use + this method to retrieve the groups. You can use the ``facet_names()`` + method to get the list of available facet names. + + >>> results = searcher.search(my_query, groupedby=["tag", "price"]) + >>> results.facet_names() + ["tag", "price"] + >>> results.groups("tag") + {"new": [12, 1, 4], "apple": [3, 10, 5], "search": [11]} + + If you only used one facet, you can call the method without a facet + name to get the groups for the facet. + + >>> results = searcher.search(my_query, groupedby="tag") + >>> results.groups() + {"new": [12, 1, 4], "apple": [3, 10, 5, 0], "search": [11]} + + By default, this returns a dictionary mapping category names to a list + of document numbers, in the same relative order as they appear in the + results. + + >>> results = mysearcher.search(myquery, groupedby="tag") + >>> docnums = results.groups() + >>> docnums['new'] + [12, 1, 4] + + You can then use :meth:`Searcher.stored_fields` to get the stored + fields associated with a document ID. + + If you specified a different ``maptype`` for the facet when you + searched, the values in the dictionary depend on the + :class:`whoosh.sorting.FacetMap`. + + >>> myfacet = sorting.FieldFacet("tag", maptype=sorting.Count) + >>> results = mysearcher.search(myquery, groupedby=myfacet) + >>> counts = results.groups() + {"new": 3, "apple": 4, "search": 1} + """ + + if (name is None or name == "facet") and len(self._facetmaps) == 1: + # If there's only one facet, just use it; convert keys() to list + # for Python 3 + name = list(self._facetmaps.keys())[0] + elif name not in self._facetmaps: + raise KeyError("%r not in facet names %r" + % (name, self.facet_names())) + return self._facetmaps[name].as_dict() + + def has_exact_length(self): + """Returns True if this results object already knows the exact number + of matching documents. + """ + + if self.collector: + return self.collector.computes_count() + else: + return self._total is not None + + def estimated_length(self): + """The estimated maximum number of matching documents, or the + exact number of matching documents if it's known. + """ + + if self.has_exact_length(): + return len(self) + else: + return self.q.estimate_size(self.searcher.reader()) + + def estimated_min_length(self): + """The estimated minimum number of matching documents, or the + exact number of matching documents if it's known. + """ + + if self.has_exact_length(): + return len(self) + else: + return self.q.estimate_min_size(self.searcher.reader()) + + def scored_length(self): + """Returns the number of scored documents in the results, equal to or + less than the ``limit`` keyword argument to the search. + + >>> r = mysearcher.search(myquery, limit=20) + >>> len(r) + 1246 + >>> r.scored_length() + 20 + + This may be fewer than the total number of documents that match the + query, which is what ``len(Results)`` returns. + """ + + return len(self.top_n) + + def docs(self): + """Returns a set-like object containing the document numbers that + matched the query. + """ + + if self.docset is None: + self.docset = set(self.collector.all_ids()) + return self.docset + + def copy(self): + """Returns a deep copy of this results object. + """ + + # Shallow copy self to get attributes + r = copy.copy(self) + # Deep copies of docset and top_n in case they're modified + r.docset = copy.deepcopy(self.docset) + r.top_n = copy.deepcopy(self.top_n) + return r + + def score(self, n): + """Returns the score for the document at the Nth position in the list + of ranked documents. If the search was not scored, this may return + None. + """ + + return self.top_n[n][0] + + def docnum(self, n): + """Returns the document number of the result at position n in the list + of ranked documents. + """ + return self.top_n[n][1] + + def query_terms(self, expand=False, fieldname=None): + return self.q.existing_terms(self.searcher.reader(), + fieldname=fieldname, expand=expand) + + def has_matched_terms(self): + """Returns True if the search recorded which terms matched in which + documents. + + >>> r = searcher.search(myquery) + >>> r.has_matched_terms() + False + >>> + """ + + return hasattr(self, "docterms") and hasattr(self, "termdocs") + + def matched_terms(self): + """Returns the set of ``("fieldname", "text")`` tuples representing + terms from the query that matched one or more of the TOP N documents + (this does not report terms for documents that match the query but did + not score high enough to make the top N results). You can compare this + set to the terms from the original query to find terms which didn't + occur in any matching documents. + + This is only valid if you used ``terms=True`` in the search call to + record matching terms. Otherwise it will raise an exception. + + >>> q = myparser.parse("alfa OR bravo OR charlie") + >>> results = searcher.search(q, terms=True) + >>> results.terms() + set([("content", "alfa"), ("content", "charlie")]) + >>> q.all_terms() - results.terms() + set([("content", "bravo")]) + """ + + if not self.has_matched_terms(): + raise NoTermsException + return set(self.termdocs.keys()) + + def _get_fragmenter(self): + return self.highlighter.fragmenter + + def _set_fragmenter(self, f): + self.highlighter.fragmenter = f + + fragmenter = property(_get_fragmenter, _set_fragmenter) + + def _get_formatter(self): + return self.highlighter.formatter + + def _set_formatter(self, f): + self.highlighter.formatter = f + + formatter = property(_get_formatter, _set_formatter) + + def _get_scorer(self): + return self.highlighter.scorer + + def _set_scorer(self, s): + self.highlighter.scorer = s + + scorer = property(_get_scorer, _set_scorer) + + def _get_order(self): + return self.highlighter.order + + def _set_order(self, o): + self.highlighter.order = o + + order = property(_get_order, _set_order) + + def key_terms(self, fieldname, docs=10, numterms=5, + model=classify.Bo1Model, normalize=True): + """Returns the 'numterms' most important terms from the top 'docs' + documents in these results. "Most important" is generally defined as + terms that occur frequently in the top hits but relatively infrequently + in the collection as a whole. + + :param fieldname: Look at the terms in this field. This field must + store vectors. + :param docs: Look at this many of the top documents of the results. + :param numterms: Return this number of important terms. + :param model: The classify.ExpansionModel to use. See the classify + module. + :returns: list of unicode strings. + """ + + if not len(self): + return [] + docs = min(docs, len(self)) + + reader = self.searcher.reader() + + expander = classify.Expander(reader, fieldname, model=model) + for _, docnum in self.top_n[:docs]: + expander.add_document(docnum) + + return expander.expanded_terms(numterms, normalize=normalize) + + def extend(self, results): + """Appends hits from 'results' (that are not already in this + results object) to the end of these results. + + :param results: another results object. + """ + + docs = self.docs() + for item in results.top_n: + if item[1] not in docs: + self.top_n.append(item) + self.docset = docs | results.docs() + self._total = len(self.docset) + + def filter(self, results): + """Removes any hits that are not also in the other results object. + """ + + if not len(results): + return + + otherdocs = results.docs() + items = [item for item in self.top_n if item[1] in otherdocs] + self.docset = self.docs() & otherdocs + self.top_n = items + + def upgrade(self, results, reverse=False): + """Re-sorts the results so any hits that are also in 'results' appear + before hits not in 'results', otherwise keeping their current relative + positions. This does not add the documents in the other results object + to this one. + + :param results: another results object. + :param reverse: if True, lower the position of hits in the other + results object instead of raising them. + """ + + if not len(results): + return + + otherdocs = results.docs() + arein = [item for item in self.top_n if item[1] in otherdocs] + notin = [item for item in self.top_n if item[1] not in otherdocs] + + if reverse: + items = notin + arein + else: + items = arein + notin + + self.top_n = items + + def upgrade_and_extend(self, results): + """Combines the effects of extend() and upgrade(): hits that are also + in 'results' are raised. Then any hits from the other results object + that are not in this results object are appended to the end. + + :param results: another results object. + """ + + if not len(results): + return + + docs = self.docs() + otherdocs = results.docs() + + arein = [item for item in self.top_n if item[1] in otherdocs] + notin = [item for item in self.top_n if item[1] not in otherdocs] + other = [item for item in results.top_n if item[1] not in docs] + + self.docset = docs | otherdocs + self.top_n = arein + notin + other + + +class Hit(object): + """Represents a single search result ("hit") in a Results object. + + This object acts like a dictionary of the matching document's stored + fields. If for some reason you need an actual ``dict`` object, use + ``Hit.fields()`` to get one. + + >>> r = searcher.search(query.Term("content", "render")) + >>> r[0] + < Hit {title = u"Rendering the scene"} > + >>> r[0].rank + 0 + >>> r[0].docnum == 4592 + True + >>> r[0].score + 2.52045682 + >>> r[0]["title"] + "Rendering the scene" + >>> r[0].keys() + ["title"] + """ + + def __init__(self, results, docnum, pos=None, score=None): + """ + :param results: the Results object this hit belongs to. + :param pos: the position in the results list of this hit, for example + pos = 0 means this is the first (highest scoring) hit. + :param docnum: the document number of this hit. + :param score: the score of this hit. + """ + + self.results = results + self.searcher = results.searcher + self.reader = self.searcher.reader() + self.pos = self.rank = pos + self.docnum = docnum + self.score = score + self._fields = None + + def fields(self): + """Returns a dictionary of the stored fields of the document this + object represents. + """ + + if self._fields is None: + self._fields = self.searcher.stored_fields(self.docnum) + return self._fields + + def matched_terms(self): + """Returns the set of ``("fieldname", "text")`` tuples representing + terms from the query that matched in this document. You can + compare this set to the terms from the original query to find terms + which didn't occur in this document. + + This is only valid if you used ``terms=True`` in the search call to + record matching terms. Otherwise it will raise an exception. + + >>> q = myparser.parse("alfa OR bravo OR charlie") + >>> results = searcher.search(q, terms=True) + >>> for hit in results: + ... print(hit["title"]) + ... print("Contains:", hit.matched_terms()) + ... print("Doesn't contain:", q.all_terms() - hit.matched_terms()) + """ + + if not self.results.has_matched_terms(): + raise NoTermsException + return self.results.docterms.get(self.docnum, []) + + def highlights(self, fieldname, text=None, top=3, minscore=1): + """Returns highlighted snippets from the given field:: + + r = searcher.search(myquery) + for hit in r: + print(hit["title"]) + print(hit.highlights("content")) + + See :doc:`/highlight`. + + To change the fragmeter, formatter, order, or scorer used in + highlighting, you can set attributes on the results object:: + + from whoosh import highlight + + results = searcher.search(myquery, terms=True) + results.fragmenter = highlight.SentenceFragmenter() + + ...or use a custom :class:`whoosh.highlight.Highlighter` object:: + + hl = highlight.Highlighter(fragmenter=sf) + results.highlighter = hl + + :param fieldname: the name of the field you want to highlight. + :param text: by default, the method will attempt to load the contents + of the field from the stored fields for the document. If the field + you want to highlight isn't stored in the index, but you have + access to the text another way (for example, loading from a file or + a database), you can supply it using the ``text`` parameter. + :param top: the maximum number of fragments to return. + :param minscore: the minimum score for fragments to appear in the + highlights. + """ + + hliter = self.results.highlighter + return hliter.highlight_hit(self, fieldname, text=text, top=top, + minscore=minscore) + + def more_like_this(self, fieldname, text=None, top=10, numterms=5, + model=classify.Bo1Model, normalize=True, filter=None): + """Returns a new Results object containing documents similar to this + hit, based on "key terms" in the given field:: + + r = searcher.search(myquery) + for hit in r: + print(hit["title"]) + print("Top 3 similar documents:") + for subhit in hit.more_like_this("content", top=3): + print(" ", subhit["title"]) + + :param fieldname: the name of the field to use to test similarity. + :param text: by default, the method will attempt to load the contents + of the field from the stored fields for the document, or from a + term vector. If the field isn't stored or vectored in the index, + but you have access to the text another way (for example, loading + from a file or a database), you can supply it using the ``text`` + parameter. + :param top: the number of results to return. + :param numterms: the number of "key terms" to extract from the hit and + search for. Using more terms is slower but gives potentially more + and more accurate results. + :param model: (expert) a :class:`whoosh.classify.ExpansionModel` to use + to compute "key terms". + :param normalize: whether to normalize term weights. + """ + + return self.searcher.more_like(self.docnum, fieldname, text=text, + top=top, numterms=numterms, model=model, + normalize=normalize, filter=filter) + + def __repr__(self): + return "<%s %r>" % (self.__class__.__name__, self.fields()) + + def __eq__(self, other): + if isinstance(other, Hit): + return self.fields() == other.fields() + elif isinstance(other, dict): + return self.fields() == other + else: + return False + + def __len__(self): + return len(self.fields()) + + def __iter__(self): + return iterkeys(self.fields()) + + def __getitem__(self, fieldname): + if fieldname in self.fields(): + return self._fields[fieldname] + + reader = self.reader + if reader.has_column(fieldname): + cr = reader.column_reader(fieldname) + return cr[self.docnum] + + raise KeyError(fieldname) + + def __contains__(self, key): + return (key in self.fields() + or self.reader.has_column(key)) + + def items(self): + return list(self.fields().items()) + + def keys(self): + return list(self.fields().keys()) + + def values(self): + return list(self.fields().values()) + + def iteritems(self): + return iteritems(self.fields()) + + def iterkeys(self): + return iterkeys(self.fields()) + + def itervalues(self): + return itervalues(self.fields()) + + def get(self, key, default=None): + return self.fields().get(key, default) + + def __setitem__(self, key, value): + raise NotImplementedError("You cannot modify a search result") + + def __delitem__(self, key, value): + raise NotImplementedError("You cannot modify a search result") + + def clear(self): + raise NotImplementedError("You cannot modify a search result") + + def update(self, dict=None, **kwargs): + raise NotImplementedError("You cannot modify a search result") + + +class ResultsPage(object): + """Represents a single page out of a longer list of results, as returned + by :func:`whoosh.searching.Searcher.search_page`. Supports a subset of the + interface of the :class:`~whoosh.searching.Results` object, namely getting + stored fields with __getitem__ (square brackets), iterating, and the + ``score()`` and ``docnum()`` methods. + + The ``offset`` attribute contains the results number this page starts at + (numbered from 0). For example, if the page length is 10, the ``offset`` + attribute on the second page will be ``10``. + + The ``pagecount`` attribute contains the number of pages available. + + The ``pagenum`` attribute contains the page number. This may be less than + the page you requested if the results had too few pages. For example, if + you do:: + + ResultsPage(results, 5) + + but the results object only contains 3 pages worth of hits, ``pagenum`` + will be 3. + + The ``pagelen`` attribute contains the number of results on this page + (which may be less than the page length you requested if this is the last + page of the results). + + The ``total`` attribute contains the total number of hits in the results. + + >>> mysearcher = myindex.searcher() + >>> pagenum = 2 + >>> page = mysearcher.find_page(pagenum, myquery) + >>> print("Page %s of %s, results %s to %s of %s" % + ... (pagenum, page.pagecount, page.offset+1, + ... page.offset+page.pagelen, page.total)) + >>> for i, fields in enumerate(page): + ... print("%s. %r" % (page.offset + i + 1, fields)) + >>> mysearcher.close() + + To set highlighter attributes (for example ``formatter``), access the + underlying :class:`Results` object:: + + page.results.formatter = highlight.UppercaseFormatter() + + """ + + def __init__(self, results, pagenum, pagelen=10): + """ + :param results: a :class:`~whoosh.searching.Results` object. + :param pagenum: which page of the results to use, numbered from ``1``. + :param pagelen: the number of hits per page. + """ + + self.results = results + self.total = len(results) + + if pagenum < 1: + raise ValueError("pagenum must be >= 1") + + self.pagecount = int(ceil(self.total / pagelen)) + self.pagenum = min(self.pagecount, pagenum) + + offset = (self.pagenum - 1) * pagelen + if (offset + pagelen) > self.total: + pagelen = self.total - offset + self.offset = offset + self.pagelen = pagelen + + def __getitem__(self, n): + offset = self.offset + if isinstance(n, slice): + start, stop, step = n.indices(self.pagelen) + return self.results.__getitem__(slice(start + offset, + stop + offset, step)) + else: + return self.results.__getitem__(n + offset) + + def __iter__(self): + return iter(self.results[self.offset:self.offset + self.pagelen]) + + def __len__(self): + return self.total + + def scored_length(self): + return self.results.scored_length() + + def score(self, n): + """Returns the score of the hit at the nth position on this page. + """ + return self.results.score(n + self.offset) + + def docnum(self, n): + """Returns the document number of the hit at the nth position on this + page. + """ + return self.results.docnum(n + self.offset) + + def is_last_page(self): + """Returns True if this object represents the last page of results. + """ + + return self.pagecount == 0 or self.pagenum == self.pagecount diff --git a/nstock/modules/whoosh/sorting.py b/nstock/modules/whoosh/sorting.py new file mode 100644 index 0000000..4935bf6 --- /dev/null +++ b/nstock/modules/whoosh/sorting.py @@ -0,0 +1,1156 @@ +# Copyright 2011 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from array import array +from collections import defaultdict + +from whoosh.compat import string_type +from whoosh.compat import iteritems, izip, xrange + + +# Faceting objects + +class FacetType(object): + """Base class for "facets", aspects that can be sorted/faceted. + """ + + maptype = None + + def categorizer(self, global_searcher): + """Returns a :class:`Categorizer` corresponding to this facet. + + :param global_searcher: A parent searcher. You can use this searcher if + you need global document ID references. + """ + + raise NotImplementedError + + def map(self, default=None): + t = self.maptype + if t is None: + t = default + + if t is None: + return OrderedList() + elif type(t) is type: + return t() + else: + return t + + def default_name(self): + return "facet" + + +class Categorizer(object): + """Base class for categorizer objects which compute a key value for a + document based on certain criteria, for use in sorting/faceting. + + Categorizers are created by FacetType objects through the + :meth:`FacetType.categorizer` method. The + :class:`whoosh.searching.Searcher` object passed to the ``categorizer`` + method may be a composite searcher (that is, wrapping a multi-reader), but + categorizers are always run **per-segment**, with segment-relative document + numbers. + + The collector will call a categorizer's ``set_searcher`` method as it + searches each segment to let the cateogorizer set up whatever segment- + specific data it needs. + + ``Collector.allow_overlap`` should be ``True`` if the caller can use the + ``keys_for`` method instead of ``key_for`` to group documents into + potentially overlapping groups. The default is ``False``. + + If a categorizer subclass can categorize the document using only the + document number, it should set ``Collector.needs_current`` to ``False`` + (this is the default) and NOT USE the given matcher in the ``key_for`` or + ``keys_for`` methods, since in that case ``segment_docnum`` is not + guaranteed to be consistent with the given matcher. If a categorizer + subclass needs to access information on the matcher, it should set + ``needs_current`` to ``True``. This will prevent the caller from using + optimizations that might leave the matcher in an inconsistent state. + """ + + allow_overlap = False + needs_current = False + + def set_searcher(self, segment_searcher, docoffset): + """Called by the collector when the collector moves to a new segment. + The ``segment_searcher`` will be atomic. The ``docoffset`` is the + offset of the segment's document numbers relative to the entire index. + You can use the offset to get absolute index docnums by adding the + offset to segment-relative docnums. + """ + + pass + + def key_for(self, matcher, segment_docnum): + """Returns a key for the current match. + + :param matcher: a :class:`whoosh.matching.Matcher` object. If + ``self.needs_current`` is ``False``, DO NOT use this object, + since it may be inconsistent. Use the given ``segment_docnum`` + instead. + :param segment_docnum: the segment-relative document number of the + current match. + """ + + # Backwards compatibility + if hasattr(self, "key_for_id"): + return self.key_for_id(segment_docnum) + elif hasattr(self, "key_for_matcher"): + return self.key_for_matcher(matcher) + + raise NotImplementedError(self.__class__) + + def keys_for(self, matcher, segment_docnum): + """Yields a series of keys for the current match. + + This method will be called instead of ``key_for`` if + ``self.allow_overlap`` is ``True``. + + :param matcher: a :class:`whoosh.matching.Matcher` object. If + ``self.needs_current`` is ``False``, DO NOT use this object, + since it may be inconsistent. Use the given ``segment_docnum`` + instead. + :param segment_docnum: the segment-relative document number of the + current match. + """ + + # Backwards compatibility + if hasattr(self, "keys_for_id"): + return self.keys_for_id(segment_docnum) + + raise NotImplementedError(self.__class__) + + def key_to_name(self, key): + """Returns a representation of the key to be used as a dictionary key + in faceting. For example, the sorting key for date fields is a large + integer; this method translates it into a ``datetime`` object to make + the groupings clearer. + """ + + return key + + +# General field facet + +class FieldFacet(FacetType): + """Sorts/facets by the contents of a field. + + For example, to sort by the contents of the "path" field in reverse order, + and facet by the contents of the "tag" field:: + + paths = FieldFacet("path", reverse=True) + tags = FieldFacet("tag") + results = searcher.search(myquery, sortedby=paths, groupedby=tags) + + This facet returns different categorizers based on the field type. + """ + + def __init__(self, fieldname, reverse=False, allow_overlap=False, + maptype=None): + """ + :param fieldname: the name of the field to sort/facet on. + :param reverse: if True, when sorting, reverse the sort order of this + facet. + :param allow_overlap: if True, when grouping, allow documents to appear + in multiple groups when they have multiple terms in the field. + """ + + self.fieldname = fieldname + self.reverse = reverse + self.allow_overlap = allow_overlap + self.maptype = maptype + + def default_name(self): + return self.fieldname + + def categorizer(self, global_searcher): + # The searcher we're passed here may wrap a multireader, but the + # actual key functions will always be called per-segment following a + # Categorizer.set_searcher method call + fieldname = self.fieldname + fieldobj = global_searcher.schema[fieldname] + + # If we're grouping with allow_overlap=True, all we can use is + # OverlappingCategorizer + if self.allow_overlap: + return OverlappingCategorizer(global_searcher, fieldname) + + if global_searcher.reader().has_column(fieldname): + coltype = fieldobj.column_type + if coltype.reversible or not self.reverse: + c = ColumnCategorizer(global_searcher, fieldname, self.reverse) + else: + c = ReversedColumnCategorizer(global_searcher, fieldname) + else: + c = PostingCategorizer(global_searcher, fieldname, + self.reverse) + return c + + +class ColumnCategorizer(Categorizer): + def __init__(self, global_searcher, fieldname, reverse=False): + self._fieldname = fieldname + self._fieldobj = global_searcher.schema[self._fieldname] + self._column_type = self._fieldobj.column_type + self._reverse = reverse + + # The column reader is set in set_searcher() as we iterate over the + # sub-searchers + self._creader = None + + def __repr__(self): + return "%s(%r, %r, reverse=%r)" % (self.__class__.__name__, + self._fieldobj, self._fieldname, + self._reverse) + + def set_searcher(self, segment_searcher, docoffset): + r = segment_searcher.reader() + self._creader = r.column_reader(self._fieldname, + reverse=self._reverse, + translate=False) + + def key_for(self, matcher, segment_docnum): + return self._creader.sort_key(segment_docnum) + + def key_to_name(self, key): + return self._fieldobj.from_column_value(key) + + +class ReversedColumnCategorizer(ColumnCategorizer): + """Categorizer that reverses column values for columns that aren't + naturally reversible. + """ + + def __init__(self, global_searcher, fieldname): + ColumnCategorizer.__init__(self, global_searcher, fieldname) + + reader = global_searcher.reader() + self._doccount = reader.doc_count_all() + + global_creader = reader.column_reader(fieldname, translate=False) + self._values = sorted(set(global_creader)) + + def key_for(self, matcher, segment_docnum): + value = self._creader[segment_docnum] + order = self._values.index(value) + # Subtract from 0 to reverse the order + return 0 - order + + def key_to_name(self, key): + # Re-reverse the key to get the index into _values + key = self._values[0 - key] + return ColumnCategorizer.key_to_name(self, key) + + +class OverlappingCategorizer(Categorizer): + allow_overlap = True + + def __init__(self, global_searcher, fieldname): + self._fieldname = fieldname + self._fieldobj = global_searcher.schema[fieldname] + + field = global_searcher.schema[fieldname] + reader = global_searcher.reader() + self._use_vectors = bool(field.vector) + self._use_column = (reader.has_column(fieldname) + and field.column_type.stores_lists()) + + # These are set in set_searcher() as we iterate over the sub-searchers + self._segment_searcher = None + self._creader = None + self._lists = None + + def set_searcher(self, segment_searcher, docoffset): + fieldname = self._fieldname + self._segment_searcher = segment_searcher + reader = segment_searcher.reader() + + if self._use_vectors: + pass + elif self._use_column: + self._creader = reader.column_reader(fieldname, translate=False) + else: + # Otherwise, cache the values in each document in a huge list + # of lists + dc = segment_searcher.doc_count_all() + field = segment_searcher.schema[fieldname] + from_bytes = field.from_bytes + + self._lists = [[] for _ in xrange(dc)] + for btext in field.sortable_terms(reader, fieldname): + text = from_bytes(btext) + postings = reader.postings(fieldname, btext) + for docid in postings.all_ids(): + self._lists[docid].append(text) + + def keys_for(self, matcher, docid): + if self._use_vectors: + try: + v = self._segment_searcher.vector(docid, self._fieldname) + return list(v.all_ids()) + except KeyError: + return [] + elif self._use_column: + return self._creader[docid] + else: + return self._lists[docid] or [None] + + def key_for(self, matcher, docid): + if self._use_vectors: + try: + v = self._segment_searcher.vector(docid, self._fieldname) + return v.id() + except KeyError: + return None + elif self._use_column: + return self._creader.sort_key(docid) + else: + ls = self._lists[docid] + if ls: + return ls[0] + else: + return None + + +class PostingCategorizer(Categorizer): + """ + Categorizer for fields that don't store column values. This is very + inefficient. Instead of relying on this categorizer you should plan for + which fields you'll want to sort on and set ``sortable=True`` in their + field type. + + This object builds an array caching the order of all documents according to + the field, then uses the cached order as a numeric key. This is useful when + a field cache is not available, and also for reversed fields (since field + cache keys for non- numeric fields are arbitrary data, it's not possible to + "negate" them to reverse the sort order). + """ + + def __init__(self, global_searcher, fieldname, reverse): + self.reverse = reverse + + if fieldname in global_searcher._field_caches: + self.values, self.array = global_searcher._field_caches[fieldname] + else: + # Cache the relative positions of all docs with the given field + # across the entire index + reader = global_searcher.reader() + dc = reader.doc_count_all() + self._fieldobj = global_searcher.schema[fieldname] + from_bytes = self._fieldobj.from_bytes + + self.values = [] + self.array = array("i", [dc + 1] * dc) + + btexts = self._fieldobj.sortable_terms(reader, fieldname) + for i, btext in enumerate(btexts): + self.values.append(from_bytes(btext)) + # Get global docids from global reader + postings = reader.postings(fieldname, btext) + for docid in postings.all_ids(): + self.array[docid] = i + + global_searcher._field_caches[fieldname] = (self.values, self.array) + + def set_searcher(self, segment_searcher, docoffset): + self._searcher = segment_searcher + self.docoffset = docoffset + + def key_for(self, matcher, segment_docnum): + global_docnum = self.docoffset + segment_docnum + i = self.array[global_docnum] + if self.reverse: + i = len(self.values) - i + return i + + def key_to_name(self, i): + if i >= len(self.values): + return None + if self.reverse: + i = len(self.values) - i + return self.values[i] + + +# Special facet types + +class QueryFacet(FacetType): + """Sorts/facets based on the results of a series of queries. + """ + + def __init__(self, querydict, other=None, allow_overlap=False, + maptype=None): + """ + :param querydict: a dictionary mapping keys to + :class:`whoosh.query.Query` objects. + :param other: the key to use for documents that don't match any of the + queries. + """ + + self.querydict = querydict + self.other = other + self.maptype = maptype + self.allow_overlap = allow_overlap + + def categorizer(self, global_searcher): + return self.QueryCategorizer(self.querydict, self.other, self.allow_overlap) + + class QueryCategorizer(Categorizer): + def __init__(self, querydict, other, allow_overlap=False): + self.querydict = querydict + self.other = other + self.allow_overlap = allow_overlap + + def set_searcher(self, segment_searcher, offset): + self.docsets = {} + for qname, q in self.querydict.items(): + docset = set(q.docs(segment_searcher)) + if docset: + self.docsets[qname] = docset + self.offset = offset + + def key_for(self, matcher, docid): + for qname in self.docsets: + if docid in self.docsets[qname]: + return qname + return self.other + + def keys_for(self, matcher, docid): + found = False + for qname in self.docsets: + if docid in self.docsets[qname]: + yield qname + found = True + if not found: + yield None + + +class RangeFacet(QueryFacet): + """Sorts/facets based on numeric ranges. For textual ranges, use + :class:`QueryFacet`. + + For example, to facet the "price" field into $100 buckets, up to $1000:: + + prices = RangeFacet("price", 0, 1000, 100) + results = searcher.search(myquery, groupedby=prices) + + The ranges/buckets are always **inclusive** at the start and **exclusive** + at the end. + """ + + def __init__(self, fieldname, start, end, gap, hardend=False, + maptype=None): + """ + :param fieldname: the numeric field to sort/facet on. + :param start: the start of the entire range. + :param end: the end of the entire range. + :param gap: the size of each "bucket" in the range. This can be a + sequence of sizes. For example, ``gap=[1,5,10]`` will use 1 as the + size of the first bucket, 5 as the size of the second bucket, and + 10 as the size of all subsequent buckets. + :param hardend: if True, the end of the last bucket is clamped to the + value of ``end``. If False (the default), the last bucket is always + ``gap`` sized, even if that means the end of the last bucket is + after ``end``. + """ + + self.fieldname = fieldname + self.start = start + self.end = end + self.gap = gap + self.hardend = hardend + self.maptype = maptype + self._queries() + + def default_name(self): + return self.fieldname + + def _rangetype(self): + from whoosh import query + + return query.NumericRange + + def _range_name(self, startval, endval): + return (startval, endval) + + def _queries(self): + if not self.gap: + raise Exception("No gap secified (%r)" % self.gap) + if isinstance(self.gap, (list, tuple)): + gaps = self.gap + gapindex = 0 + else: + gaps = [self.gap] + gapindex = -1 + + rangetype = self._rangetype() + self.querydict = {} + cstart = self.start + while cstart < self.end: + thisgap = gaps[gapindex] + if gapindex >= 0: + gapindex += 1 + if gapindex == len(gaps): + gapindex = -1 + + cend = cstart + thisgap + if self.hardend: + cend = min(self.end, cend) + + rangename = self._range_name(cstart, cend) + q = rangetype(self.fieldname, cstart, cend, endexcl=True) + self.querydict[rangename] = q + + cstart = cend + + def categorizer(self, global_searcher): + return QueryFacet(self.querydict).categorizer(global_searcher) + + +class DateRangeFacet(RangeFacet): + """Sorts/facets based on date ranges. This is the same as RangeFacet + except you are expected to use ``daterange`` objects as the start and end + of the range, and ``timedelta`` or ``relativedelta`` objects as the gap(s), + and it generates :class:`~whoosh.query.DateRange` queries instead of + :class:`~whoosh.query.TermRange` queries. + + For example, to facet a "birthday" range into 5 year buckets:: + + from datetime import datetime + from whoosh.support.relativedelta import relativedelta + + startdate = datetime(1920, 0, 0) + enddate = datetime.now() + gap = relativedelta(years=5) + bdays = DateRangeFacet("birthday", startdate, enddate, gap) + results = searcher.search(myquery, groupedby=bdays) + + The ranges/buckets are always **inclusive** at the start and **exclusive** + at the end. + """ + + def _rangetype(self): + from whoosh import query + + return query.DateRange + + +class ScoreFacet(FacetType): + """Uses a document's score as a sorting criterion. + + For example, to sort by the ``tag`` field, and then within that by relative + score:: + + tag_score = MultiFacet(["tag", ScoreFacet()]) + results = searcher.search(myquery, sortedby=tag_score) + """ + + def categorizer(self, global_searcher): + return self.ScoreCategorizer(global_searcher) + + class ScoreCategorizer(Categorizer): + needs_current = True + + def __init__(self, global_searcher): + w = global_searcher.weighting + self.use_final = w.use_final + if w.use_final: + self.final = w.final + + def set_searcher(self, segment_searcher, offset): + self.segment_searcher = segment_searcher + + def key_for(self, matcher, docid): + score = matcher.score() + if self.use_final: + score = self.final(self.segment_searcher, docid, score) + # Negate the score so higher values sort first + return 0 - score + + +class FunctionFacet(FacetType): + """This facet type is low-level. In most cases you should use + :class:`TranslateFacet` instead. + + This facet type ets you pass an arbitrary function that will compute the + key. This may be easier than subclassing FacetType and Categorizer to set up + the desired behavior. + + The function is called with the arguments ``(searcher, docid)``, where the + ``searcher`` may be a composite searcher, and the ``docid`` is an absolute + index document number (not segment-relative). + + For example, to use the number of words in the document's "content" field + as the sorting/faceting key:: + + fn = lambda s, docid: s.doc_field_length(docid, "content") + lengths = FunctionFacet(fn) + """ + + def __init__(self, fn, maptype=None): + self.fn = fn + self.maptype = maptype + + def categorizer(self, global_searcher): + return self.FunctionCategorizer(global_searcher, self.fn) + + class FunctionCategorizer(Categorizer): + def __init__(self, global_searcher, fn): + self.global_searcher = global_searcher + self.fn = fn + + def set_searcher(self, segment_searcher, docoffset): + self.offset = docoffset + + def key_for(self, matcher, docid): + return self.fn(self.global_searcher, docid + self.offset) + + +class TranslateFacet(FacetType): + """Lets you specify a function to compute the key based on a key generated + by a wrapped facet. + + This is useful if you want to use a custom ordering of a sortable field. For + example, if you want to use an implementation of the Unicode Collation + Algorithm (UCA) to sort a field using the rules from a particular language:: + + from pyuca import Collator + + # The Collator object has a sort_key() method which takes a unicode + # string and returns a sort key + c = Collator("allkeys.txt") + + # Make a facet object for the field you want to sort on + facet = sorting.FieldFacet("name") + # Wrap the facet in a TranslateFacet with the translation function + # (the Collator object's sort_key method) + facet = sorting.TranslateFacet(c.sort_key, facet) + + # Use the facet to sort the search results + results = searcher.search(myquery, sortedby=facet) + + You can pass multiple facets to the + """ + + def __init__(self, fn, *facets): + """ + :param fn: The function to apply. For each matching document, this + function will be called with the values of the given facets as + arguments. + :param facets: One or more :class:`FacetType` objects. These facets are + used to compute facet value(s) for a matching document, and then the + value(s) is/are passed to the function. + """ + self.fn = fn + self.facets = facets + self.maptype = None + + def categorizer(self, global_searcher): + catters = [facet.categorizer(global_searcher) for facet in self.facets] + return self.TranslateCategorizer(self.fn, catters) + + class TranslateCategorizer(Categorizer): + def __init__(self, fn, catters): + self.fn = fn + self.catters = catters + + def set_searcher(self, segment_searcher, docoffset): + for catter in self.catters: + catter.set_searcher(segment_searcher, docoffset) + + def key_for(self, matcher, segment_docnum): + keys = [catter.key_for(matcher, segment_docnum) + for catter in self.catters] + return self.fn(*keys) + + +class StoredFieldFacet(FacetType): + """Lets you sort/group using the value in an unindexed, stored field (e.g. + :class:`whoosh.fields.STORED`). This is usually slower than using an indexed + field. + + For fields where the stored value is a space-separated list of keywords, + (e.g. ``"tag1 tag2 tag3"``), you can use the ``allow_overlap`` keyword + argument to allow overlapped faceting on the result of calling the + ``split()`` method on the field value (or calling a custom split function + if one is supplied). + """ + + def __init__(self, fieldname, allow_overlap=False, split_fn=None, + maptype=None): + """ + :param fieldname: the name of the stored field. + :param allow_overlap: if True, when grouping, allow documents to appear + in multiple groups when they have multiple terms in the field. The + categorizer uses ``string.split()`` or the custom ``split_fn`` to + convert the stored value into a list of facet values. + :param split_fn: a custom function to split a stored field value into + multiple facet values when ``allow_overlap`` is True. If not + supplied, the categorizer simply calls the value's ``split()`` + method. + """ + + self.fieldname = fieldname + self.allow_overlap = allow_overlap + self.split_fn = split_fn + self.maptype = maptype + + def default_name(self): + return self.fieldname + + def categorizer(self, global_searcher): + return self.StoredFieldCategorizer(self.fieldname, self.allow_overlap, + self.split_fn) + + class StoredFieldCategorizer(Categorizer): + def __init__(self, fieldname, allow_overlap, split_fn): + self.fieldname = fieldname + self.allow_overlap = allow_overlap + self.split_fn = split_fn + + def set_searcher(self, segment_searcher, docoffset): + self.segment_searcher = segment_searcher + + def keys_for(self, matcher, docid): + d = self.segment_searcher.stored_fields(docid) + value = d.get(self.fieldname) + if self.split_fn: + return self.split_fn(value) + else: + return value.split() + + def key_for(self, matcher, docid): + d = self.segment_searcher.stored_fields(docid) + return d.get(self.fieldname) + + +class MultiFacet(FacetType): + """Sorts/facets by the combination of multiple "sub-facets". + + For example, to sort by the value of the "tag" field, and then (for + documents where the tag is the same) by the value of the "path" field:: + + facet = MultiFacet(FieldFacet("tag"), FieldFacet("path") + results = searcher.search(myquery, sortedby=facet) + + As a shortcut, you can use strings to refer to field names, and they will + be assumed to be field names and turned into FieldFacet objects:: + + facet = MultiFacet("tag", "path") + + You can also use the ``add_*`` methods to add criteria to the multifacet:: + + facet = MultiFacet() + facet.add_field("tag") + facet.add_field("path", reverse=True) + facet.add_query({"a-m": TermRange("name", "a", "m"), + "n-z": TermRange("name", "n", "z")}) + """ + + def __init__(self, items=None, maptype=None): + self.facets = [] + if items: + for item in items: + self._add(item) + self.maptype = maptype + + def __repr__(self): + return "%s(%r, %r)" % (self.__class__.__name__, + self.facets, + self.maptype) + + @classmethod + def from_sortedby(cls, sortedby): + multi = cls() + if isinstance(sortedby, string_type): + multi._add(sortedby) + elif (isinstance(sortedby, (list, tuple)) + or hasattr(sortedby, "__iter__")): + for item in sortedby: + multi._add(item) + else: + multi._add(sortedby) + return multi + + def _add(self, item): + if isinstance(item, FacetType): + self.add_facet(item) + elif isinstance(item, string_type): + self.add_field(item) + else: + raise Exception("Don't know what to do with facet %r" % (item,)) + + def add_field(self, fieldname, reverse=False): + self.facets.append(FieldFacet(fieldname, reverse=reverse)) + return self + + def add_query(self, querydict, other=None, allow_overlap=False): + self.facets.append(QueryFacet(querydict, other=other, + allow_overlap=allow_overlap)) + return self + + def add_score(self): + self.facets.append(ScoreFacet()) + return self + + def add_facet(self, facet): + if not isinstance(facet, FacetType): + raise TypeError("%r is not a facet object, perhaps you meant " + "add_field()" % (facet,)) + self.facets.append(facet) + return self + + def categorizer(self, global_searcher): + if not self.facets: + raise Exception("No facets") + elif len(self.facets) == 1: + catter = self.facets[0].categorizer(global_searcher) + else: + catter = self.MultiCategorizer([facet.categorizer(global_searcher) + for facet in self.facets]) + return catter + + class MultiCategorizer(Categorizer): + def __init__(self, catters): + self.catters = catters + + @property + def needs_current(self): + return any(c.needs_current for c in self.catters) + + def set_searcher(self, segment_searcher, docoffset): + for catter in self.catters: + catter.set_searcher(segment_searcher, docoffset) + + def key_for(self, matcher, docid): + return tuple(catter.key_for(matcher, docid) + for catter in self.catters) + + def key_to_name(self, key): + return tuple(catter.key_to_name(keypart) + for catter, keypart + in izip(self.catters, key)) + + +class Facets(object): + """Maps facet names to :class:`FacetType` objects, for creating multiple + groupings of documents. + + For example, to group by tag, and **also** group by price range:: + + facets = Facets() + facets.add_field("tag") + facets.add_facet("price", RangeFacet("price", 0, 1000, 100)) + results = searcher.search(myquery, groupedby=facets) + + tag_groups = results.groups("tag") + price_groups = results.groups("price") + + (To group by the combination of multiple facets, use :class:`MultiFacet`.) + """ + + def __init__(self, x=None): + self.facets = {} + if x: + self.add_facets(x) + + @classmethod + def from_groupedby(cls, groupedby): + facets = cls() + if isinstance(groupedby, (cls, dict)): + facets.add_facets(groupedby) + elif isinstance(groupedby, string_type): + facets.add_field(groupedby) + elif isinstance(groupedby, FacetType): + facets.add_facet(groupedby.default_name(), groupedby) + elif isinstance(groupedby, (list, tuple)): + for item in groupedby: + facets.add_facets(cls.from_groupedby(item)) + else: + raise Exception("Don't know what to do with groupedby=%r" + % groupedby) + + return facets + + def names(self): + """Returns an iterator of the facet names in this object. + """ + + return iter(self.facets) + + def items(self): + """Returns a list of (facetname, facetobject) tuples for the facets in + this object. + """ + + return self.facets.items() + + def add_field(self, fieldname, **kwargs): + """Adds a :class:`FieldFacet` for the given field name (the field name + is automatically used as the facet name). + """ + + self.facets[fieldname] = FieldFacet(fieldname, **kwargs) + return self + + def add_query(self, name, querydict, **kwargs): + """Adds a :class:`QueryFacet` under the given ``name``. + + :param name: a name for the facet. + :param querydict: a dictionary mapping keys to + :class:`whoosh.query.Query` objects. + """ + + self.facets[name] = QueryFacet(querydict, **kwargs) + return self + + def add_facet(self, name, facet): + """Adds a :class:`FacetType` object under the given ``name``. + """ + + if not isinstance(facet, FacetType): + raise Exception("%r:%r is not a facet" % (name, facet)) + self.facets[name] = facet + return self + + def add_facets(self, facets, replace=True): + """Adds the contents of the given ``Facets`` or ``dict`` object to this + object. + """ + + if not isinstance(facets, (dict, Facets)): + raise Exception("%r is not a Facets object or dict" % facets) + for name, facet in facets.items(): + if replace or name not in self.facets: + self.facets[name] = facet + return self + + +# Objects for holding facet groups + +class FacetMap(object): + """Base class for objects holding the results of grouping search results by + a Facet. Use an object's ``as_dict()`` method to access the results. + + You can pass a subclass of this to the ``maptype`` keyword argument when + creating a ``FacetType`` object to specify what information the facet + should record about the group. For example:: + + # Record each document in each group in its sorted order + myfacet = FieldFacet("size", maptype=OrderedList) + + # Record only the count of documents in each group + myfacet = FieldFacet("size", maptype=Count) + """ + + def add(self, groupname, docid, sortkey): + """Adds a document to the facet results. + + :param groupname: the name of the group to add this document to. + :param docid: the document number of the document to add. + :param sortkey: a value representing the sort position of the document + in the full results. + """ + + raise NotImplementedError + + def as_dict(self): + """Returns a dictionary object mapping group names to + implementation-specific values. For example, the value might be a list + of document numbers, or a integer representing the number of documents + in the group. + """ + + raise NotImplementedError + + +class OrderedList(FacetMap): + """Stores a list of document numbers for each group, in the same order as + they appear in the search results. + + The ``as_dict`` method returns a dictionary mapping group names to lists + of document numbers. + """ + + def __init__(self): + self.dict = defaultdict(list) + + def __repr__(self): + return "<%s %r>" % (self.__class__.__name__, self.dict) + + def add(self, groupname, docid, sortkey): + self.dict[groupname].append((sortkey, docid)) + + def as_dict(self): + d = {} + for key, items in iteritems(self.dict): + d[key] = [docnum for _, docnum in sorted(items)] + return d + + +class UnorderedList(FacetMap): + """Stores a list of document numbers for each group, in arbitrary order. + This is slightly faster and uses less memory than + :class:`OrderedListResult` if you don't care about the ordering of the + documents within groups. + + The ``as_dict`` method returns a dictionary mapping group names to lists + of document numbers. + """ + + def __init__(self): + self.dict = defaultdict(list) + + def __repr__(self): + return "<%s %r>" % (self.__class__.__name__, self.dict) + + def add(self, groupname, docid, sortkey): + self.dict[groupname].append(docid) + + def as_dict(self): + return dict(self.dict) + + +class Count(FacetMap): + """Stores the number of documents in each group. + + The ``as_dict`` method returns a dictionary mapping group names to + integers. + """ + + def __init__(self): + self.dict = defaultdict(int) + + def __repr__(self): + return "<%s %r>" % (self.__class__.__name__, self.dict) + + def add(self, groupname, docid, sortkey): + self.dict[groupname] += 1 + + def as_dict(self): + return dict(self.dict) + + +class Best(FacetMap): + """Stores the "best" document in each group (that is, the one with the + highest sort key). + + The ``as_dict`` method returns a dictionary mapping group names to + docnument numbers. + """ + + def __init__(self): + self.bestids = {} + self.bestkeys = {} + + def __repr__(self): + return "<%s %r>" % (self.__class__.__name__, self.bestids) + + def add(self, groupname, docid, sortkey): + if groupname not in self.bestids or sortkey < self.bestkeys[groupname]: + self.bestids[groupname] = docid + self.bestkeys[groupname] = sortkey + + def as_dict(self): + return self.bestids + + +# Helper functions + +def add_sortable(writer, fieldname, facet, column=None): + """Adds a per-document value column to an existing field which was created + without the ``sortable`` keyword argument. + + >>> from whoosh import index, sorting + >>> ix = index.open_dir("indexdir") + >>> with ix.writer() as w: + ... facet = sorting.FieldFacet("price") + ... sorting.add_sortable(w, "price", facet) + ... + + :param writer: a :class:`whoosh.writing.IndexWriter` object. + :param fieldname: the name of the field to add the per-document sortable + values to. If this field doesn't exist in the writer's schema, the + function will add a :class:`whoosh.fields.COLUMN` field to the schema, + and you must specify the column object to using the ``column`` keyword + argument. + :param facet: a :class:`FacetType` object to use to generate the + per-document values. + :param column: a :class:`whosh.columns.ColumnType` object to use to store + the per-document values. If you don't specify a column object, the + function will use the default column type for the given field. + """ + + storage = writer.storage + schema = writer.schema + + field = None + if fieldname in schema: + field = schema[fieldname] + if field.column_type: + raise Exception("%r field is already sortable" % fieldname) + + if column: + if fieldname not in schema: + from whoosh.fields import COLUMN + field = COLUMN(column) + schema.add(fieldname, field) + else: + if fieldname in schema: + column = field.default_column() + else: + raise Exception("Field %r does not exist" % fieldname) + + searcher = writer.searcher() + catter = facet.categorizer(searcher) + for subsearcher, docoffset in searcher.leaf_searchers(): + catter.set_searcher(subsearcher, docoffset) + reader = subsearcher.reader() + + if reader.has_column(fieldname): + raise Exception("%r field already has a column" % fieldname) + + codec = reader.codec() + segment = reader.segment() + + colname = codec.column_filename(segment, fieldname) + colfile = storage.create_file(colname) + try: + colwriter = column.writer(colfile) + for docnum in reader.all_doc_ids(): + v = catter.key_to_name(catter.key_for(None, docnum)) + cv = field.to_column_value(v) + colwriter.add(docnum, cv) + colwriter.finish(reader.doc_count_all()) + finally: + colfile.close() + + field.column_type = column + + + diff --git a/nstock/modules/whoosh/spelling.py b/nstock/modules/whoosh/spelling.py new file mode 100644 index 0000000..d1dde0c --- /dev/null +++ b/nstock/modules/whoosh/spelling.py @@ -0,0 +1,343 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +""" +This module contains helper functions for correcting typos in user queries. +""" + +from bisect import bisect_left +from heapq import heappush, heapreplace + +from whoosh import highlight +from whoosh.compat import iteritems, xrange + + +# Corrector objects + +class Corrector(object): + """ + Base class for spelling correction objects. Concrete sub-classes should + implement the ``_suggestions`` method. + """ + + def suggest(self, text, limit=5, maxdist=2, prefix=0): + """ + :param text: the text to check. This word will **not** be added to the + suggestions, even if it appears in the word graph. + :param limit: only return up to this many suggestions. If there are not + enough terms in the field within ``maxdist`` of the given word, the + returned list will be shorter than this number. + :param maxdist: the largest edit distance from the given word to look + at. Values higher than 2 are not very effective or efficient. + :param prefix: require suggestions to share a prefix of this length + with the given word. This is often justifiable since most + misspellings do not involve the first letter of the word. Using a + prefix dramatically decreases the time it takes to generate the + list of words. + """ + + _suggestions = self._suggestions + + heap = [] + for item in _suggestions(text, maxdist, prefix): + # Note that the *higher* scores (item[0]) are better! + if len(heap) < limit: + heappush(heap, item) + elif item > heap[0]: + heapreplace(heap, item) + + sugs = sorted(heap, key=lambda x: (0 - x[0], x[1])) + return [sug for _, sug in sugs] + + def _suggestions(self, text, maxdist, prefix): + """ + Low-level method that yields a series of (score, "suggestion") + tuples. + + :param text: the text to check. + :param maxdist: the maximum edit distance. + :param prefix: require suggestions to share a prefix of this length + with the given word. + """ + + raise NotImplementedError + + +class ReaderCorrector(Corrector): + """ + Suggests corrections based on the content of a field in a reader. + + Ranks suggestions by the edit distance, then by highest to lowest + frequency. + """ + + def __init__(self, reader, fieldname, fieldobj): + self.reader = reader + self.fieldname = fieldname + self.fieldobj = fieldobj + + def _suggestions(self, text, maxdist, prefix): + reader = self.reader + freq = reader.frequency + + fieldname = self.fieldname + fieldobj = reader.schema[fieldname] + sugfield = fieldobj.spelling_fieldname(fieldname) + + for sug in reader.terms_within(sugfield, text, maxdist, prefix=prefix): + # Higher scores are better, so negate the distance and frequency + f = freq(fieldname, sug) or 1 + score = 0 - (maxdist + (1.0 / f * 0.5)) + yield (score, sug) + + +class ListCorrector(Corrector): + """ + Suggests corrections based on the content of a sorted list of strings. + """ + + def __init__(self, wordlist): + self.wordlist = wordlist + + def _suggestions(self, text, maxdist, prefix): + from whoosh.automata.lev import levenshtein_automaton + from whoosh.automata.fsa import find_all_matches + + seen = set() + for i in xrange(1, maxdist + 1): + dfa = levenshtein_automaton(text, maxdist, prefix).to_dfa() + sk = self.Skipper(self.wordlist) + for sug in find_all_matches(dfa, sk): + if sug not in seen: + seen.add(sug) + yield (0 - maxdist), sug + + class Skipper(object): + def __init__(self, data): + self.data = data + self.i = 0 + + def __call__(self, w): + if self.data[self.i] == w: + return w + self.i += 1 + pos = bisect_left(self.data, w, self.i) + if pos < len(self.data): + return self.data[pos] + else: + return None + + +class MultiCorrector(Corrector): + """ + Merges suggestions from a list of sub-correctors. + """ + + def __init__(self, correctors, op): + self.correctors = correctors + self.op = op + + def _suggestions(self, text, maxdist, prefix): + op = self.op + seen = {} + for corr in self.correctors: + for score, sug in corr._suggestions(text, maxdist, prefix): + if sug in seen: + seen[sug] = op(seen[sug], score) + else: + seen[sug] = score + return iteritems(seen) + + +# Query correction + +class Correction(object): + """ + Represents the corrected version of a user query string. Has the + following attributes: + + ``query`` + The corrected :class:`whoosh.query.Query` object. + ``string`` + The corrected user query string. + ``original_query`` + The original :class:`whoosh.query.Query` object that was corrected. + ``original_string`` + The original user query string. + ``tokens`` + A list of token objects representing the corrected words. + + You can also use the :meth:`Correction.format_string` method to reformat the + corrected query string using a :class:`whoosh.highlight.Formatter` class. + For example, to display the corrected query string as HTML with the + changed words emphasized:: + + from whoosh import highlight + + correction = mysearcher.correct_query(q, qstring) + + hf = highlight.HtmlFormatter(classname="change") + html = correction.format_string(hf) + """ + + def __init__(self, q, qstring, corr_q, tokens): + self.original_query = q + self.query = corr_q + self.original_string = qstring + self.tokens = tokens + + if self.original_string: + self.string = self.format_string(highlight.NullFormatter()) + else: + self.string = '' + + def __repr__(self): + return "%s(%r, %r)" % (self.__class__.__name__, self.query, + self.string) + + def format_string(self, formatter): + """ + Highlights the corrected words in the original query string using the + given :class:`~whoosh.highlight.Formatter`. + + :param formatter: A :class:`whoosh.highlight.Formatter` instance. + :return: the output of the formatter (usually a string). + """ + + if not self.original_string: + return '' + if isinstance(formatter, type): + formatter = formatter() + + fragment = highlight.Fragment(self.original_string, self.tokens) + return formatter.format_fragment(fragment, replace=True) + + +# QueryCorrector objects + +class QueryCorrector(object): + """ + Base class for objects that correct words in a user query. + """ + + def __init__(self, fieldname): + self.fieldname = fieldname + + def correct_query(self, q, qstring): + """ + Returns a :class:`Correction` object representing the corrected + form of the given query. + + :param q: the original :class:`whoosh.query.Query` tree to be + corrected. + :param qstring: the original user query. This may be None if the + original query string is not available, in which case the + ``Correction.string`` attribute will also be None. + :rtype: :class:`Correction` + """ + + raise NotImplementedError + + def field(self): + return self.fieldname + + +class SimpleQueryCorrector(QueryCorrector): + """ + A simple query corrector based on a mapping of field names to + :class:`Corrector` objects, and a list of ``("fieldname", "text")`` tuples + to correct. And terms in the query that appear in list of term tuples are + corrected using the appropriate corrector. + """ + + def __init__(self, correctors, terms, aliases=None, prefix=0, maxdist=2): + """ + :param correctors: a dictionary mapping field names to + :class:`Corrector` objects. + :param terms: a sequence of ``("fieldname", "text")`` tuples + representing terms to be corrected. + :param aliases: a dictionary mapping field names in the query to + field names for spelling suggestions. + :param prefix: suggested replacement words must share this number of + initial characters with the original word. Increasing this even to + just ``1`` can dramatically speed up suggestions, and may be + justifiable since spellling mistakes rarely involve the first + letter of a word. + :param maxdist: the maximum number of "edits" (insertions, deletions, + subsitutions, or transpositions of letters) allowed between the + original word and any suggestion. Values higher than ``2`` may be + slow. + """ + + self.correctors = correctors + self.aliases = aliases or {} + self.termset = frozenset(terms) + self.prefix = prefix + self.maxdist = maxdist + + def correct_query(self, q, qstring): + correctors = self.correctors + aliases = self.aliases + termset = self.termset + prefix = self.prefix + maxdist = self.maxdist + + # A list of tokens that were changed by a corrector + corrected_tokens = [] + + # The corrected query tree. We don't need to deepcopy the original + # because we use Query.replace() to find-and-replace the corrected + # words and it returns a copy of the query tree. + corrected_q = q + + # For every word in the original query... + # Note we can't put these in a set, because we must preserve WHERE + # in the query each token occured so we can format them later + for token in q.all_tokens(): + fname = token.fieldname + aname = aliases.get(fname, fname) + + # If this is one of the words we're supposed to correct... + if (fname, token.text) in termset: + c = correctors[aname] + sugs = c.suggest(token.text, prefix=prefix, maxdist=maxdist) + if sugs: + # This is a "simple" corrector, so we just pick the first + # suggestion :/ + sug = sugs[0] + + # Return a new copy of the original query with this word + # replaced by the correction + corrected_q = corrected_q.replace(token.fieldname, + token.text, sug) + # Add the token to the list of corrected tokens (for the + # formatter to use later) + token.original = token.text + token.text = sug + corrected_tokens.append(token) + + return Correction(q, qstring, corrected_q, corrected_tokens) diff --git a/nstock/modules/whoosh/support/__init__.py b/nstock/modules/whoosh/support/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/nstock/modules/whoosh/support/base85.py b/nstock/modules/whoosh/support/base85.py new file mode 100644 index 0000000..87a4df8 --- /dev/null +++ b/nstock/modules/whoosh/support/base85.py @@ -0,0 +1,103 @@ +""" +This module contains generic base85 encoding and decoding functions. The +whoosh.util.numeric module contains faster variants for encoding and +decoding integers. + +Modified from: +http://paste.lisp.org/display/72815 +""" + +import struct + +from whoosh.compat import xrange + + +# Instead of using the character set from the ascii85 algorithm, I put the +# characters in order so that the encoded text sorts properly (my life would be +# a lot easier if they had just done that from the start) +b85chars = ("!$%&*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "^_abcdefghijklmnopqrstuvwxyz{|}~") +b85dec = {} +for i in range(len(b85chars)): + b85dec[b85chars[i]] = i + + +# Integer encoding and decoding functions + +def to_base85(x, islong=False): + "Encodes the given integer using base 85." + + size = 10 if islong else 5 + rems = "" + for i in xrange(size): + rems = b85chars[x % 85] + rems + x //= 85 + return rems + + +def from_base85(text): + "Decodes the given base 85 text into an integer." + + acc = 0 + for c in text: + acc = acc * 85 + b85dec[c] + return acc + + +# Bytes encoding and decoding functions + +def b85encode(text, pad=False): + l = len(text) + r = l % 4 + if r: + text += '\0' * (4 - r) + longs = len(text) >> 2 + out = [] + words = struct.unpack('>' + 'L' * longs, text[0:longs * 4]) + for word in words: + rems = [0, 0, 0, 0, 0] + for i in range(4, -1, -1): + rems[i] = b85chars[word % 85] + word /= 85 + out.extend(rems) + + out = ''.join(out) + if pad: + return out + + # Trim padding + olen = l % 4 + if olen: + olen += 1 + olen += l / 4 * 5 + return out[0:olen] + + +def b85decode(text): + l = len(text) + out = [] + for i in range(0, len(text), 5): + chunk = text[i:i + 5] + acc = 0 + for j in range(len(chunk)): + try: + acc = acc * 85 + b85dec[chunk[j]] + except KeyError: + raise TypeError('Bad base85 character at byte %d' % (i + j)) + if acc > 4294967295: + raise OverflowError('Base85 overflow in hunk starting at byte %d' % i) + out.append(acc) + + # Pad final chunk if necessary + cl = l % 5 + if cl: + acc *= 85 ** (5 - cl) + if cl > 1: + acc += 0xffffff >> (cl - 2) * 8 + out[-1] = acc + + out = struct.pack('>' + 'L' * ((l + 4) / 5), *out) + if cl: + out = out[:-(5 - cl)] + + return out diff --git a/nstock/modules/whoosh/support/bench.py b/nstock/modules/whoosh/support/bench.py new file mode 100644 index 0000000..22d526e --- /dev/null +++ b/nstock/modules/whoosh/support/bench.py @@ -0,0 +1,610 @@ +# Copyright 2010 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from __future__ import division +import os.path +from optparse import OptionParser +from shutil import rmtree + +from whoosh import index, qparser, query, scoring +from whoosh.util import now, find_object + +try: + import xappy +except ImportError: + pass +try: + import xapian +except ImportError: + pass +try: + import pysolr +except ImportError: + pass + +try: + from persistent import Persistent + + class ZDoc(Persistent): + def __init__(self, d): + self.__dict__.update(d) +except ImportError: + pass + + +class Module(object): + def __init__(self, bench, options, args): + self.bench = bench + self.options = options + self.args = args + + def __repr__(self): + return self.__class__.__name__ + + def indexer(self, **kwargs): + pass + + def index_document(self, d): + raise NotImplementedError + + def finish(self, **kwargs): + pass + + def _process_result(self, d): + attrname = "process_result_%s" % self.options.lib + if hasattr(self.bench.spec, attrname): + method = getattr(self.bench.spec, attrname) + self._process_result = method + return method(d) + else: + self._process_result = lambda x: x + return d + + def searcher(self): + pass + + def query(self): + raise NotImplementedError + + def find(self, q): + raise NotImplementedError + + def findterms(self, terms): + raise NotImplementedError + + def results(self, r): + for hit in r: + yield self._process_result(hit) + + +class Spec(object): + headline_field = "title" + main_field = "body" + + def __init__(self, options, args): + self.options = options + self.args = args + + def documents(self): + raise NotImplementedError + + def setup(self): + pass + + def print_results(self, ls): + showbody = self.options.showbody + snippets = self.options.snippets + limit = self.options.limit + for i, hit in enumerate(ls): + if i >= limit: + break + + print("%d. %s" % (i + 1, hit.get(self.headline_field))) + if snippets: + print(self.show_snippet(hit)) + if showbody: + print(hit.get(self.main_field)) + + +class WhooshModule(Module): + def indexer(self, create=True): + schema = self.bench.spec.whoosh_schema() + path = os.path.join(self.options.dir, "%s_whoosh" + % self.options.indexname) + + if not os.path.exists(path): + os.mkdir(path) + if create: + ix = index.create_in(path, schema) + else: + ix = index.open_dir(path) + + poolclass = None + if self.options.pool: + poolclass = find_object(self.options.pool) + + self.writer = ix.writer(limitmb=int(self.options.limitmb), + poolclass=poolclass, + dir=self.options.tempdir, + procs=int(self.options.procs), + batchsize=int(self.options.batch), + multisegment=self.options.xms) + self._procdoc = None + if hasattr(self.bench.spec, "process_document_whoosh"): + self._procdoc = self.bench.spec.process_document_whoosh + + def index_document(self, d): + _procdoc = self._procdoc + if _procdoc: + _procdoc(d) + self.writer.add_document(**d) + + def finish(self, merge=True, optimize=False): + self.writer.commit(merge=merge, optimize=optimize) + + def searcher(self): + path = os.path.join(self.options.dir, "%s_whoosh" + % self.options.indexname) + ix = index.open_dir(path) + self.srch = ix.searcher(weighting=scoring.PL2()) + self.parser = qparser.QueryParser(self.bench.spec.main_field, + schema=ix.schema) + + def query(self): + qstring = " ".join(self.args).decode("utf-8") + return self.parser.parse(qstring) + + def find(self, q): + return self.srch.search(q, limit=int(self.options.limit), + optimize=self.options.optimize) + + def findterms(self, terms): + limit = int(self.options.limit) + s = self.srch + q = query.Term(self.bench.spec.main_field, None) + for term in terms: + q.text = term + yield s.search(q, limit=limit) + + +class XappyModule(Module): + def indexer(self, **kwargs): + path = os.path.join(self.options.dir, "%s_xappy" + % self.options.indexname) + conn = self.bench.spec.xappy_connection(path) + return conn + + def index_document(self, conn, d): + if hasattr(self.bench, "process_document_xappy"): + self.bench.process_document_xappy(d) + doc = xappy.UnprocessedDocument() + for key, values in d: + if not isinstance(values, list): + values = [values] + for value in values: + doc.fields.append(xappy.Field(key, value)) + conn.add(doc) + + def finish(self, conn): + conn.flush() + + def searcher(self): + path = os.path.join(self.options.dir, "%s_xappy" + % self.options.indexname) + return xappy.SearchConnection(path) + + def query(self, conn): + return conn.query_parse(" ".join(self.args)) + + def find(self, conn, q): + return conn.search(q, 0, int(self.options.limit)) + + def findterms(self, conn, terms): + limit = int(self.options.limit) + for term in terms: + q = conn.query_field(self.bench.spec.main_field, term) + yield conn.search(q, 0, limit) + + def results(self, r): + hf = self.bench.spec.headline_field + mf = self.bench.spec.main_field + for hit in r: + yield self._process_result({hf: hit.data[hf], mf: hit.data[mf]}) + + +class XapianModule(Module): + def indexer(self, **kwargs): + path = os.path.join(self.options.dir, "%s_xapian" + % self.options.indexname) + self.database = xapian.WritableDatabase(path, xapian.DB_CREATE_OR_OPEN) + self.ixer = xapian.TermGenerator() + + def index_document(self, d): + if hasattr(self.bench, "process_document_xapian"): + self.bench.process_document_xapian(d) + doc = xapian.Document() + doc.add_value(0, d.get(self.bench.spec.headline_field, "-")) + doc.set_data(d[self.bench.spec.main_field]) + self.ixer.set_document(doc) + self.ixer.index_text(d[self.bench.spec.main_field]) + self.database.add_document(doc) + + def finish(self, **kwargs): + self.database.flush() + + def searcher(self): + path = os.path.join(self.options.dir, "%s_xappy" + % self.options.indexname) + self.db = xapian.Database(path) + self.enq = xapian.Enquire(self.db) + self.qp = xapian.QueryParser() + self.qp.set_database(self.db) + + def query(self): + return self.qp.parse_query(" ".join(self.args)) + + def find(self, q): + self.enq.set_query(q) + return self.enq.get_mset(0, int(self.options.limit)) + + def findterms(self, terms): + limit = int(self.options.limit) + for term in terms: + q = self.qp.parse_query(term) + self.enq.set_query(q) + yield self.enq.get_mset(0, limit) + + def results(self, matches): + hf = self.bench.spec.headline_field + mf = self.bench.spec.main_field + for m in matches: + yield self._process_result({hf: m.document.get_value(0), + mf: m.document.get_data()}) + + +class SolrModule(Module): + def indexer(self, **kwargs): + self.solr_doclist = [] + self.conn = pysolr.Solr(self.options.url) + self.conn.delete("*:*") + self.conn.commit() + + def index_document(self, d): + self.solr_doclist.append(d) + if len(self.solr_doclist) >= int(self.options.batch): + self.conn.add(self.solr_doclist, commit=False) + self.solr_doclist = [] + + def finish(self, **kwargs): + if self.solr_doclist: + self.conn.add(self.solr_doclist) + del self.solr_doclist + self.conn.optimize(block=True) + + def searcher(self): + self.solr = pysolr.Solr(self.options.url) + + def query(self): + return " ".join(self.args) + + def find(self, q): + return self.solr.search(q, limit=int(self.options.limit)) + + def findterms(self, terms): + limit = int(self.options.limit) + for term in terms: + yield self.solr.search("body:" + term, limit=limit) + + +class ZcatalogModule(Module): + def indexer(self, **kwargs): + from ZODB.FileStorage import FileStorage # @UnresolvedImport + from ZODB.DB import DB # @UnresolvedImport + from zcatalog import catalog # @UnresolvedImport + from zcatalog import indexes # @UnresolvedImport + import transaction # @UnresolvedImport + + dir = os.path.join(self.options.dir, "%s_zcatalog" + % self.options.indexname) + if os.path.exists(dir): + rmtree(dir) + os.mkdir(dir) + + storage = FileStorage(os.path.join(dir, "index")) + db = DB(storage) + conn = db.open() + + self.cat = catalog.Catalog() + self.bench.spec.zcatalog_setup(self.cat) + conn.root()["cat"] = self.cat + transaction.commit() + + self.zcatalog_count = 0 + + def index_document(self, d): + if hasattr(self.bench, "process_document_zcatalog"): + self.bench.process_document_zcatalog(d) + doc = ZDoc(d) + self.cat.index_doc(doc) + self.zcatalog_count += 1 + if self.zcatalog_count >= 100: + import transaction # @UnresolvedImport + transaction.commit() + self.zcatalog_count = 0 + + def finish(self, **kwargs): + import transaction # @UnresolvedImport + transaction.commit() + del self.zcatalog_count + + def searcher(self): + from ZODB.FileStorage import FileStorage # @UnresolvedImport + from ZODB.DB import DB # @UnresolvedImport + from zcatalog import catalog # @UnresolvedImport + from zcatalog import indexes # @UnresolvedImport + import transaction # @UnresolvedImport + + path = os.path.join(self.options.dir, "%s_zcatalog" + % self.options.indexname, "index") + storage = FileStorage(path) + db = DB(storage) + conn = db.open() + + self.cat = conn.root()["cat"] + + def query(self): + return " ".join(self.args) + + def find(self, q): + return self.cat.searchResults(body=q) + + def findterms(self, terms): + for term in terms: + yield self.cat.searchResults(body=term) + + def results(self, r): + hf = self.bench.spec.headline_field + mf = self.bench.spec.main_field + for hit in r: + # Have to access the attributes for them to be retrieved + yield self._process_result({hf: getattr(hit, hf), + mf: getattr(hit, mf)}) + + +class NucularModule(Module): + def indexer(self, create=True): + import shutil + from nucular import Nucular + + dir = os.path.join(self.options.dir, "%s_nucular" + % self.options.indexname) + if create: + if os.path.exists(dir): + shutil.rmtree(dir) + os.mkdir(dir) + self.archive = Nucular.Nucular(dir) + if create: + self.archive.create() + self.count = 0 + + def index_document(self, d): + try: + self.archive.indexDictionary(str(self.count), d) + except ValueError: + print("d=", d) + raise + self.count += 1 + if not self.count % int(self.options.batch): + t = now() + self.archive.store(lazy=True) + self.indexer(create=False) + + def finish(self, **kwargs): + self.archive.store(lazy=False) + self.archive.aggregateRecent(fast=False, verbose=True) + self.archive.moveTransientToBase(verbose=True) + self.archive.cleanUp() + + def searcher(self): + from nucular import Nucular + + dir = os.path.join(self.options.dir, "%s_nucular" + % self.options.indexname) + self.archive = Nucular.Nucular(dir) + + def query(self): + return " ".join(self.args) + + def find(self, q): + return self.archive.dictionaries(q) + + def findterms(self, terms): + for term in terms: + q = self.archive.Query() + q.anyWord(term) + yield q.resultDictionaries() + + +class Bench(object): + libs = {"whoosh": WhooshModule, "xappy": XappyModule, + "xapian": XapianModule, "solr": SolrModule, + "zcatalog": ZcatalogModule, "nucular": NucularModule} + + def index(self, lib): + print("Indexing with %s..." % lib) + + options = self.options + every = None if options.every is None else int(options.every) + merge = options.merge + chunk = int(options.chunk) + skip = int(options.skip) + upto = int(options.upto) + count = 0 + skipc = skip + + starttime = chunkstarttime = now() + + lib.indexer() + + for d in self.spec.documents(): + skipc -= 1 + if not skipc: + lib.index_document(d) + count += 1 + skipc = skip + if chunk and not count % chunk: + t = now() + sofar = t - starttime + print("Done %d docs, %0.3f secs for %d, %0.3f total, %0.3f docs/s" % (count, t - chunkstarttime, chunk, sofar, count / sofar)) + chunkstarttime = t + if count > upto: + break + if every and not count % every: + print("----Commit") + lib.finish(merge=merge) + lib.indexer(create=False) + + spooltime = now() + print("Spool time:", spooltime - starttime) + lib.finish(merge=merge) + committime = now() + print("Commit time:", committime - spooltime) + totaltime = committime - starttime + print("Total time to index %d documents: %0.3f secs (%0.3f minutes)" % (count, totaltime, totaltime / 60.0)) + print("Indexed %0.3f docs/s" % (count / totaltime)) + + def search(self, lib): + lib.searcher() + + t = now() + q = lib.query() + print("Query:", q) + r = lib.find(q) + print("Search time:", now() - t) + + t = now() + self.spec.print_results(lib.results(r)) + print("Print time:", now() - t) + + def search_file(self, lib): + f = open(self.options.termfile, "rb") + terms = [line.strip() for line in f] + f.close() + + print("Searching %d terms with %s" % (len(terms), lib)) + lib.searcher() + starttime = now() + for r in lib.findterms(terms): + pass + searchtime = now() - starttime + print("Search time:", searchtime, "searches/s:", float(len(terms)) / searchtime) + + def _parser(self, name): + p = OptionParser() + p.add_option("-x", "--lib", dest="lib", + help="Name of the library to use to index/search.", + default="whoosh") + p.add_option("-d", "--dir", dest="dir", metavar="DIRNAME", + help="Directory in which to store index.", default=".") + p.add_option("-s", "--setup", dest="setup", action="store_true", + help="Set up any support files or caches.", default=False) + p.add_option("-i", "--index", dest="index", action="store_true", + help="Index the documents.", default=False) + p.add_option("-n", "--name", dest="indexname", metavar="PREFIX", + help="Index name prefix.", default="%s_index" % name) + p.add_option("-U", "--url", dest="url", metavar="URL", + help="Solr URL", default="http://localhost:8983/solr") + p.add_option("-m", "--mb", dest="limitmb", + help="Max. memory usage, in MB", default="128") + p.add_option("-c", "--chunk", dest="chunk", + help="Number of documents to index between progress messages.", + default=1000) + p.add_option("-B", "--batch", dest="batch", + help="Batch size for batch adding documents.", + default=1000) + p.add_option("-k", "--skip", dest="skip", metavar="N", + help="Index every Nth document.", default=1) + p.add_option("-e", "--commit-every", dest="every", metavar="NUM", + help="Commit every NUM documents", default=None) + p.add_option("-M", "--no-merge", dest="merge", action="store_false", + help="Don't merge segments when doing multiple commits", + default=True) + p.add_option("-u", "--upto", dest="upto", metavar="N", + help="Index up to this document number.", default=600000) + p.add_option("-p", "--procs", dest="procs", metavar="NUMBER", + help="Number of processors to use.", default=0) + p.add_option("-l", "--limit", dest="limit", metavar="N", + help="Maximum number of search results to retrieve.", + default=10) + p.add_option("-b", "--body", dest="showbody", action="store_true", + help="Show the body text in search results.", + default=False) + p.add_option("-g", "--gen", dest="generate", metavar="N", + help="Generate a list at most N terms present in all libraries.", + default=None) + p.add_option("-f", "--file", dest="termfile", metavar="FILENAME", + help="Search using the list of terms in this file.", + default=None) + p.add_option("-t", "--tempdir", dest="tempdir", metavar="DIRNAME", + help="Whoosh temp dir", default=None) + p.add_option("-P", "--pool", dest="pool", metavar="CLASSNAME", + help="Whoosh pool class", default=None) + p.add_option("-X", "--xms", dest="xms", action="store_true", + help="Experimental Whoosh feature", default=False) + p.add_option("-Z", "--storebody", dest="storebody", action="store_true", + help="Store the body text in index", default=False) + p.add_option("-q", "--snippets", dest="snippets", action="store_true", + help="Show highlighted snippets", default=False) + p.add_option("-O", "--no-optimize", dest="optimize", action="store_false", + help="Turn off searcher optimization", default=True) + + return p + + def run(self, specclass): + parser = self._parser(specclass.name) + options, args = parser.parse_args() + self.options = options + self.args = args + + if options.lib not in self.libs: + raise Exception("Unknown library: %r" % options.lib) + lib = self.libs[options.lib](self, options, args) + + self.spec = specclass(options, args) + + if options.setup: + self.spec.setup() + + action = self.search + if options.index: + action = self.index + if options.termfile: + action = self.search_file + if options.generate: + action = self.generate_search_file + + action(lib) diff --git a/nstock/modules/whoosh/support/charset.py b/nstock/modules/whoosh/support/charset.py new file mode 100644 index 0000000..29d936a --- /dev/null +++ b/nstock/modules/whoosh/support/charset.py @@ -0,0 +1,1379 @@ +# coding=utf-8 + +"""This module contains tools for working with Sphinx charset table files. These files +are useful for doing case and accent folding. +See :class:`whoosh.analysis.CharsetTokenizer` and :class:`whoosh.analysis.CharsetFilter`. +""" + +from collections import defaultdict +import re + +from whoosh.compat import izip, u, iteritems, unichr, xrange + +# This is a straightforward accent-folding charset taken from Carlos Bueno's +# article "Accent Folding for Auto-Complete", for use with CharsetFilter. +# +# http://www.alistapart.com/articles/accent-folding-for-auto-complete/ +# +# See the article for information and caveats. The code is lifted directly +# from here: +# +# http://github.com/aristus/accent-folding/blob/master/accent_fold.py + +accent_map = { + u('H'): u('h'), # H -> h + u('I'): u('i'), # I -> i + u('J'): u('j'), # J -> j + u('N'): u('n'), # N -> n + u('P'): u('p'), # P -> p + u('S'): u('s'), # S -> s + u('T'): u('t'), # T -> t + u('W'): u('w'), # W -> w + u('Y'): u('y'), # Y -> y + u('i'): u('i'), # i -> i + u('n'): u('n'), # n -> n + u('p'): u('p'), # p -> p + u('s'): u('s'), # s -> s + u('\xc0'): u('a'), # À -> a + u('\xc1'): u('a'), # Á -> a + u('\xc2'): u('a'), # Â -> a + u('\xc3'): u('a'), # Ã -> a + u('\xc4'): u('a'), # Ä -> a + u('\xc5'): u('a'), # Å -> a + u('\xc7'): u('c'), # Ç -> c + u('\xc8'): u('e'), # È -> e + u('\xc9'): u('e'), # É -> e + u('\xca'): u('e'), # Ê -> e + u('\xcb'): u('e'), # Ë -> e + u('\xcc'): u('i'), # Ì -> i + u('\xcd'): u('i'), # Í -> i + u('\xce'): u('i'), # Î -> i + u('\xcf'): u('i'), # Ï -> i + u('\xd1'): u('n'), # Ñ -> n + u('\xd2'): u('o'), # Ò -> o + u('\xd3'): u('o'), # Ó -> o + u('\xd4'): u('o'), # Ô -> o + u('\xd5'): u('o'), # Õ -> o + u('\xd6'): u('o'), # Ö -> o + u('\xd8'): u('o'), # Ø -> o + u('\xd9'): u('u'), # Ù -> u + u('\xda'): u('u'), # Ú -> u + u('\xdb'): u('u'), # Û -> u + u('\xdc'): u('u'), # Ü -> u + u('\xdd'): u('y'), # Ý -> y + u('\xde'): u('t'), # Þ -> t + u('\xdf'): u('s'), # ß -> s + u('\xe0'): u('a'), # à -> a + u('\xe1'): u('a'), # á -> a + u('\xe2'): u('a'), # â -> a + u('\xe3'): u('a'), # ã -> a + u('\xe4'): u('a'), # ä -> a + u('\xe5'): u('a'), # å -> a + u('\xe7'): u('c'), # ç -> c + u('\xe8'): u('e'), # è -> e + u('\xe9'): u('e'), # é -> e + u('\xea'): u('e'), # ê -> e + u('\xeb'): u('e'), # ë -> e + u('\xec'): u('i'), # ì -> i + u('\xed'): u('i'), # í -> i + u('\xee'): u('i'), # î -> i + u('\xef'): u('i'), # ï -> i + u('\xf0'): u('d'), # ð -> d + u('\xf1'): u('n'), # ñ -> n + u('\xf2'): u('o'), # ò -> o + u('\xf3'): u('o'), # ó -> o + u('\xf4'): u('o'), # ô -> o + u('\xf5'): u('o'), # õ -> o + u('\xf6'): u('o'), # ö -> o + u('\xf8'): u('o'), # ø -> o + u('\xf9'): u('u'), # ù -> u + u('\xfa'): u('u'), # ú -> u + u('\xfb'): u('u'), # û -> u + u('\xfc'): u('u'), # ü -> u + u('\xfd'): u('y'), # ý -> y + u('\xfe'): u('t'), # þ -> t + u('\xff'): u('y'), # ÿ -> y + u('\u0100'): u('a'), # Ā -> a + u('\u0101'): u('a'), # ā -> a + u('\u0102'): u('a'), # Ă -> a + u('\u0103'): u('a'), # ă -> a + u('\u0104'): u('a'), # Ą -> a + u('\u0105'): u('a'), # ą -> a + u('\u0106'): u('c'), # Ć -> c + u('\u0107'): u('c'), # ć -> c + u('\u0108'): u('c'), # Ĉ -> c + u('\u0109'): u('c'), # ĉ -> c + u('\u010a'): u('c'), # Ċ -> c + u('\u010b'): u('c'), # ċ -> c + u('\u010c'): u('c'), # Č -> c + u('\u010d'): u('c'), # č -> c + u('\u010e'): u('d'), # Ď -> d + u('\u010f'): u('d'), # ď -> d + u('\u0110'): u('d'), # Đ -> d + u('\u0111'): u('d'), # đ -> d + u('\u0112'): u('e'), # Ē -> e + u('\u0113'): u('e'), # ē -> e + u('\u0114'): u('e'), # Ĕ -> e + u('\u0115'): u('e'), # ĕ -> e + u('\u0116'): u('e'), # Ė -> e + u('\u0117'): u('e'), # ė -> e + u('\u0118'): u('e'), # Ę -> e + u('\u0119'): u('e'), # ę -> e + u('\u011a'): u('e'), # Ě -> e + u('\u011b'): u('e'), # ě -> e + u('\u011c'): u('g'), # Ĝ -> g + u('\u011d'): u('g'), # ĝ -> g + u('\u011e'): u('g'), # Ğ -> g + u('\u011f'): u('g'), # ğ -> g + u('\u0120'): u('g'), # Ġ -> g + u('\u0121'): u('g'), # ġ -> g + u('\u0122'): u('g'), # Ģ -> g + u('\u0123'): u('g'), # ģ -> g + u('\u0124'): u('h'), # Ĥ -> h + u('\u0125'): u('h'), # ĥ -> h + u('\u0126'): u('h'), # Ħ -> h + u('\u0127'): u('h'), # ħ -> h + u('\u0128'): u('i'), # Ĩ -> i + u('\u0129'): u('i'), # ĩ -> i + u('\u012a'): u('i'), # Ī -> i + u('\u012b'): u('i'), # ī -> i + u('\u012c'): u('i'), # Ĭ -> i + u('\u012d'): u('i'), # ĭ -> i + u('\u012e'): u('i'), # Į -> i + u('\u012f'): u('i'), # į -> i + u('\u0130'): u('i'), # İ -> i + u('\u0131'): u('i'), # ı -> i + u('\u0134'): u('j'), # Ĵ -> j + u('\u0135'): u('j'), # ĵ -> j + u('\u0136'): u('k'), # Ķ -> k + u('\u0137'): u('k'), # ķ -> k + u('\u0139'): u('a'), # Ĺ -> a + u('\u013a'): u('l'), # ĺ -> l + u('\u013b'): u('l'), # Ļ -> l + u('\u013c'): u('l'), # ļ -> l + u('\u013d'): u('l'), # Ľ -> l + u('\u013e'): u('l'), # ľ -> l + u('\u013f'): u('l'), # Ŀ -> l + u('\u0140'): u('l'), # ŀ -> l + u('\u0141'): u('l'), # Ł -> l + u('\u0142'): u('l'), # ł -> l + u('\u0143'): u('n'), # Ń -> n + u('\u0144'): u('n'), # ń -> n + u('\u0145'): u('n'), # Ņ -> n + u('\u0146'): u('n'), # ņ -> n + u('\u0147'): u('n'), # Ň -> n + u('\u0148'): u('n'), # ň -> n + u('\u014c'): u('o'), # Ō -> o + u('\u014d'): u('o'), # ō -> o + u('\u014e'): u('o'), # Ŏ -> o + u('\u014f'): u('o'), # ŏ -> o + u('\u0150'): u('o'), # Ő -> o + u('\u0151'): u('o'), # ő -> o + u('\u0154'): u('r'), # Ŕ -> r + u('\u0155'): u('r'), # ŕ -> r + u('\u0156'): u('r'), # Ŗ -> r + u('\u0157'): u('r'), # ŗ -> r + u('\u0158'): u('r'), # Ř -> r + u('\u0159'): u('r'), # ř -> r + u('\u015a'): u('s'), # Ś -> s + u('\u015b'): u('s'), # ś -> s + u('\u015c'): u('s'), # Ŝ -> s + u('\u015d'): u('s'), # ŝ -> s + u('\u015e'): u('s'), # Ş -> s + u('\u015f'): u('s'), # ş -> s + u('\u0160'): u('s'), # Š -> s + u('\u0161'): u('s'), # š -> s + u('\u0162'): u('t'), # Ţ -> t + u('\u0163'): u('t'), # ţ -> t + u('\u0164'): u('t'), # Ť -> t + u('\u0165'): u('t'), # ť -> t + u('\u0166'): u('t'), # Ŧ -> t + u('\u0167'): u('t'), # ŧ -> t + u('\u0168'): u('u'), # Ũ -> u + u('\u0169'): u('u'), # ũ -> u + u('\u016a'): u('u'), # Ū -> u + u('\u016b'): u('u'), # ū -> u + u('\u016c'): u('u'), # Ŭ -> u + u('\u016d'): u('u'), # ŭ -> u + u('\u016e'): u('u'), # Ů -> u + u('\u016f'): u('u'), # ů -> u + u('\u0170'): u('u'), # Ű -> u + u('\u0171'): u('u'), # ű -> u + u('\u0172'): u('u'), # Ų -> u + u('\u0173'): u('u'), # ų -> u + u('\u0174'): u('w'), # Ŵ -> w + u('\u0175'): u('w'), # ŵ -> w + u('\u0176'): u('y'), # Ŷ -> y + u('\u0177'): u('y'), # ŷ -> y + u('\u0178'): u('y'), # Ÿ -> y + u('\u0179'): u('z'), # Ź -> z + u('\u017a'): u('z'), # ź -> z + u('\u017b'): u('z'), # Ż -> z + u('\u017c'): u('z'), # ż -> z + u('\u017d'): u('z'), # Ž -> z + u('\u017e'): u('z'), # ž -> z + u('\u0180'): u('b'), # ƀ -> b + u('\u0181'): u('b'), # Ɓ -> b + u('\u0182'): u('b'), # Ƃ -> b + u('\u0183'): u('b'), # ƃ -> b + u('\u0187'): u('c'), # Ƈ -> c + u('\u0188'): u('c'), # ƈ -> c + u('\u0189'): u('d'), # Ɖ -> d + u('\u018a'): u('d'), # Ɗ -> d + u('\u018b'): u('d'), # Ƌ -> d + u('\u018c'): u('d'), # ƌ -> d + u('\u018e'): u('e'), # Ǝ -> e + u('\u018f'): u('e'), # Ə -> e + u('\u0191'): u('f'), # Ƒ -> f + u('\u0192'): u('f'), # ƒ -> f + u('\u0193'): u('g'), # Ɠ -> g + u('\u0197'): u('i'), # Ɨ -> i + u('\u0198'): u('k'), # Ƙ -> k + u('\u0199'): u('k'), # ƙ -> k + u('\u019a'): u('l'), # ƚ -> l + u('\u019d'): u('n'), # Ɲ -> n + u('\u019e'): u('n'), # ƞ -> n + u('\u019f'): u('o'), # Ɵ -> o + u('\u01a0'): u('o'), # Ơ -> o + u('\u01a1'): u('o'), # ơ -> o + u('\u01a4'): u('p'), # Ƥ -> p + u('\u01a5'): u('p'), # ƥ -> p + u('\u01ab'): u('t'), # ƫ -> t + u('\u01ac'): u('t'), # Ƭ -> t + u('\u01ad'): u('t'), # ƭ -> t + u('\u01ae'): u('t'), # Ʈ -> t + u('\u01af'): u('u'), # Ư -> u + u('\u01b0'): u('u'), # ư -> u + u('\u01b2'): u('v'), # Ʋ -> v + u('\u01b3'): u('y'), # Ƴ -> y + u('\u01b4'): u('y'), # ƴ -> y + u('\u01b5'): u('z'), # Ƶ -> z + u('\u01b6'): u('z'), # ƶ -> z + u('\u01ba'): u('z'), # ƺ -> z + u('\u01cd'): u('a'), # Ǎ -> a + u('\u01ce'): u('a'), # ǎ -> a + u('\u01cf'): u('i'), # Ǐ -> i + u('\u01d0'): u('i'), # ǐ -> i + u('\u01d1'): u('o'), # Ǒ -> o + u('\u01d2'): u('o'), # ǒ -> o + u('\u01d3'): u('u'), # Ǔ -> u + u('\u01d4'): u('u'), # ǔ -> u + u('\u01d5'): u('u'), # Ǖ -> u + u('\u01d6'): u('u'), # ǖ -> u + u('\u01d7'): u('u'), # Ǘ -> u + u('\u01d8'): u('u'), # ǘ -> u + u('\u01d9'): u('u'), # Ǚ -> u + u('\u01da'): u('u'), # ǚ -> u + u('\u01db'): u('u'), # Ǜ -> u + u('\u01dc'): u('u'), # ǜ -> u + u('\u01dd'): u('e'), # ǝ -> e + u('\u01de'): u('a'), # Ǟ -> a + u('\u01df'): u('a'), # ǟ -> a + u('\u01e0'): u('a'), # Ǡ -> a + u('\u01e1'): u('a'), # ǡ -> a + u('\u01e2'): u('a'), # Ǣ -> a + u('\u01e3'): u('a'), # ǣ -> a + u('\u01e4'): u('g'), # Ǥ -> g + u('\u01e5'): u('g'), # ǥ -> g + u('\u01e6'): u('g'), # Ǧ -> g + u('\u01e7'): u('g'), # ǧ -> g + u('\u01e8'): u('k'), # Ǩ -> k + u('\u01e9'): u('k'), # ǩ -> k + u('\u01ea'): u('o'), # Ǫ -> o + u('\u01eb'): u('o'), # ǫ -> o + u('\u01ec'): u('o'), # Ǭ -> o + u('\u01ed'): u('o'), # ǭ -> o + u('\u01ee'): u('z'), # Ǯ -> z + u('\u01ef'): u('z'), # ǯ -> z + u('\u01f0'): u('j'), # ǰ -> j + u('\u01f4'): u('g'), # Ǵ -> g + u('\u01f5'): u('g'), # ǵ -> g + u('\u01f8'): u('n'), # Ǹ -> n + u('\u01f9'): u('n'), # ǹ -> n + u('\u01fa'): u('a'), # Ǻ -> a + u('\u01fb'): u('a'), # ǻ -> a + u('\u01fc'): u('a'), # Ǽ -> a + u('\u01fd'): u('a'), # ǽ -> a + u('\u01fe'): u('o'), # Ǿ -> o + u('\u01ff'): u('o'), # ǿ -> o + u('\u0200'): u('a'), # Ȁ -> a + u('\u0201'): u('a'), # ȁ -> a + u('\u0202'): u('a'), # Ȃ -> a + u('\u0203'): u('a'), # ȃ -> a + u('\u0204'): u('e'), # Ȅ -> e + u('\u0205'): u('e'), # ȅ -> e + u('\u0206'): u('e'), # Ȇ -> e + u('\u0207'): u('e'), # ȇ -> e + u('\u0208'): u('i'), # Ȉ -> i + u('\u0209'): u('i'), # ȉ -> i + u('\u020a'): u('i'), # Ȋ -> i + u('\u020b'): u('i'), # ȋ -> i + u('\u020c'): u('o'), # Ȍ -> o + u('\u020d'): u('o'), # ȍ -> o + u('\u020e'): u('o'), # Ȏ -> o + u('\u020f'): u('o'), # ȏ -> o + u('\u0210'): u('r'), # Ȑ -> r + u('\u0211'): u('r'), # ȑ -> r + u('\u0212'): u('r'), # Ȓ -> r + u('\u0213'): u('r'), # ȓ -> r + u('\u0214'): u('u'), # Ȕ -> u + u('\u0215'): u('u'), # ȕ -> u + u('\u0216'): u('u'), # Ȗ -> u + u('\u0217'): u('u'), # ȗ -> u + u('\u0218'): u('s'), # Ș -> s + u('\u0219'): u('s'), # ș -> s + u('\u021a'): u('t'), # Ț -> t + u('\u021b'): u('t'), # ț -> t + u('\u021e'): u('h'), # Ȟ -> h + u('\u021f'): u('h'), # ȟ -> h + u('\u0220'): u('n'), # Ƞ -> n + u('\u0221'): u('d'), # ȡ -> d + u('\u0224'): u('z'), # Ȥ -> z + u('\u0225'): u('z'), # ȥ -> z + u('\u0226'): u('a'), # Ȧ -> a + u('\u0227'): u('a'), # ȧ -> a + u('\u0228'): u('e'), # Ȩ -> e + u('\u0229'): u('e'), # ȩ -> e + u('\u022a'): u('o'), # Ȫ -> o + u('\u022b'): u('o'), # ȫ -> o + u('\u022c'): u('o'), # Ȭ -> o + u('\u022d'): u('o'), # ȭ -> o + u('\u022e'): u('o'), # Ȯ -> o + u('\u022f'): u('o'), # ȯ -> o + u('\u0230'): u('o'), # Ȱ -> o + u('\u0231'): u('o'), # ȱ -> o + u('\u0232'): u('y'), # Ȳ -> y + u('\u0233'): u('y'), # ȳ -> y + u('\u0234'): u('l'), # ȴ -> l + u('\u0235'): u('n'), # ȵ -> n + u('\u0236'): u('t'), # ȶ -> t + u('\u0237'): u('j'), # ȷ -> j + u('\u023a'): u('a'), # Ⱥ -> a + u('\u023b'): u('c'), # Ȼ -> c + u('\u023c'): u('c'), # ȼ -> c + u('\u023d'): u('l'), # Ƚ -> l + u('\u023e'): u('t'), # Ⱦ -> t + u('\u0243'): u('b'), # Ƀ -> b + u('\u0244'): u('u'), # Ʉ -> u + u('\u0246'): u('e'), # Ɇ -> e + u('\u0247'): u('e'), # ɇ -> e + u('\u0248'): u('j'), # Ɉ -> j + u('\u0249'): u('j'), # ɉ -> j + u('\u024a'): u('q'), # Ɋ -> q + u('\u024b'): u('q'), # ɋ -> q + u('\u024c'): u('r'), # Ɍ -> r + u('\u024d'): u('r'), # ɍ -> r + u('\u024e'): u('y'), # Ɏ -> y + u('\u024f'): u('y'), # ɏ -> y + u('\u0253'): u('b'), # ɓ -> b + u('\u0255'): u('c'), # ɕ -> c + u('\u0256'): u('d'), # ɖ -> d + u('\u0257'): u('d'), # ɗ -> d + u('\u025a'): u('e'), # ɚ -> e + u('\u025d'): u('e'), # ɝ -> e + u('\u025f'): u('j'), # ɟ -> j + u('\u0260'): u('g'), # ɠ -> g + u('\u0268'): u('i'), # ɨ -> i + u('\u026b'): u('l'), # ɫ -> l + u('\u026c'): u('l'), # ɬ -> l + u('\u026d'): u('l'), # ɭ -> l + u('\u0271'): u('m'), # ɱ -> m + u('\u0272'): u('n'), # ɲ -> n + u('\u0273'): u('n'), # ɳ -> n + u('\u0275'): u('o'), # ɵ -> o + u('\u027c'): u('r'), # ɼ -> r + u('\u027d'): u('r'), # ɽ -> r + u('\u027e'): u('r'), # ɾ -> r + u('\u0282'): u('s'), # ʂ -> s + u('\u0284'): u('j'), # ʄ -> j + u('\u0288'): u('t'), # ʈ -> t + u('\u0289'): u('u'), # ʉ -> u + u('\u028b'): u('v'), # ʋ -> v + u('\u028f'): u('y'), # ʏ -> y + u('\u0290'): u('z'), # ʐ -> z + u('\u0291'): u('z'), # ʑ -> z + u('\u029d'): u('j'), # ʝ -> j + u('\u02a0'): u('q'), # ʠ -> q + u('\u0303'): u('p'), # ̃ -> p + u('\u0308'): u('t'), # ̈ -> t + u('\u030a'): u('y'), # ̊ -> y + u('\u030c'): u('j'), # ̌ -> j + u('\u0323'): u('l'), # ̣ -> l + u('\u0329'): u('s'), # ̩ -> s + u('\u0331'): u('h'), # ̱ -> h + u('\u1d6c'): u('b'), # ᵬ -> b + u('\u1d6d'): u('d'), # ᵭ -> d + u('\u1d6e'): u('f'), # ᵮ -> f + u('\u1d72'): u('r'), # ᵲ -> r + u('\u1d73'): u('r'), # ᵳ -> r + u('\u1d75'): u('t'), # ᵵ -> t + u('\u1e00'): u('a'), # Ḁ -> a + u('\u1e01'): u('a'), # ḁ -> a + u('\u1e02'): u('b'), # Ḃ -> b + u('\u1e03'): u('b'), # ḃ -> b + u('\u1e04'): u('b'), # Ḅ -> b + u('\u1e05'): u('b'), # ḅ -> b + u('\u1e06'): u('b'), # Ḇ -> b + u('\u1e07'): u('b'), # ḇ -> b + u('\u1e08'): u('c'), # Ḉ -> c + u('\u1e09'): u('c'), # ḉ -> c + u('\u1e0a'): u('d'), # Ḋ -> d + u('\u1e0b'): u('d'), # ḋ -> d + u('\u1e0c'): u('d'), # Ḍ -> d + u('\u1e0d'): u('d'), # ḍ -> d + u('\u1e0e'): u('d'), # Ḏ -> d + u('\u1e0f'): u('d'), # ḏ -> d + u('\u1e10'): u('d'), # Ḑ -> d + u('\u1e11'): u('d'), # ḑ -> d + u('\u1e12'): u('d'), # Ḓ -> d + u('\u1e13'): u('d'), # ḓ -> d + u('\u1e14'): u('e'), # Ḕ -> e + u('\u1e15'): u('e'), # ḕ -> e + u('\u1e16'): u('e'), # Ḗ -> e + u('\u1e17'): u('e'), # ḗ -> e + u('\u1e18'): u('e'), # Ḙ -> e + u('\u1e19'): u('e'), # ḙ -> e + u('\u1e1a'): u('e'), # Ḛ -> e + u('\u1e1b'): u('e'), # ḛ -> e + u('\u1e1c'): u('e'), # Ḝ -> e + u('\u1e1d'): u('e'), # ḝ -> e + u('\u1e1e'): u('f'), # Ḟ -> f + u('\u1e1f'): u('f'), # ḟ -> f + u('\u1e20'): u('g'), # Ḡ -> g + u('\u1e21'): u('g'), # ḡ -> g + u('\u1e22'): u('h'), # Ḣ -> h + u('\u1e23'): u('h'), # ḣ -> h + u('\u1e24'): u('h'), # Ḥ -> h + u('\u1e25'): u('h'), # ḥ -> h + u('\u1e26'): u('h'), # Ḧ -> h + u('\u1e27'): u('h'), # ḧ -> h + u('\u1e28'): u('h'), # Ḩ -> h + u('\u1e29'): u('h'), # ḩ -> h + u('\u1e2a'): u('h'), # Ḫ -> h + u('\u1e2b'): u('h'), # ḫ -> h + u('\u1e2c'): u('i'), # Ḭ -> i + u('\u1e2d'): u('i'), # ḭ -> i + u('\u1e2e'): u('i'), # Ḯ -> i + u('\u1e2f'): u('i'), # ḯ -> i + u('\u1e30'): u('k'), # Ḱ -> k + u('\u1e31'): u('k'), # ḱ -> k + u('\u1e32'): u('k'), # Ḳ -> k + u('\u1e33'): u('k'), # ḳ -> k + u('\u1e34'): u('k'), # Ḵ -> k + u('\u1e35'): u('k'), # ḵ -> k + u('\u1e36'): u('l'), # Ḷ -> l + u('\u1e37'): u('l'), # ḷ -> l + u('\u1e38'): u('l'), # Ḹ -> l + u('\u1e39'): u('l'), # ḹ -> l + u('\u1e3a'): u('l'), # Ḻ -> l + u('\u1e3b'): u('l'), # ḻ -> l + u('\u1e3c'): u('l'), # Ḽ -> l + u('\u1e3d'): u('l'), # ḽ -> l + u('\u1e3e'): u('m'), # Ḿ -> m + u('\u1e3f'): u('m'), # ḿ -> m + u('\u1e40'): u('m'), # Ṁ -> m + u('\u1e41'): u('m'), # ṁ -> m + u('\u1e42'): u('m'), # Ṃ -> m + u('\u1e43'): u('m'), # ṃ -> m + u('\u1e44'): u('n'), # Ṅ -> n + u('\u1e45'): u('n'), # ṅ -> n + u('\u1e46'): u('n'), # Ṇ -> n + u('\u1e47'): u('n'), # ṇ -> n + u('\u1e48'): u('n'), # Ṉ -> n + u('\u1e49'): u('n'), # ṉ -> n + u('\u1e4a'): u('n'), # Ṋ -> n + u('\u1e4b'): u('n'), # ṋ -> n + u('\u1e4c'): u('o'), # Ṍ -> o + u('\u1e4d'): u('o'), # ṍ -> o + u('\u1e4e'): u('o'), # Ṏ -> o + u('\u1e4f'): u('o'), # ṏ -> o + u('\u1e50'): u('o'), # Ṑ -> o + u('\u1e51'): u('o'), # ṑ -> o + u('\u1e52'): u('o'), # Ṓ -> o + u('\u1e53'): u('o'), # ṓ -> o + u('\u1e54'): u('p'), # Ṕ -> p + u('\u1e55'): u('p'), # ṕ -> p + u('\u1e56'): u('p'), # Ṗ -> p + u('\u1e57'): u('p'), # ṗ -> p + u('\u1e58'): u('r'), # Ṙ -> r + u('\u1e59'): u('r'), # ṙ -> r + u('\u1e5a'): u('r'), # Ṛ -> r + u('\u1e5b'): u('r'), # ṛ -> r + u('\u1e5c'): u('r'), # Ṝ -> r + u('\u1e5d'): u('r'), # ṝ -> r + u('\u1e5e'): u('r'), # Ṟ -> r + u('\u1e5f'): u('r'), # ṟ -> r + u('\u1e60'): u('s'), # Ṡ -> s + u('\u1e61'): u('s'), # ṡ -> s + u('\u1e62'): u('s'), # Ṣ -> s + u('\u1e63'): u('s'), # ṣ -> s + u('\u1e64'): u('s'), # Ṥ -> s + u('\u1e65'): u('s'), # ṥ -> s + u('\u1e66'): u('s'), # Ṧ -> s + u('\u1e67'): u('s'), # ṧ -> s + u('\u1e68'): u('s'), # Ṩ -> s + u('\u1e69'): u('s'), # ṩ -> s + u('\u1e6a'): u('t'), # Ṫ -> t + u('\u1e6b'): u('t'), # ṫ -> t + u('\u1e6c'): u('t'), # Ṭ -> t + u('\u1e6d'): u('t'), # ṭ -> t + u('\u1e6e'): u('t'), # Ṯ -> t + u('\u1e6f'): u('t'), # ṯ -> t + u('\u1e70'): u('t'), # Ṱ -> t + u('\u1e71'): u('t'), # ṱ -> t + u('\u1e72'): u('u'), # Ṳ -> u + u('\u1e73'): u('u'), # ṳ -> u + u('\u1e74'): u('u'), # Ṵ -> u + u('\u1e75'): u('u'), # ṵ -> u + u('\u1e76'): u('u'), # Ṷ -> u + u('\u1e77'): u('u'), # ṷ -> u + u('\u1e78'): u('u'), # Ṹ -> u + u('\u1e79'): u('u'), # ṹ -> u + u('\u1e7a'): u('u'), # Ṻ -> u + u('\u1e7b'): u('u'), # ṻ -> u + u('\u1e7c'): u('v'), # Ṽ -> v + u('\u1e7d'): u('v'), # ṽ -> v + u('\u1e7e'): u('v'), # Ṿ -> v + u('\u1e7f'): u('v'), # ṿ -> v + u('\u1e80'): u('w'), # Ẁ -> w + u('\u1e81'): u('w'), # ẁ -> w + u('\u1e82'): u('w'), # Ẃ -> w + u('\u1e83'): u('w'), # ẃ -> w + u('\u1e84'): u('w'), # Ẅ -> w + u('\u1e85'): u('w'), # ẅ -> w + u('\u1e86'): u('w'), # Ẇ -> w + u('\u1e87'): u('w'), # ẇ -> w + u('\u1e88'): u('w'), # Ẉ -> w + u('\u1e89'): u('w'), # ẉ -> w + u('\u1e8a'): u('x'), # Ẋ -> x + u('\u1e8b'): u('x'), # ẋ -> x + u('\u1e8c'): u('x'), # Ẍ -> x + u('\u1e8d'): u('x'), # ẍ -> x + u('\u1e8e'): u('y'), # Ẏ -> y + u('\u1e8f'): u('y'), # ẏ -> y + u('\u1e90'): u('z'), # Ẑ -> z + u('\u1e91'): u('z'), # ẑ -> z + u('\u1e92'): u('z'), # Ẓ -> z + u('\u1e93'): u('z'), # ẓ -> z + u('\u1e94'): u('z'), # Ẕ -> z + u('\u1e95'): u('z'), # ẕ -> z + u('\u1e96'): u('h'), # ẖ -> h + u('\u1e97'): u('t'), # ẗ -> t + u('\u1e98'): u('w'), # ẘ -> w + u('\u1e99'): u('y'), # ẙ -> y + u('\u1e9a'): u('a'), # ẚ -> a + u('\u1e9b'): u('s'), # ẛ -> s + u('\u1ea0'): u('a'), # Ạ -> a + u('\u1ea1'): u('a'), # ạ -> a + u('\u1ea2'): u('a'), # Ả -> a + u('\u1ea3'): u('a'), # ả -> a + u('\u1ea4'): u('a'), # Ấ -> a + u('\u1ea5'): u('a'), # ấ -> a + u('\u1ea6'): u('a'), # Ầ -> a + u('\u1ea7'): u('a'), # ầ -> a + u('\u1ea8'): u('a'), # Ẩ -> a + u('\u1ea9'): u('a'), # ẩ -> a + u('\u1eaa'): u('a'), # Ẫ -> a + u('\u1eab'): u('a'), # ẫ -> a + u('\u1eac'): u('a'), # Ậ -> a + u('\u1ead'): u('a'), # ậ -> a + u('\u1eae'): u('a'), # Ắ -> a + u('\u1eaf'): u('a'), # ắ -> a + u('\u1eb0'): u('a'), # Ằ -> a + u('\u1eb1'): u('a'), # ằ -> a + u('\u1eb2'): u('a'), # Ẳ -> a + u('\u1eb3'): u('a'), # ẳ -> a + u('\u1eb4'): u('a'), # Ẵ -> a + u('\u1eb5'): u('a'), # ẵ -> a + u('\u1eb6'): u('a'), # Ặ -> a + u('\u1eb7'): u('a'), # ặ -> a + u('\u1eb8'): u('e'), # Ẹ -> e + u('\u1eb9'): u('e'), # ẹ -> e + u('\u1eba'): u('e'), # Ẻ -> e + u('\u1ebb'): u('e'), # ẻ -> e + u('\u1ebc'): u('e'), # Ẽ -> e + u('\u1ebd'): u('e'), # ẽ -> e + u('\u1ebe'): u('e'), # Ế -> e + u('\u1ebf'): u('e'), # ế -> e + u('\u1ec0'): u('e'), # Ề -> e + u('\u1ec1'): u('e'), # ề -> e + u('\u1ec2'): u('e'), # Ể -> e + u('\u1ec3'): u('e'), # ể -> e + u('\u1ec4'): u('e'), # Ễ -> e + u('\u1ec5'): u('e'), # ễ -> e + u('\u1ec6'): u('e'), # Ệ -> e + u('\u1ec7'): u('e'), # ệ -> e + u('\u1ec8'): u('i'), # Ỉ -> i + u('\u1ec9'): u('i'), # ỉ -> i + u('\u1eca'): u('i'), # Ị -> i + u('\u1ecb'): u('i'), # ị -> i + u('\u1ecc'): u('o'), # Ọ -> o + u('\u1ecd'): u('o'), # ọ -> o + u('\u1ece'): u('o'), # Ỏ -> o + u('\u1ecf'): u('o'), # ỏ -> o + u('\u1ed0'): u('o'), # Ố -> o + u('\u1ed1'): u('o'), # ố -> o + u('\u1ed2'): u('o'), # Ồ -> o + u('\u1ed3'): u('o'), # ồ -> o + u('\u1ed4'): u('o'), # Ổ -> o + u('\u1ed5'): u('o'), # ổ -> o + u('\u1ed6'): u('o'), # Ỗ -> o + u('\u1ed7'): u('o'), # ỗ -> o + u('\u1ed8'): u('o'), # Ộ -> o + u('\u1ed9'): u('o'), # ộ -> o + u('\u1eda'): u('o'), # Ớ -> o + u('\u1edb'): u('o'), # ớ -> o + u('\u1edc'): u('o'), # Ờ -> o + u('\u1edd'): u('o'), # ờ -> o + u('\u1ede'): u('o'), # Ở -> o + u('\u1edf'): u('o'), # ở -> o + u('\u1ee0'): u('o'), # Ỡ -> o + u('\u1ee1'): u('o'), # ỡ -> o + u('\u1ee2'): u('o'), # Ợ -> o + u('\u1ee3'): u('o'), # ợ -> o + u('\u1ee4'): u('u'), # Ụ -> u + u('\u1ee5'): u('u'), # ụ -> u + u('\u1ee6'): u('u'), # Ủ -> u + u('\u1ee7'): u('u'), # ủ -> u + u('\u1ee8'): u('u'), # Ứ -> u + u('\u1ee9'): u('u'), # ứ -> u + u('\u1eea'): u('u'), # Ừ -> u + u('\u1eeb'): u('u'), # ừ -> u + u('\u1eec'): u('u'), # Ử -> u + u('\u1eed'): u('u'), # ử -> u + u('\u1eee'): u('u'), # Ữ -> u + u('\u1eef'): u('u'), # ữ -> u + u('\u1ef0'): u('u'), # Ự -> u + u('\u1ef1'): u('u'), # ự -> u + u('\u1ef2'): u('y'), # Ỳ -> y + u('\u1ef3'): u('y'), # ỳ -> y + u('\u1ef4'): u('y'), # Ỵ -> y + u('\u1ef5'): u('y'), # ỵ -> y + u('\u1ef6'): u('y'), # Ỷ -> y + u('\u1ef7'): u('y'), # ỷ -> y + u('\u1ef8'): u('y'), # Ỹ -> y + u('\u1ef9'): u('y'), # ỹ -> y + u('\u2c60'): u('l'), # Ⱡ -> l + u('\u2c61'): u('l'), # ⱡ -> l + u('\u2c62'): u('l'), # Ɫ -> l + u('\u2c63'): u('p'), # Ᵽ -> p + u('\u2c64'): u('r'), # Ɽ -> r + u('\u2c65'): u('a'), # ⱥ -> a + u('\u2c66'): u('t'), # ⱦ -> t + u('\u2c67'): u('h'), # Ⱨ -> h + u('\u2c68'): u('h'), # ⱨ -> h + u('\u2c69'): u('k'), # Ⱪ -> k + u('\u2c6a'): u('k'), # ⱪ -> k + u('\u2c6b'): u('z'), # Ⱬ -> z + u('\u2c6c'): u('z'), # ⱬ -> z + u('\uff10'): u('0'), # 0 -> 0 + u('\uff11'): u('1'), # 1 -> 1 + u('\uff12'): u('2'), # 2 -> 2 + u('\uff13'): u('3'), # 3 -> 3 + u('\uff14'): u('4'), # 4 -> 4 + u('\uff15'): u('5'), # 5 -> 5 + u('\uff16'): u('6'), # 6 -> 6 + u('\uff17'): u('7'), # 7 -> 7 + u('\uff18'): u('8'), # 8 -> 8 + u('\uff19'): u('9'), # 9 -> 9 + u('\uff21'): u('A'), # A -> A + u('\uff22'): u('B'), # B -> B + u('\uff23'): u('C'), # C -> C + u('\uff24'): u('D'), # D -> D + u('\uff25'): u('E'), # E -> E + u('\uff26'): u('F'), # F -> F + u('\uff27'): u('G'), # G -> G + u('\uff28'): u('H'), # H -> H + u('\uff29'): u('I'), # I -> I + u('\uff2a'): u('J'), # J -> J + u('\uff2b'): u('K'), # K -> K + u('\uff2c'): u('L'), # L -> L + u('\uff2d'): u('M'), # M -> M + u('\uff2e'): u('N'), # N -> N + u('\uff2f'): u('O'), # O -> O + u('\uff30'): u('P'), # P -> P + u('\uff31'): u('Q'), # Q -> Q + u('\uff32'): u('R'), # R -> R + u('\uff33'): u('S'), # S -> S + u('\uff34'): u('T'), # T -> T + u('\uff35'): u('U'), # U -> U + u('\uff36'): u('V'), # V -> V + u('\uff37'): u('W'), # W -> W + u('\uff38'): u('X'), # X -> X + u('\uff39'): u('Y'), # Y -> Y + u('\uff3a'): u('Z'), # Z -> Z + u('\uff41'): u('a'), # a -> a + u('\uff42'): u('b'), # b -> b + u('\uff43'): u('c'), # c -> c + u('\uff44'): u('d'), # d -> d + u('\uff45'): u('e'), # e -> e + u('\uff46'): u('f'), # f -> f + u('\uff47'): u('g'), # g -> g + u('\uff48'): u('h'), # h -> h + u('\uff49'): u('i'), # i -> i + u('\uff4a'): u('j'), # j -> j + u('\uff4b'): u('k'), # k -> k + u('\uff4c'): u('l'), # l -> l + u('\uff4d'): u('m'), # m -> m + u('\uff4e'): u('n'), # n -> n + u('\uff4f'): u('o'), # o -> o + u('\uff50'): u('p'), # p -> p + u('\uff51'): u('q'), # q -> q + u('\uff52'): u('r'), # r -> r + u('\uff53'): u('s'), # s -> s + u('\uff54'): u('t'), # t -> t + u('\uff55'): u('u'), # u -> u + u('\uff56'): u('v'), # v -> v + u('\uff57'): u('w'), # w -> w + u('\uff58'): u('x'), # x -> x + u('\uff59'): u('y'), # y -> y + u('\uff5a'): u('z'), # z -> z +} + +# The unicode.translate() method actually requires a dictionary mapping +# character *numbers* to characters, for some reason. +accent_map = dict((ord(k), v) for k, v in iteritems(accent_map)) + + +# This Sphinx charset table taken from http://speeple.com/unicode-maps.txt + +default_charset = """ +################################################## +# Latin +# A +U+00C0->a, U+00C1->a, U+00C2->a, U+00C3->a, U+00C4->a, U+00C5->a, U+00E0->a, U+00E1->a, U+00E2->a, U+00E3->a, U+00E4->a, U+00E5->a, +U+0100->a, U+0101->a, U+0102->a, U+0103->a, U+010300->a, U+0104->a, U+0105->a, U+01CD->a, U+01CE->a, U+01DE->a, U+01DF->a, U+01E0->a, +U+01E1->a, U+01FA->a, U+01FB->a, U+0200->a, U+0201->a, U+0202->a, U+0203->a, U+0226->a, U+0227->a, U+023A->a, U+0250->a, U+04D0->a, +U+04D1->a, U+1D2C->a, U+1D43->a, U+1D44->a, U+1D8F->a, U+1E00->a, U+1E01->a, U+1E9A->a, U+1EA0->a, U+1EA1->a, U+1EA2->a, U+1EA3->a, +U+1EA4->a, U+1EA5->a, U+1EA6->a, U+1EA7->a, U+1EA8->a, U+1EA9->a, U+1EAA->a, U+1EAB->a, U+1EAC->a, U+1EAD->a, U+1EAE->a, U+1EAF->a, +U+1EB0->a, U+1EB1->a, U+1EB2->a, U+1EB3->a, U+1EB4->a, U+1EB5->a, U+1EB6->a, U+1EB7->a, U+2090->a, U+2C65->a + +# B +U+0180->b, U+0181->b, U+0182->b, U+0183->b, U+0243->b, U+0253->b, U+0299->b, U+16D2->b, U+1D03->b, U+1D2E->b, U+1D2F->b, U+1D47->b, +U+1D6C->b, U+1D80->b, U+1E02->b, U+1E03->b, U+1E04->b, U+1E05->b, U+1E06->b, U+1E07->b + +# C +U+00C7->c, U+00E7->c, U+0106->c, U+0107->c, U+0108->c, U+0109->c, U+010A->c, U+010B->c, U+010C->c, U+010D->c, U+0187->c, U+0188->c, +U+023B->c, U+023C->c, U+0255->c, U+0297->c, U+1D9C->c, U+1D9D->c, U+1E08->c, U+1E09->c, U+212D->c, U+2184->c + +# D +U+010E->d, U+010F->d, U+0110->d, U+0111->d, U+0189->d, U+018A->d, U+018B->d, U+018C->d, U+01C5->d, U+01F2->d, U+0221->d, U+0256->d, +U+0257->d, U+1D05->d, U+1D30->d, U+1D48->d, U+1D6D->d, U+1D81->d, U+1D91->d, U+1E0A->d, U+1E0B->d, U+1E0C->d, U+1E0D->d, U+1E0E->d, +U+1E0F->d, U+1E10->d, U+1E11->d, U+1E12->d, U+1E13->d + +# E +U+00C8->e, U+00C9->e, U+00CA->e, U+00CB->e, U+00E8->e, U+00E9->e, U+00EA->e, U+00EB->e, U+0112->e, U+0113->e, U+0114->e, U+0115->e, +U+0116->e, U+0117->e, U+0118->e, U+0119->e, U+011A->e, U+011B->e, U+018E->e, U+0190->e, U+01DD->e, U+0204->e, U+0205->e, U+0206->e, +U+0207->e, U+0228->e, U+0229->e, U+0246->e, U+0247->e, U+0258->e, U+025B->e, U+025C->e, U+025D->e, U+025E->e, U+029A->e, U+1D07->e, +U+1D08->e, U+1D31->e, U+1D32->e, U+1D49->e, U+1D4B->e, U+1D4C->e, U+1D92->e, U+1D93->e, U+1D94->e, U+1D9F->e, U+1E14->e, U+1E15->e, +U+1E16->e, U+1E17->e, U+1E18->e, U+1E19->e, U+1E1A->e, U+1E1B->e, U+1E1C->e, U+1E1D->e, U+1EB8->e, U+1EB9->e, U+1EBA->e, U+1EBB->e, +U+1EBC->e, U+1EBD->e, U+1EBE->e, U+1EBF->e, U+1EC0->e, U+1EC1->e, U+1EC2->e, U+1EC3->e, U+1EC4->e, U+1EC5->e, U+1EC6->e, U+1EC7->e, +U+2091->e + +# F +U+0191->f, U+0192->f, U+1D6E->f, U+1D82->f, U+1DA0->f, U+1E1E->f, U+1E1F->f + +# G +U+011C->g, U+011D->g, U+011E->g, U+011F->g, U+0120->g, U+0121->g, U+0122->g, U+0123->g, U+0193->g, U+01E4->g, U+01E5->g, U+01E6->g, +U+01E7->g, U+01F4->g, U+01F5->g, U+0260->g, U+0261->g, U+0262->g, U+029B->g, U+1D33->g, U+1D4D->g, U+1D77->g, U+1D79->g, U+1D83->g, +U+1DA2->g, U+1E20->g, U+1E21->g + +# H +U+0124->h, U+0125->h, U+0126->h, U+0127->h, U+021E->h, U+021F->h, U+0265->h, U+0266->h, U+029C->h, U+02AE->h, U+02AF->h, U+02B0->h, +U+02B1->h, U+1D34->h, U+1DA3->h, U+1E22->h, U+1E23->h, U+1E24->h, U+1E25->h, U+1E26->h, U+1E27->h, U+1E28->h, U+1E29->h, U+1E2A->h, +U+1E2B->h, U+1E96->h, U+210C->h, U+2C67->h, U+2C68->h, U+2C75->h, U+2C76->h + +# I +U+00CC->i, U+00CD->i, U+00CE->i, U+00CF->i, U+00EC->i, U+00ED->i, U+00EE->i, U+00EF->i, U+010309->i, U+0128->i, U+0129->i, U+012A->i, +U+012B->i, U+012C->i, U+012D->i, U+012E->i, U+012F->i, U+0130->i, U+0131->i, U+0197->i, U+01CF->i, U+01D0->i, U+0208->i, U+0209->i, +U+020A->i, U+020B->i, U+0268->i, U+026A->i, U+040D->i, U+0418->i, U+0419->i, U+0438->i, U+0439->i, U+0456->i, U+1D09->i, U+1D35->i, +U+1D4E->i, U+1D62->i, U+1D7B->i, U+1D96->i, U+1DA4->i, U+1DA6->i, U+1DA7->i, U+1E2C->i, U+1E2D->i, U+1E2E->i, U+1E2F->i, U+1EC8->i, +U+1EC9->i, U+1ECA->i, U+1ECB->i, U+2071->i, U+2111->i + +# J +U+0134->j, U+0135->j, U+01C8->j, U+01CB->j, U+01F0->j, U+0237->j, U+0248->j, U+0249->j, U+025F->j, U+0284->j, U+029D->j, U+02B2->j, +U+1D0A->j, U+1D36->j, U+1DA1->j, U+1DA8->j + +# K +U+0136->k, U+0137->k, U+0198->k, U+0199->k, U+01E8->k, U+01E9->k, U+029E->k, U+1D0B->k, U+1D37->k, U+1D4F->k, U+1D84->k, U+1E30->k, +U+1E31->k, U+1E32->k, U+1E33->k, U+1E34->k, U+1E35->k, U+2C69->k, U+2C6A->k + +# L +U+0139->l, U+013A->l, U+013B->l, U+013C->l, U+013D->l, U+013E->l, U+013F->l, U+0140->l, U+0141->l, U+0142->l, U+019A->l, U+01C8->l, +U+0234->l, U+023D->l, U+026B->l, U+026C->l, U+026D->l, U+029F->l, U+02E1->l, U+1D0C->l, U+1D38->l, U+1D85->l, U+1DA9->l, U+1DAA->l, +U+1DAB->l, U+1E36->l, U+1E37->l, U+1E38->l, U+1E39->l, U+1E3A->l, U+1E3B->l, U+1E3C->l, U+1E3D->l, U+2C60->l, U+2C61->l, U+2C62->l + +# M +U+019C->m, U+026F->m, U+0270->m, U+0271->m, U+1D0D->m, U+1D1F->m, U+1D39->m, U+1D50->m, U+1D5A->m, U+1D6F->m, U+1D86->m, U+1DAC->m, +U+1DAD->m, U+1E3E->m, U+1E3F->m, U+1E40->m, U+1E41->m, U+1E42->m, U+1E43->m + +# N +U+00D1->n, U+00F1->n, U+0143->n, U+0144->n, U+0145->n, U+0146->n, U+0147->n, U+0148->n, U+0149->n, U+019D->n, U+019E->n, U+01CB->n, +U+01F8->n, U+01F9->n, U+0220->n, U+0235->n, U+0272->n, U+0273->n, U+0274->n, U+1D0E->n, U+1D3A->n, U+1D3B->n, U+1D70->n, U+1D87->n, +U+1DAE->n, U+1DAF->n, U+1DB0->n, U+1E44->n, U+1E45->n, U+1E46->n, U+1E47->n, U+1E48->n, U+1E49->n, U+1E4A->n, U+1E4B->n, U+207F->n + +# O +U+00D2->o, U+00D3->o, U+00D4->o, U+00D5->o, U+00D6->o, U+00D8->o, U+00F2->o, U+00F3->o, U+00F4->o, U+00F5->o, U+00F6->o, U+00F8->o, +U+01030F->o, U+014C->o, U+014D->o, U+014E->o, U+014F->o, U+0150->o, U+0151->o, U+0186->o, U+019F->o, U+01A0->o, U+01A1->o, U+01D1->o, +U+01D2->o, U+01EA->o, U+01EB->o, U+01EC->o, U+01ED->o, U+01FE->o, U+01FF->o, U+020C->o, U+020D->o, U+020E->o, U+020F->o, U+022A->o, +U+022B->o, U+022C->o, U+022D->o, U+022E->o, U+022F->o, U+0230->o, U+0231->o, U+0254->o, U+0275->o, U+043E->o, U+04E6->o, U+04E7->o, +U+04E8->o, U+04E9->o, U+04EA->o, U+04EB->o, U+1D0F->o, U+1D10->o, U+1D11->o, U+1D12->o, U+1D13->o, U+1D16->o, U+1D17->o, U+1D3C->o, +U+1D52->o, U+1D53->o, U+1D54->o, U+1D55->o, U+1D97->o, U+1DB1->o, U+1E4C->o, U+1E4D->o, U+1E4E->o, U+1E4F->o, U+1E50->o, U+1E51->o, +U+1E52->o, U+1E53->o, U+1ECC->o, U+1ECD->o, U+1ECE->o, U+1ECF->o, U+1ED0->o, U+1ED1->o, U+1ED2->o, U+1ED3->o, U+1ED4->o, U+1ED5->o, +U+1ED6->o, U+1ED7->o, U+1ED8->o, U+1ED9->o, U+1EDA->o, U+1EDB->o, U+1EDC->o, U+1EDD->o, U+1EDE->o, U+1EDF->o, U+1EE0->o, U+1EE1->o, +U+1EE2->o, U+1EE3->o, U+2092->o, U+2C9E->o, U+2C9F->o + +# P +U+01A4->p, U+01A5->p, U+1D18->p, U+1D3E->p, U+1D56->p, U+1D71->p, U+1D7D->p, U+1D88->p, U+1E54->p, U+1E55->p, U+1E56->p, U+1E57->p, +U+2C63->p + +# Q +U+024A->q, U+024B->q, U+02A0->q + +# R +U+0154->r, U+0155->r, U+0156->r, U+0157->r, U+0158->r, U+0159->r, U+0210->r, U+0211->r, U+0212->r, U+0213->r, U+024C->r, U+024D->r, +U+0279->r, U+027A->r, U+027B->r, U+027C->r, U+027D->r, U+027E->r, U+027F->r, U+0280->r, U+0281->r, U+02B3->r, U+02B4->r, U+02B5->r, +U+02B6->r, U+1D19->r, U+1D1A->r, U+1D3F->r, U+1D63->r, U+1D72->r, U+1D73->r, U+1D89->r, U+1DCA->r, U+1E58->r, U+1E59->r, U+1E5A->r, +U+1E5B->r, U+1E5C->r, U+1E5D->r, U+1E5E->r, U+1E5F->r, U+211C->r, U+2C64->r + +# S +U+00DF->s, U+015A->s, U+015B->s, U+015C->s, U+015D->s, U+015E->s, U+015F->s, U+0160->s, U+0161->s, U+017F->s, U+0218->s, U+0219->s, +U+023F->s, U+0282->s, U+02E2->s, U+1D74->s, U+1D8A->s, U+1DB3->s, U+1E60->s, U+1E61->s, U+1E62->s, U+1E63->s, U+1E64->s, U+1E65->s, +U+1E66->s, U+1E67->s, U+1E68->s, U+1E69->s, U+1E9B->s + +# T +U+0162->t, U+0163->t, U+0164->t, U+0165->t, U+0166->t, U+0167->t, U+01AB->t, U+01AC->t, U+01AD->t, U+01AE->t, U+021A->t, U+021B->t, +U+0236->t, U+023E->t, U+0287->t, U+0288->t, U+1D1B->t, U+1D40->t, U+1D57->t, U+1D75->t, U+1DB5->t, U+1E6A->t, U+1E6B->t, U+1E6C->t, +U+1E6D->t, U+1E6E->t, U+1E6F->t, U+1E70->t, U+1E71->t, U+1E97->t, U+2C66->t + +# U +U+00D9->u, U+00DA->u, U+00DB->u, U+00DC->u, U+00F9->u, U+00FA->u, U+00FB->u, U+00FC->u, U+010316->u, U+0168->u, U+0169->u, U+016A->u, +U+016B->u, U+016C->u, U+016D->u, U+016E->u, U+016F->u, U+0170->u, U+0171->u, U+0172->u, U+0173->u, U+01AF->u, U+01B0->u, U+01D3->u, +U+01D4->u, U+01D5->u, U+01D6->u, U+01D7->u, U+01D8->u, U+01D9->u, U+01DA->u, U+01DB->u, U+01DC->u, U+0214->u, U+0215->u, U+0216->u, +U+0217->u, U+0244->u, U+0289->u, U+1D1C->u, U+1D1D->u, U+1D1E->u, U+1D41->u, U+1D58->u, U+1D59->u, U+1D64->u, U+1D7E->u, U+1D99->u, +U+1DB6->u, U+1DB8->u, U+1E72->u, U+1E73->u, U+1E74->u, U+1E75->u, U+1E76->u, U+1E77->u, U+1E78->u, U+1E79->u, U+1E7A->u, U+1E7B->u, +U+1EE4->u, U+1EE5->u, U+1EE6->u, U+1EE7->u, U+1EE8->u, U+1EE9->u, U+1EEA->u, U+1EEB->u, U+1EEC->u, U+1EED->u, U+1EEE->u, U+1EEF->u, +U+1EF0->u, U+1EF1->u + +# V +U+01B2->v, U+0245->v, U+028B->v, U+028C->v, U+1D20->v, U+1D5B->v, U+1D65->v, U+1D8C->v, U+1DB9->v, U+1DBA->v, U+1E7C->v, U+1E7D->v, +U+1E7E->v, U+1E7F->v, U+2C74->v + +# W +U+0174->w, U+0175->w, U+028D->w, U+02B7->w, U+1D21->w, U+1D42->w, U+1E80->w, U+1E81->w, U+1E82->w, U+1E83->w, U+1E84->w, U+1E85->w, +U+1E86->w, U+1E87->w, U+1E88->w, U+1E89->w, U+1E98->w + +# X +U+02E3->x, U+1D8D->x, U+1E8A->x, U+1E8B->x, U+1E8C->x, U+1E8D->x, U+2093->x + +# Y +U+00DD->y, U+00FD->y, U+00FF->y, U+0176->y, U+0177->y, U+0178->y, U+01B3->y, U+01B4->y, U+0232->y, U+0233->y, U+024E->y, U+024F->y, +U+028E->y, U+028F->y, U+02B8->y, U+1E8E->y, U+1E8F->y, U+1E99->y, U+1EF2->y, U+1EF3->y, U+1EF4->y, U+1EF5->y, U+1EF6->y, U+1EF7->y, +U+1EF8->y, U+1EF9->y + +# Z +U+0179->z, U+017A->z, U+017B->z, U+017C->z, U+017D->z, U+017E->z, U+01B5->z, U+01B6->z, U+0224->z, U+0225->z, U+0240->z, U+0290->z, +U+0291->z, U+1D22->z, U+1D76->z, U+1D8E->z, U+1DBB->z, U+1DBC->z, U+1DBD->z, U+1E90->z, U+1E91->z, U+1E92->z, U+1E93->z, U+1E94->z, +U+1E95->z, U+2128->z, U+2C6B->z, U+2C6C->z + +# Latin Extras: +U+00C6->U+00E6, U+01E2->U+00E6, U+01E3->U+00E6, U+01FC->U+00E6, U+01FD->U+00E6, U+1D01->U+00E6, U+1D02->U+00E6, U+1D2D->U+00E6, +U+1D46->U+00E6, U+00E6 + +################################################## +# Arabic +U+0622->U+0627, U+0623->U+0627, U+0624->U+0648, U+0625->U+0627, U+0626->U+064A, U+06C0->U+06D5, U+06C2->U+06C1, U+06D3->U+06D2, +U+FB50->U+0671, U+FB51->U+0671, U+FB52->U+067B, U+FB53->U+067B, U+FB54->U+067B, U+FB56->U+067E, U+FB57->U+067E, U+FB58->U+067E, +U+FB5A->U+0680, U+FB5B->U+0680, U+FB5C->U+0680, U+FB5E->U+067A, U+FB5F->U+067A, U+FB60->U+067A, U+FB62->U+067F, U+FB63->U+067F, +U+FB64->U+067F, U+FB66->U+0679, U+FB67->U+0679, U+FB68->U+0679, U+FB6A->U+06A4, U+FB6B->U+06A4, U+FB6C->U+06A4, U+FB6E->U+06A6, +U+FB6F->U+06A6, U+FB70->U+06A6, U+FB72->U+0684, U+FB73->U+0684, U+FB74->U+0684, U+FB76->U+0683, U+FB77->U+0683, U+FB78->U+0683, +U+FB7A->U+0686, U+FB7B->U+0686, U+FB7C->U+0686, U+FB7E->U+0687, U+FB7F->U+0687, U+FB80->U+0687, U+FB82->U+068D, U+FB83->U+068D, +U+FB84->U+068C, U+FB85->U+068C, U+FB86->U+068E, U+FB87->U+068E, U+FB88->U+0688, U+FB89->U+0688, U+FB8A->U+0698, U+FB8B->U+0698, +U+FB8C->U+0691, U+FB8D->U+0691, U+FB8E->U+06A9, U+FB8F->U+06A9, U+FB90->U+06A9, U+FB92->U+06AF, U+FB93->U+06AF, U+FB94->U+06AF, +U+FB96->U+06B3, U+FB97->U+06B3, U+FB98->U+06B3, U+FB9A->U+06B1, U+FB9B->U+06B1, U+FB9C->U+06B1, U+FB9E->U+06BA, U+FB9F->U+06BA, +U+FBA0->U+06BB, U+FBA1->U+06BB, U+FBA2->U+06BB, U+FBA4->U+06C0, U+FBA5->U+06C0, U+FBA6->U+06C1, U+FBA7->U+06C1, U+FBA8->U+06C1, +U+FBAA->U+06BE, U+FBAB->U+06BE, U+FBAC->U+06BE, U+FBAE->U+06D2, U+FBAF->U+06D2, U+FBB0->U+06D3, U+FBB1->U+06D3, U+FBD3->U+06AD, +U+FBD4->U+06AD, U+FBD5->U+06AD, U+FBD7->U+06C7, U+FBD8->U+06C7, U+FBD9->U+06C6, U+FBDA->U+06C6, U+FBDB->U+06C8, U+FBDC->U+06C8, +U+FBDD->U+0677, U+FBDE->U+06CB, U+FBDF->U+06CB, U+FBE0->U+06C5, U+FBE1->U+06C5, U+FBE2->U+06C9, U+FBE3->U+06C9, U+FBE4->U+06D0, +U+FBE5->U+06D0, U+FBE6->U+06D0, U+FBE8->U+0649, U+FBFC->U+06CC, U+FBFD->U+06CC, U+FBFE->U+06CC, U+0621, U+0627..U+063A, U+0641..U+064A, +U+0660..U+0669, U+066E, U+066F, U+0671..U+06BF, U+06C1, U+06C3..U+06D2, U+06D5, U+06EE..U+06FC, U+06FF, U+0750..U+076D, U+FB55, U+FB59, +U+FB5D, U+FB61, U+FB65, U+FB69, U+FB6D, U+FB71, U+FB75, U+FB79, U+FB7D, U+FB81, U+FB91, U+FB95, U+FB99, U+FB9D, U+FBA3, U+FBA9, U+FBAD, +U+FBD6, U+FBE7, U+FBE9, U+FBFF + +################################################## +# Armenian +U+0531..U+0556->U+0561..U+0586, U+0561..U+0586, U+0587 + +################################################# +# Bengali +U+09DC->U+09A1, U+09DD->U+09A2, U+09DF->U+09AF, U+09F0->U+09AC, U+09F1->U+09AC, U+0985..U+0990, U+0993..U+09B0, U+09B2, U+09B6..U+09B9, +U+09CE, U+09E0, U+09E1, U+09E6..U+09EF + +################################################# +# CJK* +U+F900->U+8C48, U+F901->U+66F4, U+F902->U+8ECA, U+F903->U+8CC8, U+F904->U+6ED1, U+F905->U+4E32, U+F906->U+53E5, U+F907->U+9F9C, +U+F908->U+9F9C, U+F909->U+5951, U+F90A->U+91D1, U+F90B->U+5587, U+F90C->U+5948, U+F90D->U+61F6, U+F90E->U+7669, U+F90F->U+7F85, +U+F910->U+863F, U+F911->U+87BA, U+F912->U+88F8, U+F913->U+908F, U+F914->U+6A02, U+F915->U+6D1B, U+F916->U+70D9, U+F917->U+73DE, +U+F918->U+843D, U+F919->U+916A, U+F91A->U+99F1, U+F91B->U+4E82, U+F91C->U+5375, U+F91D->U+6B04, U+F91E->U+721B, U+F91F->U+862D, +U+F920->U+9E1E, U+F921->U+5D50, U+F922->U+6FEB, U+F923->U+85CD, U+F924->U+8964, U+F925->U+62C9, U+F926->U+81D8, U+F927->U+881F, +U+F928->U+5ECA, U+F929->U+6717, U+F92A->U+6D6A, U+F92B->U+72FC, U+F92C->U+90CE, U+F92D->U+4F86, U+F92E->U+51B7, U+F92F->U+52DE, +U+F930->U+64C4, U+F931->U+6AD3, U+F932->U+7210, U+F933->U+76E7, U+F934->U+8001, U+F935->U+8606, U+F936->U+865C, U+F937->U+8DEF, +U+F938->U+9732, U+F939->U+9B6F, U+F93A->U+9DFA, U+F93B->U+788C, U+F93C->U+797F, U+F93D->U+7DA0, U+F93E->U+83C9, U+F93F->U+9304, +U+F940->U+9E7F, U+F941->U+8AD6, U+F942->U+58DF, U+F943->U+5F04, U+F944->U+7C60, U+F945->U+807E, U+F946->U+7262, U+F947->U+78CA, +U+F948->U+8CC2, U+F949->U+96F7, U+F94A->U+58D8, U+F94B->U+5C62, U+F94C->U+6A13, U+F94D->U+6DDA, U+F94E->U+6F0F, U+F94F->U+7D2F, +U+F950->U+7E37, U+F951->U+964B, U+F952->U+52D2, U+F953->U+808B, U+F954->U+51DC, U+F955->U+51CC, U+F956->U+7A1C, U+F957->U+7DBE, +U+F958->U+83F1, U+F959->U+9675, U+F95A->U+8B80, U+F95B->U+62CF, U+F95C->U+6A02, U+F95D->U+8AFE, U+F95E->U+4E39, U+F95F->U+5BE7, +U+F960->U+6012, U+F961->U+7387, U+F962->U+7570, U+F963->U+5317, U+F964->U+78FB, U+F965->U+4FBF, U+F966->U+5FA9, U+F967->U+4E0D, +U+F968->U+6CCC, U+F969->U+6578, U+F96A->U+7D22, U+F96B->U+53C3, U+F96C->U+585E, U+F96D->U+7701, U+F96E->U+8449, U+F96F->U+8AAA, +U+F970->U+6BBA, U+F971->U+8FB0, U+F972->U+6C88, U+F973->U+62FE, U+F974->U+82E5, U+F975->U+63A0, U+F976->U+7565, U+F977->U+4EAE, +U+F978->U+5169, U+F979->U+51C9, U+F97A->U+6881, U+F97B->U+7CE7, U+F97C->U+826F, U+F97D->U+8AD2, U+F97E->U+91CF, U+F97F->U+52F5, +U+F980->U+5442, U+F981->U+5973, U+F982->U+5EEC, U+F983->U+65C5, U+F984->U+6FFE, U+F985->U+792A, U+F986->U+95AD, U+F987->U+9A6A, +U+F988->U+9E97, U+F989->U+9ECE, U+F98A->U+529B, U+F98B->U+66C6, U+F98C->U+6B77, U+F98D->U+8F62, U+F98E->U+5E74, U+F98F->U+6190, +U+F990->U+6200, U+F991->U+649A, U+F992->U+6F23, U+F993->U+7149, U+F994->U+7489, U+F995->U+79CA, U+F996->U+7DF4, U+F997->U+806F, +U+F998->U+8F26, U+F999->U+84EE, U+F99A->U+9023, U+F99B->U+934A, U+F99C->U+5217, U+F99D->U+52A3, U+F99E->U+54BD, U+F99F->U+70C8, +U+F9A0->U+88C2, U+F9A1->U+8AAA, U+F9A2->U+5EC9, U+F9A3->U+5FF5, U+F9A4->U+637B, U+F9A5->U+6BAE, U+F9A6->U+7C3E, U+F9A7->U+7375, +U+F9A8->U+4EE4, U+F9A9->U+56F9, U+F9AA->U+5BE7, U+F9AB->U+5DBA, U+F9AC->U+601C, U+F9AD->U+73B2, U+F9AE->U+7469, U+F9AF->U+7F9A, +U+F9B0->U+8046, U+F9B1->U+9234, U+F9B2->U+96F6, U+F9B3->U+9748, U+F9B4->U+9818, U+F9B5->U+4F8B, U+F9B6->U+79AE, U+F9B7->U+91B4, +U+F9B8->U+96B8, U+F9B9->U+60E1, U+F9BA->U+4E86, U+F9BB->U+50DA, U+F9BC->U+5BEE, U+F9BD->U+5C3F, U+F9BE->U+6599, U+F9BF->U+6A02, +U+F9C0->U+71CE, U+F9C1->U+7642, U+F9C2->U+84FC, U+F9C3->U+907C, U+F9C4->U+9F8D, U+F9C5->U+6688, U+F9C6->U+962E, U+F9C7->U+5289, +U+F9C8->U+677B, U+F9C9->U+67F3, U+F9CA->U+6D41, U+F9CB->U+6E9C, U+F9CC->U+7409, U+F9CD->U+7559, U+F9CE->U+786B, U+F9CF->U+7D10, +U+F9D0->U+985E, U+F9D1->U+516D, U+F9D2->U+622E, U+F9D3->U+9678, U+F9D4->U+502B, U+F9D5->U+5D19, U+F9D6->U+6DEA, U+F9D7->U+8F2A, +U+F9D8->U+5F8B, U+F9D9->U+6144, U+F9DA->U+6817, U+F9DB->U+7387, U+F9DC->U+9686, U+F9DD->U+5229, U+F9DE->U+540F, U+F9DF->U+5C65, +U+F9E0->U+6613, U+F9E1->U+674E, U+F9E2->U+68A8, U+F9E3->U+6CE5, U+F9E4->U+7406, U+F9E5->U+75E2, U+F9E6->U+7F79, U+F9E7->U+88CF, +U+F9E8->U+88E1, U+F9E9->U+91CC, U+F9EA->U+96E2, U+F9EB->U+533F, U+F9EC->U+6EBA, U+F9ED->U+541D, U+F9EE->U+71D0, U+F9EF->U+7498, +U+F9F0->U+85FA, U+F9F1->U+96A3, U+F9F2->U+9C57, U+F9F3->U+9E9F, U+F9F4->U+6797, U+F9F5->U+6DCB, U+F9F6->U+81E8, U+F9F7->U+7ACB, +U+F9F8->U+7B20, U+F9F9->U+7C92, U+F9FA->U+72C0, U+F9FB->U+7099, U+F9FC->U+8B58, U+F9FD->U+4EC0, U+F9FE->U+8336, U+F9FF->U+523A, +U+FA00->U+5207, U+FA01->U+5EA6, U+FA02->U+62D3, U+FA03->U+7CD6, U+FA04->U+5B85, U+FA05->U+6D1E, U+FA06->U+66B4, U+FA07->U+8F3B, +U+FA08->U+884C, U+FA09->U+964D, U+FA0A->U+898B, U+FA0B->U+5ED3, U+FA0C->U+5140, U+FA0D->U+55C0, U+FA10->U+585A, U+FA12->U+6674, +U+FA15->U+51DE, U+FA16->U+732A, U+FA17->U+76CA, U+FA18->U+793C, U+FA19->U+795E, U+FA1A->U+7965, U+FA1B->U+798F, U+FA1C->U+9756, +U+FA1D->U+7CBE, U+FA1E->U+7FBD, U+FA20->U+8612, U+FA22->U+8AF8, U+FA25->U+9038, U+FA26->U+90FD, U+FA2A->U+98EF, U+FA2B->U+98FC, +U+FA2C->U+9928, U+FA2D->U+9DB4, U+FA30->U+4FAE, U+FA31->U+50E7, U+FA32->U+514D, U+FA33->U+52C9, U+FA34->U+52E4, U+FA35->U+5351, +U+FA36->U+559D, U+FA37->U+5606, U+FA38->U+5668, U+FA39->U+5840, U+FA3A->U+58A8, U+FA3B->U+5C64, U+FA3C->U+5C6E, U+FA3D->U+6094, +U+FA3E->U+6168, U+FA3F->U+618E, U+FA40->U+61F2, U+FA41->U+654F, U+FA42->U+65E2, U+FA43->U+6691, U+FA44->U+6885, U+FA45->U+6D77, +U+FA46->U+6E1A, U+FA47->U+6F22, U+FA48->U+716E, U+FA49->U+722B, U+FA4A->U+7422, U+FA4B->U+7891, U+FA4C->U+793E, U+FA4D->U+7949, +U+FA4E->U+7948, U+FA4F->U+7950, U+FA50->U+7956, U+FA51->U+795D, U+FA52->U+798D, U+FA53->U+798E, U+FA54->U+7A40, U+FA55->U+7A81, +U+FA56->U+7BC0, U+FA57->U+7DF4, U+FA58->U+7E09, U+FA59->U+7E41, U+FA5A->U+7F72, U+FA5B->U+8005, U+FA5C->U+81ED, U+FA5D->U+8279, +U+FA5E->U+8279, U+FA5F->U+8457, U+FA60->U+8910, U+FA61->U+8996, U+FA62->U+8B01, U+FA63->U+8B39, U+FA64->U+8CD3, U+FA65->U+8D08, +U+FA66->U+8FB6, U+FA67->U+9038, U+FA68->U+96E3, U+FA69->U+97FF, U+FA6A->U+983B, U+FA70->U+4E26, U+FA71->U+51B5, U+FA72->U+5168, +U+FA73->U+4F80, U+FA74->U+5145, U+FA75->U+5180, U+FA76->U+52C7, U+FA77->U+52FA, U+FA78->U+559D, U+FA79->U+5555, U+FA7A->U+5599, +U+FA7B->U+55E2, U+FA7C->U+585A, U+FA7D->U+58B3, U+FA7E->U+5944, U+FA7F->U+5954, U+FA80->U+5A62, U+FA81->U+5B28, U+FA82->U+5ED2, +U+FA83->U+5ED9, U+FA84->U+5F69, U+FA85->U+5FAD, U+FA86->U+60D8, U+FA87->U+614E, U+FA88->U+6108, U+FA89->U+618E, U+FA8A->U+6160, +U+FA8B->U+61F2, U+FA8C->U+6234, U+FA8D->U+63C4, U+FA8E->U+641C, U+FA8F->U+6452, U+FA90->U+6556, U+FA91->U+6674, U+FA92->U+6717, +U+FA93->U+671B, U+FA94->U+6756, U+FA95->U+6B79, U+FA96->U+6BBA, U+FA97->U+6D41, U+FA98->U+6EDB, U+FA99->U+6ECB, U+FA9A->U+6F22, +U+FA9B->U+701E, U+FA9C->U+716E, U+FA9D->U+77A7, U+FA9E->U+7235, U+FA9F->U+72AF, U+FAA0->U+732A, U+FAA1->U+7471, U+FAA2->U+7506, +U+FAA3->U+753B, U+FAA4->U+761D, U+FAA5->U+761F, U+FAA6->U+76CA, U+FAA7->U+76DB, U+FAA8->U+76F4, U+FAA9->U+774A, U+FAAA->U+7740, +U+FAAB->U+78CC, U+FAAC->U+7AB1, U+FAAD->U+7BC0, U+FAAE->U+7C7B, U+FAAF->U+7D5B, U+FAB0->U+7DF4, U+FAB1->U+7F3E, U+FAB2->U+8005, +U+FAB3->U+8352, U+FAB4->U+83EF, U+FAB5->U+8779, U+FAB6->U+8941, U+FAB7->U+8986, U+FAB8->U+8996, U+FAB9->U+8ABF, U+FABA->U+8AF8, +U+FABB->U+8ACB, U+FABC->U+8B01, U+FABD->U+8AFE, U+FABE->U+8AED, U+FABF->U+8B39, U+FAC0->U+8B8A, U+FAC1->U+8D08, U+FAC2->U+8F38, +U+FAC3->U+9072, U+FAC4->U+9199, U+FAC5->U+9276, U+FAC6->U+967C, U+FAC7->U+96E3, U+FAC8->U+9756, U+FAC9->U+97DB, U+FACA->U+97FF, +U+FACB->U+980B, U+FACC->U+983B, U+FACD->U+9B12, U+FACE->U+9F9C, U+FACF->U+2284A, U+FAD0->U+22844, U+FAD1->U+233D5, U+FAD2->U+3B9D, +U+FAD3->U+4018, U+FAD4->U+4039, U+FAD5->U+25249, U+FAD6->U+25CD0, U+FAD7->U+27ED3, U+FAD8->U+9F43, U+FAD9->U+9F8E, U+2F800->U+4E3D, +U+2F801->U+4E38, U+2F802->U+4E41, U+2F803->U+20122, U+2F804->U+4F60, U+2F805->U+4FAE, U+2F806->U+4FBB, U+2F807->U+5002, U+2F808->U+507A, +U+2F809->U+5099, U+2F80A->U+50E7, U+2F80B->U+50CF, U+2F80C->U+349E, U+2F80D->U+2063A, U+2F80E->U+514D, U+2F80F->U+5154, U+2F810->U+5164, +U+2F811->U+5177, U+2F812->U+2051C, U+2F813->U+34B9, U+2F814->U+5167, U+2F815->U+518D, U+2F816->U+2054B, U+2F817->U+5197, +U+2F818->U+51A4, U+2F819->U+4ECC, U+2F81A->U+51AC, U+2F81B->U+51B5, U+2F81C->U+291DF, U+2F81D->U+51F5, U+2F81E->U+5203, +U+2F81F->U+34DF, U+2F820->U+523B, U+2F821->U+5246, U+2F822->U+5272, U+2F823->U+5277, U+2F824->U+3515, U+2F825->U+52C7, +U+2F826->U+52C9, U+2F827->U+52E4, U+2F828->U+52FA, U+2F829->U+5305, U+2F82A->U+5306, U+2F82B->U+5317, U+2F82C->U+5349, +U+2F82D->U+5351, U+2F82E->U+535A, U+2F82F->U+5373, U+2F830->U+537D, U+2F831->U+537F, U+2F832->U+537F, U+2F833->U+537F, +U+2F834->U+20A2C, U+2F835->U+7070, U+2F836->U+53CA, U+2F837->U+53DF, U+2F838->U+20B63, U+2F839->U+53EB, U+2F83A->U+53F1, +U+2F83B->U+5406, U+2F83C->U+549E, U+2F83D->U+5438, U+2F83E->U+5448, U+2F83F->U+5468, U+2F840->U+54A2, U+2F841->U+54F6, +U+2F842->U+5510, U+2F843->U+5553, U+2F844->U+5563, U+2F845->U+5584, U+2F846->U+5584, U+2F847->U+5599, U+2F848->U+55AB, +U+2F849->U+55B3, U+2F84A->U+55C2, U+2F84B->U+5716, U+2F84C->U+5606, U+2F84D->U+5717, U+2F84E->U+5651, U+2F84F->U+5674, +U+2F850->U+5207, U+2F851->U+58EE, U+2F852->U+57CE, U+2F853->U+57F4, U+2F854->U+580D, U+2F855->U+578B, U+2F856->U+5832, +U+2F857->U+5831, U+2F858->U+58AC, U+2F859->U+214E4, U+2F85A->U+58F2, U+2F85B->U+58F7, U+2F85C->U+5906, U+2F85D->U+591A, +U+2F85E->U+5922, U+2F85F->U+5962, U+2F860->U+216A8, U+2F861->U+216EA, U+2F862->U+59EC, U+2F863->U+5A1B, U+2F864->U+5A27, +U+2F865->U+59D8, U+2F866->U+5A66, U+2F867->U+36EE, U+2F868->U+36FC, U+2F869->U+5B08, U+2F86A->U+5B3E, U+2F86B->U+5B3E, +U+2F86C->U+219C8, U+2F86D->U+5BC3, U+2F86E->U+5BD8, U+2F86F->U+5BE7, U+2F870->U+5BF3, U+2F871->U+21B18, U+2F872->U+5BFF, +U+2F873->U+5C06, U+2F874->U+5F53, U+2F875->U+5C22, U+2F876->U+3781, U+2F877->U+5C60, U+2F878->U+5C6E, U+2F879->U+5CC0, +U+2F87A->U+5C8D, U+2F87B->U+21DE4, U+2F87C->U+5D43, U+2F87D->U+21DE6, U+2F87E->U+5D6E, U+2F87F->U+5D6B, U+2F880->U+5D7C, +U+2F881->U+5DE1, U+2F882->U+5DE2, U+2F883->U+382F, U+2F884->U+5DFD, U+2F885->U+5E28, U+2F886->U+5E3D, U+2F887->U+5E69, +U+2F888->U+3862, U+2F889->U+22183, U+2F88A->U+387C, U+2F88B->U+5EB0, U+2F88C->U+5EB3, U+2F88D->U+5EB6, U+2F88E->U+5ECA, +U+2F88F->U+2A392, U+2F890->U+5EFE, U+2F891->U+22331, U+2F892->U+22331, U+2F893->U+8201, U+2F894->U+5F22, U+2F895->U+5F22, +U+2F896->U+38C7, U+2F897->U+232B8, U+2F898->U+261DA, U+2F899->U+5F62, U+2F89A->U+5F6B, U+2F89B->U+38E3, U+2F89C->U+5F9A, +U+2F89D->U+5FCD, U+2F89E->U+5FD7, U+2F89F->U+5FF9, U+2F8A0->U+6081, U+2F8A1->U+393A, U+2F8A2->U+391C, U+2F8A3->U+6094, +U+2F8A4->U+226D4, U+2F8A5->U+60C7, U+2F8A6->U+6148, U+2F8A7->U+614C, U+2F8A8->U+614E, U+2F8A9->U+614C, U+2F8AA->U+617A, +U+2F8AB->U+618E, U+2F8AC->U+61B2, U+2F8AD->U+61A4, U+2F8AE->U+61AF, U+2F8AF->U+61DE, U+2F8B0->U+61F2, U+2F8B1->U+61F6, +U+2F8B2->U+6210, U+2F8B3->U+621B, U+2F8B4->U+625D, U+2F8B5->U+62B1, U+2F8B6->U+62D4, U+2F8B7->U+6350, U+2F8B8->U+22B0C, +U+2F8B9->U+633D, U+2F8BA->U+62FC, U+2F8BB->U+6368, U+2F8BC->U+6383, U+2F8BD->U+63E4, U+2F8BE->U+22BF1, U+2F8BF->U+6422, +U+2F8C0->U+63C5, U+2F8C1->U+63A9, U+2F8C2->U+3A2E, U+2F8C3->U+6469, U+2F8C4->U+647E, U+2F8C5->U+649D, U+2F8C6->U+6477, +U+2F8C7->U+3A6C, U+2F8C8->U+654F, U+2F8C9->U+656C, U+2F8CA->U+2300A, U+2F8CB->U+65E3, U+2F8CC->U+66F8, U+2F8CD->U+6649, +U+2F8CE->U+3B19, U+2F8CF->U+6691, U+2F8D0->U+3B08, U+2F8D1->U+3AE4, U+2F8D2->U+5192, U+2F8D3->U+5195, U+2F8D4->U+6700, +U+2F8D5->U+669C, U+2F8D6->U+80AD, U+2F8D7->U+43D9, U+2F8D8->U+6717, U+2F8D9->U+671B, U+2F8DA->U+6721, U+2F8DB->U+675E, +U+2F8DC->U+6753, U+2F8DD->U+233C3, U+2F8DE->U+3B49, U+2F8DF->U+67FA, U+2F8E0->U+6785, U+2F8E1->U+6852, U+2F8E2->U+6885, +U+2F8E3->U+2346D, U+2F8E4->U+688E, U+2F8E5->U+681F, U+2F8E6->U+6914, U+2F8E7->U+3B9D, U+2F8E8->U+6942, U+2F8E9->U+69A3, +U+2F8EA->U+69EA, U+2F8EB->U+6AA8, U+2F8EC->U+236A3, U+2F8ED->U+6ADB, U+2F8EE->U+3C18, U+2F8EF->U+6B21, U+2F8F0->U+238A7, +U+2F8F1->U+6B54, U+2F8F2->U+3C4E, U+2F8F3->U+6B72, U+2F8F4->U+6B9F, U+2F8F5->U+6BBA, U+2F8F6->U+6BBB, U+2F8F7->U+23A8D, +U+2F8F8->U+21D0B, U+2F8F9->U+23AFA, U+2F8FA->U+6C4E, U+2F8FB->U+23CBC, U+2F8FC->U+6CBF, U+2F8FD->U+6CCD, U+2F8FE->U+6C67, +U+2F8FF->U+6D16, U+2F900->U+6D3E, U+2F901->U+6D77, U+2F902->U+6D41, U+2F903->U+6D69, U+2F904->U+6D78, U+2F905->U+6D85, +U+2F906->U+23D1E, U+2F907->U+6D34, U+2F908->U+6E2F, U+2F909->U+6E6E, U+2F90A->U+3D33, U+2F90B->U+6ECB, U+2F90C->U+6EC7, +U+2F90D->U+23ED1, U+2F90E->U+6DF9, U+2F90F->U+6F6E, U+2F910->U+23F5E, U+2F911->U+23F8E, U+2F912->U+6FC6, U+2F913->U+7039, +U+2F914->U+701E, U+2F915->U+701B, U+2F916->U+3D96, U+2F917->U+704A, U+2F918->U+707D, U+2F919->U+7077, U+2F91A->U+70AD, +U+2F91B->U+20525, U+2F91C->U+7145, U+2F91D->U+24263, U+2F91E->U+719C, U+2F91F->U+243AB, U+2F920->U+7228, U+2F921->U+7235, +U+2F922->U+7250, U+2F923->U+24608, U+2F924->U+7280, U+2F925->U+7295, U+2F926->U+24735, U+2F927->U+24814, U+2F928->U+737A, +U+2F929->U+738B, U+2F92A->U+3EAC, U+2F92B->U+73A5, U+2F92C->U+3EB8, U+2F92D->U+3EB8, U+2F92E->U+7447, U+2F92F->U+745C, +U+2F930->U+7471, U+2F931->U+7485, U+2F932->U+74CA, U+2F933->U+3F1B, U+2F934->U+7524, U+2F935->U+24C36, U+2F936->U+753E, +U+2F937->U+24C92, U+2F938->U+7570, U+2F939->U+2219F, U+2F93A->U+7610, U+2F93B->U+24FA1, U+2F93C->U+24FB8, U+2F93D->U+25044, +U+2F93E->U+3FFC, U+2F93F->U+4008, U+2F940->U+76F4, U+2F941->U+250F3, U+2F942->U+250F2, U+2F943->U+25119, U+2F944->U+25133, +U+2F945->U+771E, U+2F946->U+771F, U+2F947->U+771F, U+2F948->U+774A, U+2F949->U+4039, U+2F94A->U+778B, U+2F94B->U+4046, +U+2F94C->U+4096, U+2F94D->U+2541D, U+2F94E->U+784E, U+2F94F->U+788C, U+2F950->U+78CC, U+2F951->U+40E3, U+2F952->U+25626, +U+2F953->U+7956, U+2F954->U+2569A, U+2F955->U+256C5, U+2F956->U+798F, U+2F957->U+79EB, U+2F958->U+412F, U+2F959->U+7A40, +U+2F95A->U+7A4A, U+2F95B->U+7A4F, U+2F95C->U+2597C, U+2F95D->U+25AA7, U+2F95E->U+25AA7, U+2F95F->U+7AEE, U+2F960->U+4202, +U+2F961->U+25BAB, U+2F962->U+7BC6, U+2F963->U+7BC9, U+2F964->U+4227, U+2F965->U+25C80, U+2F966->U+7CD2, U+2F967->U+42A0, +U+2F968->U+7CE8, U+2F969->U+7CE3, U+2F96A->U+7D00, U+2F96B->U+25F86, U+2F96C->U+7D63, U+2F96D->U+4301, U+2F96E->U+7DC7, +U+2F96F->U+7E02, U+2F970->U+7E45, U+2F971->U+4334, U+2F972->U+26228, U+2F973->U+26247, U+2F974->U+4359, U+2F975->U+262D9, +U+2F976->U+7F7A, U+2F977->U+2633E, U+2F978->U+7F95, U+2F979->U+7FFA, U+2F97A->U+8005, U+2F97B->U+264DA, U+2F97C->U+26523, +U+2F97D->U+8060, U+2F97E->U+265A8, U+2F97F->U+8070, U+2F980->U+2335F, U+2F981->U+43D5, U+2F982->U+80B2, U+2F983->U+8103, +U+2F984->U+440B, U+2F985->U+813E, U+2F986->U+5AB5, U+2F987->U+267A7, U+2F988->U+267B5, U+2F989->U+23393, U+2F98A->U+2339C, +U+2F98B->U+8201, U+2F98C->U+8204, U+2F98D->U+8F9E, U+2F98E->U+446B, U+2F98F->U+8291, U+2F990->U+828B, U+2F991->U+829D, +U+2F992->U+52B3, U+2F993->U+82B1, U+2F994->U+82B3, U+2F995->U+82BD, U+2F996->U+82E6, U+2F997->U+26B3C, U+2F998->U+82E5, +U+2F999->U+831D, U+2F99A->U+8363, U+2F99B->U+83AD, U+2F99C->U+8323, U+2F99D->U+83BD, U+2F99E->U+83E7, U+2F99F->U+8457, +U+2F9A0->U+8353, U+2F9A1->U+83CA, U+2F9A2->U+83CC, U+2F9A3->U+83DC, U+2F9A4->U+26C36, U+2F9A5->U+26D6B, U+2F9A6->U+26CD5, +U+2F9A7->U+452B, U+2F9A8->U+84F1, U+2F9A9->U+84F3, U+2F9AA->U+8516, U+2F9AB->U+273CA, U+2F9AC->U+8564, U+2F9AD->U+26F2C, +U+2F9AE->U+455D, U+2F9AF->U+4561, U+2F9B0->U+26FB1, U+2F9B1->U+270D2, U+2F9B2->U+456B, U+2F9B3->U+8650, U+2F9B4->U+865C, +U+2F9B5->U+8667, U+2F9B6->U+8669, U+2F9B7->U+86A9, U+2F9B8->U+8688, U+2F9B9->U+870E, U+2F9BA->U+86E2, U+2F9BB->U+8779, +U+2F9BC->U+8728, U+2F9BD->U+876B, U+2F9BE->U+8786, U+2F9BF->U+45D7, U+2F9C0->U+87E1, U+2F9C1->U+8801, U+2F9C2->U+45F9, +U+2F9C3->U+8860, U+2F9C4->U+8863, U+2F9C5->U+27667, U+2F9C6->U+88D7, U+2F9C7->U+88DE, U+2F9C8->U+4635, U+2F9C9->U+88FA, +U+2F9CA->U+34BB, U+2F9CB->U+278AE, U+2F9CC->U+27966, U+2F9CD->U+46BE, U+2F9CE->U+46C7, U+2F9CF->U+8AA0, U+2F9D0->U+8AED, +U+2F9D1->U+8B8A, U+2F9D2->U+8C55, U+2F9D3->U+27CA8, U+2F9D4->U+8CAB, U+2F9D5->U+8CC1, U+2F9D6->U+8D1B, U+2F9D7->U+8D77, +U+2F9D8->U+27F2F, U+2F9D9->U+20804, U+2F9DA->U+8DCB, U+2F9DB->U+8DBC, U+2F9DC->U+8DF0, U+2F9DD->U+208DE, U+2F9DE->U+8ED4, +U+2F9DF->U+8F38, U+2F9E0->U+285D2, U+2F9E1->U+285ED, U+2F9E2->U+9094, U+2F9E3->U+90F1, U+2F9E4->U+9111, U+2F9E5->U+2872E, +U+2F9E6->U+911B, U+2F9E7->U+9238, U+2F9E8->U+92D7, U+2F9E9->U+92D8, U+2F9EA->U+927C, U+2F9EB->U+93F9, U+2F9EC->U+9415, +U+2F9ED->U+28BFA, U+2F9EE->U+958B, U+2F9EF->U+4995, U+2F9F0->U+95B7, U+2F9F1->U+28D77, U+2F9F2->U+49E6, U+2F9F3->U+96C3, +U+2F9F4->U+5DB2, U+2F9F5->U+9723, U+2F9F6->U+29145, U+2F9F7->U+2921A, U+2F9F8->U+4A6E, U+2F9F9->U+4A76, U+2F9FA->U+97E0, +U+2F9FB->U+2940A, U+2F9FC->U+4AB2, U+2F9FD->U+29496, U+2F9FE->U+980B, U+2F9FF->U+980B, U+2FA00->U+9829, U+2FA01->U+295B6, +U+2FA02->U+98E2, U+2FA03->U+4B33, U+2FA04->U+9929, U+2FA05->U+99A7, U+2FA06->U+99C2, U+2FA07->U+99FE, U+2FA08->U+4BCE, +U+2FA09->U+29B30, U+2FA0A->U+9B12, U+2FA0B->U+9C40, U+2FA0C->U+9CFD, U+2FA0D->U+4CCE, U+2FA0E->U+4CED, U+2FA0F->U+9D67, +U+2FA10->U+2A0CE, U+2FA11->U+4CF8, U+2FA12->U+2A105, U+2FA13->U+2A20E, U+2FA14->U+2A291, U+2FA15->U+9EBB, U+2FA16->U+4D56, +U+2FA17->U+9EF9, U+2FA18->U+9EFE, U+2FA19->U+9F05, U+2FA1A->U+9F0F, U+2FA1B->U+9F16, U+2FA1C->U+9F3B, U+2FA1D->U+2A600, +U+2F00->U+4E00, U+2F01->U+4E28, U+2F02->U+4E36, U+2F03->U+4E3F, U+2F04->U+4E59, U+2F05->U+4E85, U+2F06->U+4E8C, U+2F07->U+4EA0, +U+2F08->U+4EBA, U+2F09->U+513F, U+2F0A->U+5165, U+2F0B->U+516B, U+2F0C->U+5182, U+2F0D->U+5196, U+2F0E->U+51AB, U+2F0F->U+51E0, +U+2F10->U+51F5, U+2F11->U+5200, U+2F12->U+529B, U+2F13->U+52F9, U+2F14->U+5315, U+2F15->U+531A, U+2F16->U+5338, U+2F17->U+5341, +U+2F18->U+535C, U+2F19->U+5369, U+2F1A->U+5382, U+2F1B->U+53B6, U+2F1C->U+53C8, U+2F1D->U+53E3, U+2F1E->U+56D7, U+2F1F->U+571F, +U+2F20->U+58EB, U+2F21->U+5902, U+2F22->U+590A, U+2F23->U+5915, U+2F24->U+5927, U+2F25->U+5973, U+2F26->U+5B50, U+2F27->U+5B80, +U+2F28->U+5BF8, U+2F29->U+5C0F, U+2F2A->U+5C22, U+2F2B->U+5C38, U+2F2C->U+5C6E, U+2F2D->U+5C71, U+2F2E->U+5DDB, U+2F2F->U+5DE5, +U+2F30->U+5DF1, U+2F31->U+5DFE, U+2F32->U+5E72, U+2F33->U+5E7A, U+2F34->U+5E7F, U+2F35->U+5EF4, U+2F36->U+5EFE, U+2F37->U+5F0B, +U+2F38->U+5F13, U+2F39->U+5F50, U+2F3A->U+5F61, U+2F3B->U+5F73, U+2F3C->U+5FC3, U+2F3D->U+6208, U+2F3E->U+6236, U+2F3F->U+624B, +U+2F40->U+652F, U+2F41->U+6534, U+2F42->U+6587, U+2F43->U+6597, U+2F44->U+65A4, U+2F45->U+65B9, U+2F46->U+65E0, U+2F47->U+65E5, +U+2F48->U+66F0, U+2F49->U+6708, U+2F4A->U+6728, U+2F4B->U+6B20, U+2F4C->U+6B62, U+2F4D->U+6B79, U+2F4E->U+6BB3, U+2F4F->U+6BCB, +U+2F50->U+6BD4, U+2F51->U+6BDB, U+2F52->U+6C0F, U+2F53->U+6C14, U+2F54->U+6C34, U+2F55->U+706B, U+2F56->U+722A, U+2F57->U+7236, +U+2F58->U+723B, U+2F59->U+723F, U+2F5A->U+7247, U+2F5B->U+7259, U+2F5C->U+725B, U+2F5D->U+72AC, U+2F5E->U+7384, U+2F5F->U+7389, +U+2F60->U+74DC, U+2F61->U+74E6, U+2F62->U+7518, U+2F63->U+751F, U+2F64->U+7528, U+2F65->U+7530, U+2F66->U+758B, U+2F67->U+7592, +U+2F68->U+7676, U+2F69->U+767D, U+2F6A->U+76AE, U+2F6B->U+76BF, U+2F6C->U+76EE, U+2F6D->U+77DB, U+2F6E->U+77E2, U+2F6F->U+77F3, +U+2F70->U+793A, U+2F71->U+79B8, U+2F72->U+79BE, U+2F73->U+7A74, U+2F74->U+7ACB, U+2F75->U+7AF9, U+2F76->U+7C73, U+2F77->U+7CF8, +U+2F78->U+7F36, U+2F79->U+7F51, U+2F7A->U+7F8A, U+2F7B->U+7FBD, U+2F7C->U+8001, U+2F7D->U+800C, U+2F7E->U+8012, U+2F7F->U+8033, +U+2F80->U+807F, U+2F81->U+8089, U+2F82->U+81E3, U+2F83->U+81EA, U+2F84->U+81F3, U+2F85->U+81FC, U+2F86->U+820C, U+2F87->U+821B, +U+2F88->U+821F, U+2F89->U+826E, U+2F8A->U+8272, U+2F8B->U+8278, U+2F8C->U+864D, U+2F8D->U+866B, U+2F8E->U+8840, U+2F8F->U+884C, +U+2F90->U+8863, U+2F91->U+897E, U+2F92->U+898B, U+2F93->U+89D2, U+2F94->U+8A00, U+2F95->U+8C37, U+2F96->U+8C46, U+2F97->U+8C55, +U+2F98->U+8C78, U+2F99->U+8C9D, U+2F9A->U+8D64, U+2F9B->U+8D70, U+2F9C->U+8DB3, U+2F9D->U+8EAB, U+2F9E->U+8ECA, U+2F9F->U+8F9B, +U+2FA0->U+8FB0, U+2FA1->U+8FB5, U+2FA2->U+9091, U+2FA3->U+9149, U+2FA4->U+91C6, U+2FA5->U+91CC, U+2FA6->U+91D1, U+2FA7->U+9577, +U+2FA8->U+9580, U+2FA9->U+961C, U+2FAA->U+96B6, U+2FAB->U+96B9, U+2FAC->U+96E8, U+2FAD->U+9751, U+2FAE->U+975E, U+2FAF->U+9762, +U+2FB0->U+9769, U+2FB1->U+97CB, U+2FB2->U+97ED, U+2FB3->U+97F3, U+2FB4->U+9801, U+2FB5->U+98A8, U+2FB6->U+98DB, U+2FB7->U+98DF, +U+2FB8->U+9996, U+2FB9->U+9999, U+2FBA->U+99AC, U+2FBB->U+9AA8, U+2FBC->U+9AD8, U+2FBD->U+9ADF, U+2FBE->U+9B25, U+2FBF->U+9B2F, +U+2FC0->U+9B32, U+2FC1->U+9B3C, U+2FC2->U+9B5A, U+2FC3->U+9CE5, U+2FC4->U+9E75, U+2FC5->U+9E7F, U+2FC6->U+9EA5, U+2FC7->U+9EBB, +U+2FC8->U+9EC3, U+2FC9->U+9ECD, U+2FCA->U+9ED1, U+2FCB->U+9EF9, U+2FCC->U+9EFD, U+2FCD->U+9F0E, U+2FCE->U+9F13, U+2FCF->U+9F20, +U+2FD0->U+9F3B, U+2FD1->U+9F4A, U+2FD2->U+9F52, U+2FD3->U+9F8D, U+2FD4->U+9F9C, U+2FD5->U+9FA0, U+3042->U+3041, U+3044->U+3043, +U+3046->U+3045, U+3048->U+3047, U+304A->U+3049, U+304C->U+304B, U+304E->U+304D, U+3050->U+304F, U+3052->U+3051, U+3054->U+3053, +U+3056->U+3055, U+3058->U+3057, U+305A->U+3059, U+305C->U+305B, U+305E->U+305D, U+3060->U+305F, U+3062->U+3061, U+3064->U+3063, +U+3065->U+3063, U+3067->U+3066, U+3069->U+3068, U+3070->U+306F, U+3071->U+306F, U+3073->U+3072, U+3074->U+3072, U+3076->U+3075, +U+3077->U+3075, U+3079->U+3078, U+307A->U+3078, U+307C->U+307B, U+307D->U+307B, U+3084->U+3083, U+3086->U+3085, U+3088->U+3087, +U+308F->U+308E, U+3094->U+3046, U+3095->U+304B, U+3096->U+3051, U+30A2->U+30A1, U+30A4->U+30A3, U+30A6->U+30A5, U+30A8->U+30A7, +U+30AA->U+30A9, U+30AC->U+30AB, U+30AE->U+30AD, U+30B0->U+30AF, U+30B2->U+30B1, U+30B4->U+30B3, U+30B6->U+30B5, U+30B8->U+30B7, +U+30BA->U+30B9, U+30BC->U+30BB, U+30BE->U+30BD, U+30C0->U+30BF, U+30C2->U+30C1, U+30C5->U+30C4, U+30C7->U+30C6, U+30C9->U+30C8, +U+30D0->U+30CF, U+30D1->U+30CF, U+30D3->U+30D2, U+30D4->U+30D2, U+30D6->U+30D5, U+30D7->U+30D5, U+30D9->U+30D8, U+30DA->U+30D8, +U+30DC->U+30DB, U+30DD->U+30DB, U+30E4->U+30E3, U+30E6->U+30E5, U+30E8->U+30E7, U+30EF->U+30EE, U+30F4->U+30A6, U+30AB->U+30F5, +U+30B1->U+30F6, U+30F7->U+30EF, U+30F8->U+30F0, U+30F9->U+30F1, U+30FA->U+30F2, U+30AF->U+31F0, U+30B7->U+31F1, U+30B9->U+31F2, +U+30C8->U+31F3, U+30CC->U+31F4, U+30CF->U+31F5, U+30D2->U+31F6, U+30D5->U+31F7, U+30D8->U+31F8, U+30DB->U+31F9, U+30E0->U+31FA, +U+30E9->U+31FB, U+30EA->U+31FC, U+30EB->U+31FD, U+30EC->U+31FE, U+30ED->U+31FF, U+FF66->U+30F2, U+FF67->U+30A1, U+FF68->U+30A3, +U+FF69->U+30A5, U+FF6A->U+30A7, U+FF6B->U+30A9, U+FF6C->U+30E3, U+FF6D->U+30E5, U+FF6E->U+30E7, U+FF6F->U+30C3, U+FF71->U+30A1, +U+FF72->U+30A3, U+FF73->U+30A5, U+FF74->U+30A7, U+FF75->U+30A9, U+FF76->U+30AB, U+FF77->U+30AD, U+FF78->U+30AF, U+FF79->U+30B1, +U+FF7A->U+30B3, U+FF7B->U+30B5, U+FF7C->U+30B7, U+FF7D->U+30B9, U+FF7E->U+30BB, U+FF7F->U+30BD, U+FF80->U+30BF, U+FF81->U+30C1, +U+FF82->U+30C3, U+FF83->U+30C6, U+FF84->U+30C8, U+FF85->U+30CA, U+FF86->U+30CB, U+FF87->U+30CC, U+FF88->U+30CD, U+FF89->U+30CE, +U+FF8A->U+30CF, U+FF8B->U+30D2, U+FF8C->U+30D5, U+FF8D->U+30D8, U+FF8E->U+30DB, U+FF8F->U+30DE, U+FF90->U+30DF, U+FF91->U+30E0, +U+FF92->U+30E1, U+FF93->U+30E2, U+FF94->U+30E3, U+FF95->U+30E5, U+FF96->U+30E7, U+FF97->U+30E9, U+FF98->U+30EA, U+FF99->U+30EB, +U+FF9A->U+30EC, U+FF9B->U+30ED, U+FF9C->U+30EF, U+FF9D->U+30F3, U+FFA0->U+3164, U+FFA1->U+3131, U+FFA2->U+3132, U+FFA3->U+3133, +U+FFA4->U+3134, U+FFA5->U+3135, U+FFA6->U+3136, U+FFA7->U+3137, U+FFA8->U+3138, U+FFA9->U+3139, U+FFAA->U+313A, U+FFAB->U+313B, +U+FFAC->U+313C, U+FFAD->U+313D, U+FFAE->U+313E, U+FFAF->U+313F, U+FFB0->U+3140, U+FFB1->U+3141, U+FFB2->U+3142, U+FFB3->U+3143, +U+FFB4->U+3144, U+FFB5->U+3145, U+FFB6->U+3146, U+FFB7->U+3147, U+FFB8->U+3148, U+FFB9->U+3149, U+FFBA->U+314A, U+FFBB->U+314B, +U+FFBC->U+314C, U+FFBD->U+314D, U+FFBE->U+314E, U+FFC2->U+314F, U+FFC3->U+3150, U+FFC4->U+3151, U+FFC5->U+3152, U+FFC6->U+3153, +U+FFC7->U+3154, U+FFCA->U+3155, U+FFCB->U+3156, U+FFCC->U+3157, U+FFCD->U+3158, U+FFCE->U+3159, U+FFCF->U+315A, U+FFD2->U+315B, +U+FFD3->U+315C, U+FFD4->U+315D, U+FFD5->U+315E, U+FFD6->U+315F, U+FFD7->U+3160, U+FFDA->U+3161, U+FFDB->U+3162, U+FFDC->U+3163, +U+3131->U+1100, U+3132->U+1101, U+3133->U+11AA, U+3134->U+1102, U+3135->U+11AC, U+3136->U+11AD, U+3137->U+1103, U+3138->U+1104, +U+3139->U+1105, U+313A->U+11B0, U+313B->U+11B1, U+313C->U+11B2, U+313D->U+11B3, U+313E->U+11B4, U+313F->U+11B5, U+3140->U+111A, +U+3141->U+1106, U+3142->U+1107, U+3143->U+1108, U+3144->U+1121, U+3145->U+1109, U+3146->U+110A, U+3147->U+110B, U+3148->U+110C, +U+3149->U+110D, U+314A->U+110E, U+314B->U+110F, U+314C->U+1110, U+314D->U+1111, U+314E->U+1112, U+314F->U+1161, U+3150->U+1162, +U+3151->U+1163, U+3152->U+1164, U+3153->U+1165, U+3154->U+1166, U+3155->U+1167, U+3156->U+1168, U+3157->U+1169, U+3158->U+116A, +U+3159->U+116B, U+315A->U+116C, U+315B->U+116D, U+315C->U+116E, U+315D->U+116F, U+315E->U+1170, U+315F->U+1171, U+3160->U+1172, +U+3161->U+1173, U+3162->U+1174, U+3163->U+1175, U+3165->U+1114, U+3166->U+1115, U+3167->U+11C7, U+3168->U+11C8, U+3169->U+11CC, +U+316A->U+11CE, U+316B->U+11D3, U+316C->U+11D7, U+316D->U+11D9, U+316E->U+111C, U+316F->U+11DD, U+3170->U+11DF, U+3171->U+111D, +U+3172->U+111E, U+3173->U+1120, U+3174->U+1122, U+3175->U+1123, U+3176->U+1127, U+3177->U+1129, U+3178->U+112B, U+3179->U+112C, +U+317A->U+112D, U+317B->U+112E, U+317C->U+112F, U+317D->U+1132, U+317E->U+1136, U+317F->U+1140, U+3180->U+1147, U+3181->U+114C, +U+3182->U+11F1, U+3183->U+11F2, U+3184->U+1157, U+3185->U+1158, U+3186->U+1159, U+3187->U+1184, U+3188->U+1185, U+3189->U+1188, +U+318A->U+1191, U+318B->U+1192, U+318C->U+1194, U+318D->U+119E, U+318E->U+11A1, U+A490->U+A408, U+A491->U+A1B9, U+4E00..U+9FBB, +U+3400..U+4DB5, U+20000..U+2A6D6, U+FA0E, U+FA0F, U+FA11, U+FA13, U+FA14, U+FA1F, U+FA21, U+FA23, U+FA24, U+FA27, U+FA28, U+FA29, +U+3105..U+312C, U+31A0..U+31B7, U+3041, U+3043, U+3045, U+3047, U+3049, U+304B, U+304D, U+304F, U+3051, U+3053, U+3055, U+3057, +U+3059, U+305B, U+305D, U+305F, U+3061, U+3063, U+3066, U+3068, U+306A..U+306F, U+3072, U+3075, U+3078, U+307B, U+307E..U+3083, +U+3085, U+3087, U+3089..U+308E, U+3090..U+3093, U+30A1, U+30A3, U+30A5, U+30A7, U+30A9, U+30AD, U+30AF, U+30B3, U+30B5, U+30BB, +U+30BD, U+30BF, U+30C1, U+30C3, U+30C4, U+30C6, U+30CA, U+30CB, U+30CD, U+30CE, U+30DE, U+30DF, U+30E1, U+30E2, U+30E3, U+30E5, +U+30E7, U+30EE, U+30F0..U+30F3, U+30F5, U+30F6, U+31F0, U+31F1, U+31F2, U+31F3, U+31F4, U+31F5, U+31F6, U+31F7, U+31F8, U+31F9, +U+31FA, U+31FB, U+31FC, U+31FD, U+31FE, U+31FF, U+AC00..U+D7A3, U+1100..U+1159, U+1161..U+11A2, U+11A8..U+11F9, U+A000..U+A48C, +U+A492..U+A4C6 + +################################################## +# Coptic +# Notes: Some shared Greek characters, may require amendments. +U+2C80->U+2C81, U+2C81, U+2C82->U+2C83, U+2C83, U+2C84->U+2C85, U+2C85, U+2C86->U+2C87, U+2C87, U+2C88->U+2C89, U+2C89, U+2C8A->U+2C8B, +U+2C8B, U+2C8C->U+2C8D, U+2C8D, U+2C8E->U+2C8F, U+2C8F, U+2C90->U+2C91, U+2C91, U+2C92->U+2C93, U+2C93, U+2C94->U+2C95, U+2C95, +U+2C96->U+2C97, U+2C97, U+2C98->U+2C99, U+2C99, U+2C9A->U+2C9B, U+2C9B, U+2C9C->U+2C9D, U+2C9D, U+2C9E->U+2C9F, U+2C9F, U+2CA0->U+2CA1, +U+2CA1, U+2CA2->U+2CA3, U+2CA3, U+2CA4->U+2CA5, U+2CA5, U+2CA6->U+2CA7, U+2CA7, U+2CA8->U+2CA9, U+2CA9, U+2CAA->U+2CAB, U+2CAB, +U+2CAC->U+2CAD, U+2CAD, U+2CAE->U+2CAF, U+2CAF, U+2CB0->U+2CB1, U+2CB1, U+2CB2->U+2CB3, U+2CB3, U+2CB4->U+2CB5, U+2CB5, +U+2CB6->U+2CB7, U+2CB7, U+2CB8->U+2CB9, U+2CB9, U+2CBA->U+2CBB, U+2CBB, U+2CBC->U+2CBD, U+2CBD, U+2CBE->U+2CBF, U+2CBF, +U+2CC0->U+2CC1, U+2CC1, U+2CC2->U+2CC3, U+2CC3, U+2CC4->U+2CC5, U+2CC5, U+2CC6->U+2CC7, U+2CC7, U+2CC8->U+2CC9, U+2CC9, +U+2CCA->U+2CCB, U+2CCB, U+2CCC->U+2CCD, U+2CCD, U+2CCE->U+2CCF, U+2CCF, U+2CD0->U+2CD1, U+2CD1, U+2CD2->U+2CD3, U+2CD3, +U+2CD4->U+2CD5, U+2CD5, U+2CD6->U+2CD7, U+2CD7, U+2CD8->U+2CD9, U+2CD9, U+2CDA->U+2CDB, U+2CDB, U+2CDC->U+2CDD, U+2CDD, +U+2CDE->U+2CDF, U+2CDF, U+2CE0->U+2CE1, U+2CE1, U+2CE2->U+2CE3, U+2CE3 + +################################################## +# Cryllic* +U+0400->U+0435, U+0401->U+0435, U+0402->U+0452, U+0452, U+0403->U+0433, U+0404->U+0454, U+0454, U+0405->U+0455, U+0455, +U+0406->U+0456, U+0407->U+0456, U+0457->U+0456, U+0456, U+0408..U+040B->U+0458..U+045B, U+0458..U+045B, U+040C->U+043A, +U+040D->U+0438, U+040E->U+0443, U+040F->U+045F, U+045F, U+0450->U+0435, U+0451->U+0435, U+0453->U+0433, U+045C->U+043A, +U+045D->U+0438, U+045E->U+0443, U+0460->U+0461, U+0461, U+0462->U+0463, U+0463, U+0464->U+0465, U+0465, U+0466->U+0467, +U+0467, U+0468->U+0469, U+0469, U+046A->U+046B, U+046B, U+046C->U+046D, U+046D, U+046E->U+046F, U+046F, U+0470->U+0471, +U+0471, U+0472->U+0473, U+0473, U+0474->U+0475, U+0476->U+0475, U+0477->U+0475, U+0475, U+0478->U+0479, U+0479, U+047A->U+047B, +U+047B, U+047C->U+047D, U+047D, U+047E->U+047F, U+047F, U+0480->U+0481, U+0481, U+048A->U+0438, U+048B->U+0438, U+048C->U+044C, +U+048D->U+044C, U+048E->U+0440, U+048F->U+0440, U+0490->U+0433, U+0491->U+0433, U+0490->U+0433, U+0491->U+0433, U+0492->U+0433, +U+0493->U+0433, U+0494->U+0433, U+0495->U+0433, U+0496->U+0436, U+0497->U+0436, U+0498->U+0437, U+0499->U+0437, U+049A->U+043A, +U+049B->U+043A, U+049C->U+043A, U+049D->U+043A, U+049E->U+043A, U+049F->U+043A, U+04A0->U+043A, U+04A1->U+043A, U+04A2->U+043D, +U+04A3->U+043D, U+04A4->U+043D, U+04A5->U+043D, U+04A6->U+043F, U+04A7->U+043F, U+04A8->U+04A9, U+04A9, U+04AA->U+0441, +U+04AB->U+0441, U+04AC->U+0442, U+04AD->U+0442, U+04AE->U+0443, U+04AF->U+0443, U+04B0->U+0443, U+04B1->U+0443, U+04B2->U+0445, +U+04B3->U+0445, U+04B4->U+04B5, U+04B5, U+04B6->U+0447, U+04B7->U+0447, U+04B8->U+0447, U+04B9->U+0447, U+04BA->U+04BB, U+04BB, +U+04BC->U+04BD, U+04BE->U+04BD, U+04BF->U+04BD, U+04BD, U+04C0->U+04CF, U+04CF, U+04C1->U+0436, U+04C2->U+0436, U+04C3->U+043A, +U+04C4->U+043A, U+04C5->U+043B, U+04C6->U+043B, U+04C7->U+043D, U+04C8->U+043D, U+04C9->U+043D, U+04CA->U+043D, U+04CB->U+0447, +U+04CC->U+0447, U+04CD->U+043C, U+04CE->U+043C, U+04D0->U+0430, U+04D1->U+0430, U+04D2->U+0430, U+04D3->U+0430, U+04D4->U+00E6, +U+04D5->U+00E6, U+04D6->U+0435, U+04D7->U+0435, U+04D8->U+04D9, U+04DA->U+04D9, U+04DB->U+04D9, U+04D9, U+04DC->U+0436, +U+04DD->U+0436, U+04DE->U+0437, U+04DF->U+0437, U+04E0->U+04E1, U+04E1, U+04E2->U+0438, U+04E3->U+0438, U+04E4->U+0438, +U+04E5->U+0438, U+04E6->U+043E, U+04E7->U+043E, U+04E8->U+043E, U+04E9->U+043E, U+04EA->U+043E, U+04EB->U+043E, U+04EC->U+044D, +U+04ED->U+044D, U+04EE->U+0443, U+04EF->U+0443, U+04F0->U+0443, U+04F1->U+0443, U+04F2->U+0443, U+04F3->U+0443, U+04F4->U+0447, +U+04F5->U+0447, U+04F6->U+0433, U+04F7->U+0433, U+04F8->U+044B, U+04F9->U+044B, U+04FA->U+0433, U+04FB->U+0433, U+04FC->U+0445, +U+04FD->U+0445, U+04FE->U+0445, U+04FF->U+0445, U+0410..U+0418->U+0430..U+0438, U+0419->U+0438, U+0430..U+0438, +U+041A..U+042F->U+043A..U+044F, U+043A..U+044F + +################################################## +# Devanagari +U+0929->U+0928, U+0931->U+0930, U+0934->U+0933, U+0958->U+0915, U+0959->U+0916, U+095A->U+0917, U+095B->U+091C, U+095C->U+0921, +U+095D->U+0922, U+095E->U+092B, U+095F->U+092F, U+0904..U+0928, U+092A..U+0930, U+0932, U+0933, U+0935..U+0939, U+0960, U+0961, +U+0966..U+096F, U+097B..U+097F + +################################################## +# Georgian +U+10FC->U+10DC, U+10D0..U+10FA, U+10A0..U+10C5->U+2D00..U+2D25, U+2D00..U+2D25 + +################################################## +# Greek +U+0386->U+03B1, U+0388->U+03B5, U+0389->U+03B7, U+038A->U+03B9, U+038C->U+03BF, U+038E->U+03C5, U+038F->U+03C9, U+0390->U+03B9, +U+03AA->U+03B9, U+03AB->U+03C5, U+03AC->U+03B1, U+03AD->U+03B5, U+03AE->U+03B7, U+03AF->U+03B9, U+03B0->U+03C5, U+03CA->U+03B9, +U+03CB->U+03C5, U+03CC->U+03BF, U+03CD->U+03C5, U+03CE->U+03C9, U+03D0->U+03B2, U+03D1->U+03B8, U+03D2->U+03C5, U+03D3->U+03C5, +U+03D4->U+03C5, U+03D5->U+03C6, U+03D6->U+03C0, U+03D8->U+03D9, U+03DA->U+03DB, U+03DC->U+03DD, U+03DE->U+03DF, U+03E0->U+03E1, +U+03E2->U+03E3, U+03E4->U+03E5, U+03E6->U+03E7, U+03E8->U+03E9, U+03EA->U+03EB, U+03EC->U+03ED, U+03EE->U+03EF, U+03F0->U+03BA, +U+03F1->U+03C1, U+03F2->U+03C3, U+03F4->U+03B8, U+03F5->U+03B5, U+03F6->U+03B5, U+03F7->U+03F8, U+03F9->U+03C3, U+03FA->U+03FB, +U+1F00->U+03B1, U+1F01->U+03B1, U+1F02->U+03B1, U+1F03->U+03B1, U+1F04->U+03B1, U+1F05->U+03B1, U+1F06->U+03B1, U+1F07->U+03B1, +U+1F08->U+03B1, U+1F09->U+03B1, U+1F0A->U+03B1, U+1F0B->U+03B1, U+1F0C->U+03B1, U+1F0D->U+03B1, U+1F0E->U+03B1, U+1F0F->U+03B1, +U+1F10->U+03B5, U+1F11->U+03B5, U+1F12->U+03B5, U+1F13->U+03B5, U+1F14->U+03B5, U+1F15->U+03B5, U+1F18->U+03B5, U+1F19->U+03B5, +U+1F1A->U+03B5, U+1F1B->U+03B5, U+1F1C->U+03B5, U+1F1D->U+03B5, U+1F20->U+03B7, U+1F21->U+03B7, U+1F22->U+03B7, U+1F23->U+03B7, +U+1F24->U+03B7, U+1F25->U+03B7, U+1F26->U+03B7, U+1F27->U+03B7, U+1F28->U+03B7, U+1F29->U+03B7, U+1F2A->U+03B7, U+1F2B->U+03B7, +U+1F2C->U+03B7, U+1F2D->U+03B7, U+1F2E->U+03B7, U+1F2F->U+03B7, U+1F30->U+03B9, U+1F31->U+03B9, U+1F32->U+03B9, U+1F33->U+03B9, +U+1F34->U+03B9, U+1F35->U+03B9, U+1F36->U+03B9, U+1F37->U+03B9, U+1F38->U+03B9, U+1F39->U+03B9, U+1F3A->U+03B9, U+1F3B->U+03B9, +U+1F3C->U+03B9, U+1F3D->U+03B9, U+1F3E->U+03B9, U+1F3F->U+03B9, U+1F40->U+03BF, U+1F41->U+03BF, U+1F42->U+03BF, U+1F43->U+03BF, +U+1F44->U+03BF, U+1F45->U+03BF, U+1F48->U+03BF, U+1F49->U+03BF, U+1F4A->U+03BF, U+1F4B->U+03BF, U+1F4C->U+03BF, U+1F4D->U+03BF, +U+1F50->U+03C5, U+1F51->U+03C5, U+1F52->U+03C5, U+1F53->U+03C5, U+1F54->U+03C5, U+1F55->U+03C5, U+1F56->U+03C5, U+1F57->U+03C5, +U+1F59->U+03C5, U+1F5B->U+03C5, U+1F5D->U+03C5, U+1F5F->U+03C5, U+1F60->U+03C9, U+1F61->U+03C9, U+1F62->U+03C9, U+1F63->U+03C9, +U+1F64->U+03C9, U+1F65->U+03C9, U+1F66->U+03C9, U+1F67->U+03C9, U+1F68->U+03C9, U+1F69->U+03C9, U+1F6A->U+03C9, U+1F6B->U+03C9, +U+1F6C->U+03C9, U+1F6D->U+03C9, U+1F6E->U+03C9, U+1F6F->U+03C9, U+1F70->U+03B1, U+1F71->U+03B1, U+1F72->U+03B5, U+1F73->U+03B5, +U+1F74->U+03B7, U+1F75->U+03B7, U+1F76->U+03B9, U+1F77->U+03B9, U+1F78->U+03BF, U+1F79->U+03BF, U+1F7A->U+03C5, U+1F7B->U+03C5, +U+1F7C->U+03C9, U+1F7D->U+03C9, U+1F80->U+03B1, U+1F81->U+03B1, U+1F82->U+03B1, U+1F83->U+03B1, U+1F84->U+03B1, U+1F85->U+03B1, +U+1F86->U+03B1, U+1F87->U+03B1, U+1F88->U+03B1, U+1F89->U+03B1, U+1F8A->U+03B1, U+1F8B->U+03B1, U+1F8C->U+03B1, U+1F8D->U+03B1, +U+1F8E->U+03B1, U+1F8F->U+03B1, U+1F90->U+03B7, U+1F91->U+03B7, U+1F92->U+03B7, U+1F93->U+03B7, U+1F94->U+03B7, U+1F95->U+03B7, +U+1F96->U+03B7, U+1F97->U+03B7, U+1F98->U+03B7, U+1F99->U+03B7, U+1F9A->U+03B7, U+1F9B->U+03B7, U+1F9C->U+03B7, U+1F9D->U+03B7, +U+1F9E->U+03B7, U+1F9F->U+03B7, U+1FA0->U+03C9, U+1FA1->U+03C9, U+1FA2->U+03C9, U+1FA3->U+03C9, U+1FA4->U+03C9, U+1FA5->U+03C9, +U+1FA6->U+03C9, U+1FA7->U+03C9, U+1FA8->U+03C9, U+1FA9->U+03C9, U+1FAA->U+03C9, U+1FAB->U+03C9, U+1FAC->U+03C9, U+1FAD->U+03C9, +U+1FAE->U+03C9, U+1FAF->U+03C9, U+1FB0->U+03B1, U+1FB1->U+03B1, U+1FB2->U+03B1, U+1FB3->U+03B1, U+1FB4->U+03B1, U+1FB6->U+03B1, +U+1FB7->U+03B1, U+1FB8->U+03B1, U+1FB9->U+03B1, U+1FBA->U+03B1, U+1FBB->U+03B1, U+1FBC->U+03B1, U+1FC2->U+03B7, U+1FC3->U+03B7, +U+1FC4->U+03B7, U+1FC6->U+03B7, U+1FC7->U+03B7, U+1FC8->U+03B5, U+1FC9->U+03B5, U+1FCA->U+03B7, U+1FCB->U+03B7, U+1FCC->U+03B7, +U+1FD0->U+03B9, U+1FD1->U+03B9, U+1FD2->U+03B9, U+1FD3->U+03B9, U+1FD6->U+03B9, U+1FD7->U+03B9, U+1FD8->U+03B9, U+1FD9->U+03B9, +U+1FDA->U+03B9, U+1FDB->U+03B9, U+1FE0->U+03C5, U+1FE1->U+03C5, U+1FE2->U+03C5, U+1FE3->U+03C5, U+1FE4->U+03C1, U+1FE5->U+03C1, +U+1FE6->U+03C5, U+1FE7->U+03C5, U+1FE8->U+03C5, U+1FE9->U+03C5, U+1FEA->U+03C5, U+1FEB->U+03C5, U+1FEC->U+03C1, U+1FF2->U+03C9, +U+1FF3->U+03C9, U+1FF4->U+03C9, U+1FF6->U+03C9, U+1FF7->U+03C9, U+1FF8->U+03BF, U+1FF9->U+03BF, U+1FFA->U+03C9, U+1FFB->U+03C9, +U+1FFC->U+03C9, U+0391..U+03A1->U+03B1..U+03C1, U+03B1..U+03C1, U+03A3..U+03A9->U+03C3..U+03C9, U+03C3..U+03C9, U+03C2, U+03D9, +U+03DB, U+03DD, U+03DF, U+03E1, U+03E3, U+03E5, U+03E7, U+03E9, U+03EB, U+03ED, U+03EF, U+03F3, U+03F8, U+03FB + +################################################## +# Gujarati +U+0A85..U+0A8C, U+0A8F, U+0A90, U+0A93..U+0AB0, U+0AB2, U+0AB3, U+0AB5..U+0AB9, U+0AE0, U+0AE1, U+0AE6..U+0AEF + +################################################## +# Gurmukhi +U+0A33->U+0A32, U+0A36->U+0A38, U+0A59->U+0A16, U+0A5A->U+0A17, U+0A5B->U+0A1C, U+0A5E->U+0A2B, U+0A05..U+0A0A, U+0A0F, U+0A10, +U+0A13..U+0A28, U+0A2A..U+0A30, U+0A32, U+0A35, U+0A38, U+0A39, U+0A5C, U+0A66..U+0A6F + +################################################# +# Hebrew* +U+FB1D->U+05D9, U+FB1F->U+05F2, U+FB20->U+05E2, U+FB21->U+05D0, U+FB22->U+05D3, U+FB23->U+05D4, U+FB24->U+05DB, U+FB25->U+05DC, +U+FB26->U+05DD, U+FB27->U+05E8, U+FB28->U+05EA, U+FB2A->U+05E9, U+FB2B->U+05E9, U+FB2C->U+05E9, U+FB2D->U+05E9, U+FB2E->U+05D0, +U+FB2F->U+05D0, U+FB30->U+05D0, U+FB31->U+05D1, U+FB32->U+05D2, U+FB33->U+05D3, U+FB34->U+05D4, U+FB35->U+05D5, U+FB36->U+05D6, +U+FB38->U+05D8, U+FB39->U+05D9, U+FB3A->U+05DA, U+FB3B->U+05DB, U+FB3C->U+05DC, U+FB3E->U+05DE, U+FB40->U+05E0, U+FB41->U+05E1, +U+FB43->U+05E3, U+FB44->U+05E4, U+FB46->U+05E6, U+FB47->U+05E7, U+FB48->U+05E8, U+FB49->U+05E9, U+FB4A->U+05EA, U+FB4B->U+05D5, +U+FB4C->U+05D1, U+FB4D->U+05DB, U+FB4E->U+05E4, U+FB4F->U+05D0, U+05D0..U+05F2 + +################################################# +# Kannada +U+0C85..U+0C8C, U+0C8E..U+0C90, U+0C92..U+0CA8, U+0CAA..U+0CB3, U+0CB5..U+0CB9, U+0CE0, U+0CE1, U+0CE6..U+0CEF + +################################################# +# Limbu +U+1900..U+191C, U+1930..U+1938, U+1946..U+194F + +################################################# +# Malayalam +U+0D05..U+0D0C, U+0D0E..U+0D10, U+0D12..U+0D28, U+0D2A..U+0D39, U+0D60, U+0D61, U+0D66..U+0D6F + +################################################# +# Tamil +U+0B94->U+0B92, U+0B85..U+0B8A, U+0B8E..U+0B90, U+0B92, U+0B93, U+0B95, U+0B99, U+0B9A, U+0B9C, U+0B9E, U+0B9F, U+0BA3, U+0BA4, +U+0BA8..U+0BAA, U+0BAE..U+0BB9, U+0BE6..U+0BEF + +################################################# +# Thai +U+0E01..U+0E30, U+0E32, U+0E33, U+0E40..U+0E46, U+0E50..U+0E5B + +################################################## +# Common +U+FF10..U+FF19->0..9, U+FF21..U+FF3A->a..z, U+FF41..U+FF5A->a..z, 0..9, A..Z->a..z, a..z +""" + +# The expected value format is a commas-separated list of mappings. +# Two simplest mappings simply declare a character as valid, and map a single character +# to another single character, respectively. But specifying the whole table in such +# form would result in bloated and barely manageable specifications. So there are +# several syntax shortcuts that let you map ranges of characters at once. The complete +# list is as follows: +# +# A->a +# Single char mapping, declares source char 'A' as allowed to occur within keywords +# and maps it to destination char 'a' (but does not declare 'a' as allowed). +# A..Z->a..z +# Range mapping, declares all chars in source range as allowed and maps them to +# the destination range. Does not declare destination range as allowed. Also checks +# ranges' lengths (the lengths must be equal). +# a +# Stray char mapping, declares a character as allowed and maps it to itself. +# Equivalent to a->a single char mapping. +# a..z +# Stray range mapping, declares all characters in range as allowed and maps them to +# themselves. Equivalent to a..z->a..z range mapping. +# A..Z/2 +# Checkerboard range map. Maps every pair of chars to the second char. +# More formally, declares odd characters in range as allowed and maps them to the +# even ones; also declares even characters as allowed and maps them to themselves. +# For instance, A..Z/2 is equivalent to A->B, B->B, C->D, D->D, ..., Y->Z, Z->Z. +# This mapping shortcut is helpful for a number of Unicode blocks where uppercase +# and lowercase letters go in such interleaved order instead of contiguous chunks. + +_dewhite = re.compile(r"\s") +_char = r"((?:U\+[0-9A-Fa-f]{4,6})|.)" +_char_map = re.compile("^" + _char + "->" + _char + "$") +_range_map = re.compile("^" + _char + r"\.\." + _char + "->" + _char + ".." + _char + "$") +_stray_char = re.compile("^" + _char + "$") +_stray_range = re.compile("^" + _char + r"\.\." + _char + "$") +_checker_range = re.compile("^" + _char + r"\.\." + _char + "/2$") + + +def charspec_to_int(string): + # Converts a character specification of the form 'A' or 'U+23BC' + # to an integer + if string.startswith("U+"): + return int(string[2:], 16) + elif len(string) == 1: + return ord(string) + else: + raise Exception("Can't convert charspec: %r" % string) + + +def charset_table_to_dict(tablestring): + """Takes a string with the contents of a Sphinx charset table file and + returns a mapping object (a defaultdict, actually) of the kind expected by + the unicode.translate() method: that is, it maps a character number to a unicode + character or None if the character is not a valid word character. + + The Sphinx charset table format is described at + http://www.sphinxsearch.com/docs/current.html#conf-charset-table. + """ + + #map = {} + map = defaultdict(lambda: None) + for line in tablestring.split("\n"): + if not line or line.startswith("#"): + continue + line = _dewhite.sub("", line) + for item in line.split(","): + if not item: + continue + match = _range_map.match(item) + if match: + start1 = charspec_to_int(match.group(1)) + end1 = charspec_to_int(match.group(2)) + start2 = charspec_to_int(match.group(3)) + end2 = charspec_to_int(match.group(4)) + assert (end1 - start1) == (end2 - start2) + try: + for fromord, tooord in izip(xrange(start1, end1 + 1), + xrange(start2, end2 + 1)): + map[fromord] = unichr(tooord) + except ValueError: + pass + continue + + match = _char_map.match(item) + if match: + fromord = charspec_to_int(match.group(1)) + toord = charspec_to_int(match.group(2)) + try: + map[fromord] = unichr(toord) + except ValueError: + pass + continue + + match = _stray_char.match(item) + if match: + ord = charspec_to_int(match.group(0)) + try: + map[ord] = unichr(ord) + except ValueError: + pass + continue + + match = _stray_range.match(item) + if match: + start = charspec_to_int(match.group(1)) + end = charspec_to_int(match.group(2)) + try: + for ord in xrange(start, end + 1): + map[ord] = unichr(ord) + except ValueError: + pass + continue + + match = _checker_range.match(item) + if match: + fromord = charspec_to_int(match.group(1)) + toord = charspec_to_int(match.group(2)) + assert toord - fromord % 2 == 0 + for ord in xrange(fromord, toord + 1, 2): + try: + map[ord] = unichr(ord + 1) + map[ord + 1] = unichr(ord + 1) + except ValueError: + pass + continue + + raise Exception("Don't know what to do with %r" % item) + return dict(map) diff --git a/nstock/modules/whoosh/support/levenshtein.py b/nstock/modules/whoosh/support/levenshtein.py new file mode 100644 index 0000000..dbe476c --- /dev/null +++ b/nstock/modules/whoosh/support/levenshtein.py @@ -0,0 +1,70 @@ +""" +Contains functions implementing edit distance algorithms. +""" + +from whoosh.compat import xrange + + +def levenshtein(seq1, seq2, limit=None): + """Returns the Levenshtein edit distance between two strings. + """ + + oneago = None + thisrow = list(range(1, len(seq2) + 1)) + [0] + for x in xrange(len(seq1)): + # Python lists wrap around for negative indices, so put the + # leftmost column at the *end* of the list. This matches with + # the zero-indexed strings and saves extra calculation. + oneago, thisrow = thisrow, [0] * len(seq2) + [x + 1] + for y in xrange(len(seq2)): + delcost = oneago[y] + 1 + addcost = thisrow[y - 1] + 1 + subcost = oneago[y - 1] + (seq1[x] != seq2[y]) + thisrow[y] = min(delcost, addcost, subcost) + + if limit and x > limit and min(thisrow) > limit: + return limit + 1 + + return thisrow[len(seq2) - 1] + + +def damerau_levenshtein(seq1, seq2, limit=None): + """Returns the Damerau-Levenshtein edit distance between two strings. + """ + + oneago = None + thisrow = list(range(1, len(seq2) + 1)) + [0] + for x in xrange(len(seq1)): + # Python lists wrap around for negative indices, so put the + # leftmost column at the *end* of the list. This matches with + # the zero-indexed strings and saves extra calculation. + twoago, oneago, thisrow = oneago, thisrow, [0] * len(seq2) + [x + 1] + for y in xrange(len(seq2)): + delcost = oneago[y] + 1 + addcost = thisrow[y - 1] + 1 + subcost = oneago[y - 1] + (seq1[x] != seq2[y]) + thisrow[y] = min(delcost, addcost, subcost) + # This block deals with transpositions + if (x > 0 and y > 0 and seq1[x] == seq2[y - 1] + and seq1[x - 1] == seq2[y] and seq1[x] != seq2[y]): + thisrow[y] = min(thisrow[y], twoago[y - 2] + 1) + + if limit and x > limit and min(thisrow) > limit: + return limit + 1 + + return thisrow[len(seq2) - 1] + + +def relative(a, b): + """Returns the relative distance between two strings, in the range + [0-1] where 1 means total equality. + """ + + d = distance(a, b) + longer = float(max((len(a), len(b)))) + shorter = float(min((len(a), len(b)))) + r = ((longer - d) / longer) * (shorter / longer) + return r + + +distance = damerau_levenshtein diff --git a/nstock/modules/whoosh/support/relativedelta.py b/nstock/modules/whoosh/support/relativedelta.py new file mode 100644 index 0000000..23ca7ee --- /dev/null +++ b/nstock/modules/whoosh/support/relativedelta.py @@ -0,0 +1,437 @@ +""" +Copyright (c) 2003-2010 Gustavo Niemeyer + +This module offers extensions to the standard python 2.3+ +datetime module. +""" +__author__ = "Gustavo Niemeyer " +__license__ = "PSF License" + +import datetime +import calendar + +__all__ = ["relativedelta", "MO", "TU", "WE", "TH", "FR", "SA", "SU"] + + +class weekday(object): + __slots__ = ["weekday", "n"] + + def __init__(self, weekday, n=None): + self.weekday = weekday + self.n = n + + def __call__(self, n): + if n == self.n: + return self + else: + return self.__class__(self.weekday, n) + + def __eq__(self, other): + try: + if self.weekday != other.weekday or self.n != other.n: + return False + except AttributeError: + return False + return True + + def __repr__(self): + s = ("MO", "TU", "WE", "TH", "FR", "SA", "SU")[self.weekday] + if not self.n: + return s + else: + return "%s(%+d)" % (s, self.n) + +MO, TU, WE, TH, FR, SA, SU = weekdays = tuple([weekday(x) for x in range(7)]) + + +class relativedelta: + """ +The relativedelta type is based on the specification of the excellent +work done by M.-A. Lemburg in his mx.DateTime extension. However, +notice that this type does *NOT* implement the same algorithm as +his work. Do *NOT* expect it to behave like mx.DateTime's counterpart. + +There's two different ways to build a relativedelta instance. The +first one is passing it two date/datetime classes: + + relativedelta(datetime1, datetime2) + +And the other way is to use the following keyword arguments: + + year, month, day, hour, minute, second, microsecond: + Absolute information. + + years, months, weeks, days, hours, minutes, seconds, microseconds: + Relative information, may be negative. + + weekday: + One of the weekday instances (MO, TU, etc). These instances may + receive a parameter N, specifying the Nth weekday, which could + be positive or negative (like MO(+1) or MO(-2). Not specifying + it is the same as specifying +1. You can also use an integer, + where 0=MO. + + leapdays: + Will add given days to the date found, if year is a leap + year, and the date found is post 28 of february. + + yearday, nlyearday: + Set the yearday or the non-leap year day (jump leap days). + These are converted to day/month/leapdays information. + +Here is the behavior of operations with relativedelta: + +1) Calculate the absolute year, using the 'year' argument, or the + original datetime year, if the argument is not present. + +2) Add the relative 'years' argument to the absolute year. + +3) Do steps 1 and 2 for month/months. + +4) Calculate the absolute day, using the 'day' argument, or the + original datetime day, if the argument is not present. Then, + subtract from the day until it fits in the year and month + found after their operations. + +5) Add the relative 'days' argument to the absolute day. Notice + that the 'weeks' argument is multiplied by 7 and added to + 'days'. + +6) Do steps 1 and 2 for hour/hours, minute/minutes, second/seconds, + microsecond/microseconds. + +7) If the 'weekday' argument is present, calculate the weekday, + with the given (wday, nth) tuple. wday is the index of the + weekday (0-6, 0=Mon), and nth is the number of weeks to add + forward or backward, depending on its signal. Notice that if + the calculated date is already Monday, for example, using + (0, 1) or (0, -1) won't change the day. + """ + + def __init__(self, dt1=None, dt2=None, + years=0, months=0, days=0, leapdays=0, weeks=0, + hours=0, minutes=0, seconds=0, microseconds=0, + year=None, month=None, day=None, weekday=None, + yearday=None, nlyearday=None, + hour=None, minute=None, second=None, microsecond=None): + if dt1 and dt2: + if not isinstance(dt1, datetime.date) or \ + not isinstance(dt2, datetime.date): + raise TypeError("relativedelta only diffs datetime/date") + if type(dt1) is not type(dt2): + if not isinstance(dt1, datetime.datetime): + dt1 = datetime.datetime.fromordinal(dt1.toordinal()) + elif not isinstance(dt2, datetime.datetime): + dt2 = datetime.datetime.fromordinal(dt2.toordinal()) + self.years = 0 + self.months = 0 + self.days = 0 + self.leapdays = 0 + self.hours = 0 + self.minutes = 0 + self.seconds = 0 + self.microseconds = 0 + self.year = None + self.month = None + self.day = None + self.weekday = None + self.hour = None + self.minute = None + self.second = None + self.microsecond = None + self._has_time = 0 + + months = (dt1.year * 12 + dt1.month) - (dt2.year * 12 + dt2.month) + self._set_months(months) + dtm = self.__radd__(dt2) + if dt1 < dt2: + while dt1 > dtm: + months += 1 + self._set_months(months) + dtm = self.__radd__(dt2) + else: + while dt1 < dtm: + months -= 1 + self._set_months(months) + dtm = self.__radd__(dt2) + delta = dt1 - dtm + self.seconds = delta.seconds + delta.days * 86400 + self.microseconds = delta.microseconds + else: + self.years = years + self.months = months + self.days = days + weeks * 7 + self.leapdays = leapdays + self.hours = hours + self.minutes = minutes + self.seconds = seconds + self.microseconds = microseconds + self.year = year + self.month = month + self.day = day + self.hour = hour + self.minute = minute + self.second = second + self.microsecond = microsecond + + if type(weekday) is int: + self.weekday = weekdays[weekday] + else: + self.weekday = weekday + + yday = 0 + if nlyearday: + yday = nlyearday + elif yearday: + yday = yearday + if yearday > 59: + self.leapdays = -1 + if yday: + ydayidx = [31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, + 366] + for idx, ydays in enumerate(ydayidx): + if yday <= ydays: + self.month = idx + 1 + if idx == 0: + self.day = yday + else: + self.day = yday - ydayidx[idx - 1] + break + else: + raise ValueError("invalid year day (%d)" % yday) + + self._fix() + + def _fix(self): + if abs(self.microseconds) > 999999: + s = self.microseconds // abs(self.microseconds) + div, mod = divmod(self.microseconds * s, 1000000) + self.microseconds = mod * s + self.seconds += div * s + if abs(self.seconds) > 59: + s = self.seconds // abs(self.seconds) + div, mod = divmod(self.seconds * s, 60) + self.seconds = mod * s + self.minutes += div * s + if abs(self.minutes) > 59: + s = self.minutes // abs(self.minutes) + div, mod = divmod(self.minutes * s, 60) + self.minutes = mod * s + self.hours += div * s + if abs(self.hours) > 23: + s = self.hours // abs(self.hours) + div, mod = divmod(self.hours * s, 24) + self.hours = mod * s + self.days += div * s + if abs(self.months) > 11: + s = self.months // abs(self.months) + div, mod = divmod(self.months * s, 12) + self.months = mod * s + self.years += div * s + if (self.hours or self.minutes or self.seconds or self.microseconds or + self.hour is not None or self.minute is not None or + self.second is not None or self.microsecond is not None): + self._has_time = 1 + else: + self._has_time = 0 + + def _set_months(self, months): + self.months = months + if abs(self.months) > 11: + s = self.months // abs(self.months) + div, mod = divmod(self.months * s, 12) + self.months = mod * s + self.years = div * s + else: + self.years = 0 + + def __radd__(self, other): + if not isinstance(other, datetime.date): + raise TypeError("unsupported type for add operation") + elif self._has_time and not isinstance(other, datetime.datetime): + other = datetime.datetime.fromordinal(other.toordinal()) + year = (self.year or other.year) + self.years + month = self.month or other.month + if self.months: + assert 1 <= abs(self.months) <= 12 + month += self.months + if month > 12: + year += 1 + month -= 12 + elif month < 1: + year -= 1 + month += 12 + day = min(calendar.monthrange(year, month)[1], + self.day or other.day) + repl = {"year": year, "month": month, "day": day} + for attr in ["hour", "minute", "second", "microsecond"]: + value = getattr(self, attr) + if value is not None: + repl[attr] = value + days = self.days + if self.leapdays and month > 2 and calendar.isleap(year): + days += self.leapdays + ret = (other.replace(**repl) + + datetime.timedelta(days=days, + hours=self.hours, + minutes=self.minutes, + seconds=self.seconds, + microseconds=self.microseconds)) + if self.weekday: + weekday, nth = self.weekday.weekday, self.weekday.n or 1 + jumpdays = (abs(nth) - 1) * 7 + if nth > 0: + jumpdays += (7 - ret.weekday() + weekday) % 7 + else: + jumpdays += (ret.weekday() - weekday) % 7 + jumpdays *= -1 + ret += datetime.timedelta(days=jumpdays) + return ret + + def __rsub__(self, other): + return self.__neg__().__radd__(other) + + def __add__(self, other): + if not isinstance(other, relativedelta): + raise TypeError("unsupported type for add operation") + return relativedelta(years=other.years + self.years, + months=other.months + self.months, + days=other.days + self.days, + hours=other.hours + self.hours, + minutes=other.minutes + self.minutes, + seconds=other.seconds + self.seconds, + microseconds=other.microseconds + self.microseconds, + leapdays=other.leapdays or self.leapdays, + year=other.year or self.year, + month=other.month or self.month, + day=other.day or self.day, + weekday=other.weekday or self.weekday, + hour=other.hour or self.hour, + minute=other.minute or self.minute, + second=other.second or self.second, + microsecond=other.second or self.microsecond) + + def __sub__(self, other): + if not isinstance(other, relativedelta): + raise TypeError("unsupported type for sub operation") + return relativedelta(years=other.years - self.years, + months=other.months - self.months, + days=other.days - self.days, + hours=other.hours - self.hours, + minutes=other.minutes - self.minutes, + seconds=other.seconds - self.seconds, + microseconds=other.microseconds - self.microseconds, + leapdays=other.leapdays or self.leapdays, + year=other.year or self.year, + month=other.month or self.month, + day=other.day or self.day, + weekday=other.weekday or self.weekday, + hour=other.hour or self.hour, + minute=other.minute or self.minute, + second=other.second or self.second, + microsecond=other.second or self.microsecond) + + def __neg__(self): + return relativedelta(years= -self.years, + months= -self.months, + days= -self.days, + hours= -self.hours, + minutes= -self.minutes, + seconds= -self.seconds, + microseconds= -self.microseconds, + leapdays=self.leapdays, + year=self.year, + month=self.month, + day=self.day, + weekday=self.weekday, + hour=self.hour, + minute=self.minute, + second=self.second, + microsecond=self.microsecond) + + def __nonzero__(self): + return not (not self.years and + not self.months and + not self.days and + not self.hours and + not self.minutes and + not self.seconds and + not self.microseconds and + not self.leapdays and + self.year is None and + self.month is None and + self.day is None and + self.weekday is None and + self.hour is None and + self.minute is None and + self.second is None and + self.microsecond is None) + + __bool__ = __nonzero__ + + def __mul__(self, other): + f = float(other) + return relativedelta(years=self.years * f, + months=self.months * f, + days=self.days * f, + hours=self.hours * f, + minutes=self.minutes * f, + seconds=self.seconds * f, + microseconds=self.microseconds * f, + leapdays=self.leapdays, + year=self.year, + month=self.month, + day=self.day, + weekday=self.weekday, + hour=self.hour, + minute=self.minute, + second=self.second, + microsecond=self.microsecond) + + def __eq__(self, other): + if not isinstance(other, relativedelta): + return False + if self.weekday or other.weekday: + if not self.weekday or not other.weekday: + return False + if self.weekday.weekday != other.weekday.weekday: + return False + n1, n2 = self.weekday.n, other.weekday.n + if n1 != n2 and not ((not n1 or n1 == 1) and (not n2 or n2 == 1)): + return False + return (self.years == other.years and + self.months == other.months and + self.days == other.days and + self.hours == other.hours and + self.minutes == other.minutes and + self.seconds == other.seconds and + self.leapdays == other.leapdays and + self.year == other.year and + self.month == other.month and + self.day == other.day and + self.hour == other.hour and + self.minute == other.minute and + self.second == other.second and + self.microsecond == other.microsecond) + + def __ne__(self, other): + return not self.__eq__(other) + + def __div__(self, other): + return self.__mul__(1 / float(other)) + + def __repr__(self): + l = [] + for attr in ["years", "months", "days", "leapdays", + "hours", "minutes", "seconds", "microseconds"]: + value = getattr(self, attr) + if value: + l.append("%s=%+d" % (attr, value)) + for attr in ["year", "month", "day", "weekday", + "hour", "minute", "second", "microsecond"]: + value = getattr(self, attr) + if value is not None: + l.append("%s=%s" % (attr, repr(value))) + return "%s(%s)" % (self.__class__.__name__, ", ".join(l)) + +# vim:ts=4:sw=4:et diff --git a/nstock/modules/whoosh/support/unicode.py b/nstock/modules/whoosh/support/unicode.py new file mode 100644 index 0000000..7d42f56 --- /dev/null +++ b/nstock/modules/whoosh/support/unicode.py @@ -0,0 +1,527 @@ +import re +from bisect import bisect_right + +from whoosh.compat import text_type, u + + +# http://unicode.org/Public/UNIDATA/Blocks.txt +_blockdata = ''' +# Blocks-5.1.0.txt +# Date: 2008-03-20, 17:41:00 PDT [KW] +# +# Unicode Character Database +# Copyright (c) 1991-2008 Unicode, Inc. +# For terms of use, see http://www.unicode.org/terms_of_use.html +# For documentation, see UCD.html +# +# Note: The casing of block names is not normative. +# For example, "Basic Latin" and "BASIC LATIN" are equivalent. +# +# Format: +# Start Code..End Code; Block Name + +# ================================================ + +# Note: When comparing block names, casing, whitespace, hyphens, +# and underbars are ignored. +# For example, "Latin Extended-A" and "latin extended a" are equivalent +# For more information on the comparison of property values, +# see UCD.html. +# +# All code points not explicitly listed for Block +# have the value No_Block. + +# Property: Block +# +# @missing: 0000..10FFFF; No_Block + +0000..007F; Basic Latin +0080..00FF; Latin-1 Supplement +0100..017F; Latin Extended-A +0180..024F; Latin Extended-B +0250..02AF; IPA Extensions +02B0..02FF; Spacing Modifier Letters +0300..036F; Combining Diacritical Marks +0370..03FF; Greek and Coptic +0400..04FF; Cyrillic +0500..052F; Cyrillic Supplement +0530..058F; Armenian +0590..05FF; Hebrew +0600..06FF; Arabic +0700..074F; Syriac +0750..077F; Arabic Supplement +0780..07BF; Thaana +07C0..07FF; NKo +0900..097F; Devanagari +0980..09FF; Bengali +0A00..0A7F; Gurmukhi +0A80..0AFF; Gujarati +0B00..0B7F; Oriya +0B80..0BFF; Tamil +0C00..0C7F; Telugu +0C80..0CFF; Kannada +0D00..0D7F; Malayalam +0D80..0DFF; Sinhala +0E00..0E7F; Thai +0E80..0EFF; Lao +0F00..0FFF; Tibetan +1000..109F; Myanmar +10A0..10FF; Georgian +1100..11FF; Hangul Jamo +1200..137F; Ethiopic +1380..139F; Ethiopic Supplement +13A0..13FF; Cherokee +1400..167F; Unified Canadian Aboriginal Syllabics +1680..169F; Ogham +16A0..16FF; Runic +1700..171F; Tagalog +1720..173F; Hanunoo +1740..175F; Buhid +1760..177F; Tagbanwa +1780..17FF; Khmer +1800..18AF; Mongolian +1900..194F; Limbu +1950..197F; Tai Le +1980..19DF; New Tai Lue +19E0..19FF; Khmer Symbols +1A00..1A1F; Buginese +1B00..1B7F; Balinese +1B80..1BBF; Sundanese +1C00..1C4F; Lepcha +1C50..1C7F; Ol Chiki +1D00..1D7F; Phonetic Extensions +1D80..1DBF; Phonetic Extensions Supplement +1DC0..1DFF; Combining Diacritical Marks Supplement +1E00..1EFF; Latin Extended Additional +1F00..1FFF; Greek Extended +2000..206F; General Punctuation +2070..209F; Superscripts and Subscripts +20A0..20CF; Currency Symbols +20D0..20FF; Combining Diacritical Marks for Symbols +2100..214F; Letterlike Symbols +2150..218F; Number Forms +2190..21FF; Arrows +2200..22FF; Mathematical Operators +2300..23FF; Miscellaneous Technical +2400..243F; Control Pictures +2440..245F; Optical Character Recognition +2460..24FF; Enclosed Alphanumerics +2500..257F; Box Drawing +2580..259F; Block Elements +25A0..25FF; Geometric Shapes +2600..26FF; Miscellaneous Symbols +2700..27BF; Dingbats +27C0..27EF; Miscellaneous Mathematical Symbols-A +27F0..27FF; Supplemental Arrows-A +2800..28FF; Braille Patterns +2900..297F; Supplemental Arrows-B +2980..29FF; Miscellaneous Mathematical Symbols-B +2A00..2AFF; Supplemental Mathematical Operators +2B00..2BFF; Miscellaneous Symbols and Arrows +2C00..2C5F; Glagolitic +2C60..2C7F; Latin Extended-C +2C80..2CFF; Coptic +2D00..2D2F; Georgian Supplement +2D30..2D7F; Tifinagh +2D80..2DDF; Ethiopic Extended +2DE0..2DFF; Cyrillic Extended-A +2E00..2E7F; Supplemental Punctuation +2E80..2EFF; CJK Radicals Supplement +2F00..2FDF; Kangxi Radicals +2FF0..2FFF; Ideographic Description Characters +3000..303F; CJK Symbols and Punctuation +3040..309F; Hiragana +30A0..30FF; Katakana +3100..312F; Bopomofo +3130..318F; Hangul Compatibility Jamo +3190..319F; Kanbun +31A0..31BF; Bopomofo Extended +31C0..31EF; CJK Strokes +31F0..31FF; Katakana Phonetic Extensions +3200..32FF; Enclosed CJK Letters and Months +3300..33FF; CJK Compatibility +3400..4DBF; CJK Unified Ideographs Extension A +4DC0..4DFF; Yijing Hexagram Symbols +4E00..9FFF; CJK Unified Ideographs +A000..A48F; Yi Syllables +A490..A4CF; Yi Radicals +A500..A63F; Vai +A640..A69F; Cyrillic Extended-B +A700..A71F; Modifier Tone Letters +A720..A7FF; Latin Extended-D +A800..A82F; Syloti Nagri +A840..A87F; Phags-pa +A880..A8DF; Saurashtra +A900..A92F; Kayah Li +A930..A95F; Rejang +AA00..AA5F; Cham +AC00..D7AF; Hangul Syllables +D800..DB7F; High Surrogates +DB80..DBFF; High Private Use Surrogates +DC00..DFFF; Low Surrogates +E000..F8FF; Private Use Area +F900..FAFF; CJK Compatibility Ideographs +FB00..FB4F; Alphabetic Presentation Forms +FB50..FDFF; Arabic Presentation Forms-A +FE00..FE0F; Variation Selectors +FE10..FE1F; Vertical Forms +FE20..FE2F; Combining Half Marks +FE30..FE4F; CJK Compatibility Forms +FE50..FE6F; Small Form Variants +FE70..FEFF; Arabic Presentation Forms-B +FF00..FFEF; Halfwidth and Fullwidth Forms +FFF0..FFFF; Specials +10000..1007F; Linear B Syllabary +10080..100FF; Linear B Ideograms +10100..1013F; Aegean Numbers +10140..1018F; Ancient Greek Numbers +10190..101CF; Ancient Symbols +101D0..101FF; Phaistos Disc +10280..1029F; Lycian +102A0..102DF; Carian +10300..1032F; Old Italic +10330..1034F; Gothic +10380..1039F; Ugaritic +103A0..103DF; Old Persian +10400..1044F; Deseret +10450..1047F; Shavian +10480..104AF; Osmanya +10800..1083F; Cypriot Syllabary +10900..1091F; Phoenician +10920..1093F; Lydian +10A00..10A5F; Kharoshthi +12000..123FF; Cuneiform +12400..1247F; Cuneiform Numbers and Punctuation +1D000..1D0FF; Byzantine Musical Symbols +1D100..1D1FF; Musical Symbols +1D200..1D24F; Ancient Greek Musical Notation +1D300..1D35F; Tai Xuan Jing Symbols +1D360..1D37F; Counting Rod Numerals +1D400..1D7FF; Mathematical Alphanumeric Symbols +1F000..1F02F; Mahjong Tiles +1F030..1F09F; Domino Tiles +20000..2A6DF; CJK Unified Ideographs Extension B +2F800..2FA1F; CJK Compatibility Ideographs Supplement +E0000..E007F; Tags +E0100..E01EF; Variation Selectors Supplement +F0000..FFFFF; Supplementary Private Use Area-A +100000..10FFFF; Supplementary Private Use Area-B + +# EOF +''' + + +pattern = re.compile(r'([0-9A-F]+)\.\.([0-9A-F]+);\ (\S.*\S)') +_starts = [] +_ends = [] +_names = [] + + +class blocks(object): + pass + + +def _init(): + count = 0 + for line in _blockdata.splitlines(): + m = pattern.match(line) + if m: + start, end, name = m.groups() + _starts.append(int(start, 16)) + _ends.append(int(end, 16)) + _names.append(name) + setattr(blocks, name.replace(" ", "_"), count) + count += 1 +_init() + + +def blockname(ch): + """Return the Unicode block name for ch, or None if ch has no block. + + >>> blockname(u'a') + 'Basic Latin' + >>> blockname(unichr(0x0b80)) + 'Tamil' + >>> block(unichr(2048)) + None + """ + + assert isinstance(ch, text_type) and len(ch) == 1, repr(ch) + cp = ord(ch) + i = bisect_right(_starts, cp) - 1 + end = _ends[i] + if cp > end: + return None + return _names[i] + + +def blocknum(ch): + """Returns the unicode block number for ch, or None if ch has no block. + + >>> blocknum(u'a') + 0 + >>> blocknum(unichr(0x0b80)) + 22 + >>> blocknum(unichr(2048)) + None + """ + + cp = ord(ch) + i = bisect_right(_starts, cp) - 1 + end = _ends[i] + if cp > end: + return None + return i + + +digits = u('0123456789\xb2\xb3\xb9\u0660\u0661\u0662\u0663\u0664\u0665\u0666' + '\u0667\u0668\u0669\u06f0\u06f1\u06f2\u06f3\u06f4\u06f5\u06f6\u06f7' + '\u06f8\u06f9\u07c0\u07c1\u07c2\u07c3\u07c4\u07c5\u07c6\u07c7\u07c8' + '\u07c9\u0966\u0967\u0968\u0969\u096a\u096b\u096c\u096d\u096e\u096f' + '\u09e6\u09e7\u09e8\u09e9\u09ea\u09eb\u09ec\u09ed\u09ee\u09ef\u0a66' + '\u0a67\u0a68\u0a69\u0a6a\u0a6b\u0a6c\u0a6d\u0a6e\u0a6f\u0ae6\u0ae7' + '\u0ae8\u0ae9\u0aea\u0aeb\u0aec\u0aed\u0aee\u0aef\u0b66\u0b67\u0b68' + '\u0b69\u0b6a\u0b6b\u0b6c\u0b6d\u0b6e\u0b6f\u0be6\u0be7\u0be8\u0be9' + '\u0bea\u0beb\u0bec\u0bed\u0bee\u0bef\u0c66\u0c67\u0c68\u0c69\u0c6a' + '\u0c6b\u0c6c\u0c6d\u0c6e\u0c6f\u0ce6\u0ce7\u0ce8\u0ce9\u0cea\u0ceb' + '\u0cec\u0ced\u0cee\u0cef\u0d66\u0d67\u0d68\u0d69\u0d6a\u0d6b\u0d6c' + '\u0d6d\u0d6e\u0d6f\u0e50\u0e51\u0e52\u0e53\u0e54\u0e55\u0e56\u0e57' + '\u0e58\u0e59\u0ed0\u0ed1\u0ed2\u0ed3\u0ed4\u0ed5\u0ed6\u0ed7\u0ed8' + '\u0ed9\u0f20\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\u0f29' + '\u1040\u1041\u1042\u1043\u1044\u1045\u1046\u1047\u1048\u1049\u1090' + '\u1091\u1092\u1093\u1094\u1095\u1096\u1097\u1098\u1099\u1369\u136a' + '\u136b\u136c\u136d\u136e\u136f\u1370\u1371\u17e0\u17e1\u17e2\u17e3' + '\u17e4\u17e5\u17e6\u17e7\u17e8\u17e9\u1810\u1811\u1812\u1813\u1814' + '\u1815\u1816\u1817\u1818\u1819\u1946\u1947\u1948\u1949\u194a\u194b' + '\u194c\u194d\u194e\u194f\u19d0\u19d1\u19d2\u19d3\u19d4\u19d5\u19d6' + '\u19d7\u19d8\u19d9\u19da\u1a80\u1a81\u1a82\u1a83\u1a84\u1a85\u1a86' + '\u1a87\u1a88\u1a89\u1a90\u1a91\u1a92\u1a93\u1a94\u1a95\u1a96\u1a97' + '\u1a98\u1a99\u1b50\u1b51\u1b52\u1b53\u1b54\u1b55\u1b56\u1b57\u1b58' + '\u1b59\u1bb0\u1bb1\u1bb2\u1bb3\u1bb4\u1bb5\u1bb6\u1bb7\u1bb8\u1bb9' + '\u1c40\u1c41\u1c42\u1c43\u1c44\u1c45\u1c46\u1c47\u1c48\u1c49\u1c50' + '\u1c51\u1c52\u1c53\u1c54\u1c55\u1c56\u1c57\u1c58\u1c59\u2070\u2074' + '\u2075\u2076\u2077\u2078\u2079\u2080\u2081\u2082\u2083\u2084\u2085' + '\u2086\u2087\u2088\u2089\u2460\u2461\u2462\u2463\u2464\u2465\u2466' + '\u2467\u2468\u2474\u2475\u2476\u2477\u2478\u2479\u247a\u247b\u247c' + '\u2488\u2489\u248a\u248b\u248c\u248d\u248e\u248f\u2490\u24ea\u24f5' + '\u24f6\u24f7\u24f8\u24f9\u24fa\u24fb\u24fc\u24fd\u24ff\u2776\u2777' + '\u2778\u2779\u277a\u277b\u277c\u277d\u277e\u2780\u2781\u2782\u2783' + '\u2784\u2785\u2786\u2787\u2788\u278a\u278b\u278c\u278d\u278e\u278f' + '\u2790\u2791\u2792\ua620\ua621\ua622\ua623\ua624\ua625\ua626\ua627' + '\ua628\ua629\ua8d0\ua8d1\ua8d2\ua8d3\ua8d4\ua8d5\ua8d6\ua8d7\ua8d8' + '\ua8d9\ua900\ua901\ua902\ua903\ua904\ua905\ua906\ua907\ua908\ua909' + '\ua9d0\ua9d1\ua9d2\ua9d3\ua9d4\ua9d5\ua9d6\ua9d7\ua9d8\ua9d9\uaa50' + '\uaa51\uaa52\uaa53\uaa54\uaa55\uaa56\uaa57\uaa58\uaa59\uabf0\uabf1' + '\uabf2\uabf3\uabf4\uabf5\uabf6\uabf7\uabf8\uabf9\uff10\uff11\uff12' + '\uff13\uff14\uff15\uff16\uff17\uff18\uff19') +lowercase = u('abcdefghijklmnopqrstuvwxyz\xaa\xb5\xba\xdf\xe0\xe1\xe2\xe3\xe4' + '\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3' + '\xf4\xf5\xf6\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff\u0101\u0103\u0105' + '\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119' + '\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d' + '\u012f\u0131\u0133\u0135\u0137\u0138\u013a\u013c\u013e\u0140' + '\u0142\u0144\u0146\u0148\u0149\u014b\u014d\u014f\u0151\u0153' + '\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167' + '\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c' + '\u017e\u017f\u0180\u0183\u0185\u0188\u018c\u018d\u0192\u0195' + '\u0199\u019a\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01aa\u01ab' + '\u01ad\u01b0\u01b4\u01b6\u01b9\u01ba\u01bd\u01be\u01bf\u01c6' + '\u01c9\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc' + '\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef' + '\u01f0\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205' + '\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219' + '\u021b\u021d\u021f\u0221\u0223\u0225\u0227\u0229\u022b\u022d' + '\u022f\u0231\u0233\u0234\u0235\u0236\u0237\u0238\u0239\u023c' + '\u023f\u0240\u0242\u0247\u0249\u024b\u024d\u024f\u0250\u0251' + '\u0252\u0253\u0254\u0255\u0256\u0257\u0258\u0259\u025a\u025b' + '\u025c\u025d\u025e\u025f\u0260\u0261\u0262\u0263\u0264\u0265' + '\u0266\u0267\u0268\u0269\u026a\u026b\u026c\u026d\u026e\u026f' + '\u0270\u0271\u0272\u0273\u0274\u0275\u0276\u0277\u0278\u0279' + '\u027a\u027b\u027c\u027d\u027e\u027f\u0280\u0281\u0282\u0283' + '\u0284\u0285\u0286\u0287\u0288\u0289\u028a\u028b\u028c\u028d' + '\u028e\u028f\u0290\u0291\u0292\u0293\u0295\u0296\u0297\u0298' + '\u0299\u029a\u029b\u029c\u029d\u029e\u029f\u02a0\u02a1\u02a2' + '\u02a3\u02a4\u02a5\u02a6\u02a7\u02a8\u02a9\u02aa\u02ab\u02ac' + '\u02ad\u02ae\u02af\u0371\u0373\u0377\u037b\u037c\u037d\u0390' + '\u03ac\u03ad\u03ae\u03af\u03b0\u03b1\u03b2\u03b3\u03b4\u03b5' + '\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf' + '\u03c0\u03c1\u03c2\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9' + '\u03ca\u03cb\u03cc\u03cd\u03ce\u03d0\u03d1\u03d5\u03d6\u03d7' + '\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb' + '\u03ed\u03ef\u03f0\u03f1\u03f2\u03f3\u03f5\u03f8\u03fb\u03fc' + '\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439' + '\u043a\u043b\u043c\u043d\u043e\u043f\u0440\u0441\u0442\u0443' + '\u0444\u0445\u0446\u0447\u0448\u0449\u044a\u044b\u044c\u044d' + '\u044e\u044f\u0450\u0451\u0452\u0453\u0454\u0455\u0456\u0457' + '\u0458\u0459\u045a\u045b\u045c\u045d\u045e\u045f\u0461\u0463' + '\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477' + '\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493' + '\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7' + '\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb' + '\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce\u04cf' + '\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3' + '\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f7' + '\u04f9\u04fb\u04fd\u04ff\u0501\u0503\u0505\u0507\u0509\u050b' + '\u050d\u050f\u0511\u0513\u0515\u0517\u0519\u051b\u051d\u051f' + '\u0521\u0523\u0525\u0561\u0562\u0563\u0564\u0565\u0566\u0567' + '\u0568\u0569\u056a\u056b\u056c\u056d\u056e\u056f\u0570\u0571' + '\u0572\u0573\u0574\u0575\u0576\u0577\u0578\u0579\u057a\u057b' + '\u057c\u057d\u057e\u057f\u0580\u0581\u0582\u0583\u0584\u0585' + '\u0586\u0587\u1d00\u1d01\u1d02\u1d03\u1d04\u1d05\u1d06\u1d07' + '\u1d08\u1d09\u1d0a\u1d0b\u1d0c\u1d0d\u1d0e\u1d0f\u1d10\u1d11' + '\u1d12\u1d13\u1d14\u1d15\u1d16\u1d17\u1d18\u1d19\u1d1a\u1d1b' + '\u1d1c\u1d1d\u1d1e\u1d1f\u1d20\u1d21\u1d22\u1d23\u1d24\u1d25' + '\u1d26\u1d27\u1d28\u1d29\u1d2a\u1d2b\u1d62\u1d63\u1d64\u1d65' + '\u1d66\u1d67\u1d68\u1d69\u1d6a\u1d6b\u1d6c\u1d6d\u1d6e\u1d6f' + '\u1d70\u1d71\u1d72\u1d73\u1d74\u1d75\u1d76\u1d77\u1d79\u1d7a' + '\u1d7b\u1d7c\u1d7d\u1d7e\u1d7f\u1d80\u1d81\u1d82\u1d83\u1d84' + '\u1d85\u1d86\u1d87\u1d88\u1d89\u1d8a\u1d8b\u1d8c\u1d8d\u1d8e' + '\u1d8f\u1d90\u1d91\u1d92\u1d93\u1d94\u1d95\u1d96\u1d97\u1d98' + '\u1d99\u1d9a\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f' + '\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23' + '\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37' + '\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b' + '\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f' + '\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e71\u1e73' + '\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87' + '\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95\u1e96\u1e97\u1e98' + '\u1e99\u1e9a\u1e9b\u1e9c\u1e9d\u1e9f\u1ea1\u1ea3\u1ea5\u1ea7' + '\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb' + '\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf' + '\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3' + '\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7' + '\u1ef9\u1efb\u1efd\u1eff\u1f00\u1f01\u1f02\u1f03\u1f04\u1f05' + '\u1f06\u1f07\u1f10\u1f11\u1f12\u1f13\u1f14\u1f15\u1f20\u1f21' + '\u1f22\u1f23\u1f24\u1f25\u1f26\u1f27\u1f30\u1f31\u1f32\u1f33' + '\u1f34\u1f35\u1f36\u1f37\u1f40\u1f41\u1f42\u1f43\u1f44\u1f45' + '\u1f50\u1f51\u1f52\u1f53\u1f54\u1f55\u1f56\u1f57\u1f60\u1f61' + '\u1f62\u1f63\u1f64\u1f65\u1f66\u1f67\u1f70\u1f71\u1f72\u1f73' + '\u1f74\u1f75\u1f76\u1f77\u1f78\u1f79\u1f7a\u1f7b\u1f7c\u1f7d' + '\u1f80\u1f81\u1f82\u1f83\u1f84\u1f85\u1f86\u1f87\u1f90\u1f91' + '\u1f92\u1f93\u1f94\u1f95\u1f96\u1f97\u1fa0\u1fa1\u1fa2\u1fa3' + '\u1fa4\u1fa5\u1fa6\u1fa7\u1fb0\u1fb1\u1fb2\u1fb3\u1fb4\u1fb6' + '\u1fb7\u1fbe\u1fc2\u1fc3\u1fc4\u1fc6\u1fc7\u1fd0\u1fd1\u1fd2' + '\u1fd3\u1fd6\u1fd7\u1fe0\u1fe1\u1fe2\u1fe3\u1fe4\u1fe5\u1fe6' + '\u1fe7\u1ff2\u1ff3\u1ff4\u1ff6\u1ff7\u210a\u210e\u210f\u2113' + '\u212f\u2134\u2139\u213c\u213d\u2146\u2147\u2148\u2149\u214e' + '\u2184\u2c30\u2c31\u2c32\u2c33\u2c34\u2c35\u2c36\u2c37\u2c38' + '\u2c39\u2c3a\u2c3b\u2c3c\u2c3d\u2c3e\u2c3f\u2c40\u2c41\u2c42' + '\u2c43\u2c44\u2c45\u2c46\u2c47\u2c48\u2c49\u2c4a\u2c4b\u2c4c' + '\u2c4d\u2c4e\u2c4f\u2c50\u2c51\u2c52\u2c53\u2c54\u2c55\u2c56' + '\u2c57\u2c58\u2c59\u2c5a\u2c5b\u2c5c\u2c5d\u2c5e\u2c61\u2c65' + '\u2c66\u2c68\u2c6a\u2c6c\u2c71\u2c73\u2c74\u2c76\u2c77\u2c78' + '\u2c79\u2c7a\u2c7b\u2c7c\u2c81\u2c83\u2c85\u2c87\u2c89\u2c8b' + '\u2c8d\u2c8f\u2c91\u2c93\u2c95\u2c97\u2c99\u2c9b\u2c9d\u2c9f' + '\u2ca1\u2ca3\u2ca5\u2ca7\u2ca9\u2cab\u2cad\u2caf\u2cb1\u2cb3' + '\u2cb5\u2cb7\u2cb9\u2cbb\u2cbd\u2cbf\u2cc1\u2cc3\u2cc5\u2cc7' + '\u2cc9\u2ccb\u2ccd\u2ccf\u2cd1\u2cd3\u2cd5\u2cd7\u2cd9\u2cdb' + '\u2cdd\u2cdf\u2ce1\u2ce3\u2ce4\u2cec\u2cee\u2d00\u2d01\u2d02' + '\u2d03\u2d04\u2d05\u2d06\u2d07\u2d08\u2d09\u2d0a\u2d0b\u2d0c' + '\u2d0d\u2d0e\u2d0f\u2d10\u2d11\u2d12\u2d13\u2d14\u2d15\u2d16' + '\u2d17\u2d18\u2d19\u2d1a\u2d1b\u2d1c\u2d1d\u2d1e\u2d1f\u2d20' + '\u2d21\u2d22\u2d23\u2d24\u2d25\ua641\ua643\ua645\ua647\ua649' + '\ua64b\ua64d\ua64f\ua651\ua653\ua655\ua657\ua659\ua65b\ua65d' + '\ua65f\ua663\ua665\ua667\ua669\ua66b\ua66d\ua681\ua683\ua685' + '\ua687\ua689\ua68b\ua68d\ua68f\ua691\ua693\ua695\ua697\ua723' + '\ua725\ua727\ua729\ua72b\ua72d\ua72f\ua730\ua731\ua733\ua735' + '\ua737\ua739\ua73b\ua73d\ua73f\ua741\ua743\ua745\ua747\ua749' + '\ua74b\ua74d\ua74f\ua751\ua753\ua755\ua757\ua759\ua75b\ua75d' + '\ua75f\ua761\ua763\ua765\ua767\ua769\ua76b\ua76d\ua76f\ua771' + '\ua772\ua773\ua774\ua775\ua776\ua777\ua778\ua77a\ua77c\ua77f' + '\ua781\ua783\ua785\ua787\ua78c\ufb00\ufb01\ufb02\ufb03\ufb04' + '\ufb05\ufb06\ufb13\ufb14\ufb15\ufb16\ufb17\uff41\uff42\uff43' + '\uff44\uff45\uff46\uff47\uff48\uff49\uff4a\uff4b\uff4c\uff4d' + '\uff4e\uff4f\uff50\uff51\uff52\uff53\uff54\uff55\uff56\uff57' + '\uff58\uff59\uff5a') +uppercase = u('ABCDEFGHIJKLMNOPQRSTUVWXYZ\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8' + '\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd8' + '\xd9\xda\xdb\xdc\xdd\xde\u0100\u0102\u0104\u0106\u0108\u010a' + '\u010c\u010e\u0110\u0112\u0114\u0116\u0118\u011a\u011c\u011e' + '\u0120\u0122\u0124\u0126\u0128\u012a\u012c\u012e\u0130\u0132' + '\u0134\u0136\u0139\u013b\u013d\u013f\u0141\u0143\u0145\u0147' + '\u014a\u014c\u014e\u0150\u0152\u0154\u0156\u0158\u015a\u015c' + '\u015e\u0160\u0162\u0164\u0166\u0168\u016a\u016c\u016e\u0170' + '\u0172\u0174\u0176\u0178\u0179\u017b\u017d\u0181\u0182\u0184' + '\u0186\u0187\u0189\u018a\u018b\u018e\u018f\u0190\u0191\u0193' + '\u0194\u0196\u0197\u0198\u019c\u019d\u019f\u01a0\u01a2\u01a4' + '\u01a6\u01a7\u01a9\u01ac\u01ae\u01af\u01b1\u01b2\u01b3\u01b5' + '\u01b7\u01b8\u01bc\u01c4\u01c7\u01ca\u01cd\u01cf\u01d1\u01d3' + '\u01d5\u01d7\u01d9\u01db\u01de\u01e0\u01e2\u01e4\u01e6\u01e8' + '\u01ea\u01ec\u01ee\u01f1\u01f4\u01f6\u01f7\u01f8\u01fa\u01fc' + '\u01fe\u0200\u0202\u0204\u0206\u0208\u020a\u020c\u020e\u0210' + '\u0212\u0214\u0216\u0218\u021a\u021c\u021e\u0220\u0222\u0224' + '\u0226\u0228\u022a\u022c\u022e\u0230\u0232\u023a\u023b\u023d' + '\u023e\u0241\u0243\u0244\u0245\u0246\u0248\u024a\u024c\u024e' + '\u0370\u0372\u0376\u0386\u0388\u0389\u038a\u038c\u038e\u038f' + '\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a' + '\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\u03a3\u03a4\u03a5' + '\u03a6\u03a7\u03a8\u03a9\u03aa\u03ab\u03cf\u03d2\u03d3\u03d4' + '\u03d8\u03da\u03dc\u03de\u03e0\u03e2\u03e4\u03e6\u03e8\u03ea' + '\u03ec\u03ee\u03f4\u03f7\u03f9\u03fa\u03fd\u03fe\u03ff\u0400' + '\u0401\u0402\u0403\u0404\u0405\u0406\u0407\u0408\u0409\u040a' + '\u040b\u040c\u040d\u040e\u040f\u0410\u0411\u0412\u0413\u0414' + '\u0415\u0416\u0417\u0418\u0419\u041a\u041b\u041c\u041d\u041e' + '\u041f\u0420\u0421\u0422\u0423\u0424\u0425\u0426\u0427\u0428' + '\u0429\u042a\u042b\u042c\u042d\u042e\u042f\u0460\u0462\u0464' + '\u0466\u0468\u046a\u046c\u046e\u0470\u0472\u0474\u0476\u0478' + '\u047a\u047c\u047e\u0480\u048a\u048c\u048e\u0490\u0492\u0494' + '\u0496\u0498\u049a\u049c\u049e\u04a0\u04a2\u04a4\u04a6\u04a8' + '\u04aa\u04ac\u04ae\u04b0\u04b2\u04b4\u04b6\u04b8\u04ba\u04bc' + '\u04be\u04c0\u04c1\u04c3\u04c5\u04c7\u04c9\u04cb\u04cd\u04d0' + '\u04d2\u04d4\u04d6\u04d8\u04da\u04dc\u04de\u04e0\u04e2\u04e4' + '\u04e6\u04e8\u04ea\u04ec\u04ee\u04f0\u04f2\u04f4\u04f6\u04f8' + '\u04fa\u04fc\u04fe\u0500\u0502\u0504\u0506\u0508\u050a\u050c' + '\u050e\u0510\u0512\u0514\u0516\u0518\u051a\u051c\u051e\u0520' + '\u0522\u0524\u0531\u0532\u0533\u0534\u0535\u0536\u0537\u0538' + '\u0539\u053a\u053b\u053c\u053d\u053e\u053f\u0540\u0541\u0542' + '\u0543\u0544\u0545\u0546\u0547\u0548\u0549\u054a\u054b\u054c' + '\u054d\u054e\u054f\u0550\u0551\u0552\u0553\u0554\u0555\u0556' + '\u10a0\u10a1\u10a2\u10a3\u10a4\u10a5\u10a6\u10a7\u10a8\u10a9' + '\u10aa\u10ab\u10ac\u10ad\u10ae\u10af\u10b0\u10b1\u10b2\u10b3' + '\u10b4\u10b5\u10b6\u10b7\u10b8\u10b9\u10ba\u10bb\u10bc\u10bd' + '\u10be\u10bf\u10c0\u10c1\u10c2\u10c3\u10c4\u10c5\u1e00\u1e02' + '\u1e04\u1e06\u1e08\u1e0a\u1e0c\u1e0e\u1e10\u1e12\u1e14\u1e16' + '\u1e18\u1e1a\u1e1c\u1e1e\u1e20\u1e22\u1e24\u1e26\u1e28\u1e2a' + '\u1e2c\u1e2e\u1e30\u1e32\u1e34\u1e36\u1e38\u1e3a\u1e3c\u1e3e' + '\u1e40\u1e42\u1e44\u1e46\u1e48\u1e4a\u1e4c\u1e4e\u1e50\u1e52' + '\u1e54\u1e56\u1e58\u1e5a\u1e5c\u1e5e\u1e60\u1e62\u1e64\u1e66' + '\u1e68\u1e6a\u1e6c\u1e6e\u1e70\u1e72\u1e74\u1e76\u1e78\u1e7a' + '\u1e7c\u1e7e\u1e80\u1e82\u1e84\u1e86\u1e88\u1e8a\u1e8c\u1e8e' + '\u1e90\u1e92\u1e94\u1e9e\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa' + '\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6\u1eb8\u1eba\u1ebc\u1ebe' + '\u1ec0\u1ec2\u1ec4\u1ec6\u1ec8\u1eca\u1ecc\u1ece\u1ed0\u1ed2' + '\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2\u1ee4\u1ee6' + '\u1ee8\u1eea\u1eec\u1eee\u1ef0\u1ef2\u1ef4\u1ef6\u1ef8\u1efa' + '\u1efc\u1efe\u1f08\u1f09\u1f0a\u1f0b\u1f0c\u1f0d\u1f0e\u1f0f' + '\u1f18\u1f19\u1f1a\u1f1b\u1f1c\u1f1d\u1f28\u1f29\u1f2a\u1f2b' + '\u1f2c\u1f2d\u1f2e\u1f2f\u1f38\u1f39\u1f3a\u1f3b\u1f3c\u1f3d' + '\u1f3e\u1f3f\u1f48\u1f49\u1f4a\u1f4b\u1f4c\u1f4d\u1f59\u1f5b' + '\u1f5d\u1f5f\u1f68\u1f69\u1f6a\u1f6b\u1f6c\u1f6d\u1f6e\u1f6f' + '\u1fb8\u1fb9\u1fba\u1fbb\u1fc8\u1fc9\u1fca\u1fcb\u1fd8\u1fd9' + '\u1fda\u1fdb\u1fe8\u1fe9\u1fea\u1feb\u1fec\u1ff8\u1ff9\u1ffa' + '\u1ffb\u2102\u2107\u210b\u210c\u210d\u2110\u2111\u2112\u2115' + '\u2119\u211a\u211b\u211c\u211d\u2124\u2126\u2128\u212a\u212b' + '\u212c\u212d\u2130\u2131\u2132\u2133\u213e\u213f\u2145\u2183' + '\u2c00\u2c01\u2c02\u2c03\u2c04\u2c05\u2c06\u2c07\u2c08\u2c09' + '\u2c0a\u2c0b\u2c0c\u2c0d\u2c0e\u2c0f\u2c10\u2c11\u2c12\u2c13' + '\u2c14\u2c15\u2c16\u2c17\u2c18\u2c19\u2c1a\u2c1b\u2c1c\u2c1d' + '\u2c1e\u2c1f\u2c20\u2c21\u2c22\u2c23\u2c24\u2c25\u2c26\u2c27' + '\u2c28\u2c29\u2c2a\u2c2b\u2c2c\u2c2d\u2c2e\u2c60\u2c62\u2c63' + '\u2c64\u2c67\u2c69\u2c6b\u2c6d\u2c6e\u2c6f\u2c70\u2c72\u2c75' + '\u2c7e\u2c7f\u2c80\u2c82\u2c84\u2c86\u2c88\u2c8a\u2c8c\u2c8e' + '\u2c90\u2c92\u2c94\u2c96\u2c98\u2c9a\u2c9c\u2c9e\u2ca0\u2ca2' + '\u2ca4\u2ca6\u2ca8\u2caa\u2cac\u2cae\u2cb0\u2cb2\u2cb4\u2cb6' + '\u2cb8\u2cba\u2cbc\u2cbe\u2cc0\u2cc2\u2cc4\u2cc6\u2cc8\u2cca' + '\u2ccc\u2cce\u2cd0\u2cd2\u2cd4\u2cd6\u2cd8\u2cda\u2cdc\u2cde' + '\u2ce0\u2ce2\u2ceb\u2ced\ua640\ua642\ua644\ua646\ua648\ua64a' + '\ua64c\ua64e\ua650\ua652\ua654\ua656\ua658\ua65a\ua65c\ua65e' + '\ua662\ua664\ua666\ua668\ua66a\ua66c\ua680\ua682\ua684\ua686' + '\ua688\ua68a\ua68c\ua68e\ua690\ua692\ua694\ua696\ua722\ua724' + '\ua726\ua728\ua72a\ua72c\ua72e\ua732\ua734\ua736\ua738\ua73a' + '\ua73c\ua73e\ua740\ua742\ua744\ua746\ua748\ua74a\ua74c\ua74e' + '\ua750\ua752\ua754\ua756\ua758\ua75a\ua75c\ua75e\ua760\ua762' + '\ua764\ua766\ua768\ua76a\ua76c\ua76e\ua779\ua77b\ua77d\ua77e' + '\ua780\ua782\ua784\ua786\ua78b\uff21\uff22\uff23\uff24\uff25' + '\uff26\uff27\uff28\uff29\uff2a\uff2b\uff2c\uff2d\uff2e\uff2f' + '\uff30\uff31\uff32\uff33\uff34\uff35\uff36\uff37\uff38\uff39' + '\uff3a') diff --git a/nstock/modules/whoosh/system.py b/nstock/modules/whoosh/system.py new file mode 100644 index 0000000..2bdce1b --- /dev/null +++ b/nstock/modules/whoosh/system.py @@ -0,0 +1,79 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +import sys +from struct import Struct, calcsize + + +IS_LITTLE = sys.byteorder == "little" + +_INT_SIZE = calcsize("!i") +_SHORT_SIZE = calcsize("!H") +_LONG_SIZE = calcsize("!Q") +_FLOAT_SIZE = calcsize("!f") +_DOUBLE_SIZE = calcsize("!d") + +_byte_struct = Struct("!B") +_sbyte_struct = Struct("!b") +_ushort_struct = Struct("!H") +_int_struct = Struct("!i") +_uint_struct = Struct("!I") +_long_struct = Struct("!q") +_ulong_struct = Struct("!Q") +_float_struct = Struct("!f") +_double_struct = Struct("!d") +_ushort_le_struct = Struct("= 3: + return bytes(gen) + else: + return array("B", gen).tostring() + + +def make_binary_tree(fn, args, **kwargs): + """Takes a function/class that takes two positional arguments and a list of + arguments and returns a binary tree of results/instances. + + >>> make_binary_tree(UnionMatcher, [matcher1, matcher2, matcher3]) + UnionMatcher(matcher1, UnionMatcher(matcher2, matcher3)) + + Any keyword arguments given to this function are passed to the class + initializer. + """ + + count = len(args) + if not count: + raise ValueError("Called make_binary_tree with empty list") + elif count == 1: + return args[0] + + half = count // 2 + return fn(make_binary_tree(fn, args[:half], **kwargs), + make_binary_tree(fn, args[half:], **kwargs), **kwargs) + + +def make_weighted_tree(fn, ls, **kwargs): + """Takes a function/class that takes two positional arguments and a list of + (weight, argument) tuples and returns a huffman-like weighted tree of + results/instances. + """ + + if not ls: + raise ValueError("Called make_weighted_tree with empty list") + + ls.sort() + while len(ls) > 1: + a = ls.pop(0) + b = ls.pop(0) + insort(ls, (a[0] + b[0], fn(a[1], b[1]))) + return ls[0][1] + + +# Fibonacci function + +_fib_cache = {} + + +def fib(n): + """Returns the nth value in the Fibonacci sequence. + """ + + if n <= 2: + return n + if n in _fib_cache: + return _fib_cache[n] + result = fib(n - 1) + fib(n - 2) + _fib_cache[n] = result + return result + + +# Decorators + +def synchronized(func): + """Decorator for storage-access methods, which synchronizes on a threading + lock. The parent object must have 'is_closed' and '_sync_lock' attributes. + """ + + @wraps(func) + def synchronized_wrapper(self, *args, **kwargs): + with self._sync_lock: + return func(self, *args, **kwargs) + + return synchronized_wrapper + + +def unclosed(method): + """ + Decorator to check if the object is closed. + """ + + @wraps(method) + def unclosed_wrapper(self, *args, **kwargs): + if self.closed: + raise ValueError("Operation on a closed object") + return method(self, *args, **kwargs) + return unclosed_wrapper diff --git a/nstock/modules/whoosh/util/cache.py b/nstock/modules/whoosh/util/cache.py new file mode 100644 index 0000000..064129e --- /dev/null +++ b/nstock/modules/whoosh/util/cache.py @@ -0,0 +1,375 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from __future__ import with_statement +import functools, random +from array import array +from heapq import nsmallest +from operator import itemgetter +from threading import Lock +from time import time + +from whoosh.compat import iteritems, xrange + + +try: + from collections import Counter +except ImportError: + class Counter(dict): + def __missing__(self, key): + return 0 + + +def unbound_cache(func): + """Caching decorator with an unbounded cache size. + """ + + cache = {} + + @functools.wraps(func) + def caching_wrapper(*args): + try: + return cache[args] + except KeyError: + result = func(*args) + cache[args] = result + return result + + return caching_wrapper + + +def lru_cache(maxsize=100): + """A simple cache that, when the cache is full, deletes the least recently + used 10% of the cached values. + + This function duplicates (more-or-less) the protocol of the + ``functools.lru_cache`` decorator in the Python 3.2 standard library. + + Arguments to the cached function must be hashable. + + View the cache statistics tuple ``(hits, misses, maxsize, currsize)`` + with f.cache_info(). Clear the cache and statistics with f.cache_clear(). + Access the underlying function with f.__wrapped__. + """ + + def decorating_function(user_function): + stats = [0, 0] # Hits, misses + data = {} + lastused = {} + + @functools.wraps(user_function) + def wrapper(*args): + try: + result = data[args] + stats[0] += 1 # Hit + except KeyError: + stats[1] += 1 # Miss + if len(data) == maxsize: + for k, _ in nsmallest(maxsize // 10 or 1, + iteritems(lastused), + key=itemgetter(1)): + del data[k] + del lastused[k] + data[args] = user_function(*args) + result = data[args] + finally: + lastused[args] = time() + return result + + def cache_info(): + return stats[0], stats[1], maxsize, len(data) + + def cache_clear(): + data.clear() + lastused.clear() + stats[0] = stats[1] = 0 + + wrapper.cache_info = cache_info + wrapper.cache_clear = cache_clear + return wrapper + return decorating_function + + +def lfu_cache(maxsize=100): + """A simple cache that, when the cache is full, deletes the least frequently + used 10% of the cached values. + + This function duplicates (more-or-less) the protocol of the + ``functools.lru_cache`` decorator in the Python 3.2 standard library. + + Arguments to the cached function must be hashable. + + View the cache statistics tuple ``(hits, misses, maxsize, currsize)`` + with f.cache_info(). Clear the cache and statistics with f.cache_clear(). + Access the underlying function with f.__wrapped__. + """ + + def decorating_function(user_function): + stats = [0, 0] # Hits, misses + data = {} + usecount = Counter() + + @functools.wraps(user_function) + def wrapper(*args): + try: + result = data[args] + stats[0] += 1 # Hit + except KeyError: + stats[1] += 1 # Miss + if len(data) == maxsize: + for k, _ in nsmallest(maxsize // 10 or 1, + iteritems(usecount), + key=itemgetter(1)): + del data[k] + del usecount[k] + data[args] = user_function(*args) + result = data[args] + finally: + usecount[args] += 1 + return result + + def cache_info(): + return stats[0], stats[1], maxsize, len(data) + + def cache_clear(): + data.clear() + usecount.clear() + + wrapper.cache_info = cache_info + wrapper.cache_clear = cache_clear + return wrapper + return decorating_function + + +def random_cache(maxsize=100): + """A very simple cache that, when the cache is filled, deletes 10% of the + cached values AT RANDOM. + + This function duplicates (more-or-less) the protocol of the + ``functools.lru_cache`` decorator in the Python 3.2 standard library. + + Arguments to the cached function must be hashable. + + View the cache statistics tuple ``(hits, misses, maxsize, currsize)`` + with f.cache_info(). Clear the cache and statistics with f.cache_clear(). + Access the underlying function with f.__wrapped__. + """ + + def decorating_function(user_function): + stats = [0, 0] # hits, misses + data = {} + + @functools.wraps(user_function) + def wrapper(*args): + try: + result = data[args] + stats[0] += 1 # Hit + except KeyError: + stats[1] += 1 # Miss + if len(data) == maxsize: + keys = data.keys() + for i in xrange(maxsize // 10 or 1): + n = random.randint(0, len(keys) - 1) + k = keys.pop(n) + del data[k] + data[args] = user_function(*args) + result = data[args] + return result + + def cache_info(): + return stats[0], stats[1], maxsize, len(data) + + def cache_clear(): + data.clear() + + wrapper.cache_info = cache_info + wrapper.cache_clear = cache_clear + return wrapper + return decorating_function + + +def db_lru_cache(maxsize=100): + """Double-barrel least-recently-used cache decorator. This is a simple + LRU algorithm that keeps a primary and secondary dict. Keys are checked + in the primary dict, and then the secondary. Once the primary dict fills + up, the secondary dict is cleared and the two dicts are swapped. + + This function duplicates (more-or-less) the protocol of the + ``functools.lru_cache`` decorator in the Python 3.2 standard library. + + Arguments to the cached function must be hashable. + + View the cache statistics tuple ``(hits, misses, maxsize, currsize)`` + with f.cache_info(). Clear the cache and statistics with f.cache_clear(). + Access the underlying function with f.__wrapped__. + """ + + def decorating_function(user_function): + # Cache1, Cache2, Pointer, Hits, Misses + stats = [{}, {}, 0, 0, 0] + + @functools.wraps(user_function) + def wrapper(*args): + ptr = stats[2] + a = stats[ptr] + b = stats[not ptr] + key = args + + if key in a: + stats[3] += 1 # Hit + return a[key] + elif key in b: + stats[3] += 1 # Hit + return b[key] + else: + stats[4] += 1 # Miss + result = user_function(*args) + a[key] = result + if len(a) >= maxsize: + stats[2] = not ptr + b.clear() + return result + + def cache_info(): + return stats[3], stats[4], maxsize, len(stats[0]) + len(stats[1]) + + def cache_clear(): + """Clear the cache and cache statistics""" + stats[0].clear() + stats[1].clear() + stats[3] = stats[4] = 0 + + wrapper.cache_info = cache_info + wrapper.cache_clear = cache_clear + + return wrapper + return decorating_function + + +def clockface_lru_cache(maxsize=100): + """Least-recently-used cache decorator. + + This function duplicates (more-or-less) the protocol of the + ``functools.lru_cache`` decorator in the Python 3.2 standard library, but + uses the clock face LRU algorithm instead of an ordered dictionary. + + If *maxsize* is set to None, the LRU features are disabled and the cache + can grow without bound. + + Arguments to the cached function must be hashable. + + View the cache statistics named tuple (hits, misses, maxsize, currsize) + with f.cache_info(). Clear the cache and statistics with f.cache_clear(). + Access the underlying function with f.__wrapped__. + """ + + def decorating_function(user_function): + stats = [0, 0, 0] # hits, misses, hand + data = {} + + if maxsize: + # The keys at each point on the clock face + clock_keys = [None] * maxsize + # The "referenced" bits at each point on the clock face + clock_refs = array("B", (0 for _ in xrange(maxsize))) + lock = Lock() + + @functools.wraps(user_function) + def wrapper(*args): + key = args + try: + with lock: + pos, result = data[key] + # The key is in the cache. Set the key's reference bit + clock_refs[pos] = 1 + # Record a cache hit + stats[0] += 1 + except KeyError: + # Compute the value + result = user_function(*args) + with lock: + # Current position of the clock hand + hand = stats[2] + # Remember to stop here after a full revolution + end = hand + # Sweep around the clock looking for a position with + # the reference bit off + while True: + hand = (hand + 1) % maxsize + current_ref = clock_refs[hand] + if current_ref: + # This position's "referenced" bit is set. Turn + # the bit off and move on. + clock_refs[hand] = 0 + elif not current_ref or hand == end: + # We've either found a position with the + # "reference" bit off or reached the end of the + # circular cache. So we'll replace this + # position with the new key + current_key = clock_keys[hand] + if current_key in data: + del data[current_key] + clock_keys[hand] = key + clock_refs[hand] = 1 + break + # Put the key and result in the cache + data[key] = (hand, result) + # Save the new hand position + stats[2] = hand + # Record a cache miss + stats[1] += 1 + return result + + else: + @functools.wraps(user_function) + def wrapper(*args): + key = args + try: + result = data[key] + stats[0] += 1 + except KeyError: + result = user_function(*args) + data[key] = result + stats[1] += 1 + return result + + def cache_info(): + return stats[0], stats[1], maxsize, len(data) + + def cache_clear(): + """Clear the cache and cache statistics""" + data.clear() + stats[0] = stats[1] = stats[2] = 0 + for i in xrange(maxsize): + clock_keys[i] = None + clock_refs[i] = 0 + + wrapper.cache_info = cache_info + wrapper.cache_clear = cache_clear + return wrapper + return decorating_function + diff --git a/nstock/modules/whoosh/util/filelock.py b/nstock/modules/whoosh/util/filelock.py new file mode 100644 index 0000000..382c40d --- /dev/null +++ b/nstock/modules/whoosh/util/filelock.py @@ -0,0 +1,163 @@ +# Copyright 2010 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +""" +This module contains classes implementing exclusive locks for platforms with +fcntl (UNIX and Mac OS X) and Windows. Whoosh originally used directory +creation as a locking method, but it had the problem that if the program +crashed the lock directory was left behind and would keep the index locked +until it was cleaned up. Using OS-level file locks fixes this. +""" + +import errno +import os +import sys +import time + + +def try_for(fn, timeout=5.0, delay=0.1): + """Calls ``fn`` every ``delay`` seconds until it returns True or + ``timeout`` seconds elapse. Returns True if the lock was acquired, or False + if the timeout was reached. + + :param timeout: Length of time (in seconds) to keep retrying to acquire the + lock. 0 means return immediately. Only used when blocking is False. + :param delay: How often (in seconds) to retry acquiring the lock during + the timeout period. Only used when blocking is False and timeout > 0. + """ + + until = time.time() + timeout + v = fn() + while not v and time.time() < until: + time.sleep(delay) + v = fn() + return v + + +class LockBase(object): + """Base class for file locks. + """ + + def __init__(self, filename): + self.fd = None + self.filename = filename + self.locked = False + + def __del__(self): + if hasattr(self, "fd") and self.fd: + try: + self.release() + except: + pass + + def acquire(self, blocking=False): + """Acquire the lock. Returns True if the lock was acquired. + + :param blocking: if True, call blocks until the lock is acquired. + This may not be available on all platforms. On Windows, this is + actually just a delay of 10 seconds, rechecking every second. + """ + pass + + def release(self): + pass + + +class FcntlLock(LockBase): + """File lock based on UNIX-only fcntl module. + """ + + def acquire(self, blocking=False): + import fcntl # @UnresolvedImport + + flags = os.O_CREAT | os.O_WRONLY + self.fd = os.open(self.filename, flags) + + mode = fcntl.LOCK_EX + if not blocking: + mode |= fcntl.LOCK_NB + + try: + fcntl.flock(self.fd, mode) + self.locked = True + return True + except IOError: + e = sys.exc_info()[1] + if e.errno not in (errno.EAGAIN, errno.EACCES): + raise + os.close(self.fd) + self.fd = None + return False + + def release(self): + if self.fd is None: + raise Exception("Lock was not acquired") + + import fcntl # @UnresolvedImport + fcntl.flock(self.fd, fcntl.LOCK_UN) + os.close(self.fd) + self.fd = None + + +class MsvcrtLock(LockBase): + """File lock based on Windows-only msvcrt module. + """ + + def acquire(self, blocking=False): + import msvcrt # @UnresolvedImport + + flags = os.O_CREAT | os.O_WRONLY + mode = msvcrt.LK_NBLCK + if blocking: + mode = msvcrt.LK_LOCK + + self.fd = os.open(self.filename, flags) + try: + msvcrt.locking(self.fd, mode, 1) + return True + except IOError: + e = sys.exc_info()[1] + if e.errno not in (errno.EAGAIN, errno.EACCES, errno.EDEADLK): + raise + os.close(self.fd) + self.fd = None + return False + + def release(self): + import msvcrt # @UnresolvedImport + + if self.fd is None: + raise Exception("Lock was not acquired") + msvcrt.locking(self.fd, msvcrt.LK_UNLCK, 1) + os.close(self.fd) + self.fd = None + + +if os.name == "nt": + FileLock = MsvcrtLock +else: + FileLock = FcntlLock diff --git a/nstock/modules/whoosh/util/loading.py b/nstock/modules/whoosh/util/loading.py new file mode 100644 index 0000000..1de00f7 --- /dev/null +++ b/nstock/modules/whoosh/util/loading.py @@ -0,0 +1,84 @@ +# Copyright 2012 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +import pickle + + +class RenamingUnpickler(pickle.Unpickler): + """Subclasses ``pickle.Unpickler`` to allow remapping of class names before + loading them. + """ + + def __init__(self, f, objmap, shortcuts=None): + pickle.Unpickler.__init__(self, f) + + if shortcuts: + objmap = dict((k % shortcuts, v % shortcuts) + for k, v in objmap.items()) + self._objmap = objmap + + def find_class(self, modulename, objname): + fqname = "%s.%s" % (modulename, objname) + if fqname in self._objmap: + fqname = self._objmap[fqname] + try: + obj = find_object(fqname) + except ImportError: + raise ImportError("Couldn't find %r" % fqname) + return obj + + +def find_object(name, blacklist=None, whitelist=None): + """Imports and returns an object given a fully qualified name. + + >>> find_object("whoosh.analysis.StopFilter") + + """ + + if blacklist: + for pre in blacklist: + if name.startswith(pre): + raise TypeError("%r: can't instantiate names starting with %r" + % (name, pre)) + if whitelist: + passes = False + for pre in whitelist: + if name.startswith(pre): + passes = True + break + if not passes: + raise TypeError("Can't instantiate %r" % name) + + lastdot = name.rfind(".") + + assert lastdot > -1, "Name %r must be fully qualified" % name + modname = name[:lastdot] + clsname = name[lastdot + 1:] + + mod = __import__(modname, fromlist=[clsname]) + cls = getattr(mod, clsname) + return cls diff --git a/nstock/modules/whoosh/util/numeric.py b/nstock/modules/whoosh/util/numeric.py new file mode 100644 index 0000000..42291cc --- /dev/null +++ b/nstock/modules/whoosh/util/numeric.py @@ -0,0 +1,317 @@ +# Copyright 2010 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +import math, struct +from array import array +from bisect import bisect_left +from struct import pack, unpack + +from whoosh.compat import b, long_type +from whoosh.system import pack_byte, unpack_byte, pack_ushort, unpack_ushort +from whoosh.system import pack_int, unpack_int, pack_uint, unpack_uint +from whoosh.system import pack_long, unpack_long, pack_ulong, unpack_ulong +from whoosh.system import pack_float, unpack_float, pack_double, unpack_double + + +NaN = struct.unpack("i") +_qstruct = struct.Struct(">q") +_dstruct = struct.Struct(">d") +_ipack, _iunpack = _istruct.pack, _istruct.unpack +_qpack, _qunpack = _qstruct.pack, _qstruct.unpack +_dpack, _dunpack = _dstruct.pack, _dstruct.unpack + + +def to_sortable(numtype, intsize, signed, x): + if numtype is int or numtype is long_type: + if signed: + x += (1 << intsize - 1) + return x + else: + return float_to_sortable_long(x, signed) + + +def from_sortable(numtype, intsize, signed, x): + if numtype is int or numtype is long_type: + if signed: + x -= (1 << intsize - 1) + return x + else: + return sortable_long_to_float(x, signed) + + +def float_to_sortable_long(x, signed): + x = _qunpack(_dpack(x))[0] + if x < 0: + x ^= 0x7fffffffffffffff + if signed: + x += 1 << 63 + assert x >= 0 + return x + + +def sortable_long_to_float(x, signed): + if signed: + x -= 1 << 63 + if x < 0: + x ^= 0x7fffffffffffffff + x = _dunpack(_qpack(x))[0] + return x + + +# Functions for generating tiered ranges + +def split_ranges(intsize, step, start, end): + """Splits a range of numbers (from ``start`` to ``end``, inclusive) + into a sequence of trie ranges of the form ``(start, end, shift)``. The + consumer of these tuples is expected to shift the ``start`` and ``end`` + right by ``shift``. + + This is used for generating term ranges for a numeric field. The queries + for the edges of the range are generated at high precision and large blocks + in the middle are generated at low precision. + """ + + shift = 0 + while True: + diff = 1 << (shift + step) + mask = ((1 << step) - 1) << shift + setbits = lambda x: x | ((1 << shift) - 1) + + haslower = (start & mask) != 0 + hasupper = (end & mask) != mask + + not_mask = ~mask & ((1 << intsize + 1) - 1) + nextstart = (start + diff if haslower else start) & not_mask + nextend = (end - diff if hasupper else end) & not_mask + + if shift + step >= intsize or nextstart > nextend: + yield (start, setbits(end), shift) + break + + if haslower: + yield (start, setbits(start | mask), shift) + if hasupper: + yield (end & not_mask, setbits(end), shift) + + start = nextstart + end = nextend + shift += step + + +def tiered_ranges(numtype, intsize, signed, start, end, shift_step, + startexcl, endexcl): + assert numtype in (int, float) + assert intsize in (8, 16, 32, 64) + + # Convert start and end values to sortable ints + if start is None: + start = 0 + else: + start = to_sortable(numtype, intsize, signed, start) + if startexcl: + start += 1 + + if end is None: + end = 2 ** intsize - 1 + else: + end = to_sortable(numtype, intsize, signed, end) + if endexcl: + end -= 1 + + if not shift_step: + return ((start, end, 0),) + + # Yield (rstart, rend, shift) ranges for the different resolutions + return split_ranges(intsize, shift_step, start, end) + + +# Float-to-byte encoding/decoding + +def float_to_byte(value, mantissabits=5, zeroexp=2): + """Encodes a floating point number in a single byte. + """ + + # Assume int size == float size + + fzero = (63 - zeroexp) << mantissabits + bits = unpack("i", pack("f", value))[0] + smallfloat = bits >> (24 - mantissabits) + if smallfloat < fzero: + # Map negative numbers and 0 to 0 + # Map underflow to next smallest non-zero number + if bits <= 0: + result = chr(0) + else: + result = chr(1) + elif smallfloat >= fzero + 0x100: + # Map overflow to largest number + result = chr(255) + else: + result = chr(smallfloat - fzero) + return b(result) + + +def byte_to_float(b, mantissabits=5, zeroexp=2): + """Decodes a floating point number stored in a single byte. + """ + if type(b) is not int: + b = ord(b) + if b == 0: + return 0.0 + + bits = (b & 0xff) << (24 - mantissabits) + bits += (63 - zeroexp) << 24 + return unpack("f", pack("i", bits))[0] + + +# Length-to-byte approximation functions + +# Old implementation: + +#def length_to_byte(length): +# """Returns a logarithmic approximation of the given number, in the range +# 0-255. The approximation has high precision at the low end (e.g. +# 1 -> 0, 2 -> 1, 3 -> 2 ...) and low precision at the high end. Numbers +# equal to or greater than 108116 all approximate to 255. +# +# This is useful for storing field lengths, where the general case is small +# documents and very large documents are more rare. +# """ +# +# # This encoding formula works up to 108116 -> 255, so if the length is +# # equal to or greater than that limit, just return 255. +# if length >= 108116: +# return 255 +# +# # The parameters of this formula where chosen heuristically so that low +# # numbers would approximate closely, and the byte range 0-255 would cover +# # a decent range of document lengths (i.e. 1 to ~100000). +# return int(round(log((length / 27.0) + 1, 1.033))) +#def _byte_to_length(n): +# return int(round((pow(1.033, n) - 1) * 27)) +#_b2l_cache = array("i", (_byte_to_length(i) for i in xrange(256))) +#byte_to_length = _b2l_cache.__getitem__ + +# New implementation + +# Instead of computing the actual formula to get the byte for any given length, +# precompute the length associated with each byte, and use bisect to find the +# nearest value. This gives quite a large speed-up. +# +# Note that this does not give all the same answers as the old, "real" +# implementation since this implementation always "rounds down" (thanks to the +# bisect_left) while the old implementation would "round up" or "round down" +# depending on the input. Since this is a fairly gross approximation anyway, +# I don't think it matters much. + +# Values generated using the formula from the "old" implementation above +_length_byte_cache = array('i', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, +16, 17, 18, 20, 21, 23, 25, 26, 28, 30, 32, 34, 36, 38, 40, 42, 45, 47, 49, 52, +54, 57, 60, 63, 66, 69, 72, 75, 79, 82, 86, 89, 93, 97, 101, 106, 110, 114, +119, 124, 129, 134, 139, 145, 150, 156, 162, 169, 175, 182, 189, 196, 203, 211, +219, 227, 235, 244, 253, 262, 271, 281, 291, 302, 313, 324, 336, 348, 360, 373, +386, 399, 414, 428, 443, 459, 475, 491, 508, 526, 544, 563, 583, 603, 623, 645, +667, 690, 714, 738, 763, 789, 816, 844, 873, 903, 933, 965, 998, 1032, 1066, +1103, 1140, 1178, 1218, 1259, 1302, 1345, 1391, 1438, 1486, 1536, 1587, 1641, +1696, 1753, 1811, 1872, 1935, 1999, 2066, 2135, 2207, 2280, 2356, 2435, 2516, +2600, 2687, 2777, 2869, 2965, 3063, 3165, 3271, 3380, 3492, 3608, 3728, 3852, +3980, 4112, 4249, 4390, 4536, 4686, 4842, 5002, 5168, 5340, 5517, 5700, 5889, +6084, 6286, 6494, 6709, 6932, 7161, 7398, 7643, 7897, 8158, 8428, 8707, 8995, +9293, 9601, 9918, 10247, 10586, 10936, 11298, 11671, 12057, 12456, 12868, +13294, 13733, 14187, 14656, 15141, 15641, 16159, 16693, 17244, 17814, 18403, +19011, 19640, 20289, 20959, 21652, 22367, 23106, 23869, 24658, 25472, 26314, +27183, 28081, 29009, 29967, 30957, 31979, 33035, 34126, 35254, 36418, 37620, +38863, 40146, 41472, 42841, 44256, 45717, 47227, 48786, 50397, 52061, 53780, +55556, 57390, 59285, 61242, 63264, 65352, 67510, 69739, 72041, 74419, 76876, +79414, 82035, 84743, 87541, 90430, 93416, 96499, 99684, 102975, 106374]) + + +def length_to_byte(length): + if length is None: + return 0 + if length >= 106374: + return 255 + else: + return bisect_left(_length_byte_cache, length) + +byte_to_length = _length_byte_cache.__getitem__ diff --git a/nstock/modules/whoosh/util/numlists.py b/nstock/modules/whoosh/util/numlists.py new file mode 100644 index 0000000..8f3d84d --- /dev/null +++ b/nstock/modules/whoosh/util/numlists.py @@ -0,0 +1,373 @@ +from array import array + +from whoosh.compat import xrange +from whoosh.system import emptybytes +from whoosh.system import pack_byte, unpack_byte +from whoosh.system import pack_ushort_le, unpack_ushort_le +from whoosh.system import pack_uint_le, unpack_uint_le + + +def delta_encode(nums): + base = 0 + for n in nums: + yield n - base + base = n + + +def delta_decode(nums): + base = 0 + for n in nums: + base += n + yield base + + +class GrowableArray(object): + def __init__(self, inittype="B", allow_longs=True): + self.array = array(inittype) + self._allow_longs = allow_longs + + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self.array) + + def __len__(self): + return len(self.array) + + def __iter__(self): + return iter(self.array) + + def _retype(self, maxnum): + if maxnum < 2 ** 16: + newtype = "H" + elif maxnum < 2 ** 31: + newtype = "i" + elif maxnum < 2 ** 32: + newtype = "I" + elif self._allow_longs: + newtype = "q" + else: + raise OverflowError("%r is too big to fit in an array" % maxnum) + + try: + self.array = array(newtype, iter(self.array)) + except ValueError: + self.array = list(self.array) + + def append(self, n): + try: + self.array.append(n) + except OverflowError: + self._retype(n) + self.array.append(n) + + def extend(self, ns): + append = self.append + for n in ns: + append(n) + + @property + def typecode(self): + if isinstance(self.array, array): + return self.array.typecode + else: + return "q" + + def to_file(self, dbfile): + if isinstance(self.array, array): + dbfile.write_array(self.array) + else: + write_long = dbfile.write_long + for n in self.array: + write_long(n) + + +# Number list encoding base class + +class NumberEncoding(object): + maxint = None + + def write_nums(self, f, numbers): + raise NotImplementedError + + def read_nums(self, f, n): + raise NotImplementedError + + def write_deltas(self, f, numbers): + return self.write_nums(f, list(delta_encode(numbers))) + + def read_deltas(self, f, n): + return delta_decode(self.read_nums(f, n)) + + def get(self, f, pos, i): + f.seek(pos) + n = None + for n in self.read_nums(f, i + 1): + pass + return n + + +# Fixed width encodings + +class FixedEncoding(NumberEncoding): + _encode = None + _decode = None + size = None + + def write_nums(self, f, numbers): + _encode = self._encode + + for n in numbers: + f.write(_encode(n)) + + def read_nums(self, f, n): + _decode = self._decode + + for _ in xrange(n): + yield _decode(f.read(self.size)) + + def get(self, f, pos, i): + f.seek(pos + i * self.size) + return self._decode(f.read(self.size)) + + +class ByteEncoding(FixedEncoding): + size = 1 + maxint = 255 + _encode = pack_byte + _decode = unpack_byte + + +class UShortEncoding(FixedEncoding): + size = 2 + maxint = 2 ** 16 - 1 + _encode = pack_ushort_le + _decode = unpack_ushort_le + + +class UIntEncoding(FixedEncoding): + size = 4 + maxint = 2 ** 32 - 1 + _encode = pack_uint_le + _decode = unpack_uint_le + + +# High-bit encoded variable-length integer + +class Varints(NumberEncoding): + maxint = None + + def write_nums(self, f, numbers): + for n in numbers: + f.write_varint(n) + + def read_nums(self, f, n): + for _ in xrange(n): + yield f.read_varint() + + +# Simple16 algorithm for storing arrays of positive integers (usually delta +# encoded lists of sorted integers) +# +# 1. http://www2008.org/papers/pdf/p387-zhangA.pdf +# 2. http://www2009.org/proceedings/pdf/p401.pdf + +class Simple16(NumberEncoding): + # The maximum possible integer value Simple16 can encode is < 2^28. + # Therefore, in order to use Simple16, the application must have its own + # code to encode numbers in the range of [2^28, 2^32). A simple way is just + # write those numbers as 32-bit integers (that is, no compression for very + # big numbers). + _numsize = 16 + _bitsize = 28 + maxint = 2 ** _bitsize - 1 + + # Number of stored numbers per code + _num = [28, 21, 21, 21, 14, 9, 8, 7, 6, 6, 5, 5, 4, 3, 2, 1] + # Number of bits for each number per code + _bits = [ + (1,) * 28, + (2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + (1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1), + (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2), + (2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2), + (4, 3, 3, 3, 3, 3, 3, 3, 3), + (3, 4, 4, 4, 4, 3, 3, 3), + (4, 4, 4, 4, 4, 4, 4), + (5, 5, 5, 5, 4, 4), + (4, 4, 5, 5, 5, 5), + (6, 6, 6, 5, 5), + (5, 5, 6, 6, 6), + (7, 7, 7, 7), + (10, 9, 9), + (14, 14), + (28,), + ] + + def write_nums(self, f, numbers): + _compress = self._compress + + i = 0 + while i < len(numbers): + value, taken = _compress(numbers, i, len(numbers) - i) + f.write_uint_le(value) + i += taken + + def _compress(self, inarray, inoffset, n): + _numsize = self._numsize + _bitsize = self._bitsize + _num = self._num + _bits = self._bits + + for key in xrange(_numsize): + value = key << _bitsize + num = _num[key] if _num[key] < n else n + bits = 0 + + j = 0 + while j < num and inarray[inoffset + j] < (1 << _bits[key][j]): + x = inarray[inoffset + j] + value |= x << bits + bits += _bits[key][j] + j += 1 + + if j == num: + return value, num + + raise Exception + + def read_nums(self, f, n): + _decompress = self._decompress + + i = 0 + while i < n: + value = unpack_uint_le(f.read(4))[0] + for v in _decompress(value, n - i): + yield v + i += 1 + + def _decompress(self, value, n): + _numsize = self._numsize + _bitsize = self._bitsize + _num = self._num + _bits = self._bits + + key = value >> _bitsize + num = _num[key] if _num[key] < n else n + bits = 0 + for j in xrange(num): + v = value >> bits + yield v & (0xffffffff >> (32 - _bits[key][j])) + bits += _bits[key][j] + + def get(self, f, pos, i): + f.seek(pos) + base = 0 + value = unpack_uint_le(f.read(4)) + key = value >> self._bitsize + num = self._num[key] + while i > base + num: + base += num + value = unpack_uint_le(f.read(4)) + key = value >> self._bitsize + num = self._num[key] + + offset = i - base + if offset: + value = value >> sum(self._bits[key][:offset]) + return value & (2 ** self._bits[key][offset] - 1) + + +# Google Packed Ints algorithm: a set of four numbers is preceded by a "key" +# byte, which encodes how many bytes each of the next four integers use +# (stored in the byte as four 2-bit numbers) + +class GInts(NumberEncoding): + maxint = 2 ** 32 - 1 + + # Number of future bytes to expect after a "key" byte value of N -- used to + # skip ahead from a key byte + _lens = array("B", [4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10, 5, 6, + 7, 8, 6, 7, 8, 9, 7, 8, 9, 10, 8, 9, 10, 11, 6, 7, 8, 9, 7, 8, 9, 10, 8, 9, + 10, 11, 9, 10, 11, 12, 7, 8, 9, 10, 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, + 12, 13, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10, 8, 9, 10, 11, 6, 7, 8, 9, 7, + 8, 9, 10, 8, 9, 10, 11, 9, 10, 11, 12, 7, 8, 9, 10, 8, 9, 10, 11, 9, 10, + 11, 12, 10, 11, 12, 13, 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, + 12, 13, 14, 6, 7, 8, 9, 7, 8, 9, 10, 8, 9, 10, 11, 9, 10, 11, 12, 7, 8, 9, + 10, 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 8, 9, 10, 11, 9, 10, 11, + 12, 10, 11, 12, 13, 11, 12, 13, 14, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, + 13, 14, 12, 13, 14, 15, 7, 8, 9, 10, 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, + 12, 13, 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14, 9, 10, + 11, 12, 10, 11, 12, 13, 11, 12, 13, 14, 12, 13, 14, 15, 10, 11, 12, 13, 11, + 12, 13, 14, 12, 13, 14, 15, 13, 14, 15, 16]) + + def key_to_sizes(self, key): + """Returns a list of the sizes of the next four numbers given a key + byte. + """ + + return [(key >> (i * 2) & 3) + 1 for i in xrange(4)] + + def write_nums(self, f, numbers): + buf = emptybytes + count = 0 + key = 0 + for v in numbers: + shift = count * 2 + if v < 256: + buf += pack_byte(v) + elif v < 65536: + key |= 1 << shift + buf += pack_ushort_le(v) + elif v < 16777216: + key |= 2 << shift + buf += pack_uint_le(v)[:3] + else: + key |= 3 << shift + buf += pack_uint_le(v) + + count += 1 + if count == 4: + f.write_byte(key) + f.write(buf) + count = 0 + key = 0 + buf = emptybytes # Clear the buffer + + # Write out leftovers in the buffer + if count: + f.write_byte(key) + f.write(buf) + + def read_nums(self, f, n): + """Read N integers from the bytes stream dbfile. Expects that the file + is positioned at a key byte. + """ + + count = 0 + key = None + for _ in xrange(n): + if count == 0: + key = f.read_byte() + code = key >> (count * 2) & 3 + if code == 0: + yield f.read_byte() + elif code == 1: + yield f.read_ushort_le() + elif code == 2: + yield unpack_uint_le(f.read(3) + "\x00")[0] + else: + yield f.read_uint_le() + + count = (count + 1) % 4 + +# def get(self, f, pos, i): +# f.seek(pos) +# base = 0 +# key = f.read_byte() +# while i > base + 4: +# base += 4 +# f.seek(self._lens[key], 1) +# key = f.read_byte() +# +# for n in self.read_nums(f, (i + 1) - base): +# pass +# return n diff --git a/nstock/modules/whoosh/util/testing.py b/nstock/modules/whoosh/util/testing.py new file mode 100644 index 0000000..358bfc3 --- /dev/null +++ b/nstock/modules/whoosh/util/testing.py @@ -0,0 +1,130 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +import os.path +import random +import shutil +import sys +import tempfile +from contextlib import contextmanager + +from whoosh.filedb.filestore import FileStorage +from whoosh.util import now, random_name + + +class TempDir(object): + def __init__(self, basename="", parentdir=None, ext=".whoosh", + suppress=frozenset(), keepdir=False): + self.basename = basename or random_name(8) + self.parentdir = parentdir + + dirname = parentdir or tempfile.mkdtemp(ext, self.basename) + self.dir = os.path.abspath(dirname) + self.suppress = suppress + self.keepdir = keepdir + + def __enter__(self): + if not os.path.exists(self.dir): + os.makedirs(self.dir) + return self.dir + + def cleanup(self): + pass + + def __exit__(self, exc_type, exc_val, exc_tb): + self.cleanup() + if not self.keepdir: + try: + shutil.rmtree(self.dir) + except OSError: + e = sys.exc_info()[1] + #sys.stderr.write("Can't remove temp dir: " + str(e) + "\n") + #if exc_type is None: + # raise + + if exc_type is not None: + if self.keepdir: + sys.stderr.write("Temp dir=" + self.dir + "\n") + if exc_type not in self.suppress: + return False + + +class TempStorage(TempDir): + def __init__(self, debug=False, **kwargs): + TempDir.__init__(self, **kwargs) + self._debug = debug + + def cleanup(self): + self.store.close() + + def __enter__(self): + dirpath = TempDir.__enter__(self) + self.store = FileStorage(dirpath, debug=self._debug) + return self.store + + +class TempIndex(TempStorage): + def __init__(self, schema, ixname='', storage_debug=False, **kwargs): + TempStorage.__init__(self, basename=ixname, debug=storage_debug, + **kwargs) + self.schema = schema + + def __enter__(self): + fstore = TempStorage.__enter__(self) + return fstore.create_index(self.schema, indexname=self.basename) + + +def is_abstract_method(attr): + """Returns True if the given object has __isabstractmethod__ == True. + """ + + return (hasattr(attr, "__isabstractmethod__") + and getattr(attr, "__isabstractmethod__")) + + +def check_abstract_methods(base, subclass): + """Raises AssertionError if ``subclass`` does not override a method on + ``base`` that is marked as an abstract method. + """ + + for attrname in dir(base): + if attrname.startswith("_"): + continue + attr = getattr(base, attrname) + if is_abstract_method(attr): + oattr = getattr(subclass, attrname) + if is_abstract_method(oattr): + raise Exception("%s.%s not overridden" + % (subclass.__name__, attrname)) + + +@contextmanager +def timing(name=None): + t = now() + yield + t = now() - t + print("%s: %0.06f s" % (name or '', t)) diff --git a/nstock/modules/whoosh/util/text.py b/nstock/modules/whoosh/util/text.py new file mode 100644 index 0000000..d524aa1 --- /dev/null +++ b/nstock/modules/whoosh/util/text.py @@ -0,0 +1,132 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +import codecs, re + +from whoosh.compat import string_type, u, byte + + +# Note: these functions return a tuple of (text, length), so when you call +# them, you have to add [0] on the end, e.g. str = utf8encode(unicode)[0] + +utf8encode = codecs.getencoder("utf-8") +utf8decode = codecs.getdecoder("utf-8") + + +# Prefix encoding functions + +def first_diff(a, b): + """ + Returns the position of the first differing character in the sequences a + and b. For example, first_diff('render', 'rending') == 4. This function + limits the return value to 255 so the difference can be encoded in a single + byte. + """ + + i = 0 + while i <= 255 and i < len(a) and i < len(b) and a[i] == b[i]: + i += 1 + return i + + +def prefix_encode(a, b): + """ + Compresses bytestring b as a byte representing the prefix it shares with a, + followed by the suffix bytes. + """ + + i = first_diff(a, b) + return byte(i) + b[i:] + + +def prefix_encode_all(ls): + """Compresses the given list of (unicode) strings by storing each string + (except the first one) as an integer (encoded in a byte) representing + the prefix it shares with its predecessor, followed by the suffix encoded + as UTF-8. + """ + + last = u('') + for w in ls: + i = first_diff(last, w) + yield chr(i) + w[i:].encode("utf-8") + last = w + + +def prefix_decode_all(ls): + """Decompresses a list of strings compressed by prefix_encode(). + """ + + last = u('') + for w in ls: + i = ord(w[0]) + decoded = last[:i] + w[1:].decode("utf-8") + yield decoded + last = decoded + + +# Natural key sorting function + +_nkre = re.compile(r"\D+|\d+", re.UNICODE) + + +def _nkconv(i): + try: + return int(i) + except ValueError: + return i.lower() + + +def natural_key(s): + """Converts string ``s`` into a tuple that will sort "naturally" (i.e., + ``name5`` will come before ``name10`` and ``1`` will come before ``A``). + This function is designed to be used as the ``key`` argument to sorting + functions. + + :param s: the str/unicode string to convert. + :rtype: tuple + """ + + # Use _nkre to split the input string into a sequence of + # digit runs and non-digit runs. Then use _nkconv() to convert + # the digit runs into ints and the non-digit runs to lowercase. + return tuple(_nkconv(m) for m in _nkre.findall(s)) + + +# Regular expression functions + +def rcompile(pattern, flags=0, verbose=False): + """A wrapper for re.compile that checks whether "pattern" is a regex object + or a string to be compiled, and automatically adds the re.UNICODE flag. + """ + + if not isinstance(pattern, string_type): + # If it's not a string, assume it's already a compiled pattern + return pattern + if verbose: + flags |= re.VERBOSE + return re.compile(pattern, re.UNICODE | flags) diff --git a/nstock/modules/whoosh/util/times.py b/nstock/modules/whoosh/util/times.py new file mode 100644 index 0000000..e72448c --- /dev/null +++ b/nstock/modules/whoosh/util/times.py @@ -0,0 +1,467 @@ +# Copyright 2010 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +import calendar +import copy +from datetime import date, datetime, timedelta + +from whoosh.compat import iteritems + + +class TimeError(Exception): + pass + + +def relative_days(current_wday, wday, dir): + """Returns the number of days (positive or negative) to the "next" or + "last" of a certain weekday. ``current_wday`` and ``wday`` are numbers, + i.e. 0 = monday, 1 = tuesday, 2 = wednesday, etc. + + >>> # Get the number of days to the next tuesday, if today is Sunday + >>> relative_days(6, 1, 1) + 2 + + :param current_wday: the number of the current weekday. + :param wday: the target weekday. + :param dir: -1 for the "last" (past) weekday, 1 for the "next" (future) + weekday. + """ + + if current_wday == wday: + return 7 * dir + + if dir == 1: + return (wday + 7 - current_wday) % 7 + else: + return (current_wday + 7 - wday) % 7 * -1 + + +def timedelta_to_usecs(td): + total = td.days * 86400000000 # Microseconds in a day + total += td.seconds * 1000000 # Microseconds in a second + total += td.microseconds + return total + + +def datetime_to_long(dt): + """Converts a datetime object to a long integer representing the number + of microseconds since ``datetime.min``. + """ + + return timedelta_to_usecs(dt.replace(tzinfo=None) - dt.min) + + +def long_to_datetime(x): + """Converts a long integer representing the number of microseconds since + ``datetime.min`` to a datetime object. + """ + + days = x // 86400000000 # Microseconds in a day + x -= days * 86400000000 + + seconds = x // 1000000 # Microseconds in a second + x -= seconds * 1000000 + + return datetime.min + timedelta(days=days, seconds=seconds, microseconds=x) + + +# Ambiguous datetime object + +class adatetime(object): + """An "ambiguous" datetime object. This object acts like a + ``datetime.datetime`` object but can have any of its attributes set to + None, meaning unspecified. + """ + + units = frozenset(("year", "month", "day", "hour", "minute", "second", + "microsecond")) + + def __init__(self, year=None, month=None, day=None, hour=None, minute=None, + second=None, microsecond=None): + if isinstance(year, datetime): + dt = year + self.year, self.month, self.day = dt.year, dt.month, dt.day + self.hour, self.minute, self.second = dt.hour, dt.minute, dt.second + self.microsecond = dt.microsecond + else: + if month is not None and (month < 1 or month > 12): + raise TimeError("month must be in 1..12") + + if day is not None and day < 1: + raise TimeError("day must be greater than 1") + if (year is not None and month is not None and day is not None + and day > calendar.monthrange(year, month)[1]): + raise TimeError("day is out of range for month") + + if hour is not None and (hour < 0 or hour > 23): + raise TimeError("hour must be in 0..23") + if minute is not None and (minute < 0 or minute > 59): + raise TimeError("minute must be in 0..59") + if second is not None and (second < 0 or second > 59): + raise TimeError("second must be in 0..59") + if microsecond is not None and (microsecond < 0 + or microsecond > 999999): + raise TimeError("microsecond must be in 0..999999") + + self.year, self.month, self.day = year, month, day + self.hour, self.minute, self.second = hour, minute, second + self.microsecond = microsecond + + def __eq__(self, other): + if not other.__class__ is self.__class__: + if not is_ambiguous(self) and isinstance(other, datetime): + return fix(self) == other + else: + return False + return all(getattr(self, unit) == getattr(other, unit) + for unit in self.units) + + def __repr__(self): + return "%s%r" % (self.__class__.__name__, self.tuple()) + + def tuple(self): + """Returns the attributes of the ``adatetime`` object as a tuple of + ``(year, month, day, hour, minute, second, microsecond)``. + """ + + return (self.year, self.month, self.day, self.hour, self.minute, + self.second, self.microsecond) + + def date(self): + return date(self.year, self.month, self.day) + + def copy(self): + return adatetime(year=self.year, month=self.month, day=self.day, + hour=self.hour, minute=self.minute, second=self.second, + microsecond=self.microsecond) + + def replace(self, **kwargs): + """Returns a copy of this object with the attributes given as keyword + arguments replaced. + + >>> adt = adatetime(year=2009, month=10, day=31) + >>> adt.replace(year=2010) + (2010, 10, 31, None, None, None, None) + """ + + newadatetime = self.copy() + for key, value in iteritems(kwargs): + if key in self.units: + setattr(newadatetime, key, value) + else: + raise KeyError("Unknown argument %r" % key) + return newadatetime + + def floor(self): + """Returns a ``datetime`` version of this object with all unspecified + (None) attributes replaced by their lowest values. + + This method raises an error if the ``adatetime`` object has no year. + + >>> adt = adatetime(year=2009, month=5) + >>> adt.floor() + datetime.datetime(2009, 5, 1, 0, 0, 0, 0) + """ + + y, m, d, h, mn, s, ms = (self.year, self.month, self.day, self.hour, + self.minute, self.second, self.microsecond) + + if y is None: + raise ValueError("Date has no year") + + if m is None: + m = 1 + if d is None: + d = 1 + if h is None: + h = 0 + if mn is None: + mn = 0 + if s is None: + s = 0 + if ms is None: + ms = 0 + return datetime(y, m, d, h, mn, s, ms) + + def ceil(self): + """Returns a ``datetime`` version of this object with all unspecified + (None) attributes replaced by their highest values. + + This method raises an error if the ``adatetime`` object has no year. + + >>> adt = adatetime(year=2009, month=5) + >>> adt.floor() + datetime.datetime(2009, 5, 30, 23, 59, 59, 999999) + """ + + y, m, d, h, mn, s, ms = (self.year, self.month, self.day, self.hour, + self.minute, self.second, self.microsecond) + + if y is None: + raise ValueError("Date has no year") + + if m is None: + m = 12 + if d is None: + d = calendar.monthrange(y, m)[1] + if h is None: + h = 23 + if mn is None: + mn = 59 + if s is None: + s = 59 + if ms is None: + ms = 999999 + return datetime(y, m, d, h, mn, s, ms) + + def disambiguated(self, basedate): + """Returns either a ``datetime`` or unambiguous ``timespan`` version + of this object. + + Unless this ``adatetime`` object is full specified down to the + microsecond, this method will return a timespan built from the "floor" + and "ceil" of this object. + + This method raises an error if the ``adatetime`` object has no year. + + >>> adt = adatetime(year=2009, month=10, day=31) + >>> adt.disambiguated() + timespan(datetime(2009, 10, 31, 0, 0, 0, 0), datetime(2009, 10, 31, 23, 59 ,59, 999999) + """ + + dt = self + if not is_ambiguous(dt): + return fix(dt) + return timespan(dt, dt).disambiguated(basedate) + + +# Time span class + +class timespan(object): + """A span of time between two ``datetime`` or ``adatetime`` objects. + """ + + def __init__(self, start, end): + """ + :param start: a ``datetime`` or ``adatetime`` object representing the + start of the time span. + :param end: a ``datetime`` or ``adatetime`` object representing the + end of the time span. + """ + + if not isinstance(start, (datetime, adatetime)): + raise TimeError("%r is not a datetime object" % start) + if not isinstance(end, (datetime, adatetime)): + raise TimeError("%r is not a datetime object" % end) + + self.start = copy.copy(start) + self.end = copy.copy(end) + + def __eq__(self, other): + if not other.__class__ is self.__class__: + return False + return self.start == other.start and self.end == other.end + + def __repr__(self): + return "%s(%r, %r)" % (self.__class__.__name__, self.start, self.end) + + def disambiguated(self, basedate, debug=0): + """Returns an unambiguous version of this object. + + >>> start = adatetime(year=2009, month=2) + >>> end = adatetime(year=2009, month=10) + >>> ts = timespan(start, end) + >>> ts + timespan(adatetime(2009, 2, None, None, None, None, None), adatetime(2009, 10, None, None, None, None, None)) + >>> td.disambiguated(datetime.now()) + timespan(datetime(2009, 2, 28, 0, 0, 0, 0), datetime(2009, 10, 31, 23, 59 ,59, 999999) + """ + + #- If year is in start but not end, use basedate.year for end + #-- If year is in start but not end, but startdate is > basedate, + # use "next " to get end month/year + #- If year is in end but not start, copy year from end to start + #- Support "next february", "last april", etc. + + start, end = copy.copy(self.start), copy.copy(self.end) + start_year_was_amb = start.year is None + end_year_was_amb = end.year is None + + if has_no_date(start) and has_no_date(end): + # The start and end points are just times, so use the basedate + # for the date information. + by, bm, bd = basedate.year, basedate.month, basedate.day + start = start.replace(year=by, month=bm, day=bd) + end = end.replace(year=by, month=bm, day=bd) + else: + # If one side has a year and the other doesn't, the decision + # of what year to assign to the ambiguous side is kind of + # arbitrary. I've used a heuristic here based on how the range + # "reads", but it may only be reasonable in English. And maybe + # even just to me. + + if start.year is None and end.year is None: + # No year on either side, use the basedate + start.year = end.year = basedate.year + elif start.year is None: + # No year in the start, use the year from the end + start.year = end.year + elif end.year is None: + end.year = max(start.year, basedate.year) + + if start.year == end.year: + # Once again, if one side has a month and day but the other side + # doesn't, the disambiguation is arbitrary. Does "3 am to 5 am + # tomorrow" mean 3 AM today to 5 AM tomorrow, or 3am tomorrow to + # 5 am tomorrow? What I picked is similar to the year: if the + # end has a month+day and the start doesn't, copy the month+day + # from the end to the start UNLESS that would make the end come + # before the start on that day, in which case use the basedate + # instead. If the start has a month+day and the end doesn't, use + # the basedate. + start_dm = not (start.month is None and start.day is None) + end_dm = not (end.month is None and end.day is None) + if end_dm and not start_dm: + if start.floor().time() > end.ceil().time(): + start.month = basedate.month + start.day = basedate.day + else: + start.month = end.month + start.day = end.day + elif start_dm and not end_dm: + end.month = basedate.month + end.day = basedate.day + + if floor(start).date() > ceil(end).date(): + # If the disambiguated dates are out of order: + # - If no start year was given, reduce the start year to put the + # start before the end + # - If no end year was given, increase the end year to put the end + # after the start + # - If a year was specified for both, just swap the start and end + if start_year_was_amb: + start.year = end.year - 1 + elif end_year_was_amb: + end.year = start.year + 1 + else: + start, end = end, start + + start = floor(start) + end = ceil(end) + + if start.date() == end.date() and start.time() > end.time(): + # If the start and end are on the same day, but the start time + # is after the end time, move the end time to the next day + end += timedelta(days=1) + + return timespan(start, end) + + +# Functions for working with datetime/adatetime objects + +def floor(at): + if isinstance(at, datetime): + return at + return at.floor() + + +def ceil(at): + if isinstance(at, datetime): + return at + return at.ceil() + + +def fill_in(at, basedate, units=adatetime.units): + """Returns a copy of ``at`` with any unspecified (None) units filled in + with values from ``basedate``. + """ + + if isinstance(at, datetime): + return at + + args = {} + for unit in units: + v = getattr(at, unit) + if v is None: + v = getattr(basedate, unit) + args[unit] = v + return fix(adatetime(**args)) + + +def has_no_date(at): + """Returns True if the given object is an ``adatetime`` where ``year``, + ``month``, and ``day`` are all None. + """ + + if isinstance(at, datetime): + return False + return at.year is None and at.month is None and at.day is None + + +def has_no_time(at): + """Returns True if the given object is an ``adatetime`` where ``hour``, + ``minute``, ``second`` and ``microsecond`` are all None. + """ + + if isinstance(at, datetime): + return False + return (at.hour is None and at.minute is None and at.second is None + and at.microsecond is None) + + +def is_ambiguous(at): + """Returns True if the given object is an ``adatetime`` with any of its + attributes equal to None. + """ + + if isinstance(at, datetime): + return False + return any((getattr(at, attr) is None) for attr in adatetime.units) + + +def is_void(at): + """Returns True if the given object is an ``adatetime`` with all of its + attributes equal to None. + """ + + if isinstance(at, datetime): + return False + return all((getattr(at, attr) is None) for attr in adatetime.units) + + +def fix(at): + """If the given object is an ``adatetime`` that is unambiguous (because + all its attributes are specified, that is, not equal to None), returns a + ``datetime`` version of it. Otherwise returns the ``adatetime`` object + unchanged. + """ + + if is_ambiguous(at) or isinstance(at, datetime): + return at + return datetime(year=at.year, month=at.month, day=at.day, hour=at.hour, + minute=at.minute, second=at.second, + microsecond=at.microsecond) diff --git a/nstock/modules/whoosh/util/varints.py b/nstock/modules/whoosh/util/varints.py new file mode 100644 index 0000000..148c141 --- /dev/null +++ b/nstock/modules/whoosh/util/varints.py @@ -0,0 +1,110 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from array import array + +from whoosh.compat import array_tobytes, xrange + + +# Varint cache + +# Build a cache of the varint byte sequences for the first N integers, so we +# don't have to constantly recalculate them on the fly. This makes a small but +# noticeable difference. + +def _varint(i): + a = array("B") + while (i & ~0x7F) != 0: + a.append((i & 0x7F) | 0x80) + i = i >> 7 + a.append(i) + return array_tobytes(a) + + +_varint_cache_size = 512 +_varint_cache = [] +for i in xrange(0, _varint_cache_size): + _varint_cache.append(_varint(i)) +_varint_cache = tuple(_varint_cache) + + +def varint(i): + """Encodes the given integer into a string of the minimum number of bytes. + """ + if i < len(_varint_cache): + return _varint_cache[i] + return _varint(i) + + +def varint_to_int(vi): + b = ord(vi[0]) + p = 1 + i = b & 0x7f + shift = 7 + while b & 0x80 != 0: + b = ord(vi[p]) + p += 1 + i |= (b & 0x7F) << shift + shift += 7 + return i + + +def signed_varint(i): + """Zig-zag encodes a signed integer into a varint. + """ + + if i >= 0: + return varint(i << 1) + return varint((i << 1) ^ (~0)) + + +def decode_signed_varint(i): + """Zig-zag decodes an integer value. + """ + + if not i & 1: + return i >> 1 + return (i >> 1) ^ (~0) + + +def read_varint(readfn): + """ + Reads a variable-length encoded integer. + + :param readfn: a callable that reads a given number of bytes, + like file.read(). + """ + + b = ord(readfn(1)) + i = b & 0x7F + + shift = 7 + while b & 0x80 != 0: + b = ord(readfn(1)) + i |= (b & 0x7F) << shift + shift += 7 + return i diff --git a/nstock/modules/whoosh/util/versions.py b/nstock/modules/whoosh/util/versions.py new file mode 100644 index 0000000..1fcfe9c --- /dev/null +++ b/nstock/modules/whoosh/util/versions.py @@ -0,0 +1,165 @@ +# Copyright 2012 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from whoosh.util.text import rcompile + + +class BaseVersion(object): + @classmethod + def parse(cls, text): + obj = cls() + match = cls._version_exp.match(text) + if match: + groupdict = match.groupdict() + for groupname, typ in cls._parts: + v = groupdict.get(groupname) + if v is not None: + setattr(obj, groupname, typ(v)) + return obj + + def __repr__(self): + vs = ", ".join(repr(getattr(self, slot)) for slot in self.__slots__) + return "%s(%s)" % (self.__class__.__name__, vs) + + def tuple(self): + return tuple(getattr(self, slot) for slot in self.__slots__) + + def __eq__(self, other): + if not hasattr(other, "tuple"): + raise ValueError("Can't compare %r with %r" % (self, other)) + return self.tuple() == other.tuple() + + def __lt__(self, other): + if not hasattr(other, "tuple"): + raise ValueError("Can't compare %r with %r" % (self, other)) + return self.tuple() < other.tuple() + + # It's dumb that you have to define these + + def __gt__(self, other): + if not hasattr(other, "tuple"): + raise ValueError("Can't compare %r with %r" % (self, other)) + return self.tuple() > other.tuple() + + def __ge__(self, other): + if not hasattr(other, "tuple"): + raise ValueError("Can't compare %r with %r" % (self, other)) + return self.tuple() >= other.tuple() + + def __le__(self, other): + if not hasattr(other, "tuple"): + raise ValueError("Can't compare %r with %r" % (self, other)) + return self.tuple() <= other.tuple() + + def __ne__(self, other): + if not hasattr(other, "tuple"): + raise ValueError("Can't compare %r with %r" % (self, other)) + return self.tuple() != other.tuple() + + +class SimpleVersion(BaseVersion): + """An object that parses version numbers such as:: + + 12.2.5b + + The filter supports a limited subset of PEP 386 versions including:: + + 1 + 1.2 + 1.2c + 1.2c3 + 1.2.3 + 1.2.3a + 1.2.3b4 + 10.7.5rc1 + 999.999.999c999 + """ + + _version_exp = rcompile(r""" + ^ + (?P\d{1,4}) + ( + [.](?P\d{1,4}) + ( + [.](?P\d{1,4}) + )? + ( + (?P[abc]|rc) + (?P\d{1,4})? + )? + )? + $ + """, verbose=True) + + # (groupid, method, skippable, default) + _parts = [("major", int), + ("minor", int), + ("release", int), + ("ex", str), + ("exnum", int), + ] + + _ex_bits = {"a": 0, "b": 1, "c": 2, "rc": 10, "z": 15} + _bits_ex = dict((v, k) for k, v in _ex_bits.items()) + + __slots__ = ("major", "minor", "release", "ex", "exnum") + + def __init__(self, major=1, minor=0, release=0, ex="z", exnum=0): + self.major = major + self.minor = minor + self.release = release + self.ex = ex + self.exnum = exnum + + def to_int(self): + assert self.major < 1024 + n = self.major << 34 + + assert self.minor < 1024 + n |= self.minor << 24 + + assert self.release < 1024 + n |= self.release << 14 + + exbits = self._ex_bits.get(self.ex, 15) + n |= exbits << 10 + + assert self.exnum < 1024 + n |= self.exnum + + return n + + @classmethod + def from_int(cls, n): + major = (n & (1023 << 34)) >> 34 + minor = (n & (1023 << 24)) >> 24 + release = (n & (1023 << 14)) >> 14 + exbits = (n & (7 << 10)) >> 10 + ex = cls._bits_ex.get(exbits, "z") + exnum = n & 1023 + + return cls(major, minor, release, ex, exnum) diff --git a/nstock/modules/whoosh/writing.py b/nstock/modules/whoosh/writing.py new file mode 100644 index 0000000..d1033fa --- /dev/null +++ b/nstock/modules/whoosh/writing.py @@ -0,0 +1,1275 @@ +# Copyright 2007 Matt Chaput. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of Matt Chaput. + +from __future__ import with_statement +import threading, time +from bisect import bisect_right +from contextlib import contextmanager + +from whoosh import columns +from whoosh.compat import abstractmethod, bytes_type +from whoosh.externalsort import SortingPool +from whoosh.fields import UnknownFieldError +from whoosh.index import LockError +from whoosh.system import emptybytes +from whoosh.util import fib, random_name +from whoosh.util.filelock import try_for +from whoosh.util.text import utf8encode + + +# Exceptions + +class IndexingError(Exception): + pass + + +# Document grouping context manager + +@contextmanager +def groupmanager(writer): + writer.start_group() + yield + writer.end_group() + + +# Merge policies + +# A merge policy is a callable that takes the Index object, the SegmentWriter +# object, and the current segment list (not including the segment being +# written), and returns an updated segment list (not including the segment +# being written). + +def NO_MERGE(writer, segments): + """This policy does not merge any existing segments. + """ + return segments + + +def MERGE_SMALL(writer, segments): + """This policy merges small segments, where "small" is defined using a + heuristic based on the fibonacci sequence. + """ + + from whoosh.reading import SegmentReader + + unchanged_segments = [] + segments_to_merge = [] + + sorted_segment_list = sorted(segments, key=lambda s: s.doc_count_all()) + total_docs = 0 + + merge_point_found = False + for i, seg in enumerate(sorted_segment_list): + count = seg.doc_count_all() + if count > 0: + total_docs += count + + if merge_point_found: # append the remaining to unchanged + unchanged_segments.append(seg) + else: # look for a merge point + segments_to_merge.append((seg, i)) # merge every segment up to the merge point + if i > 3 and total_docs < fib(i + 5): + merge_point_found = True + + if merge_point_found and len(segments_to_merge) > 1: + for seg, i in segments_to_merge: + reader = SegmentReader(writer.storage, writer.schema, seg) + writer.add_reader(reader) + reader.close() + return unchanged_segments + else: + return segments + + +def OPTIMIZE(writer, segments): + """This policy merges all existing segments. + """ + + from whoosh.reading import SegmentReader + + for seg in segments: + reader = SegmentReader(writer.storage, writer.schema, seg) + writer.add_reader(reader) + reader.close() + return [] + + +def CLEAR(writer, segments): + """This policy DELETES all existing segments and only writes the new + segment. + """ + + return [] + + +# Customized sorting pool for postings + +class PostingPool(SortingPool): + # Subclass whoosh.externalsort.SortingPool to use knowledge of + # postings to set run size in bytes instead of items + + namechars = "abcdefghijklmnopqrstuvwxyz0123456789" + + def __init__(self, tempstore, segment, limitmb=128, **kwargs): + SortingPool.__init__(self, **kwargs) + self.tempstore = tempstore + self.segment = segment + self.limit = limitmb * 1024 * 1024 + self.currentsize = 0 + self.fieldnames = set() + + def _new_run(self): + path = "%s.run" % random_name() + f = self.tempstore.create_file(path).raw_file() + return path, f + + def _open_run(self, path): + return self.tempstore.open_file(path).raw_file() + + def _remove_run(self, path): + return self.tempstore.delete_file(path) + + def add(self, item): + # item = (fieldname, tbytes, docnum, weight, vbytes) + assert isinstance(item[1], bytes_type), "tbytes=%r" % item[1] + if item[4] is not None: + assert isinstance(item[4], bytes_type), "vbytes=%r" % item[4] + self.fieldnames.add(item[0]) + size = (28 + 4 * 5 # tuple = 28 + 4 * length + + 21 + len(item[0]) # fieldname = str = 21 + length + + 26 + len(item[1]) * 2 # text = unicode = 26 + 2 * length + + 18 # docnum = long = 18 + + 16 # weight = float = 16 + + 21 + len(item[4] or '')) # valuestring + self.currentsize += size + if self.currentsize > self.limit: + self.save() + self.current.append(item) + + def iter_postings(self): + # This is just an alias for items() to be consistent with the + # iter_postings()/add_postings() interface of a lot of other classes + return self.items() + + def save(self): + SortingPool.save(self) + self.currentsize = 0 + + +# Writer base class + +class IndexWriter(object): + """High-level object for writing to an index. + + To get a writer for a particular index, call + :meth:`~whoosh.index.Index.writer` on the Index object. + + >>> writer = myindex.writer() + + You can use this object as a context manager. If an exception is thrown + from within the context it calls :meth:`~IndexWriter.cancel` to clean up + temporary files, otherwise it calls :meth:`~IndexWriter.commit` when the + context exits. + + >>> with myindex.writer() as w: + ... w.add_document(title="First document", content="Hello there.") + ... w.add_document(title="Second document", content="This is easy!") + """ + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + if exc_type: + self.cancel() + else: + self.commit() + + def group(self): + """Returns a context manager that calls + :meth:`~IndexWriter.start_group` and :meth:`~IndexWriter.end_group` for + you, allowing you to use a ``with`` statement to group hierarchical + documents:: + + with myindex.writer() as w: + with w.group(): + w.add_document(kind="class", name="Accumulator") + w.add_document(kind="method", name="add") + w.add_document(kind="method", name="get_result") + w.add_document(kind="method", name="close") + + with w.group(): + w.add_document(kind="class", name="Calculator") + w.add_document(kind="method", name="add") + w.add_document(kind="method", name="multiply") + w.add_document(kind="method", name="get_result") + w.add_document(kind="method", name="close") + """ + + return groupmanager(self) + + def start_group(self): + """Start indexing a group of hierarchical documents. The backend should + ensure that these documents are all added to the same segment:: + + with myindex.writer() as w: + w.start_group() + w.add_document(kind="class", name="Accumulator") + w.add_document(kind="method", name="add") + w.add_document(kind="method", name="get_result") + w.add_document(kind="method", name="close") + w.end_group() + + w.start_group() + w.add_document(kind="class", name="Calculator") + w.add_document(kind="method", name="add") + w.add_document(kind="method", name="multiply") + w.add_document(kind="method", name="get_result") + w.add_document(kind="method", name="close") + w.end_group() + + A more convenient way to group documents is to use the + :meth:`~IndexWriter.group` method and the ``with`` statement. + """ + + pass + + def end_group(self): + """Finish indexing a group of hierarchical documents. See + :meth:`~IndexWriter.start_group`. + """ + + pass + + def add_field(self, fieldname, fieldtype, **kwargs): + """Adds a field to the index's schema. + + :param fieldname: the name of the field to add. + :param fieldtype: an instantiated :class:`whoosh.fields.FieldType` + object. + """ + + self.schema.add(fieldname, fieldtype, **kwargs) + + def remove_field(self, fieldname, **kwargs): + """Removes the named field from the index's schema. Depending on the + backend implementation, this may or may not actually remove existing + data for the field from the index. Optimizing the index should always + clear out existing data for a removed field. + """ + + self.schema.remove(fieldname, **kwargs) + + @abstractmethod + def reader(self, **kwargs): + """Returns a reader for the existing index. + """ + + raise NotImplementedError + + def searcher(self, **kwargs): + from whoosh.searching import Searcher + + return Searcher(self.reader(), **kwargs) + + def delete_by_term(self, fieldname, text, searcher=None): + """Deletes any documents containing "term" in the "fieldname" field. + This is useful when you have an indexed field containing a unique ID + (such as "pathname") for each document. + + :returns: the number of documents deleted. + """ + + from whoosh.query import Term + + q = Term(fieldname, text) + return self.delete_by_query(q, searcher=searcher) + + def delete_by_query(self, q, searcher=None): + """Deletes any documents matching a query object. + + :returns: the number of documents deleted. + """ + + if searcher: + s = searcher + else: + s = self.searcher() + + try: + count = 0 + for docnum in s.docs_for_query(q, for_deletion=True): + self.delete_document(docnum) + count += 1 + finally: + if not searcher: + s.close() + + return count + + @abstractmethod + def delete_document(self, docnum, delete=True): + """Deletes a document by number. + """ + raise NotImplementedError + + @abstractmethod + def add_document(self, **fields): + """The keyword arguments map field names to the values to index/store:: + + w = myindex.writer() + w.add_document(path=u"/a", title=u"First doc", text=u"Hello") + w.commit() + + Depending on the field type, some fields may take objects other than + unicode strings. For example, NUMERIC fields take numbers, and DATETIME + fields take ``datetime.datetime`` objects:: + + from datetime import datetime, timedelta + from whoosh import index + from whoosh.fields import * + + schema = Schema(date=DATETIME, size=NUMERIC(float), content=TEXT) + myindex = index.create_in("indexdir", schema) + + w = myindex.writer() + w.add_document(date=datetime.now(), size=5.5, content=u"Hello") + w.commit() + + Instead of a single object (i.e., unicode string, number, or datetime), + you can supply a list or tuple of objects. For unicode strings, this + bypasses the field's analyzer. For numbers and dates, this lets you add + multiple values for the given field:: + + date1 = datetime.now() + date2 = datetime(2005, 12, 25) + date3 = datetime(1999, 1, 1) + w.add_document(date=[date1, date2, date3], size=[9.5, 10], + content=[u"alfa", u"bravo", u"charlie"]) + + For fields that are both indexed and stored, you can specify an + alternate value to store using a keyword argument in the form + "_stored_". For example, if you have a field named "title" + and you want to index the text "a b c" but store the text "e f g", use + keyword arguments like this:: + + writer.add_document(title=u"a b c", _stored_title=u"e f g") + + You can boost the weight of all terms in a certain field by specifying + a ``__boost`` keyword argument. For example, if you have a + field named "content", you can double the weight of this document for + searches in the "content" field like this:: + + writer.add_document(content="a b c", _title_boost=2.0) + + You can boost every field at once using the ``_boost`` keyword. For + example, to boost fields "a" and "b" by 2.0, and field "c" by 3.0:: + + writer.add_document(a="alfa", b="bravo", c="charlie", + _boost=2.0, _c_boost=3.0) + + Note that some scoring algroithms, including Whoosh's default BM25F, + do not work with term weights less than 1, so you should generally not + use a boost factor less than 1. + + See also :meth:`Writer.update_document`. + """ + + raise NotImplementedError + + @abstractmethod + def add_reader(self, reader): + raise NotImplementedError + + def _doc_boost(self, fields, default=1.0): + if "_boost" in fields: + return float(fields["_boost"]) + else: + return default + + def _field_boost(self, fields, fieldname, default=1.0): + boostkw = "_%s_boost" % fieldname + if boostkw in fields: + return float(fields[boostkw]) + else: + return default + + def _unique_fields(self, fields): + # Check which of the supplied fields are unique + unique_fields = [name for name, field in self.schema.items() + if name in fields and field.unique] + return unique_fields + + def update_document(self, **fields): + """The keyword arguments map field names to the values to index/store. + + This method adds a new document to the index, and automatically deletes + any documents with the same values in any fields marked "unique" in the + schema:: + + schema = fields.Schema(path=fields.ID(unique=True, stored=True), + content=fields.TEXT) + myindex = index.create_in("index", schema) + + w = myindex.writer() + w.add_document(path=u"/", content=u"Mary had a lamb") + w.commit() + + w = myindex.writer() + w.update_document(path=u"/", content=u"Mary had a little lamb") + w.commit() + + assert myindex.doc_count() == 1 + + It is safe to use ``update_document`` in place of ``add_document``; if + there is no existing document to replace, it simply does an add. + + You cannot currently pass a list or tuple of values to a "unique" + field. + + Because this method has to search for documents with the same unique + fields and delete them before adding the new document, it is slower + than using ``add_document``. + + * Marking more fields "unique" in the schema will make each + ``update_document`` call slightly slower. + + * When you are updating multiple documents, it is faster to batch + delete all changed documents and then use ``add_document`` to add + the replacements instead of using ``update_document``. + + Note that this method will only replace a *committed* document; + currently it cannot replace documents you've added to the IndexWriter + but haven't yet committed. For example, if you do this: + + >>> writer.update_document(unique_id=u"1", content=u"Replace me") + >>> writer.update_document(unique_id=u"1", content=u"Replacement") + + ...this will add two documents with the same value of ``unique_id``, + instead of the second document replacing the first. + + See :meth:`Writer.add_document` for information on + ``_stored_``, ``__boost``, and ``_boost`` keyword + arguments. + """ + + # Delete the set of documents matching the unique terms + unique_fields = self._unique_fields(fields) + if unique_fields: + with self.searcher() as s: + uniqueterms = [(name, fields[name]) for name in unique_fields] + docs = s._find_unique(uniqueterms) + for docnum in docs: + self.delete_document(docnum) + + # Add the given fields + self.add_document(**fields) + + def commit(self): + """Finishes writing and unlocks the index. + """ + pass + + def cancel(self): + """Cancels any documents/deletions added by this object + and unlocks the index. + """ + pass + + +# Codec-based writer + +class SegmentWriter(IndexWriter): + def __init__(self, ix, poolclass=None, timeout=0.0, delay=0.1, _lk=True, + limitmb=128, docbase=0, codec=None, compound=True, **kwargs): + # Lock the index + self.writelock = None + if _lk: + self.writelock = ix.lock("WRITELOCK") + if not try_for(self.writelock.acquire, timeout=timeout, + delay=delay): + raise LockError + + if codec is None: + from whoosh.codec import default_codec + codec = default_codec() + self.codec = codec + + # Get info from the index + self.storage = ix.storage + self.indexname = ix.indexname + info = ix._read_toc() + self.generation = info.generation + 1 + self.schema = info.schema + self.segments = info.segments + self.docnum = self.docbase = docbase + self._setup_doc_offsets() + + # Internals + self._tempstorage = self.storage.temp_storage("%s.tmp" % self.indexname) + newsegment = codec.new_segment(self.storage, self.indexname) + self.newsegment = newsegment + self.compound = compound and newsegment.should_assemble() + self.is_closed = False + self._added = False + self.pool = PostingPool(self._tempstorage, self.newsegment, + limitmb=limitmb) + + # Set up writers + self.perdocwriter = codec.per_document_writer(self.storage, newsegment) + self.fieldwriter = codec.field_writer(self.storage, newsegment) + + self.merge = True + self.optimize = False + self.mergetype = None + + def __repr__(self): + return "<%s %r>" % (self.__class__.__name__, self.newsegment) + + def _check_state(self): + if self.is_closed: + raise IndexingError("This writer is closed") + + def _setup_doc_offsets(self): + self._doc_offsets = [] + base = 0 + for s in self.segments: + self._doc_offsets.append(base) + base += s.doc_count_all() + + def _document_segment(self, docnum): + #Returns the index.Segment object containing the given document + #number. + offsets = self._doc_offsets + if len(offsets) == 1: + return 0 + return bisect_right(offsets, docnum) - 1 + + def _segment_and_docnum(self, docnum): + #Returns an (index.Segment, segment_docnum) pair for the segment + #containing the given document number. + + segmentnum = self._document_segment(docnum) + offset = self._doc_offsets[segmentnum] + segment = self.segments[segmentnum] + return segment, docnum - offset + + def _process_posts(self, items, startdoc, docmap): + schema = self.schema + for fieldname, text, docnum, weight, vbytes in items: + if fieldname not in schema: + continue + if docmap is not None: + newdoc = docmap[docnum] + else: + newdoc = startdoc + docnum + + yield (fieldname, text, newdoc, weight, vbytes) + + def temp_storage(self): + return self._tempstorage + + def add_field(self, fieldname, fieldspec, **kwargs): + self._check_state() + if self._added: + raise Exception("Can't modify schema after adding data to writer") + super(SegmentWriter, self).add_field(fieldname, fieldspec, **kwargs) + + def remove_field(self, fieldname): + self._check_state() + if self._added: + raise Exception("Can't modify schema after adding data to writer") + super(SegmentWriter, self).remove_field(fieldname) + + def has_deletions(self): + """ + Returns True if the current index has documents that are marked deleted + but haven't been optimized out of the index yet. + """ + + return any(s.has_deletions() for s in self.segments) + + def delete_document(self, docnum, delete=True): + self._check_state() + if docnum >= sum(seg.doc_count_all() for seg in self.segments): + raise IndexingError("No document ID %r in this index" % docnum) + segment, segdocnum = self._segment_and_docnum(docnum) + segment.delete_document(segdocnum, delete=delete) + + def deleted_count(self): + """ + :returns: the total number of deleted documents in the index. + """ + + return sum(s.deleted_count() for s in self.segments) + + def is_deleted(self, docnum): + segment, segdocnum = self._segment_and_docnum(docnum) + return segment.is_deleted(segdocnum) + + def reader(self, reuse=None): + from whoosh.index import FileIndex + + self._check_state() + return FileIndex._reader(self.storage, self.schema, self.segments, + self.generation, reuse=reuse) + + def iter_postings(self): + return self.pool.iter_postings() + + def add_postings_to_pool(self, reader, startdoc, docmap): + items = self._process_posts(reader.iter_postings(), startdoc, docmap) + add_post = self.pool.add + for item in items: + add_post(item) + + def write_postings(self, lengths, items, startdoc, docmap): + items = self._process_posts(items, startdoc, docmap) + self.fieldwriter.add_postings(self.schema, lengths, items) + + def write_per_doc(self, fieldnames, reader): + # Very bad hack: reader should be an IndexReader, but may be a + # PerDocumentReader if this is called from multiproc, where the code + # tries to be efficient by merging per-doc and terms separately. + # TODO: fix this! + + schema = self.schema + if reader.has_deletions(): + docmap = {} + else: + docmap = None + + pdw = self.perdocwriter + # Open all column readers + cols = {} + for fieldname in fieldnames: + fieldobj = schema[fieldname] + coltype = fieldobj.column_type + if coltype and reader.has_column(fieldname): + creader = reader.column_reader(fieldname, coltype) + if isinstance(creader, columns.TranslatingColumnReader): + creader = creader.raw_column() + cols[fieldname] = creader + + for docnum, stored in reader.iter_docs(): + if docmap is not None: + docmap[docnum] = self.docnum + + pdw.start_doc(self.docnum) + for fieldname in fieldnames: + fieldobj = schema[fieldname] + length = reader.doc_field_length(docnum, fieldname) + pdw.add_field(fieldname, fieldobj, + stored.get(fieldname), length) + + if fieldobj.vector and reader.has_vector(docnum, fieldname): + v = reader.vector(docnum, fieldname, fieldobj.vector) + pdw.add_vector_matcher(fieldname, fieldobj, v) + + if fieldname in cols: + cv = cols[fieldname][docnum] + pdw.add_column_value(fieldname, fieldobj.column_type, cv) + + pdw.finish_doc() + self.docnum += 1 + + return docmap + + def add_reader(self, reader): + self._check_state() + basedoc = self.docnum + ndxnames = set(fname for fname in reader.indexed_field_names() + if fname in self.schema) + fieldnames = set(self.schema.names()) | ndxnames + + docmap = self.write_per_doc(fieldnames, reader) + self.add_postings_to_pool(reader, basedoc, docmap) + self._added = True + + def _check_fields(self, schema, fieldnames): + # Check if the caller gave us a bogus field + for name in fieldnames: + if name not in schema: + raise UnknownFieldError("No field named %r in %s" + % (name, schema)) + + def add_document(self, **fields): + self._check_state() + perdocwriter = self.perdocwriter + schema = self.schema + docnum = self.docnum + add_post = self.pool.add + + docboost = self._doc_boost(fields) + fieldnames = sorted([name for name in fields.keys() + if not name.startswith("_")]) + self._check_fields(schema, fieldnames) + + perdocwriter.start_doc(docnum) + for fieldname in fieldnames: + value = fields.get(fieldname) + if value is None: + continue + field = schema[fieldname] + + length = 0 + if field.indexed: + # TODO: Method for adding progressive field values, ie + # setting start_pos/start_char? + fieldboost = self._field_boost(fields, fieldname, docboost) + # Ask the field to return a list of (text, weight, vbytes) + # tuples + items = field.index(value) + # Only store the length if the field is marked scorable + scorable = field.scorable + # Add the terms to the pool + for tbytes, freq, weight, vbytes in items: + weight *= fieldboost + if scorable: + length += freq + add_post((fieldname, tbytes, docnum, weight, vbytes)) + + if field.separate_spelling(): + spellfield = field.spelling_fieldname(fieldname) + for word in field.spellable_words(value): + word = utf8encode(word)[0] + # item = (fieldname, tbytes, docnum, weight, vbytes) + add_post((spellfield, word, 0, 1, vbytes)) + + vformat = field.vector + if vformat: + analyzer = field.analyzer + # Call the format's word_values method to get posting values + vitems = vformat.word_values(value, analyzer, mode="index") + # Remove unused frequency field from the tuple + vitems = sorted((text, weight, vbytes) + for text, _, weight, vbytes in vitems) + perdocwriter.add_vector_items(fieldname, field, vitems) + + # Allow a custom value for stored field/column + customval = fields.get("_stored_%s" % fieldname, value) + + # Add the stored value and length for this field to the per- + # document writer + sv = customval if field.stored else None + perdocwriter.add_field(fieldname, field, sv, length) + + column = field.column_type + if column and customval is not None: + cv = field.to_column_value(customval) + perdocwriter.add_column_value(fieldname, column, cv) + + perdocwriter.finish_doc() + self._added = True + self.docnum += 1 + + def doc_count(self): + return self.docnum - self.docbase + + def get_segment(self): + newsegment = self.newsegment + newsegment.set_doc_count(self.docnum) + return newsegment + + def per_document_reader(self): + if not self.perdocwriter.is_closed: + raise Exception("Per-doc writer is still open") + return self.codec.per_document_reader(self.storage, self.get_segment()) + + # The following methods break out the commit functionality into smaller + # pieces to allow MpWriter to call them individually + + def _merge_segments(self, mergetype, optimize, merge): + # The writer supports two ways of setting mergetype/optimize/merge: + # as attributes or as keyword arguments to commit(). Originally there + # were just the keyword arguments, but then I added the ability to use + # the writer as a context manager using "with", so the user no longer + # explicitly called commit(), hence the attributes + mergetype = mergetype if mergetype is not None else self.mergetype + optimize = optimize if optimize is not None else self.optimize + merge = merge if merge is not None else self.merge + + if mergetype: + pass + elif optimize: + mergetype = OPTIMIZE + elif not merge: + mergetype = NO_MERGE + else: + mergetype = MERGE_SMALL + + # Call the merge policy function. The policy may choose to merge + # other segments into this writer's pool + return mergetype(self, self.segments) + + def _flush_segment(self): + self.perdocwriter.close() + if self.codec.length_stats: + pdr = self.per_document_reader() + else: + pdr = None + postings = self.pool.iter_postings() + self.fieldwriter.add_postings(self.schema, pdr, postings) + self.fieldwriter.close() + if pdr: + pdr.close() + + def _close_segment(self): + if not self.perdocwriter.is_closed: + self.perdocwriter.close() + if not self.fieldwriter.is_closed: + self.fieldwriter.close() + self.pool.cleanup() + + def _assemble_segment(self): + if self.compound: + # Assemble the segment files into a compound file + newsegment = self.get_segment() + newsegment.create_compound_file(self.storage) + newsegment.compound = True + + def _partial_segment(self): + # For use by a parent multiprocessing writer: Closes out the segment + # but leaves the pool files intact so the parent can access them + self._check_state() + self.perdocwriter.close() + self.fieldwriter.close() + # Don't call self.pool.cleanup()! We want to grab the pool files. + return self.get_segment() + + def _finalize_segment(self): + # Finish writing segment + self._flush_segment() + # Close segment files + self._close_segment() + # Assemble compound segment if necessary + self._assemble_segment() + + return self.get_segment() + + def _commit_toc(self, segments): + from whoosh.index import TOC, clean_files + + # Write a new TOC with the new segment list (and delete old files) + toc = TOC(self.schema, segments, self.generation) + toc.write(self.storage, self.indexname) + # Delete leftover files + clean_files(self.storage, self.indexname, self.generation, segments) + + def _finish(self): + self._tempstorage.destroy() + if self.writelock: + self.writelock.release() + self.is_closed = True + #self.storage.close() + + # Finalization methods + + def commit(self, mergetype=None, optimize=None, merge=None): + """Finishes writing and saves all additions and changes to disk. + + There are four possible ways to use this method:: + + # Merge small segments but leave large segments, trying to + # balance fast commits with fast searching: + writer.commit() + + # Merge all segments into a single segment: + writer.commit(optimize=True) + + # Don't merge any existing segments: + writer.commit(merge=False) + + # Use a custom merge function + writer.commit(mergetype=my_merge_function) + + :param mergetype: a custom merge function taking a Writer object and + segment list as arguments, and returning a new segment list. If you + supply a ``mergetype`` function, the values of the ``optimize`` and + ``merge`` arguments are ignored. + :param optimize: if True, all existing segments are merged with the + documents you've added to this writer (and the value of the + ``merge`` argument is ignored). + :param merge: if False, do not merge small segments. + """ + + self._check_state() + # Merge old segments if necessary + finalsegments = self._merge_segments(mergetype, optimize, merge) + if self._added: + # Flush the current segment being written and add it to the + # list of remaining segments returned by the merge policy + # function + finalsegments.append(self._finalize_segment()) + else: + # Close segment files + self._close_segment() + # Write TOC + self._commit_toc(finalsegments) + + # Final cleanup + self._finish() + + def cancel(self): + self._check_state() + self._close_segment() + self._finish() + + +# Writer wrappers + +class AsyncWriter(threading.Thread, IndexWriter): + """Convenience wrapper for a writer object that might fail due to locking + (i.e. the ``filedb`` writer). This object will attempt once to obtain the + underlying writer, and if it's successful, will simply pass method calls on + to it. + + If this object *can't* obtain a writer immediately, it will *buffer* + delete, add, and update method calls in memory until you call ``commit()``. + At that point, this object will start running in a separate thread, trying + to obtain the writer over and over, and once it obtains it, "replay" all + the buffered method calls on it. + + In a typical scenario where you're adding a single or a few documents to + the index as the result of a Web transaction, this lets you just create the + writer, add, and commit, without having to worry about index locks, + retries, etc. + + For example, to get an aynchronous writer, instead of this: + + >>> writer = myindex.writer() + + Do this: + + >>> from whoosh.writing import AsyncWriter + >>> writer = AsyncWriter(myindex) + """ + + def __init__(self, index, delay=0.25, writerargs=None): + """ + :param index: the :class:`whoosh.index.Index` to write to. + :param delay: the delay (in seconds) between attempts to instantiate + the actual writer. + :param writerargs: an optional dictionary specifying keyword arguments + to to be passed to the index's ``writer()`` method. + """ + + threading.Thread.__init__(self) + self.running = False + self.index = index + self.writerargs = writerargs or {} + self.delay = delay + self.events = [] + try: + self.writer = self.index.writer(**self.writerargs) + except LockError: + self.writer = None + + def reader(self): + return self.index.reader() + + def searcher(self, **kwargs): + from whoosh.searching import Searcher + return Searcher(self.reader(), fromindex=self.index, **kwargs) + + def _record(self, method, args, kwargs): + if self.writer: + getattr(self.writer, method)(*args, **kwargs) + else: + self.events.append((method, args, kwargs)) + + def run(self): + self.running = True + writer = self.writer + while writer is None: + try: + writer = self.index.writer(**self.writerargs) + except LockError: + time.sleep(self.delay) + for method, args, kwargs in self.events: + getattr(writer, method)(*args, **kwargs) + writer.commit(*self.commitargs, **self.commitkwargs) + + def delete_document(self, *args, **kwargs): + self._record("delete_document", args, kwargs) + + def add_document(self, *args, **kwargs): + self._record("add_document", args, kwargs) + + def update_document(self, *args, **kwargs): + self._record("update_document", args, kwargs) + + def add_field(self, *args, **kwargs): + self._record("add_field", args, kwargs) + + def remove_field(self, *args, **kwargs): + self._record("remove_field", args, kwargs) + + def delete_by_term(self, *args, **kwargs): + self._record("delete_by_term", args, kwargs) + + def commit(self, *args, **kwargs): + if self.writer: + self.writer.commit(*args, **kwargs) + else: + self.commitargs, self.commitkwargs = args, kwargs + self.start() + + def cancel(self, *args, **kwargs): + if self.writer: + self.writer.cancel(*args, **kwargs) + + +# Ex post factor functions + +def add_spelling(ix, fieldnames, commit=True): + """Adds spelling files to an existing index that was created without + them, and modifies the schema so the given fields have the ``spelling`` + attribute. Only works on filedb indexes. + + >>> ix = index.open_dir("testindex") + >>> add_spelling(ix, ["content", "tags"]) + + :param ix: a :class:`whoosh.filedb.fileindex.FileIndex` object. + :param fieldnames: a list of field names to create word graphs for. + :param force: if True, overwrites existing word graph files. This is only + useful for debugging. + """ + + from whoosh.automata import fst + from whoosh.reading import SegmentReader + + writer = ix.writer() + storage = writer.storage + schema = writer.schema + segments = writer.segments + + for segment in segments: + ext = segment.codec().FST_EXT + + r = SegmentReader(storage, schema, segment) + f = segment.create_file(storage, ext) + gw = fst.GraphWriter(f) + for fieldname in fieldnames: + gw.start_field(fieldname) + for word in r.lexicon(fieldname): + gw.insert(word) + gw.finish_field() + gw.close() + + for fieldname in fieldnames: + schema[fieldname].spelling = True + + if commit: + writer.commit(merge=False) + + +# Buffered writer class + +class BufferedWriter(IndexWriter): + """Convenience class that acts like a writer but buffers added documents + before dumping the buffered documents as a batch into the actual index. + + In scenarios where you are continuously adding single documents very + rapidly (for example a web application where lots of users are adding + content simultaneously), using a BufferedWriter is *much* faster than + opening and committing a writer for each document you add. If you're adding + batches of documents at a time, you can just use a regular writer. + + (This class may also be useful for batches of ``update_document`` calls. In + a normal writer, ``update_document`` calls cannot update documents you've + added *in that writer*. With ``BufferedWriter``, this will work.) + + To use this class, create it from your index and *keep it open*, sharing + it between threads. + + >>> from whoosh.writing import BufferedWriter + >>> writer = BufferedWriter(myindex, period=120, limit=20) + >>> # Then you can use the writer to add and update documents + >>> writer.add_document(...) + >>> writer.add_document(...) + >>> writer.add_document(...) + >>> # Before the writer goes out of scope, call close() on it + >>> writer.close() + + .. note:: + This object stores documents in memory and may keep an underlying + writer open, so you must explicitly call the + :meth:`~BufferedWriter.close` method on this object before it goes out + of scope to release the write lock and make sure any uncommitted + changes are saved. + + You can read/search the combination of the on-disk index and the + buffered documents in memory by calling ``BufferedWriter.reader()`` or + ``BufferedWriter.searcher()``. This allows quasi-real-time search, where + documents are available for searching as soon as they are buffered in + memory, before they are committed to disk. + + .. tip:: + By using a searcher from the shared writer, multiple *threads* can + search the buffered documents. Of course, other *processes* will only + see the documents that have been written to disk. If you want indexed + documents to become available to other processes as soon as possible, + you have to use a traditional writer instead of a ``BufferedWriter``. + + You can control how often the ``BufferedWriter`` flushes the in-memory + index to disk using the ``period`` and ``limit`` arguments. ``period`` is + the maximum number of seconds between commits. ``limit`` is the maximum + number of additions to buffer between commits. + + You don't need to call ``commit()`` on the ``BufferedWriter`` manually. + Doing so will just flush the buffered documents to disk early. You can + continue to make changes after calling ``commit()``, and you can call + ``commit()`` multiple times. + """ + + def __init__(self, index, period=60, limit=10, writerargs=None, + commitargs=None): + """ + :param index: the :class:`whoosh.index.Index` to write to. + :param period: the maximum amount of time (in seconds) between commits. + Set this to ``0`` or ``None`` to not use a timer. Do not set this + any lower than a few seconds. + :param limit: the maximum number of documents to buffer before + committing. + :param writerargs: dictionary specifying keyword arguments to be passed + to the index's ``writer()`` method when creating a writer. + """ + + self.index = index + self.period = period + self.limit = limit + self.writerargs = writerargs or {} + self.commitargs = commitargs or {} + + self.lock = threading.RLock() + self.writer = self.index.writer(**self.writerargs) + + self._make_ram_index() + self.bufferedcount = 0 + + # Start timer + if self.period: + self.timer = threading.Timer(self.period, self.commit) + self.timer.start() + + def __exit__(self, exc_type, exc_val, exc_tb): + self.close() + + def _make_ram_index(self): + from whoosh.codec.memory import MemoryCodec + + self.codec = MemoryCodec() + + def _get_ram_reader(self): + return self.codec.reader(self.schema) + + @property + def schema(self): + return self.writer.schema + + def reader(self, **kwargs): + from whoosh.reading import MultiReader + + reader = self.writer.reader() + with self.lock: + ramreader = self._get_ram_reader() + + # If there are in-memory docs, combine the readers + if ramreader.doc_count(): + if reader.is_atomic(): + reader = MultiReader([reader, ramreader]) + else: + reader.add_reader(ramreader) + + return reader + + def searcher(self, **kwargs): + from whoosh.searching import Searcher + + return Searcher(self.reader(), fromindex=self.index, **kwargs) + + def close(self): + self.commit(restart=False) + + def commit(self, restart=True): + if self.period: + self.timer.cancel() + + with self.lock: + ramreader = self._get_ram_reader() + self._make_ram_index() + + if self.bufferedcount: + self.writer.add_reader(ramreader) + self.writer.commit(**self.commitargs) + self.bufferedcount = 0 + + if restart: + self.writer = self.index.writer(**self.writerargs) + if self.period: + self.timer = threading.Timer(self.period, self.commit) + self.timer.start() + + def add_reader(self, reader): + # Pass through to the underlying on-disk index + self.writer.add_reader(reader) + self.commit() + + def add_document(self, **fields): + with self.lock: + # Hijack a writer to make the calls into the codec + with self.codec.writer(self.writer.schema) as w: + w.add_document(**fields) + + self.bufferedcount += 1 + if self.bufferedcount >= self.limit: + self.commit() + + def update_document(self, **fields): + with self.lock: + IndexWriter.update_document(self, **fields) + + def delete_document(self, docnum, delete=True): + with self.lock: + base = self.index.doc_count_all() + if docnum < base: + self.writer.delete_document(docnum, delete=delete) + else: + ramsegment = self.codec.segment + ramsegment.delete_document(docnum - base, delete=delete) + + def is_deleted(self, docnum): + base = self.index.doc_count_all() + if docnum < base: + return self.writer.is_deleted(docnum) + else: + return self._get_ram_reader().is_deleted(docnum - base) + + +# Backwards compatibility with old name +BatchWriter = BufferedWriter diff --git a/nstock/modules/z_whoosh.py b/nstock/modules/z_whoosh.py new file mode 100644 index 0000000..66bbb77 --- /dev/null +++ b/nstock/modules/z_whoosh.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +from whoosh.fields import Schema, TEXT, ID +from whoosh.index import create_in, open_dir +from gluon import current +import os +# from https://github.com/web2py/scaffold +# On new installations remove the 'whoosh' directory from the package +# and don't include it on the repository + + +class Whoosh(object): + + def __init__(self, user_id=None): + self.index = os.path.join(current.request.folder, 'whoosh') + if not os.path.exists(self.index): + os.makedirs(self.index) + self.schema = Schema(id=ID(unique=True, stored=True), text=TEXT) + self.ix = create_in( + self.index, schema=self.schema) + else: + self.ix = open_dir(self.index) + + def add_to_index(self, item_id, text): + from whoosh.writing import AsyncWriter + writer = AsyncWriter(self.ix) + writer.update_document(id=item_id, text=text.lower()) + writer.commit() + + def search(self, text, page=1, pagelen=500): + from whoosh.qparser import QueryParser + text = text.lower() + with self.ix.searcher() as searcher: + query = QueryParser("text", self.ix.schema).parse( + unicode(text.decode('utf-8'))) + results = searcher.search_page(query, page, pagelen) + return [r['id'] for r in results] diff --git a/nstock/private/appconfig.ini b/nstock/private/appconfig.ini new file mode 100644 index 0000000..3c8ac16 --- /dev/null +++ b/nstock/private/appconfig.ini @@ -0,0 +1,30 @@ +; App configuration +[app] +name = nStock +author = Yoel Benítez Fonseca +description = News Item collaborative application +keywords = web2py, python, framework, news, news items +generator = Web2py Web Framework + +; Host configuration +[host] +names = localhost:*, 127.0.0.1:*, *:*, * + +; db configuration +[db] +uri = sqlite://storage.sqlite +migrate = true +pool_size = 10 ; ignored for sqlite + +; smtp address and credentials +[smtp] +server = smtp.gmail.com:587 +sender = you@gmail.com +login = username:password +tls = true +ssl = true + +; form styling +[forms] +formstyle = bootstrap3_stacked +separator = diff --git a/nstock/private/language-codes.csv b/nstock/private/language-codes.csv new file mode 100644 index 0000000..a8db380 --- /dev/null +++ b/nstock/private/language-codes.csv @@ -0,0 +1,185 @@ +"alpha2","English" +"aa","Afar" +"ab","Abkhazian" +"ae","Avestan" +"af","Afrikaans" +"ak","Akan" +"am","Amharic" +"an","Aragonese" +"ar","Arabic" +"as","Assamese" +"av","Avaric" +"ay","Aymara" +"az","Azerbaijani" +"ba","Bashkir" +"be","Belarusian" +"bg","Bulgarian" +"bh","Bihari languages" +"bi","Bislama" +"bm","Bambara" +"bn","Bengali" +"bo","Tibetan" +"br","Breton" +"bs","Bosnian" +"ca","Catalan; Valencian" +"ce","Chechen" +"ch","Chamorro" +"co","Corsican" +"cr","Cree" +"cs","Czech" +"cu","Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic" +"cv","Chuvash" +"cy","Welsh" +"da","Danish" +"de","German" +"dv","Divehi; Dhivehi; Maldivian" +"dz","Dzongkha" +"ee","Ewe" +"el","Greek, Modern (1453-)" +"en","English" +"eo","Esperanto" +"es","Spanish; Castilian" +"et","Estonian" +"eu","Basque" +"fa","Persian" +"ff","Fulah" +"fi","Finnish" +"fj","Fijian" +"fo","Faroese" +"fr","French" +"fy","Western Frisian" +"ga","Irish" +"gd","Gaelic; Scottish Gaelic" +"gl","Galician" +"gn","Guarani" +"gu","Gujarati" +"gv","Manx" +"ha","Hausa" +"he","Hebrew" +"hi","Hindi" +"ho","Hiri Motu" +"hr","Croatian" +"ht","Haitian; Haitian Creole" +"hu","Hungarian" +"hy","Armenian" +"hz","Herero" +"ia","Interlingua (International Auxiliary Language Association)" +"id","Indonesian" +"ie","Interlingue; Occidental" +"ig","Igbo" +"ii","Sichuan Yi; Nuosu" +"ik","Inupiaq" +"io","Ido" +"is","Icelandic" +"it","Italian" +"iu","Inuktitut" +"ja","Japanese" +"jv","Javanese" +"ka","Georgian" +"kg","Kongo" +"ki","Kikuyu; Gikuyu" +"kj","Kuanyama; Kwanyama" +"kk","Kazakh" +"kl","Kalaallisut; Greenlandic" +"km","Central Khmer" +"kn","Kannada" +"ko","Korean" +"kr","Kanuri" +"ks","Kashmiri" +"ku","Kurdish" +"kv","Komi" +"kw","Cornish" +"ky","Kirghiz; Kyrgyz" +"la","Latin" +"lb","Luxembourgish; Letzeburgesch" +"lg","Ganda" +"li","Limburgan; Limburger; Limburgish" +"ln","Lingala" +"lo","Lao" +"lt","Lithuanian" +"lu","Luba-Katanga" +"lv","Latvian" +"mg","Malagasy" +"mh","Marshallese" +"mi","Maori" +"mk","Macedonian" +"ml","Malayalam" +"mn","Mongolian" +"mr","Marathi" +"ms","Malay" +"mt","Maltese" +"my","Burmese" +"na","Nauru" +"nb","Bokmål, Norwegian; Norwegian Bokmål" +"nd","Ndebele, North; North Ndebele" +"ne","Nepali" +"ng","Ndonga" +"nl","Dutch; Flemish" +"nn","Norwegian Nynorsk; Nynorsk, Norwegian" +"no","Norwegian" +"nr","Ndebele, South; South Ndebele" +"nv","Navajo; Navaho" +"ny","Chichewa; Chewa; Nyanja" +"oc","Occitan (post 1500); Provençal" +"oj","Ojibwa" +"om","Oromo" +"or","Oriya" +"os","Ossetian; Ossetic" +"pa","Panjabi; Punjabi" +"pi","Pali" +"pl","Polish" +"ps","Pushto; Pashto" +"pt","Portuguese" +"qu","Quechua" +"rm","Romansh" +"rn","Rundi" +"ro","Romanian; Moldavian; Moldovan" +"ru","Russian" +"rw","Kinyarwanda" +"sa","Sanskrit" +"sc","Sardinian" +"sd","Sindhi" +"se","Northern Sami" +"sg","Sango" +"si","Sinhala; Sinhalese" +"sk","Slovak" +"sl","Slovenian" +"sm","Samoan" +"sn","Shona" +"so","Somali" +"sq","Albanian" +"sr","Serbian" +"ss","Swati" +"st","Sotho, Southern" +"su","Sundanese" +"sv","Swedish" +"sw","Swahili" +"ta","Tamil" +"te","Telugu" +"tg","Tajik" +"th","Thai" +"ti","Tigrinya" +"tk","Turkmen" +"tl","Tagalog" +"tn","Tswana" +"to","Tonga (Tonga Islands)" +"tr","Turkish" +"ts","Tsonga" +"tt","Tatar" +"tw","Twi" +"ty","Tahitian" +"ug","Uighur; Uyghur" +"uk","Ukrainian" +"ur","Urdu" +"uz","Uzbek" +"ve","Venda" +"vi","Vietnamese" +"vo","Volapük" +"wa","Walloon" +"wo","Wolof" +"xh","Xhosa" +"yi","Yiddish" +"yo","Yoruba" +"za","Zhuang; Chuang" +"zh","Chinese" +"zu","Zulu" diff --git a/nstock/routes.example.py b/nstock/routes.example.py new file mode 100644 index 0000000..2530c9f --- /dev/null +++ b/nstock/routes.example.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- + +# ---------------------------------------------------------------------------------------------------------------------- +# This is an app-specific example router +# +# This simple router is used for setting languages from app/languages directory +# as a part of the application path: app//controller/function +# Language from default.py or 'en' (if the file is not found) is used as +# a default_language +# +# See /examples/routes.parametric.example.py for parameter's detail +# ---------------------------------------------------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------------------------------------------------- +# To enable this route file you must do the steps: +# 1. rename /examples/routes.parametric.example.py to routes.py +# 2. rename this APP/routes.example.py to APP/routes.py (where APP - is your application directory) +# 3. restart web2py (or reload routes in web2py admin interface) +# +# YOU CAN COPY THIS FILE TO ANY APPLICATION'S ROOT DIRECTORY WITHOUT CHANGES! +# ---------------------------------------------------------------------------------------------------------------------- + +from fileutils import abspath +from languages import read_possible_languages + +possible_languages = read_possible_languages(abspath('applications', app)) +# ---------------------------------------------------------------------------------------------------------------------- +# NOTE! app - is an application based router's parameter with name of an application. E.g.'welcome' +# ---------------------------------------------------------------------------------------------------------------------- + +routers = { + app: dict( + default_language=possible_languages['default'][0], + languages=[lang for lang in possible_languages if lang != 'default'] + ) +} + +# ---------------------------------------------------------------------------------------------------------------------- +# NOTE! To change language in your application using these rules add this line in one of your models files: +# ---------------------------------------------------------------------------------------------------------------------- +# if request.uri_language: T.force(request.uri_language) diff --git a/nstock/sessions/.gitignore b/nstock/sessions/.gitignore new file mode 100644 index 0000000..76bedae --- /dev/null +++ b/nstock/sessions/.gitignore @@ -0,0 +1,5 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore + diff --git a/nstock/shot-full.png b/nstock/shot-full.png new file mode 100644 index 0000000000000000000000000000000000000000..d9af37f1f9156c5d5a676d139a91ddf1254e6fc8 GIT binary patch literal 655451 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⩔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 z zS9vz4yT=HMUvaQO0B0T9q`f7_$LNACdN3W|+StyIuLDH-4sS|33xjBORyEF((hB3o z68HweAe~=BMJaPw_O*VTeR;bGk53@E3tbtvD$H2P-_bIC^4YPiYH|%qLJe9{(K6u* zNs%*jBNhq0o8$?d_vWZ;$Hz~?gX@wooeVvLRBI4){-C&E z@D*(|>r<@;*V*IpOHe$%(-mem+t(K5;22Oq3-NosLzs5D$~G=L){^)CUIjgtlz9^uaF(>l2VT@qP8=tv&h6oNO?=3TCA`w*Iz_8P@yYSIv}7X}cG<-ZE=?no zqT&8LO;|`HjOt$xj+~df<{ha@HuSR1>YPi)2g(h>sPGgq99W!NhP(Dn84bTwW!Z4J zuooQK`+842`HnPgw8h-)IR1Ap!0EkXVc)1f4*Z0R=i^8tUgb(diRAdFCcGGqOqOMn z6aD4BcytUZ8w7#njYAt#?-~vVWw~|k8Nm~vpSKG~5ZUiRDTDaxjy+XqS&kJ!jV)@s zO>~j_xz2PWJCmigz^v^BtYP<}Vh%B_BrldNfj`>g6>+FZQ};_4etW|=x%91T$?Qru z5}4EWkow+J>RDC%fSEF(rx@W|xqF*FweY0mdxTM=t7A%MDFU#61giB`=TA^#tGd}D z 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

wL;KX?j9I-b`pDUQ()N_ZnA5Z|0zL) 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

Pqf)73wogE(&ap*s>64F{YJ(}_+9 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�<6+Ezo(>j&z zWz|Ii-R@T8zAfq+358-akKL`LHjAC5o%@@PSNO@gzAmi^K{#_j6k~V{oRjcM)Tbsw z%j;(Ci%YSf&!8zA59y*-D~2YR!R@B!J@mV3&V4*5j2bw|u4ateG8Rv>r#|e?&iB^~aa`<<-7ZF9C23Qksvn_-8{P zOun9uXt}UD`qY_Mc-2C!U4c1SA?>{ZTjI`KbMo_LQY zR*^it-duEu8>#uhK87JbI%B%>Ia8E19GO6Z*C)2I52km+BsKq-bPwW zx>&TW#9?eF5->4BO`K~9p^A<@_&u7HbZP6j_up-N-!GWmec8Q42q;e(L#qZqnwocA zgU#7&unO*n_Le}6NO*@HX$jnQqIkw@?^Kaavp#u!SD80NhTuwflv=`7&eQu7)PfU( zCuO9DmdfrT6M=O*+L2>5*S)=B+^(QqG>%5A_~|7!k&}>A=7mR^-V=K(uJe+pYvM<< z<&3}t)FV=vi|RUoO!N{N@~V0zWCP}bP?yFp7cpC-dlHi4_zIU+JMs`I9-{ei+msg@ z19BMU@9kaSSB2zdE$aoA;EB}hP4C2v_-!KbFW%`kWN6QM^DWVId*D&tL=d)}^~-(I z3(I1UC#aiTi2tfi5YMMstpC2>y8iBO3ioDTV7@cFnqdAZUV9yjV;w=1>L%%-lkD;; z?4_)+4$Cwd+Ux$vyy=LgUMWwB8<4Msmfv~g0#gK#D$O5D`F1GKguhE)%>F1;3jg=y z`PZ&3C^T0xX*Ta1E=xT*u$KC!1-`?)L3fgDadfNIS9$$d!F8SyT&;5O9y%+ND4a4C zx_-0;3_HCQhUgtVKU8Kvil?vk>TKR5%ZrOkr8@k1p4S6R6|1n|djZaL=1T;y_^>_j z4d&EpkL6Ud`$IB<1`XRZz`mTIN8>1U6*)80R_;vXBAYJstBdi^9N`Gv0aIHFrF z-nNdKAr|GEI4Y>a8pKiov~dMUFhictB@jo2Hv#=Y6?C?Ru!+x|^l zZr3!~a=0?PBea14txE;;J`_NJRzmC1B%%I~mwXK7@3L)%e;QnPB8&GV`6DFzx^^uq z@jX(K1V?1FMPC`%K7)K_`uJNdvtDvAo-A&eJ3Vv>GBDGdsxTq)kV+&X!5YbWd}QSP z)EEuxRB;r?)~%5YuolG+BK^POgQ+Z&><-q_&&7Iqn*mz0Xp8!>iP5XStY4?-ejv7KokOJAX}F8AB6PZ&6PkX|XU4RMj%f%)g^%lzuQrXjJMcy{lw=cHIL1o)*KT>dqav{I7iuZx;X##y7-Mg?GwXPZ*0Y zlDG_XFNiU$dsAV}L;d=9iPXM1kczKc;T&!d`tZnCY!s<|@uq){Nqo4{b;twbxkDtaZNRMJaK!P%a`0@N43Af5vuR=7GHaEp|y;tiOsHUm1!7 zCP7%g`TW;Xx^l3`C}#H%ymse$W~}Hh%U>YL;uXDmbH7DzmbAedQMdQWo)>vvh=Q6s zE0uiQUvn7Z1T49iTI=f&j0y_KW1`=>i7d-SWFOr(i4$u2Tcc)4fGIGZd$1a^Dqz|- zg$b3<16K{Ren{z=(V}vUyFF|VF3|EK*hKexRFo|H30D_%GwLU?@^B>NU?2$dp`?+A92C0KdtB-oN+jvTON6*<<&t(;zcb6ez03&&U(Wc zMrNe)QXmg-$`9~8Y=UwJQZFB*nFT_o__*70m@wBnvT8it_bVNCF>SZ~ErcPn>#lq&z{^s@ zq41nC1Fhb@ki)FORX|RemGxpH^CXUr)2)Ij+?uxsCK-=(RfN^u0==KcV`HYt@mZvl6P|u+kW}{X*`aGhsD0JC?xOGII9p)TovT+@umcnS6jZUM?P@H zbM%eC>+9O7%At2hARJRnTYXnaH^<|N9NrQs_E#3-E^|Vr%RA?KlAe>1MTxy@72oVP z=5?b*Ur854uUA5{3B9KtN~C!=>dWV+*B4GhV`9-QVZ1aG{x$-3Zu0SN6SOo712GD9 z_g4Q82`ahYwzJZ!ipm!h zY0<5kcbZca7#nb0X94m6GYa6zHrtf`MotJK*yBm2az=UuDKbDI4e4TXW>YYnHrH>A zjHJ(g?sgLp#kU>tv?yc9>E&VS2ZqZ?wE7-d4$A%p3pIge-z%KC!h<)`x`hh&3-^+=*33g%mnug@x1?S zVLY9HlAXuUual+zQOTq~J(9|=_dr*y+_(HE;p_YF0Ivy7im%g`0jA zqT^8-=h&Ei?dArZJ06Z37-s)wHm&nC#n1hFA~4H{b1n~{lYoU!KhW@c=h^_Rc9>Po zhS&PU6_O$dZB5O+tD<*~8`6jEXZ94_Skq%v6)U9bgKi#1<EXL0>0+U%?!)KY#*!Csqff=~s zxTbdqMwFUw+O~K-dDSGY=%Ee2QR?s5ueAep(|zJ|>8ap50>;iw^KY1ZN!)oO3WbyL zgIq(F7yHWLJ5B)w^d z1NWa%SMI^PJDe-ww_KW8_}?jb0EH?WNDyA~$ga_f%&Fs3w`f3gg?HuRo4lT{5`m^Q zasm0u=G_d`XHEaCUrQa*by_oA=({((lR~dCrWq0p&U0b|5%4X)BjAb8TJl`~$@Wqi zh)uF{lq|)#B9~r9wY22I{2ybzSP5UrH3(d>yX~=DDC;52+Tj07cl^fd*EKr_!3jX_ z7f|2t5?URGz;0lx2@W=g&oLg?vW%IPW-G_&3VcsIx*BusF9c0e>KPtr49;5WHuVpu zHo4tzqKj#0FTPqI!K%6ZVOLEdz0VLX=uf1Qo594p|NYCm%eeO(rS{ ze-Y5H9@o>rzkB$C8X_v_P@3pJjynEwR5`)5OJ~do{?+cu99UG^c&}-u!)tlcuzZ7A z;gtA!#_0`A_WWn3tascepaB8Ilte1y`#~X+iIH->-V9yk5UbtbC2RL`mgNZ2#i*mx z2NhHw?FNQ9-hqsV5|7$XhQyG4VPrW5%8pnalbcF2{u(Q)HZ}RgBeIg#t9{C21I5-y zb5{lU)?HN?7DKQX2R85PisVj`?WTJHY7d|Z=q;6||fUr_e35U*{I6{Hm0L-2H*6W()AssoR!HXP>;A~DVa@nFS~M+O{S^$EH@%Az)F=-;nxhGNy9W8&tZ2v-Qt_! zpV|M63lKAcT3Fd|woUVUB}CBM)L6>Q4+xQ^nRBO_-@SiH{n5RcP+HIGR0F*Te;np* zfS$dS7J8s7${5nZ@-F_JoUD9*rl4v*(kNG&cg?Pu7f-r}nWv)grrwl{f#p`4JhztG|wCAxp@C2Zmr{P*G>DOuYvZVsC=yZ?@cMTB_Oq z)AeaQ&taO8_bl_p<>UXF5j1faT~G0;8}C5>n5_Tz`q#?DfBb-0Yg}y$dKu`4*M6IG z@+CX&2RDU1VWGZb#lLR>70SKyhZe?{xC(Rm&%iG6pw#@K`*&cI{-?ish8o#Kkh7>t z0N&CC;H}1t*dNW;4DL$4g&G|-mW4~d3^C+eGp6qs{GN1lB}Oaq`?A?!xL4Gh#E_to zKC5VDG|qXXyjIk9zx%7(DdKSTi;OYEcb|2!vUF=P$unf{j+bqgU&pu*)AHb4#vLJi z{L93q{3h~&c_v7^>~41BCV`1Gqrh1cM8@tEU57~{I+h0ctI8#dA;90dsgbHX+vNx9 zymZ{AIlxtHjYNk1-Z?u7Tqs)u=0qM2n?kBp{XuVhCT=zQ&^PYQ8S<-!!%4&q&%pEg zC@tMhd_j#rTGvP>R-Kt|ba&C!r%kgG#(bpOfJ{bv<^%?&4G*8ZA=LEFEZ^%)|0#*Y zD6lkfFJ_(yrLIdGTvE*G?UY2e7I~7zwv{U&-4?%=H&yFxXs}2pI^kQ03dH&|pRYm$ z3tqCn`#H1v)&1m3(O-qUTD)IqctGkQ+urHQkPSgqFA3PMOC_#j4z9kI@y$YGfKazi zOYQYKVfyn)$B&_zXLbJQ{QZ~StDqUu$kyiRmKJef8cUmL7|%ydV6K1Hzw|hO{^wc&NYj{GnUwb_ z6SnT^%{~qRkH}w}4_?8a>{zeuUgfG3&FxH%UtSGFn1HIKNgHSC+oM_oie)lB^zXR9!BlzIdk3{`9tk?8gHQR-luY&l^T_@=J3M;{Q%{-yqfPf=fl@hkqGG zVf`a+rAOglERa;mAAegQm1Q}5#XjClS?Yk6QRMHUj7!;4Z2V$K}DwV&->1W6S8m&&gX0?|&hQnU%{s9#3{9 z$9M0M*`kk6f<-EQE#TfR1*HHrk=b)SpuK6J!^MhNbPU-kF>*1`WqSV9{Pueix25oH zmHY|2a#6=a6YS5Mq{r(Mur7vD#4O=&tqE97LteMHe(`)%zcL!J;OZV2;WPxhVF|D97 z5bRM@=G>64{Ve*?#Af8uH<6u3|6?P}jLD_pdsoFULE)pWY8A$=#rz(L{XW*fzpZ0u51q|o$68* zX=@Bku`aMI$ayskuE6adURUN4aK>92V$=bgBl;%5s3)1R4+BdrmsRN+O-!<_Hc*U9fex8y`j@`x5#c-y zc3%8_qYIgX&k1^hV*%iQ#?)oieWsyAZH8&g@rB>;$k%6#fhFxo(-Bnf4%)8l08?Cc z=Bn3UDpHvv#9Q5mPGdv!Lfv4kKQpGXdQxkj;?J_J?cV4Irf>$$Mej&4o#Pw;4^5 zwQ?Iv^=;Di=F?&G#GFQ$V^Ej(bl=F+kFJP9s{V!Oz(-E)FDr~Pg-MH&CkZ0&j5KqBh}TlCxYvad>rJ8xBLgM)cK&7xD9>64fQplur9Qd#S#S zAH%rw-4EXPcIKiH-yJ8c_u5<@B8?ZnLIObFtXO8_osfG+Hy6Ko{pKJD11`?v1G=2Q z6xD8D?wb$idwYxS_(#0u29<25SsnFW9v7#8)svekP zibD-k$oMKm)%Cowq}%x{E1Kf+X-E?tXncUQ;f2b~=G7U|PYu~Z`UPRC*3U8v;eG}{ zMVHL;6cSH_oXna2&|~bv_}vfgy=`U6@OiwWKblqHyiB0^U95grI8XBT$Gfiz3q36> zFj^P9n{cUPN$ePk?78GM!f5lC&I4DgC33u7(I}`rAJR=ASmylmRnrt;$lP!+a)dOm z#k_LNgdh0jSN^N~__6^+lO79tD+pF3#rvod+|J2EwkbgKdj4$HW2S-hzx;|EpDM#l zRHu(TmXL6>^^3~AwAzjwLfpr>-2tXaFN7amTws+H8_i6OV!e8%C`AWzBRYl#xmzV_ zAK(wC-Lc{Xx4+>D`P1G&4^%;?eh{smxx7g~1K-zjltU8*iH%I6iJ`;@Pwgkw5;x6b8{hm20wv}))Y1_Yb-euRh`IWlM#4LTO}~d4n(cU~X+R8sGkTt1 zcSxS>eQUXC!Kqykk5w(u4CK*Df3S3ua3H#+FFBY?*lY4}9@TBBjZWVFeC;fSd*)5- zZ;i<=zwaabJkEXGp3w4nD{tCL^dd-dmdCU-xFq&aXk=xutoS!9m3$6M^M&^7FE2w`g0jZxyTX@)CaK3fL8b*s;6nrwe|~d^fnpNs(&Ps$W|do z`cMnqA_WHGuYRB8cMAxG{}~O4E|--61&1NewyESJ20Q*s?NI=01EJ2pc_)&YdJXQn zM&hr315z=iMGv>q5Y@8r^H%>JOSmUSoN3DW5u><_bG1u90>YWYIVfMh4RN6iybtwC z?z4y6-y#iRt*iU(F>D2%$|$h)K--oXD}XSS`-BczF9|98?GH<=eK+*lEedy2eFGju zF^N{C^7v(BHX#cTL_7Pbqw|LsF=j=YB2#}oBsraspzUULyesIM4-Qt(FVRhG!t)>-Nv!z zg~pU=sqHR$;StZ@U_P~Qu99>y8$a!%^#IitVz>LaR5xk%hSxT+Iayhzb>=jJ#DKln z&kjt)Ry~)Q5f79W6S4KRdVF~Wg)XkXekul(suqFYnySmwI94s~TS7LRDVGVI{JNn)M*g zo)*8ZC$<{=3cqtFmJQWo6omu#GkkY$e{o*$r|zvttAYktv~yTesCD-V=&!(;GUEwJC9mvQuXW6EKYhi zUTR41ZrN|aiG3>2a=}ccRG$z}pHVSGjik!t(4W>wID=@LnR`nC=b%~<#yH4gQ#K^g zs6t9ua5I9a19aEj1MF>6YTwTSgk}vVi819ZuMQll&?VFWV=WH$MqveT(D9$-)#AG= zjxd97*-RcgoHmV9x0!-_G~bifV`~&dQ6Ob&-I)htMgD9#0El+vq3d)dPG4%iB3^da zJTGPAS;QT(c~K$8j^On=XAoYiiICg7F-C_xDFQA&>HDb4$fagtrqE*vChtt2q7he$ zRs{iCPMG73$nL7yMO%zzk19v!wk#y%3BwGRyiU^;$4LdzA!1m9sn%IgmYqC-@W?tt zrOQS$We8206kIr)5AWXi~Qqlq{PAp-9mT3Xtherw8{paxDtIN2YF zMEoqkD{!0(=TB`U(DLFlsO~4h9|CDkety`fXA|;4+FbK!<85HRz!?hosglxm8JjlU zFq@3cPRRJ8(~kiclzV<)cuIQHq!o7xH2X`2(3#rlTc5-A3(5Ci4D494<8t^P79a*Y zM*|#8Mru$^I4(J581gh58WKITYaF`jA#D;JgP>)eviBusXzm^qEMB z4CWBP#NUSiB1u2|R3&ApyzRDNU5mk>m_CqvKSz#U`J5w1PtP_!2U-iTK=Nxr4??LD z?8?38R@t!?hcYVCjK9qX`xHf~PbLKoNlYi6zy6XSu~EOwK;l8d*T00T9uZ8MIWx0~ z+D;zJ9elKp0{nIf-9cEar-c8F&cJpCFlU_L1~vjq{YwDiX}QMz-x>?f?Q8##L;XwT zw&{zGM6_@sfOuv|#LfZumVYy@ZtD5hg?c_Pyy1>}u|n0Z6ujLIjD@(^k=nlm*3Ub7 zrI&yl_I_JWzh2FlBu&lr0=zg{9vUO=i$wPAz^FJhKj7vIU6LkYJNNc&ZPKq$Y|cI0 zMOY{AikBRGm%#l;5nA=$n_u%or$j;!qMhT3jDZcB3^^rSXGK1*0(|&67X6u5ci*kS z6fqdX z5@P*+D{KDflBH)q4{cHImb3Ce1i(vRmt~6a$R#4=n<7;^3e{HF-wMc;H*EhRYs1O{ z0;pz7Prdj+_|rjW?h?{!Gp4*a}yV{OH?l|5jRsV{M;HHcihTED})8ffi>MgN)D@eU0B9lS6KpRq#%#kt`ZY)p$j5`$@3NmdK(Ouw& zh;@%@Lbf-lGD&N-LFt|iESZ{OQVru}APaP%4x6L9*#-ZXIC zl)V%b2{L?VRxU#VJfXr6wo@%!tISt}aa%eEQ>-!3fPWO=x(*mfS!Dm3Q`acaHYohL zN69d16!tCWO`B+i@m$JhSttRXseJ~C#Tfkg3n6B6#ZGOU5T2JRFEHo$#h*QRjL5>~ zPgp$6kxBYc{G}(S=WQ!tI=@t(!gS?%UQW2dG^vKcr)Qqr>?dV*DvJ;1?r+X*uBAw^ zkrxwYj!LkQ$E8t{SfqlY8`LK+*d%#8y}pQW_Kv#a9d49xwaR!8jXA2JNAAvfd53Hz zE}a0S^n;^twCgI*;3;f9!KYXIJHj}N3jU(Dd-}&T-`JetH5LDNWfz%B*7m)S5|N2b zJ}_ys21@U}PJoWNg>BZFf8!HkI?X9T8!=mFdzr6SeHX~r%Z1c>>8Rb`LKv-!TpO+1 z<=+{2u_hd|KLeTXOYt=huKSqVez7DJVCi?(ElT%yvHt16uQHkbF z6^=*84YZTiySvAy2D)d}|FP$Zu5~?bSNzW>tcr;zj~vlR5H9H?udv(zmYg>3>Cu&z zs1DE)kyGLjgT90@#Oo^fPEPCICZM(z#7P%7F?8UJ*%Ybb2S(pI7rn_f{2pU~N4IAw z-&!<8R!?j2A&*u^GP^b8l@z8*Y;M~g7eDKi!;#^B>2#FTEZ@f2`YcPFFRkG5?QTE0 z$=c7C?9(cN>XZs=Y@vIZohBe3(suRaHYej?q7+s`@JXXo?V=%(yw+KDIGc=MUVRz~ zJ)C%PUM*L;SH)AZ!)411=5dZkqe?<1>$X&!mh#DX&4+$#DsXxy}8Ye`(_ zCW0eEUo82fC!z`&9za;K7h4VL?{Ps~A(aj@T?v5w6)=*Ag-`))JQVO?H`w}VDG)Im zisq;iaB}XEiFYs1@RJ6Xdlr z(|3oeKKh==u9c`u1Hz+{FM#l7?>t^=d_O`syws*g#j#YxtZChWuzC4bc4MYRjlZE8I%br10D^JJ_Rg57f62?DvfJNkcl!Dt@l}SxGE&{pD`&!WOLTDDFQ5gf!}W z$jwoPo+p>Vdgw&}M~Lo3SDZtFux_G5XK+EUZ$EOM5_vTKs*wiL`x;f3#0^{F0KFW@ zfS}vN&sLV^#WAglJannu9_4Q>d;AMaZ`AZSkFCcxHm4S>rGB`c=atxu^YA_rvs1&m zPc)R#Um&zT%Ahl%yp$SZFA=cQYOK{P!u1f60vQC;oTyEr#3$mJwUh#*cIDGA5IUf@ z$QnUQ_YVfm$@Yb^j_o@GcuS46R;;CGBfdO}H3K|!8A2{bWL%0xvIK;BXJ>^Z_m>`L?Eq=1tUp*Tda0?U zt~#s#WQcFw328REp^C-9I2&BpoTBa?P@&iGIgp#R!Z_;Dqth2T$wls!1lv#8&_3X-thS1H?%Fw zf`QcWhmIL+y-5HM-XUcZX+E~YGzviZo~1t8+RT%!evnPn10>+~e(_(m_)xiJr;#l+ zE3vY?1}7B(6rul7u@AGGZFzsCmUB}vke-5Q`z3&oXWak&xqAS14W0hoE&NOVjnLNn zA0_|4{)3%eI(^(b0BorTJpBN!gVg7gzQV@RPvE#Nfc?_c(Pwo%{B0}NNBHY3JYOq4 zUwMq!Sv_&P*>4o@BzFop16CsCFzMm)Rg`>Jo_T2Ub9)WtVIwRsWfD{rKz<@9VtW^1t z?XL6QPQC2{%Wl2{9P^xK_x;Ew)VF@4U0CEw)QRqi!koTNV2-c>Dv2L%S#;x7z z+9SlzqFv>_#kM2ZHpxSe8e)u5(Q$VMSA=gZJ;ElVKxTh5W=m+ttT-RpyN+(7Ip*HR zNzG*66gFpG`Nk)uOAhmD;4xOaLV&b@bzCfFd~0bc3TAQegRiaRdSKzN{j=k}WDzj% z!bmA{Q>a>s0-(~Q#?miFmcOx(8Bgueb>XUNHibQ{Ig3Ck;2?aqdK_tiD(eaTgmtfA zB4};m4G&;eFohBy!%EHf6W76wpbYV>{Q+SSC@*oDvp~&-384Af-ZNDXtEMh#d_cof=?r!?2)HugO4CNn z91a_$W~vH;=H-CwW~b`2(S9{uGJR`#7m>8y98OZF!*A#X7HupYvWuS z#H^uRJN<0ya% z!JBn-J+bB@YwAu@$6Nl~NHWyi1CY7ByM7#^qXsw`u}MiZH972;0y zwas^{Z_l!!6P*xfNfT6Pj(e=G?uhAIW4nla=}qw(Ug#!jE}QzWg?_rdeO~LHYqMp6 zGyJ-2QZ38k{#enr)6&XmrCW`yU9^SR|BTp-cR>N`DqGG|@UtM`;_{MIDHlPWeUN-A za85`)5w3FB8)-%h_*s2TgF-lfI;Q8sYid0Uu?9*7<2zCy@Z-{M-WIT%H{x7R2s<>W zQMC52bRssX5c_1XR@CR1X=7%+;@H$~u|tqz+U!7GQGh*c#<57mHP9`ree0*5D)0>o@=%Bg?wntRWmu0 z(xR;izem`c>9A*DgV=PeE}<6nvS^^d{!DGHbwO|KiUV>jJ2R2N34BGlyXU&@{WVy~3y7XZt;*Nm zp}#0c@wI&U9+)z`otQ^x)9GjoYHDlY>sAY(kDnM>VjCIz?#nI9g2uGfbth2~&%_d# zA3TkB4_`&Iy*a6{0(LTQLp_v`I;sT4My z(NW>_y90>O3H6H0(1~Yu+uUFAeZf1<2&!$e%=3!(qub3<&ZNIHuqg-nn0zJoOd$!^U=k7wzNs%cHO5Sbx4PY0(A5XD0JO zN5m!fi&sOsSmy4Y1&dC6wpYN1**~)b+{PH2RBe8XWOn)d8S^a>KG{RU@OgTt2^h>w(VQZS$LJbZxl@1KU)fr90&cs2YyxnxuOql7H@Se{cxF*IE=*H@^ zbqn7sJKdYM6M6)?9$qyBTu3fwSb-6w4HZCleuJ-|!T{I);bWb{!`#2DBh*TI%@F}b z0yp_Yp1e5qkgjO|htnwCrPHWGEh*HGr;(f4i8dWoDZS^>HOXhU@xm>lVomCbY0>XZf>^nNEWqj0#Cdv@^+!9hDO*1&yiGLZMJ2{= z=7o{%n<^qD^|?hu274eNNVV4-5eSrs_S*m<4;d+Fhp{2ay0M~hVvhp{g9&0vWvr34 zjS`Z$U!Q$xsc>Imusxk*-+*gn5)7adgnFEz{I`1iS!@osZ4gC4<{MA-Zy||@`9BoTE2hq8CdFnT3y92+$O7kQ47h+47$Cg z{rM?%V8hph!>j`Kixq3Cl{Ll-mJTGHVc61popNE0HW%Sa6qI$2@VgeU&TEzr(lW-ksQaW2*Ts<3-FF_KS@ z5k1M6PjwT!-*&RQjqp(cAkrNG+sFYuY?Wp<%cZ6*ehYBxVeN}X{ZjS{_H3R+&FLS& zg_l8j7c3Hcz32m{Cn_&Ti4vKX&c2HSxC+B>xoKDUs1ASn#kUEWBJ0<5rIjVBMwTY- zWKM0OhQFX~8csZS9@zgHn3D5dJ=yW49B(!G)**(ytH0b|sm0!LxNlnF3;$j-*y7n0 z{B?wF75Y;Kc)+#~S%nKzv2`1qS*&ZLX0n%V2aMNFga>{Qs0B>?mS}tu0f-p0Q-qzE zr63YhP!TKf^fWYU7=Tqh9fW?}jY(?dcWff!OZul6-)7u_1pNH8zyDZxk|6PcH2k}2 zyNVQsajNZj0rDrMb->g1^0Pk^P9|`&O|{#xcr6RWTGtwg&4Kg{oy%T_XX&052Y_=T z_TPE=0^W%}2wVj!<()7c4-4wG>Bf$%sqz(w}$endEr_=l4n9X*I1HrUv8uY+(>157;1cu(!rLT z)M#X7mH51+8+5p;A&s3vMeQ#F+_U6nb*%YdB!h$#J1ITKxk__oEgD;EZJagtcs*$0 z-}Ty6?&IHZ-Qf=%-{XO)C(0+5ZHSRgTj&k~u79A^7N~)_?fJmIl==8T8GP`3^xYOd zOX$A8m!U|o`37Y#uoRl1S!y;SdltVQZ0J?ggFVdMH(A4n--s-gycW^DPTggoV@gSv zrqstLy1+Ys53aKE0!CaomT=Fuz?Uk+dRbbVW1`7 z1w??!&6Lj#G#M5W3~hV@yK4)Se*(dOW%GCISb$PWPFp;qhmyjGO?dDSR4yPv|MQDR zz)0C`&}3i_~wRRO_dWwhr=1lmXQ#`pB^Y9!R++LdTO|I*|dKCXJ)@MO#DCu9`w(VF{-eJ6u4PI|-gP1Y!6VyLvu z6V*D08_9h0OD(JDM!wR(!l)Nw!yLLq_&!@c9YbvL52i=PQY&*cgGbImV2_8Qi&=3# z4+ln(3pmUpn7ey}0yy(&oS>C(kIj{(tfIPF{wz2L!==Maj8_Wy#QTgDwpW{XOA^R} zWB`o*Jw!*#8B(T>XkY`cj3dvq$W#CrCrQ=CZA8vkL3}5_&EUW@n{u=f*_=Ab34`g0 zPWMD{a~V9Z$H5Vm1^UVu^T@&7cSZBwyPtkD$s$SeNAMre7btNbITWzF4hYF`e`Ey4 z>)2H22yYzsaTt-~xW4(slF{a*y6p9u)cw8@B^nFgMp=z*Sa*OTmk-6nbc!Sf@LREt zMn{Zn-URW+w*cYR#E|VmOQ8%{K*N(s}zPk{3D0QCw81 zjqyXTD=Q~_1P)2NK%ibP7o}6}>l$%<3#LBUj<>leW`$;p9@^QdnS36HG)W;3cx@0w zUFx2w&iC1~nM0Vol5%m-H39M^qB`{HAiQPb1Hpv)^|G5w8^~Zn}@rfL=~92c)& z_7L?!PDnnVI9YKc?}L21VT1bYhQ=f~_Oo18f{>v?;rzGK4{WQFnH}EM^7mM4?ApGz z4l8A3PyMN1|Gaei9p{&|&Y!+^zfLocrHD1TWhd&`DM{Yqk1qv?-R@e<+oX_muH}u&ccx zH_|88yA@s1>b0F1KQ?%-QqmN5Hi3Lj+S`+R7B5sh_47+4gf*m)L^a%17Pl1+z>K;y zlH@gR2V}2SQ5;0#YXqaH*QaPy*`fv^jayiYeuYFJvSXwC4FIZ$U}NTBG%jM^+Jjez zJI+pg&r1Va>R{{`fYieR2>3PP`S)m)S1a?S5Zj9g=G=NdO$?HujTt*!%^-GAbw^?> zYtu=LlPoSBX3s9EVTc;5!#O()uCq%pl>XJ`0wd>Gc62?bkOy~_Qou?CCB7NGIVJNX zi^yUh$t47J0-HkZ4LE#@zyQNPeo4O7UiZoNy_=?!_~qVDTKvTbi0ZFXfEl)YRxC|0 zn-|`wik@TOZ8BsJ=Lu`vyAu~6N7l&MSh-#+WmwL8Sf5%#v7Y7h{oS~Lkm8-jv*kEf zjUyvh|BHJE-co~-#cMsn`l|svWuR30xMow{{%6zmvz2o5lN17WtFuBzuVupvFeF%( zrQV#2pUZnyADl=%1Z8bpD8foQ?xLh%_wLS|ih9L$Ytq%heLV9@-34CC`_|TN$l^&PVAVsp?9^Ozb5n)6h0HF*^%Mr6etWFCZn$XeT|Rh#91K>3gaIV5tcjp7a1 z<0>@6AAAkP-jzpWg#|9AkYQTNYqEaLga`=S`6dwWR8)Yl@;E&_H-A%GJ@vpu(KXtjt!YTwbhNSEq=N+m(+zH(U=0Dl;sK3{Id| z@5znVC$~UhHtmncbC%0uk6fGgi;s&#z&YK0rE?bLlOsyBhj+?X9t)SEq&GUYAFKz2 z-DS3pDCK1jF|#T({CSA#FmU+dwrG7C093L?3xK&iN1Ta@rFGwv3HNn~zg{9K$UK^2 zJ1(-Z^gtB)883d<%Q+%Pi6D;-LFw{{F5#M9ruvi0|A#+v62$S~AcCzfgX| zP{!J>rU{W6q`-^9)x-!4l86bym^XN_#4B?jrRqi}6^iUN2Oj81;y$ibZnc{2X_`GAef35uB4zs_(E-yhz8{=E;sHWo#}#F zgBUS+2y}S_w@=tqjwk?zcQsq1)l*NvP9^MRa#*<|yE0sbSHrf8JX_DX3 z`L?dtu)fPzevW@SPUfQa%NA8@HgCc34J#jyO6jy7Jo}(ZWnm4V#)payqt$tXeO^O~ z8a!I+e(=AtDy|0SP|%Gnm*4Am&b(8^?C_rSIhgfn)=v^nFWbhjQ(t|pcM+#o!Rvqg z{bSC4$j9ZprJ=s0g6x|TF}O+4)hQZZFycUO6njIY0(S1xe4s(q zIbq%B)%)TEYuOpq1Q)m^D`5Js*R}9ZW}yNQY8pob zI`WBQT&R2J-m=0in&-YHW!v+b#pYh5C12P*_?+NtXqyDp`$2U3iawp>qnq^_4ti^1 zCIVdMaTkKX*19*>SMg9?2H7Fc_QIzPxIG})14-qcpQI@#d-2cF{=dOG)8#E^?&fh#+?7Z|2>_`|=ds`u zgQ4&=Aheta_#=|Ku1f^^{iA7DKRFU2b{B9C9c`>7v3@?|`l_NP@7*T0q-oFq;O{8V zq>B7E)aIk-9E7KV2Rh={q`)fxj5tZ%2tQ!u)SdVI6SO%!K2Sa?da~ZBo5pqcJ|l(1 zgCzXZ!*DY#YQ5lE30KNLAdTTOkh#-HpNrmtWPXz62%c!J6r4BW(y|TCDqU-Cif)oI zSmr%>(E!__?jA_^e467eN@ut=JW#se?o zyEy}bu#&&wF^bjPZ*Bb6%dggV9QCD$7!PMXWs<0nl9_`7@Aum^7{gFO^<;Vi>hsDC5w}d= zxMjhp==*l9r(7f;z!mfolcl-sNdpbN8S(JdlN!iPQvj8r)0_DrP}vjV8%Tm<2 zpC=!(c>3?RD3+_;Q~FLO^P#zz+`3K13)5A%bvqt)Yp6X|%W7u_b8=t)*(oc9T2&nm z{0f+GJ4gjUHcr#U36HUK;qa9`;SIvlL8^;k5J(Eq+M`~ z?WsGbwsMG3#6GEC(MC_NXd}V5CJVbe4VqzD5nkVhT!BxX5`>}=II|Oob#ksRRcUXl zJ)|tm!;0cw$dm&S$4JVF$aX3%oDTG`wR(HK3Pl%(5a`>s&j^YL&OyZV0o};t5|ME0 zdIE?fVlI25v*8Mnz6kWuBa23MVl!V(EedSYOC$v4-bKMitMn~$D*~VR*HXetgs%=e zFM>b20u{)X`8)e#P`so5Ayf~KQ6HrZW%>IdsrTgAgr?*e&cU}@fDXDzg7uOJb4jee zB)18@7yv0nTMu(+6ZGAdR#fToioAEI6+T=eF0&5p1kghex@)>L11jDZ3F1z7!q3Cc ziXlL`HZ0k39y^~V0VN7c%v5d*Av{JE9+eV#iVLNMolg0J-p)+_8)MNhh@hXdrlN*z13Z8n9Eft@G_bB0Xanp@HFL4*G zHP(y7UxtFs#T^R*DQe8`H+6AI*G~57MYSM&qk^q6V;9ASx7~U-QWxk&bGOUeyr>!#PTa>*g-=k!c~p-JFS)A3PW$Lkyqkv7sk%SdAopU;JNPH zZh7*;1L>8-rVfD$DlloZp+m<~;++}##)+7T8$PZrTze36h;^uL0dU)WT2|iG2Of&& zEQFv`Q@$s=k@sw}Zy*zw7e5;BLM_hFwasRhy3MMkG>wnbFL1k7Z-A6gFQT#20CC%t zIT7`RKe}KIoA)xLg&)S&*^y_ARTyCB9j|P7$|cjxU^%6Mb4Z2f3B3z&y#T*Q$}m&E z{c!IO4oJghZZLH&(UM*}`Og*t@MP5w{7VyFW0Bk(*rn-=X=1-%P49kFtJ}Sr^de+ApZBtIZucL32LlD zoG>qRSUqFFSdafsGi|VoRQuSHbKsx}$tuV8HCF~pjyYi%Q*tOEU*tgYwj1w^7n;)# z2`Cl3dO^tn9HDGq*utO0A@z}Mx~%>e1^%xBx+B-4v$7`(*jmBJP@-)m zft)=U%fK-#&E1Elxr{0N#?+a??SsX8zEwp841>_apHh`acdq%kvnlyFPj_vTOR!Qy znN6Lt4b00a)!{ziXOV9Jt(`8z+2KuXl|St5fibyn6%pC$lZMjzn2oGjO)@*qs%PEg z>MMjPBm@$#oG{s$(b$>qnHWyhX;oxV?~aA+(Q||!xBp5b`uf8ggI%)PyvDh1 z>RyU>fo{dzR9PXCs#a%i=)p#z>ByZYKE?H|0zGCu{RuE^%I7}iwd-cO>wcW|LVVT- z+G@+rj{FE<6T5FCZ@adGeCy6BEtD6ZegWoaJNjME<5#l_wx0cDkIQ5gnR8tqU{Xyr zUBw0Bap-S#Z|Iy`0Y%ckj&>0x|K73`mj7ca|LqG0aC>sT>7f+BSMnn6-Clf(XuWu} z=SL&4gnDLob9{R9N=v@NzX-iCxDMldH+`R*esWLl$g(gO8Gv6U1PeA7jEJ^TQ?Wge zYz_Bz1yIWNRHYnJ4lxAUxC<@$>YckI;2D3C1YGlBsO-!2uF*bA+U79S5;pN*RZ8U7Lt^N2O)A)%UK~nBG#6vIaxLvZ_X8TCl` z7nqZZ6hB;M#+UlCs}(9Y1@9k(5CwP8fAKm4v_W#phUNC6UcK3ba(&6D+>XzNn@erb zPFHHupC7OkGe#4D*@SxowobS8U2};>8Rm60&3c0-OyUX*#nuA^-?`C$?w$$X9Mhlw z0^2w6t~BH&tUh=B%<~Wg%ya*4ewlwJe{Fc#NsF-o25#0-y4QT2rL=htHBAfTAS`^&{qGu3~F5W+)8QZA1uUO zcjMW7+=Iraw?wtTKF=Y($YBCpXN} z_J1EQ^VRpNx);}KicykJxpMfE9otc9Ufw2YC_HP-E0GxFYX-cC8bQtS5o=5wtD#bJ zIt6MK)*|CH@R(D>-iSAFDgqjZzpm~Jnpo2A`m@n%?yFb5riPBhpyo@O#w;R76{X*Q z@p-uk^S@e28aL^7KFnDxW6z$vIao|;)V(+iiyInFJn6p;D%MSm1|-nfd71=YBX3sl z0u;wff^pJ?uf%@p$+I&f_CddTK%r~ixPb9D412m2oSr0s+LGoRUSf9GGS{rSpy)q}W88gXt0 zHyWX1{&b5K2qE=!K&P1lbkA1aqi#@rJ?>PSnzh+VQNGrb&Bw&`)o1GZ*Dn5OT>{aNsnbEcCC4rd@SCg>mS-%ll1x)YWLkGGP=a~v({|X zddj$1hxKfm6fVod^kX(NY%w29E1UBNz84bIa#v;LxayjeQI-|fmw3(nlo1PF8x2Rz zsnO=*3pq-Vw)ZuKW-`Hrr2jHWoM>z4ZuRMRK^kORL zu2ZfIdwP9R4y1lW>6HyYq!pAmwR2x~_t{|7u7%Q+V@8?C&^dcNiXX-J4y&6P;0f&x+;69Q0aLF&bc?F%AcCe4zoz^|wN8j0( zx?3#dl1^XlDl(;<|0GY?E$TrB9Tzp4E#1y_O438_1SEk(K6;`{pV;u4Cq{wu;nh`e z^dDizc`$hFHqdgLiYUraJ!+Cx*Kc9Qdr+I0o&KX4p0|=_-+smJq#OL3-2v6yAC}D^ z(S)PrK;#^cme<%R8KO`(4a(UJmI2%Qx0J3z}w9`kh2LPme>e3a;ET8F#xE+R{C@aTEN=<940N;>@0v1$$~b zl_{3B@z{x>#hc7e4n#6-XeHY3J}sS@DiQ^PKp$=2mU4+mLvQu(;Tz)uxyH@-0i8tl&M05}Lf*==49|yMmywf1kS``SsR{{C>ZU|e1_}L9Z>Fsh zRpVZhMSZrjM>=e%X2M@~Oo{&NN`^&{SMg*);%H2U{1p$5$h%)4mEL&bh}MSz6?> zUWasDivO?lPMz(nm$H`S6V(|GJxqRAo5V)iaAL(9iRb}jTT^ZBfelWx?zCRhAzP2M zY?)Aa!n_T?9Bq?#m%&S2S5EeuMYHd^lSz!>6#OcfRN zk8AIGzcd*o7L?Jtozkerk$aS%MxMhUFp(6drOZuB5Rn9@3%|{dW5C*+AtI4A<$&3 zz2!LHJ0>rzpE^F~Rbdck0D&I)kV9hiOskEQero{|h`L+1+z%pn5$}#osp^bwCmno3 z3_Q~Om&&oz8J9%6`ufl;-MMdnduM?5g)M*NNcBY<4YQM|x4>9s|ALr$M}z zuhg_yoCTL$daLdEn{&)%9&}^)7?+N_+zKeADE(I{dK zo5akmWb~5P6g9K*_)ttUPufT>g*Y-4p7iS6Pgy-Fqc1N#2B@zaA)d0Gw&Uk6u$5Rn z%4qtZWtN|(CF@z*1zxk4B2G~t=>oVDe&qbT3tQEjG%3Evk*7U;NfQBZKWNUP7a983 zi#_Itk?{2Y^4Nyc4!?%ooLiAUh%9pRgjC;#?cFL1%{qfwe=BP`Uhvn(oBJ}D@DT>yq2Pzn+eZ3|U6RaUVq@+(op5Bc$G}~Vl zkl;7T9gcJ#T-_LXOhTG_Pf#2wNdn`vwa1W$GqOJNE7^GCZp1X}D&b81%C!oZ;Ue zf}N}Y-vB^C^hfQp;>1_4E-d94Y)<*6xt{tj*v5D8@2;4r#=p9P!4JpO!x)@zgO|~J z?wx_HKm58;k91h`=(;CZ*vZG!YuQU5XwkrddY1Q5?*-p@c^$626IFZ%deG`~NtET3 z?Hpxllm*yHO=;yo_3|8(8M^Ebm}kn_cOx$=Zvm>TQs8UH$hxE4z>TA28@{wMEyfY- z41n30FkIdUq~$x}w<#2$uR5#)E%y1#hFXo+M!c`U7I2k3@BiWm{zq>oe=GIy{D%Ht zT*{gu4ImNkN|D*43;%RVWDB&8MD3g^$^Dr{nqqE90Jv~gs7ouw%F1>P^#?1L^KJ0jcIlTzQ-z(Bz`UlCI+Q zY2b^Qx3X2Rn2#LZ_2AVUXev4$Id~7o`p|6teO$V1RYCZ5G%eku)KlH%JNndUaIg4> z6(LS8t&Meg!aDtjvm#bDNCtG+roiG3x2>n_cCU|IHt2{Tw)c~o39MYF%T~Z?48Sm; z=2g6Q{DLM#t(E?ZnyUrRsX%{OCe2$fMHXOVqfo;w3n?w$&lTXu^2^~} zc>ILsfjuUNNDj*~QQkC-Y0>b8m}?UlI1AOVVa|?VV(qQ-cei@-4ae ziI6QChq{zLXA+~SN~W^H8X0qR1oD|0SJHxrQjf1D^JH4hn|pBy)Gf8X=j{<%DCN~W z&~?WuX-|^ZwQ3#Diw=HyQf$H2-(uVV#p1fJZg=KEt?EJ&SO-DKfX_cQG+M&c@6hr~+@h~oPqi94%@clHwE}&bS62V@+h*Cs za}7;`8EyxTne?(HFP{FX-89&%s`F~WDALd?MY8~e7PT0FI!Exx2T0jU1jEbLl`^Jn z*7Vqgn%U0_*u~}&S71DRnI#TWcMD~}T^~eR)Pg2Vzd>CG!HLOkq}xAJah>{BVF%or z-#WFy!&GE@-iW7mrNC|$aFHv(Kh4>FEwJm`tAqeyV$sY^lNZ~FZp?L$c`HxY1ub_I z03wk|H=o^c6o_{wq$W=4T>6@v`p>SAcH#Gh67U$q{CEd#*~k1_Aer7bKV~_pR@$*z z8DlvV@E$DA0|9eN{%g{Mf)2(XN!P6&404LGytEq9yt|=@nTzz3fvC&(Tn}jOB!8ml zOydoJJJYH=itPd-TtT68zFW&v&tBLVPR%BUz<5M5ogL2WMRq8w^hP}wzn1zeu1wT$ znKkP9@^(qdw{5;=HD^+y)&ABU+#z7stwrATRo=;)S3?@uBfPGc%|l?~^*3X4%nEbX zHumpi{X?@j8_FF80I*O3^dG#Mp>nVkTC#hR!2R?d9B{nQJ0t0i<<1*4C%e-2q3nZIdk5v5AL7U;l<{y>iiHBsMQde~u`%X{6 z>Jq`Qao`P5ZEbhwJ$9y3t4eYgDZJ2q^YAn*OXGR7BioJr1Q_pphD>Z1@!E2_l<8q3 z&g;h&X4@1VcOAF<73Drj%!0OKVkMgqf62T*S?ZZ5wN9Z|dM!1B!i z_Wlvx%-A~HqZMmvLXZv6gVvrKisckGYn00@BQcCPWhfUdK_Ct`)EG+$UP$Ubwsf-X zaDj#VT5i|@xR5~M1KLbi?a0vWee#Owha@pzU?L*$17BE{j?mBByDagKp1jk1xk@zJ z5kLa}FXzs=Xj8TItp2&V z-tf^=3XK^?A85zJ<6k>tN+Pfr#N-|92*&8CJ-rnk@Jd)IR6WLq6*j2gnTg!Y0a)(J z88%!>g{r-Jk_lE^I>yH#YOiVFy|}-rqpH->s?V=e54xL=5-8N*=FzPbh0FW?dhV2o zE;ybGUL*1i1oAh7`%XD2KKnMg&&)5*E6!&$?z+H7xq*e+{>cd^qyzFH?4ejxuV`AE zjFblTfr^cL&CIx5*XFdig2TSdc`1z&7D7ynxww&}VH6ntzuC>7^24Vu)jUhG!%2xi zVfbcF2E-6CjIb=NbKfEPi}HLCI`_P=mEuk}zw@ngos*W$&{AuGYOhhecgJn#Lx16T z@}94r+h*7AOJT*Mt{DC)3L|4AY&r390-QupDkk2AW={x+bJVx4v9Po+B8l=@#Jf zgwiKIxAJiPc8Wpv9jc*)kISh|v~w%VJEwCip1)g#c6C=~z~^U}F!jalz`x6sb*9DY zH)8*(#c9D>cGZZywI>+>S;FYNP)5<86>OfHc?1dFyz%(&dSwUp_u1oRg{!)akN(gy zBJ=J5DnstNLQAp;L(BllXT1?b2%yT2x=vm}bDK?f0$Xe;peb5a?Z_c7AGMCsrci>? zAe<@z(Uw|a$FC+$E>?)oMBSu*vyWYeNw>`0-1vbYsd0`iT~&N=cv|~gVDv)Oj(sO^ z3?MxQl-uqP1AnDB4oEi24!7bTnK^oOzkXno1oJTHT?*IX=cOA@Ap)g29x2?(AsZ=m zo^tnT_u8~ej&OD$-`h1V_!|!-ehHRSPQtP^sZUV z(1-J33ecEFTWX0rz2sZ+JpF0_ybI`{3B%Xs*KquPjqW}P=!)B(t0o6(+20`25`Ca> zI<-q!0qg5R=`neIG}_PEw&$=0E&DK+fG%?*1II%IN}|(_(8U|=K^|?n&|oljq^om- zR3b*j?l;spfvgSPqkHhU0j7GQ-WJI|ZgY%sZox%C)Qnffs&X2J0HmmDfxwfb zYn8ldhW~&n|2IIA8IE4=?Yvo!EnQW27HXGy{k+jNw6mO=2PB|dj?s-u;~Mieu2b3# zk_gO@+cpl>Ya|d&LazR_72r8E_N`M3_>#*zdXH!(+jV`s@O1qjA}EyC8Hqa#Wj9q!GYH>|>1C@UV(be(%J9woXBa!x zX5T2R{wx1s8MD>t4&JnIWZ??umx$eqjkm);7k^AW1m*8P1T8Nmb7C(6eLS}R!`xek zMY(=$!*n+YLklQ^k|I3=NC+w^(k&v=-Q6fiC<1~Eq0-$Uom*0e9>M|XmKb4(@1DWE ze|zueIllKh-tTzhPo=Kwo^`KvuJb(Cbs0)|I;}3h)KR9lud;9*G7_ODa9jUooT>Jf zdR{f|73=So;6K)?Yfzb%-SOyaL4Xam?#^FiOTcvm<;%Q6B92X%Lpm61^hL8gI3RE> zs0br}85re%x(|pPQx;VZN_IlwTRBu858aTP%PT-*hlxWx~}U0ipq z1`UOof86Mo_J^^XO>8LlBnb@p{iu=A^Q6-d&-C$a2(X`Hl#!pv3psDSURY%i=m zU`_*qQWHFzw9y&kvA?=M>5cz8b)HvyH~x^_V*kE$vouU$ug2_AP(h}wwuf84?x0y| zxRhV%ob2OIhX~T`^5IPFki#;aIDBV=h)(k~`c#Mq_rkQ;#K0}5zJ1C+Bxy8y&3^3M zLEEM$jPqRU?WtPPs#e58fxHh@`I}z6=P)b46hl8=)c3K<<>{?$i>p*Mz~EM8H*@`@ zxetg20Va#<#+$S;pujBIEn?4{$}G zfZ-ia_JI+iaORViY4n?Fu0ET*aVy|5k?jcpK2G^dswNBdEr)SpV;-n^DZP|uFyy zF5bK+DxFLJW1z^VWcY1j#ZLmM4fbOj5@S@*?jI2IlUC0M>K{q;u(z#AI{pGmLxK|EmSskYm4tBx1kh zU!>9e%Pgw0zQP1hSRQt@eEvM362206m$cc$Cu8vkJR!8R67RIyYdf{EI^g*AIvN=4 z-9yG&v^tux0gho5jy;Cx7zW`#zE&lgJ^;NI~NDm zcK*)IEda7HB~qguph$eoWftloKmN@)|2B&;aXTa5Hs?*9x`mG4(`m5Y(-Ke+shhsv zS)|YN(d~B|dOGsDJQS6F)RiC!hTUP(LV9F?HIooO#fta6wuhT1x?%^0#>eR`nzR(nY%JSAHxY+$DrZ?<-^3mCO% z5_wZg^sG@L{-_R(j_h7sSAXOc-?LM6CdAOGHw+wcZPr_^6n#2A3qYxjq3Sf0{U^#` zf`b0GFuJkMqoORkAg8?~m&qYSZFBLmTXP*02-94Ejh0Biezy!aMSyp zC&-IB*G#VEU z)1z~>Za}G92%AFp3-N#Q9%a#a^iA(+-H$JYDBx~06jk7ygL1{Sh4w&pj5&Dyt*08P z>BW-46{3c=0@J{t1mupO3tFSvC)`I;m`xzhD$E39@XxwKYRe0Hh@CdzVM&DQ;|JY4^ zOggWig=Ll;-UXb;**3_xd0}7&kx30} z`1N>e7l?ng`Dw|3#n~bAa(4D?BW8ztv(BGOS;K~(*)Hd@cENm@k(X@3-zXiTy*r8J zGyAu-me-IX0GZ3M-vHjPQZ98oSPCloOoz&D^fWK+c z0EYL_1La0%=z(&dy~is^(ZG?OU8Ozu?2X;MOl$cpn%WCC^U9 zrj(RNg~)$fmYMYE-yZk0HXS!>X2;BE-6{ZPwAgC5$^v_uy0rmJ5>lR@C`B{Tow5k8 zZ{i;~)r@o0^O`beb^s_LeJ6Me_mIY!4rU^}Uc63iC4#wRe&WPJEV2xk^Rl)J8@1TI zhn%04HG*&d(sj&o7;|fNUs!u>?5zbh0iWysC_g_T-yaFS?$%Mf12yue*AR73?QYy@ z3Pe=#TkcM&2H+!)-@of`xGuJRIZ*naX_%kH3%meb(#Xj-al(6PzR@30dR)cIzGpS1 zi5Uu5Il2A0X4ZhiB_759cUGnO=8O?km}>q{iwq+_{Y9ZSN%cF7A?I-O>(CLV{(Gwf z^?&D4NDF%GJN63(nKWKWFC21qwy&3Ww^kH*v9A(zDJfk%e#@Ca&$qI^D9mni+VYKZ zUzp{Wg~REcEpdZrp=}*9#A&tMBsQJ>N%E&-|q_MfN50>Rf>UHp0e4JF@HCBM**)cc2$)9c1G zA!E7Q^rugTUE9)=O5-aO@s8jrSR#9GTJ}#nP3`;Azvim2H2*~wt(HuuzuJEu^mpOt zc4X&{JUl;s`Lt!4(#?VV6hMWIM>-ho2g$fXb6)cZHDhfAl(%ylCqTlvr-ZQBtXt}^ zTi~USYxR%>`<*5GJRcgSoftmZZm6K%bHB@6C{LrJpGzF$B4P3Jc81ix`y$9+NJUnB z5Dr|Z+WgAz-(zb2-47Xb3eK1{-xDu^$ zyI^)0m+p8%T1FS>f1^|09(AX1XGZ|J*%uSR-Wn+y!5);Tv$zws8AuEqK?7(}I92hf z(l&NJ>2}L+#eWiEXho{g$TFd?LDF92jc!RQUYhA?Bi^O#q`iE!%a&WZ3yy z61{zWPT#Z3NCcMcV#|-y1p#S_$DabFCk;?SRG6;k9Q4;BegL@O&v|vRu%&0uvE=~$ zN&s)=`}+_$_CjUzJeU9b7*Gfo2R)GBP{CdjG#J}og6XEf723xo|GvtF zsX^09qMjyHM1Mx<@y+~`6KS;27W-*?aPHHhlLdtx`u%-14RLE8@`@+VURb`i_oo*? zLPZGJhOo21_e{8zLq6*Bb6~W7FZL#qqqK#YMYh6*OeVGPU3#_T2U?9440-^ZhSB$b zzu#!T6z?L&DPxQmix$4Rm()fybx6!6qYGmao&dsF_{P_U!XYZ6Ibv+Vntnv1K->xw z35myg`;+#irNH*HScL~W-1hlDv4&3jNdv=xxzDqW@$uhNTjG1qrbO6I4!^w1GfXF} zO9tFM*@4f8qIPdrKTkL&8+bS(I+ha)5nAT5t56eyb^BDeqNlM;9`d=oZuGkoXtovA z0BZ4FF33HTisYC7QMWxV(aUHXaXhShg7qA@mKLm{WwMyzZO*qkJ#PfCUA1m+wa(QaIC;LuXLsjXTQMV8{V}rarIn9(C{MWoZxYI~)f5;a zwhzqhxZgKt%|A3}b!h0pvSmi?8f{sl1z4GV5J&UCeNkZxwNE^}=p`2 z&n{kK8FPc+8O6&oMr&aLnUosck&epGxA~!IWOrp7E~zDQKzrj7o88J_|8L;d@+9pn z$Y1PFWa-cPn}qmVY^;5cX!^(e7S#8?9@;F!TIy>w<#?3!Xf*m`TlV9!`OHakt_78g zfo`>cAfKhR>OsrV#Le*RA@BMeqjzw$L`Ki{7!fu_oTgSpF6shZb$X*r1ZIG)v?Bw4 z34|>zzv*~2zGHWq^$NYcmNS~f{`QYC-&4OEAH`>+p4*pDrs)rnsx_5?S%267wxT&0 zKqCn?lKX%CW%RD|WJ7#FL7~ZGq7|TK7Mc*=Cej3%gQEj#($RVQVl5Q^_AMFw8)n%l zzBcO`p4ef(r7A+_q$_Jlxaa<5St|{%c2yTyQ$R|cEROI}RYi}^&)|MBzVv>Ds37me@IHEh2BymF-PmIt_ow7){SH@@~j2E$co^aL;Bdm*^g?%h< zkmZ01fP!wh=?9@ZC=B}LhRPt_9)M?WUoIL*vcAk_f77S}|_1(|p2o>=rJ>`w1< zVZs%MGd6a8)}s$kev$h}Q_^=im{_d~7I&Shdm`(OLfC)6O9Y*E7Rvyh3mk037O6a3 z1Gsety{Ab0Ks?tRw!=*7HXR+jmaWdlP+F|*{7&VsN%GYfEa2zs)}M{QN@1haL@`VS zTrMX5k}a>A;2i^$ORJt9Dde?Z#dwWl4r{mU7EVXaB7R;qzY*`}26s2D|9TQo!v4(i z*GcV}M=g3--)WNyK4)zQXPy5-UR~n5ouUplc})szEv9$=CCj*3s|6cV`BU}O!&$eO z;e~?SR|WdWfC)kWS}QV{^a6Co5=n7;X#ZDKo-2#!}TyAo!!E%>=wNn^%#1*(?Dz# zBds;GkU2Sc>8i{u2L62%OR0*~>G08cw_il$lz~4m$nG2m|$* zWz|q>^qjGNI-PKqY$^%e{mc^NT`$Pam4_Ig&TzxY=n8qmZlQOh^J&Q-;usz2w1LnT z)5WG6_qwzlm{S(a1AQy*Vy5sVeV5m2(cPkK=FrN3|InJlf1V%fo;x|f0wrIqjBu(8 zqHO6U1f-mlR(|NYK#(37KkGlHlwhH+kW@l?nK4RGn`q`WmTE{AF~; z%D)}juX-x$=e6@wqIM)((_EeK*@>fw=<`gHu97LKCQmy(2Cn?l8kEh6AMUYI?e&L&KBmU! zfpT}>vOjz%`$yn|c|*aTw(#gdUyHoKhb@x z{;tLVr_}$}$(L^NRPX}nlgA*3LW$CcgxY|FREcf)qpAy5qsv<3ynhddsl2k=Y0QxeMxS>9(6x8H5_~gBxz_)eTg%+BXC8ItK zqnP6+44QI>RrRFf3dJerqf$N*D1rw<@#ssDz$i!E(eUu`5Eerj1{;W7PZ!(rTv z?%lVqY;yg^>kA0=dIJTuK7hkZBK!BTvfKtbo(7rLFSYRX8%2SoSnrYq`JBo?Mo6v& zirU*k?%X=K8s7R|wy0?+%50}`SZdwp=o~fn{k!mqF|5?jCT~UlM{2^kZNA|PrPa=g z!9k&lH$xjZHLIWVq_$Irkm4+5dRv~dA_3Dbs?C1>X7A4oiX;yhcaB+Ib&cXq*c!l* zdHkTlSprk*oRw^q?^Er%QNgz}I^sdl6x%X1P}foWa$ccPMP(o)F!tPgyUj5fjkNN{oBT zKOlYaS>0D-0y5^(>OTL5ymv#pX?9pO)00JO$8?^7aCoDB_u#wr=ixI?$A3Qp>kr1N z2qPT%$LZApstipROj%Nqd5Vgo>&F9c#iDN57w7KtE^GgF=8m4duJ)#I&}2I@b7sGK z2lwuUq{e<^Gd;%k=Z9v3 z%9z|)7f0<3TT^UhwH3v}TiIW454HPz@yRfXDfKJd2;`O8`D1zUuw?cG>{t82sTmb$ z_I}?0?zkE<>^+RyDz0TYgt+>UX}pMzE~UN96fB+E%^>+H+R+QQJMo)y2%8mDrk1y1 zSO0Ext@B+Y??*wi?$%o&lLZKyi9kVpE|ZU`N|t!F;m+JT!+jscO8q_jX5Zjq~%_mNQ&UQ}UI7&&8v4Q-G=xbspHOV7H|kXQQ0y zn|T!AGGkrhQm2-=_h!3}3-0vkULWoV>FE#O!ch?k|a zJ(K2g`f_J>fYrCWXHaytYQBH$c{6TTT(J0rawJopUd`|PE>E07Mc~=liB!6L(YQjbCNszG$hOVM{_oy>y2hidKB9v8u10Q>khru zAFAdct%7V*1UqV2L z^s|4JcJmFHFqz%0Zz*nMZ#yJ96SI}IQOGidO=6YS+FkV@cZr-B=MIY8;2X0@124!h zJgAk)J;QQEbgMDNlV0cnm=@PA`Z+YaPx~4zW%6|KwV*FPCLifDkdJ%MT%UMPw|b`A zjkmJS9&R57xExrQw1L&fQE=O{?BQSc=Q)%Ew;7?HPtXabIv$;ZYkUhWQ1@keyL5yI zfg^R=DPhy0-1x7v$t_5DtlEj?`M%k@eDZTubyFjnWC~aZv*lC(s_xOp^kWo z9UDSyfg)nS|5kxNHoCz_X#wYt$tk9fz0D*>ZJsS!`GWk)fbB|g1&CLF(Fzz-xyD84 zYThP9K;;>ne_r0|YoemUoBf_+!J~3C4+sv4`gu#cQSUQtMFqkKx~P7}$qODjzi737oAFU`FdR68%Z*6i2_PRK;b^gVIGKPgAzirnTj?DlbWE@W_ z4z;{;tMW~3Ki~;v(FcT9D?lSiB z{2*y?b!0iwX8=*Hntt&g%^b3Pt1(4>XXz^RUSbv^G~ulpWEE-yac`Xs>FFocR83 zG^^L+7A;{%I`UMbN_%MI-6(L3-siatLjQX;5RZ`I-geAi4iKd@QB+jah()YPx^}_x zT{tQO;;EsY{HMQ0q1sm~f4(n8h*8`4N1MW3J7bVC2>=+iXCYiFP z&W|21N9urcDhYB!rQdPQlkBTYmXVGwe23_?n(`wbW}>Tnm8V+fyHZaU9VeC+O2I<| z_eQ0F1wJg$M(q8(RQ;NX zLl$TPz~R7rD#(~OLgaf<>Ar%8KKb*IXGJm)4H4BXwe&B?R9~35#>P;VdU6E9l{a1F zn0%->+ddbYYWS0yrk299t3WN4!h`O^OyY;%*C%(b+a^Vok2(9WVY$Z{q+T_{XFVKI zP|;7WqwsN;3Z*;$`76LT>xzm$HbSZ2FI$nxm#Rbg(NWPpVxnogD$W<$d=V%r;T$8ifh0S5Z z!EB)V?Icu9yN)9JtS-|q=8X_o^z6_kwW!#i0N{=2-SMBbw`)1Vy198o@gonND=iZf z{wuywGM3!|hjT$L0gk~D!RQ*%qqyX|wp(<1ti#`^`NZco#ter1d4ecri+WI^t1~5cNwU!$I^3C&X%6uoYC6P1N z+#*N;op3>{wGVq|0tdrm%Dn-4tNB+jS)#xG-EKASk5M=8j(eZ|d-(s3XxiLY$eUHu zk$$^pH;~}1rck%PFpWmlV3R@-J&EWhq}rV98ejkPTvE6@=Z|LF&t_pmXQny#q`F7n zQYFWjvsfgLb0#;lSq@c3tu`8_8j^f?EM6N_rk;q8*qP80^e2+;VD}w89@%I^V7BSG zeC{`vwE@aAg`G4%M!n;#PZO*N<&R;LeL4jsR>}#B!~f}2YxWP(l076V<+ey z!iHL~6Xq;JX!bt6yel4whVFCPtN>y_*j!9Ilp0)kx=%DsAiKY2*5K?**qqkE z+y4WpZUbo9Hx2}qQD%yf>mbpi%pSf`?yv43Ip;>MQ5X2jX8Knf2>PuANCJ-~RDMcw zmxf9LWsoE=b)5bVZvvSEk+vK!sXEn@MBSKMgK)NJFWd-)9YW2aNKIVa9=Uciir$em zx>8UZD3z)<-dXD^tC6N!^UzPK+Sy8;FShMGA1r9G=?%HkCpFuPJ%^ZL5<^8z2`bU0 z@+yGqEU_#Iqt_`>MH3O>Ni<&=IZbao46vOs4hus;YVW<8kX5?lp7pdQh?oCYkxpAY z8H5So2tJeTjYR5?Ye^||`6#e9t)t=el;@|E z=Z8i=4`qD`a>GR)B$VpbY>o}Z5hjeuhUzNpWl+Di-6W^yDmo!d;=TGQTnHE-Yd9s0 z4Yr9^b4pdHnPH>|^e2B5-U6T!A)zZXf3O@o66FFY)$5p&58H;22sUOa`qP_8nV07} z$0zdEbJ?k=xuTWbk5L91?nPsmqR=y+t|k*(!K4OpLW^Wwun z(*A78)VP9NJnESfd)|z4K-rq3_wB!J@KDXalx6s(3qRP!k3c4fRILLxakTp&UHlD z4Z<(f8kY8zsQ}$_eiF!Bgb=oHs8_>!_%8j5@Gyx6DZq%FK5M=h38Ol99pZY`AZRX_ z!Y5$aRI4xN5qlH7mA|CR99MQ1!-qs`Uh*M_EUIHZ`n&5F%)cp^B2$R1e$A&wq11@` zqO#f(et&@-7sbKr00~3rgdt&$p)LD-_a}#*L(1&MYJ?JG{GDPAw6<=r-Xe0UWmNZA z^)>Y$g2mZQ=|nYOe3d=&Pq(dI;~x*0-;`RBk@~b^6Ms@e2HPK(UTa*=n{Tx?A@y|y zQWU4YWh33(!#q@>ogQa~m7dh=O@t7py^TK`83VtN%F+vx;l;2mCup_>fFs}HZr3vF zb>Lw=wdA4RtiH>|dOtOVNTbT7^T)-Q;?KggJH>k5(+2%n!(Y%fUAB9Iq5)Hy9e$Xax`0Z;whw|36 z`8r!or7K)~pc)VUruA}WD4SnPlPzk)ZGN-)EEcs|z3V=2dgi$U$x8Fn=Wo@PDmyMf z?!21_g#s)>Bhh%OKm_vJntoGy=jBI#q@YJ_xRrg~+0c7hVq$~^T3#{0t~HSNmt0et zU$WZ(>*Y;wN#@)Og=%jGwJMQn-{f$NYA!~ET%DBuIyrXTGnCB1%os~oX zV1W3k*(_A(G=9|k-pOe2S>t>_m6w3^jB;LNUckE7s`MvRn%U|(g&D z4q#vJX&R|wh@5vJg949VCEGY9md{f!yeO2zXMNyHzG$w773g%vD(AR%SDEx*Sxo49 zGZ_fY8muI+|A#J7@rXx4sbyFV5mf+h;WNV-$$tjKZX=X|LPNUDN{_XXdtpanUO^Q7 zxY40>9SkW6oJ4=|IAVL=vJ4+0iKe6!Cth6k%xM-V6lqh^(oewymeNVaCq`Y)YA)uJ zEp5-Oqn2i(61YAZa&8=ebBJX&=|xBHD&$BvR~qVpwW;Ur#Jj# z0qaqHztSU;a7-m;`|xKa4$3mUN@XiT_&ucCIrwSQI`94K>cgja#*CTUen(zxfv> z*o#a$a}VR;X1`hlTWLg|iNogSWT0RiH9C1_xUnBLIF&~_P1NvccezZTvR^&8c8N}JTr!LI*&5yBp8k-dAOrPabx=@^H9D`kljxC| zlc^HHmFsyD;`sBmNM6zGXLqy-nK$nFdfUGq7IwKZ5Q5$Lc(=2few0onQY@S|D+&Jw zQH6?vgsT^kgW9_%>$g%PLqZC^t1b5}Y#p;u)>hfQ_Q~L2o2Ke#Qn8Nqo*gU&0#K`e zR&!&Lsd)N1aPl3tbaVpN=56qwUVvQK)-iC;9s|vz2RzpG6z{VxsgSb!Htl64`GLQh z2M?uNmJfI7c&rujL$EEgzTbd1QyRs?Z>WO3Azs^4$$s7*14Ck-CjB?aHNNh&Ou>8C zkXl~No*VNY0&lk2Q*)H#5#ZwDT3CXt;T%iZc7X+`x(&l09QI8P!u-A@euH`biVH?6C@SKivnFSwE~c#+8Cib+DNaIDh>$x; z`re(x>;a6(z?M_-;j|lo(<3;6!)Eb5rR+b-Q%rvCogNwgYFVvljcRg=Gy7HHmlBV( zmosCy{E*h!8a*KkvIz%Ih_UfH|RBZKY3tCSYOMr7}9k|Q>z5BKoEuq4BDz*0-O!H}pP&V=%gv5vR@ zEmGq*$M7Ac+Zev%T_b?o03M>hn*^=C)UWAGRgX-$R&-hvrbmHqu~#WYw^f+)67#ag zzWz)<`uy)SNKUQLQ*Gw`!yHFk?GDE4D%LWiw%b34JOO&9-gwnfly07p;}21+SKWPu z^n)V!ACsui(`_j+bHu5U`TVEeS;^9!?eS%I0Xkwl#;oy;)~2@Gk|lIlc+WxqLC2jdrxIoBOpi%@m;i(lxfKJt$zH|R z-dB_LF__mxRhvAc?0hJ^0GPeW+<3tixrMa9L?-4=h+gd>uexVOq_Ri#PDe*BUjjyv zY1@%`koCH{)XkxsPaA)OCcK!B@FhB1ezlsp_a_dyg`K5%$ys#SV3Z$iKHUZ*=v7Uc zbNee%K<^#G+xu6}kthSJ#3wLMyXhUl&8fZ@Cly!!ch6&j7myr#jr zv)mHQs<%}{|K6A{EPWlMgMPJ2#8}M2`h+>o#+)~4Vn(7Y(}gBD^h3JpzK_XY|BXjN z&_a-oQ6XuVL2A~Q6e%>K3lCrXl{yr|Wh-D|Fel{=Tgw--dX#DUa!khFx*Dn{mTm}A zVQ&%dDb7E76L%$C+=#%Dbz*}r9N=yl z8zPO=-M{0KNB^J(B6c6=aj8hkH@@*$9m~`p(cll4R&YIhLS&J6LOsLU9wZ!bsg z7&dM+`!br7Z;-EQ?}xlFH-#6e3qK-xQ*0Ylw(G9BF-3~yLu92AyAd(OtywhfWiqU+ zFJ!x6=s9K~4u%~0dyO4Uth7w|p%{^0KSgfsj5#6aI$gIdYEISHJ}>9ZwOX5!`u=-s z)kGynBQz5HUg1a`o=y*ESo1Md)a55D5%obROj5suqIc#s z?VQLo8fnImjc<9?!eIO;_u5BVjtSn}((rO)yhWla_cx{|=Mp!X_$7`m65gC9(cmJ@mEJJMQ(@qJ_7xPu&+(r4(d=Tgb+`sxbXd6N z$5%l0aftymf}-8(4PR3U@Yd&K6OZRa8u60+8RnoXZq^mX> zk+#rQ9uV?%h@!uNl0#Xg=AP7}@()|WO;$5(ENm>kn@%{%om=*lfJ_6|QwUt*iIB0K zJVzLo(sN4H67=;XZy+C zHk4K`<(k*YN_wt}al~3i2i)Yi^|h1Xc^O;a&*qOYTFRsaw-3WXXJmvyHZcjz})zd>gYby2)WvslXH(I7Vh5|-c(i|t6%+B!mti!#J z6_%cmOwjG>-jeh%-6x%GHJQj!rS7%a4+^bF{P#Tjl#8upHxkKF@Yh(wcj!|!A`4%gL7wIn1wl9%lC_>Pys$t0y&>8tjD zG|)lmuyeJGC7!={qB1vCzKJ;5J-4(^+KcSzEDTC}ZRO zG7vd9C!^jP-?&j@bisD0jr}Z!DCD{j2m~Tx?v#L2@KT!WKSVzsPC!0#h_U%<`H!bF z7@n6hdgYO+=5G{o*&CRgDKG%VMWlWA056^uS~~z&QB}MT{SR-Z= z29E(f-7Y+;ftLE~;3ZXAdVX2fF-6`z<1#8`&=Ls1U!oPmjmtl>hxxYKf5(n5F(@Jh zqrCj7lKQW50ttc)6V|_5gayp%tS$kQ`em|bZ;XzP76`)>MUTsc{2EaLU=8EnF;_Qc z?fw79m!|Hsda~Ec-r%y>^NLyAQJVSxk_S^Cv3tJ+R>;*S<><(za_!8nOlZ9><2rhY>F zWC3VB8u$0GfZhg+egc@fC*@>XOGKmrbKCIvespKdhSBT(3{QxO_xh7sk_R4<1v>co z>W`px7vqcD;dy>c9q1tD`g`<^RS{`m(8NvZkaF3p#JS98#Cr)e! znXfq5q|VN-HIjpB;LDKbnmdsNNGK_O&l_)^T8Mxm2Pasax~#(jcpD%5{hd1G>wvk& zB^GyRiSuf43lKzN3%~!s^DxQk#qId-AObRxwgt+fghx-RH*F2OJg*owiqKV5y;Ja* zq7{vYq?RCfN34fnI!$Dv_Zsc}sLReBL;0jr} z-5TbDq(@8fg8twxPhJsD5c{kZZGe81t9JiLIY0}XCNCG=ew)sO!mKPJi8ER_bJ(kv zPN~!QBXDD6&2IHv=e|oPEZ6fo4|W!CbRM3wjzizYX$buvKx8OiijsetJY?-#<$gTI zE@a6Y$&c*SgJ|XH_hu@E?md5b?G|(B@K(alpd0-bsN8soGG9;nDuk;_b3}bx$nInF zdZst?QuaZv-jjhw-i0E3Kh-o~oSs7Yg0F$RriaPKUw@}Ms0>)C=G$kBHX%ChcXNiR zHs;5mxYMO4>fEOvrNR6jjqepaYU*LGW?|DgkNi+Pi4sLfG9i!z3Ua@WKK8X{p;dc+ zvga9GUpL0Q0sGz}wSN)GtF3&j2Ld1^Mfa`0=je3}P^MaD`4EE`ZcQ>S*8acm057FGvI!s*8O@MdlQW44~Er6QB9 zo7#$83}0sO%7=Ig0>vmTq-z$bsK1V3)bRg13rGEn-N(bq6kNW@R0*S# zPR{z-)Kk=Oyiy+MCHDJz`@m-7t7P_lcRhx1Z7e~bMmE@as0;~y>-BJQjZDQC?`|M^M9ALO(5lj_ z7-Ne%u4)-x15qqmHIarV2V0T$Ap%*yG*I%g^6by-K5p~8qG}gvzfyuu4C8*dA}gBS3%;zU4UnB_=Ui^aUjCY>6`qI2UUeA7^3!D9xp%R^eoIi z+c*Yp3LA3mJ8^tDB?2zVB@oKC_dBx|9mLMCc%lO%;Bkun$`j00C@ZZ+u}ZghQ^i3` zk>aCxQAe9S*>z==iQ{Zi#5G80hfcWxXL^3gT;9?^Shd2BC6+m*4sCKeVX!u5{-;Jb z!Uo-6N2Ie=NyQ*;F~d|91S2(TG$om(ci%AL_(kiy0gP58%OgHSM&#nyl|#a$v_Cc% z9w?d-|D$y4dN;Pd3#?q5H5mF1Fmq2Bl!(2E;^QH@1J`%_%y5z{!u};wfva<}a4;iH!{Q;a z-TRXGE0TbkuD9PVvsO)_s7Q&{OQ~xx7{i^h?g})m96||9LF^k(76G1~n=fFgsAb>P z7N{QxMDRZMak-PXZN$c|x?m*Wq>Vfq{v{y9+&N=gHBu=Qu=R_Ur-HTe87)3yxQOcK zDl~5_?q>l$<3M7!Kv!YZimA8nyA~_2~kJfd}D6Emd!@=_aVI$Wt^xdtBf}A?niHJ@fdmvwIj^H@DAfna z<&dcsl7O9Eci6s5&5p14%}~((vA^|0Y2SyoAGwG-L2Yz6Pio!~#D+u}G=RksrG8$u zaAL7TmXJFfY7OsDhYLV*&3IC*Dq&H}3cW|K>g8Dv_@Fzr6h1btC$8gRvy_p%tg675 zo-vdpZB!AC=^?TwMyMvZPRdXRT*pLlkv3an;OU;S<4ipob;5@{VF(+xj@yNjYT_K0 zkrj8$Q$1_?v|$MWS@h7zz7VcX7~X|+0e#W!V%~8rvqW=n8s{HUG#brqn$d$e_tWoL zph2p=ePc#RW)D*bQtXrG;1B z#M|%^G{$_10dE=tMOh%G*!NBH)=_>c-CSSHzE%!A&LS3E>$h&NdPlO zG-ZpOkM0IDsd;$^>L%2xxYVsE6DPQMo1eCD9 znNezX-R+o(c$`9~95uQqb1-zW$MDOm!FlwTnUEh{Iqc|-F}JRLfLa6^k0FLO!1G! zzSuobQ8GS^yz~A{XC5%nLP;@sW4%EZ)3O2o67`L1doA>;FeSH6dXF337j~fGry&H6 z>85UV?pEI$2F6umL&BvU^`8U3W0mpprGRc>I<>d|iz~WG`f#S~qF~T5DG=bjF%Ch; z{bswz`zuw`|A1oXPBO=CzgPBrFQ9>^SEJIn#(s>4!qQk zbItd}m+ud@uy^WUB;*aBdn;~1SIWqL+TE2tZy0SrsF|9;k2SV zvXuON<{>5awfo@cRpA42jf>OPW$*oE^0@(#({~8oV7oJjI?%wCUnT^&_v*<>hjvC> zc6c3`s_4rpqS^y01}wmHP8TlSoddK{F$K8UJu30)$Bj4-UYKjm+q~!=4JqhJXUpy; z3%O$vPy5vBP-My;r}qxx-f>6(cDFr|O`{4^e9%+4d&u!*sI&Z!jZ9&4kXY{VIonYO z%yi|hVtlrl_lfoA0cC8#}c#x>HqY z?U8p!`*N^q^^XkQ@2ULUaxOCtCt@LX6Ka#w2Lz)Ah9_(t$!yCEYdQLyF4sR#9T8vI z!*ijK6QoihMd(6PEOV|!_8(LOPIx#?uEpamsKAIZ)Up#cR?+oy=ixPIFw@S2Ql91H zQ8oQjv8^Jxr=-7LMM!5m0EYdWu~lQkM3beVHfl$a7fw-m0mEU@Y@J^b1>L*uOH%(> z@mKanObdEotslkp+-oi`u^&omkqI!jd7B7b>V)?*iLB)b7xJ)o{Zc2t_7R%BmsL)~F6xZmVpK!*v?vwv3JG;ip8bw6@g& zJN6NI&FEd@0&$PQj4Qu~C~ks9Re`IxI@*7j1rb^c1-s(L-k^;I>oh;p=`4yF3AF$@ zzor@CjqC_sivm5s#dV6LVRD-fx9GEq?`RIIjkLE~kkgmR{R1yKKO#@6+j&;Oj7IpI(;kxsqVHlaE&W=yx={wFy>j!x0#9DP7uyb^{BAmTXlu!HTFZcsd@cE9D z!Q0@oK_~OGqq<+rNOp?Id`vIw_W!#-(|+rEKgXcJ=YT$>uIP~L+hIo-g-QqYl^DyYN1n3g%m zst|+Mf*`H75b#zIo8kee(HDAtJa4wpYMB1LditE;Vk`5U!4Ke10AN4;+Y4dfZL3ss ztn`pCSB9^G3>6-(Pf+}(*f(IA0(k9nZ~)5(aC3*nV}+yscQGLrZMFuYXGyz{1#wiQ zJGR+8q(ZAb6{cxy?u7H>&Dih<^D%%7DRLRHX1RdvDhmvR5c{RooX0{@LW5@uf_f-(!*T^IDjv)UqWEhip~7~)tufD>&bJ^;Az(P zm~A!!vL{g4$J~fCV$fX+)f`=w(#vkXaKUxN+HE1=cx#I|cRmXcH(94*d0(OgZ~&7H z@kMads!yZLW69o0`h;z7YvBT#{kG65!Qw!m6 z`_+haHM$@9^xNzBI0g|fZ$^Ke5k5?v%V1hlksn=gVCACnD9Y|IWF?-fsvthe@xJ;4_i)v%#I+_={ihV@E&Dc2V=KT|sB*t=;n%u$?_r zkWa(mbgMYoyfvE6b5Fml26>bkqR&dPJE_K=+-q}Ha<}xO&<3y`Na!P_1}NbJ9<5cI zJFb3@?KW&YjEx<-jvx7`q!a$&MT4N78&nqpo)vYS4C)Ef$%U+Snw0KHh8#XrB6i3R_&v<%rfXyRJd2RIhSLXmg zcL<;70*h|t9^YfX3QS&B@$$jssd%D2noppF)R4%Y-Gku^+6xEk{FcKY|FEEU!+RPR zi>;evhzs)b?ZHg6=Z%^g3!SXo+h72dE@L7<^$AS&@cRh&pI!iEY_Qc6A$JzWOQa~ zkuzBHO{ANoOcoy}VMpoMCk!U-BwG8KlVTHEQIr)f!2+chA=5F^n293Rz`jb!O6IxU z8i@H|oxB@s41%JZ&YMU#ocD)dXZj2=v4@z1qdW}1$2LY-#Pc*G0r%5jNiEPkHCVJ+1~cN zWv)d&Mm|98$5MQyO9e;xqU#3uP3NVP+9DB)_rEZ(HDA5OQJ=lFf8xDrDxiLnwCWc_ zPM4d0xmX|DKQu^XPcs}$-}yvx;(BGCaX8!e?jQ?ofBqjgrbdRgf%>cy8oiFXWyr@9 zrxBU+l(nV4^2X_fHU9k-sDD3IFd~}bsn%Bhv9;dZn5o&MT@c?_oOS0l#J}!QQO#-S zz1McsuT;-)00GHkVmW2 z4(0DUjKo5ocBFX?mkg0Vs82dv;!$!d4}dI7JsX>;%+#u^aWLY0uKP*aCwsg^9GCHR zk|`sHz$-%my^=qyHC^UeLJAtYR06ZUc+yP)rRy#?w$ZI&OwC|S`(kA;)|IEOiI2pw1P3E%z zgw)lHBBMQJrk>SKKXCX6RvGEt6I^14w{DM>1J~OmqgF~Fv+1z*&US;9jAx~}oHXa< zr(F}i%e<>KxfsW9GDM69vJHR(m}gHJ4*1J|4A7&0t7{{K3a-CgGUC>bYlfdy#o=)H zUR9aNX>`O6FeBLh%b24+d~#QUSpB}BBUlgrPa+`+I1P%(i3L(f)?;yfLvlUmTd#@# z0Ud!r=+>WZi{sx}gr^+(pG*~rV@TiK;{_tCzyQk#)W59&h#T3SR(;8J|6n%GWNo8M zW*Xstz8FHwJ-|lSo1T7^n?CNp^;+x7|Q+!6(!y}HrW^ov&-`k_`L$%IpmYO^&ieNI%LA4%CO)n4>Jw<`xC)91-AG0t-RG{b@{x7I5Jxfd#x( z6`&A?{tzGiOkgcjD80~ho!GrKSx>dUsOmp;lvk--v6IP;D%%oxB%~-2}efu^J|K-PT1D*Tsu4fW(nuntwCdqoj zB(_tRNhB7TgUu__e*14({dOi>ShbHbP8IMm;F8LBf9DeA{{RL4n^F7@wsgj@*oU@Z z{3gf=c#7Z8**mxs*Jsa_4pgF0XatHhLL_h=?$=>jZ=oq^y?YBF=Tw}D-&YEqP^2xy zWe$N)$mpj%w}E6u}0$~}j19#^x&RNdyz5g8ACF|okITwuiELAs+b_y2LX;cNl% z*r3ObVQzT)li$ksd$Rfm)Lg?(_ugWO0n(9&{N;7wa3K|QfGBwMFt4sY;A!o^VyYLrISxQ_4(GORxfxMjQ%m1NZ9fHRwPPw@WOnLH`4F~fpyK>IjANMr()xu z-sFy*OcY0($u$6e+&+c3e=;=-R`U&f`O{s!H!m26^BkXhT${2V#?O^Qx6i1;1tY~A z*XBBGA7QnR*{n}K5S)1!2=6_OFhLnRoEgvfF%NL~@^1_rfm;k*0nVF=Ro3{tt6+Oh z&N-`zf^HlmfLuvZQ`e$$;j_0JmMa>o;hCh*&wLA1J@4tQvVvBzIx^(-%DQ^am|~l+vC&qi7mzv-yN+Q-6OsSx;sLOGF5^`LW!4g zkr$&ZaHH4ogl6C=F!rOi)!xS(qfYlKxLt_4COCdI?#Hz}{0(S;c<{wK-*-AC9vp*V zTx+85E(Y@B*CDSe8t;@N$%Ye{DW8m#)njARy*K4(WfNB{-Y(v4s>v!u*AaXkClV`C z@$^(9eTYyaoD8Dl(GlDI6x|4%!aUgMQ~(y)vbNd}tUu(vUm;1lwx%9~IajNAxi(>Z za&?ud)|D+J&R zuMt+BS0KlxLS*&Msmi3cBlEWL_OBXiY7;I@bo;d(r>Nr~u>9U0@GWJ$WyLkS0!&Kl zWedGD9yhvYEZM!OqW&r-Q>&{6wSI{=e2C0bYmoj?!hM55^xoXbsjVVpf%i)6x!NS; zHxKJT0uCv^*}=Suga(An!YzV_2{`;N3+V2;82_5H`f(1t=vn;SflwoHpT+UpX-B1r zjha6Y#{NM#6V&}^k)Y5NY~8nz+l~utzTfw_Op_L*tPBFt{qmrk8l+beHRhi#4AmW@^bVhC{NQ zg5Q>GkM_(V?T4hACPgvn)wC&}-x}-Gg+$zg_Y=Dug)d3*{buE+eMZ)3@9&l`t?Ve* zUZ3-eARtx&;WLd=h86}ksFGOsNgl*w3tVcxWTYhc;LaY4UhIuFp$u$Y{;RHvlvp&l z78|$hw1Zn)U%e1Dh?!hWJ(%m?|HD(bu3oIi;O?AynL8XeK8dOE@FXB#NbAD?*nKIA zU8dQQ_AC1F5!kSF+!|>kwVWi3Bx6>KY+S=})7O@*L3glPb*3oCd#S39cyFmcz)gfk z=mu7#lHY|VGVb(r#f~e@7|Q?6T1|45i3~Jo4N`vL%;8f2+&jpKx7SfwZGgJ?KfF@=6qS3~cq!M8={ zIgmat9qa$V!WoJ;J1kQRPuOENFZ!u7FU$6~ZEg{}nx_GMFDARb%{*S0d;>Vz^}(3K zg1E_Sj8r7}%#B~$;S2q&>lRT4%7JP4TsRGB&F7SU*dfV83Iqamzi;D`No2Q2)PoFUV>$aYV05jW# zN_!r5#@7s{61=Z_pC|O{3p=6P#ZyNenpEITigEUtBat=Vi@DQ&bg=|ya0E~BE9~E> zGr4bSa5-;BtLIq7_=Z-$t{IC5^#M-M^>F}SONP{J;u#Uu)CZl= z%jhf9Ncb>jxMa{b+YMUF~#uX=~ zm4lJl{sLd*`Q~&&;55)bAA?FY2ox_h#R&qny*nJ0-3SC~XQ7Ne`{?&BfsJ>*2|NCU zt>iSjQ8IgPY=xzlCS1)RhFjmLCbPur4lf8aeG7IR^f~D*9Q3^9vG;d3RBdj5f223- z{_whEc4c+$w=&*0nxUr8z~>qD4UGDiK4gCSJ~yxkdphEsZ-dXxHRdQ|S=Kj&@obgE+nR?vO$NzfCCORC2vB0p|s`wto|Zt6E*n)muttuI3ZFE;=5|;&?T@gQHG=BchXoSzz^+JpT3c zUAuOhlhr1?Io&X5jdm6AIPRSysYOTAO)5-IEQIF~QB5~*A>2Q9zn>+HT=M@0WwkYF(xdsp13aD-q^knFYOc~e>)xVG(AT`g!c|AZ zo+TT-j=BXxW20X0N73I7ZEFprWQqXzK+AT zUl~;;>XcPiXEhZzjjS#$(Zv+@m+FNdpVGgz06b;v>=;vzXrXq0B~G^D1bsQ?%OK!A zZVhep)w%uy;@-)I9%iaQiFfdpX|7SwjPQnBrNM2)#ciH7*=^WWNVDPwIp6( zuqD(L=I4BeBJz6jF`rVmrUD)A8rfq|nd>o-0%J_y$F1H^IU@zUD`mGiqbsViw&ecg z>`r!8NHkbEURjaZp`qt-+#2TxVH$K;7$_5o!F>JTgd+tG&V*;$e9)e=8P{iot zqDr;?dTvk&e~4Hb!$-fBCDZt*jOR)*+7HSy8H@HFT{! zqSnz0V;{%^2Zn9gW4!ao zb>6RG4v>NBiensx?=0)b8A~75c(@k$?0U*p><>&}&v%~%i{vhIK~|qtu$7gIYE}1$ zO*<0;6`35wgkZE10g@ImHWB@dYvWfOJ(_ojXfP0d!Ft3NJOdpxVm3*2w$NH+Frjr{)r_g>8|IX}uwZEj$hAV${T((ESr+#h=%&zP}VlCm$?# zo|M1_5v9S+>LF3=E9K;JZOAkUiphzA=<;Syt>(-cg;>g56?0wDHnIC*NJ47&%*|zq ziix?|OI2IkpG<%cbgzW7s*0WKsk=Ye##D{36mhNntK@otPkjtwr-((yj|W9o0N1n7 zi_C~8gDq7_VIoGn5VyR=R(l5)>1^9(T^g&?2w7a&)efP$@-lXWvn-%eAh@x?14)sX zb1P1FyEsZ$#=H0AHg?*_Vi8Q4#f-_;?+XB~X6yI1^t%w8R1@YFAoiFsZKhNH0+xJYun&XRTxlxFG@@%R%YVBtVK?0_jT6tZGe z71`ljpZtI_vL@Rr#~7?ot(LMZ%W>`<^eeL8Ec<`JBKQBdvB*`dSG@XvU=d8vbt7&> zo-4pU0|OA`0Fw8?LT<6>-Z%{4_*a4v*Xz&VoW94WQOVicE{`M(3=EFqDhj7!AasLy zK_!o=Y8?rtng!Z`I2vI%V%+>48<3!Q$$tY3y1u--Vu~()8vFT8pW$=fxD)AtDBSo# z@IYSSt8EKnO-JwmS7GJfth&Dc5*Gk@eBODmYXIBBg+3QVe`Y6)l)-!w!@aSw?ujCh zR*RT6rrf^O4K>yTbauE#(EKEOP_$VMUY@&}l(U39lX9I9rL z8#*0fhGYMCSTvEg+l7-Jh{GoOQzyIbuKOTK?k+w*4sKJRP`$!65U4~Rz$S)w-+8ch zNxfF7xjhaAZ~I-QAeG6Ca{z*)U?M)osl`QLT2GES{cDEj@td0fBYl1$zIYt;WE=SP zMM$8hw>L01-TS{y^C4J@0?>H={0FN|q}_nQC>ZVP#ed-1^PY>Usu2LLIrsJ_2s{g_ zeD)R&2d4MpWW#SWZRqU<=Je(G)W4>epa;AlUJPcl@)agpk+L{XBh#<%B5%SDOuh38 zFvJVljhZJWyQ4LGbBL67=$+Q=|FZcnLM)d&_wwN0^HBlMZV`zic7DG5B4Qq!QON;c z9mhrno05+$QwVAG5}4nYo4ZDz5jqIRE~#LZ>RNzKX)hEH_p!IJmwm4#C2cEZ-`Zr9 z|8`Dhm>kYldVq-)MNgXJ-`+xzlYv!=Q&D#4s={6q>z0Su9P2}NBhqRhVlzx8ye{RC zy28rfjxoQi`xx_@rLg0hTfJnsS6-oT6mQmxg|Xr5Fj5k|EMEBcAW9e;DxU8NBPy>GxqL$t11Bl+xvS z5>gZg1+Tf8kRe_E*bAk*rI}Vxv$ZjHrH%ianGE9A5>+PhV6zj*%1hxVz4<>fHAzRzcP$BNb7ZoO*Rz*x^<+-5@v&I$A-?a$vN>4mJ& z*1JIjY$;jwLR#1loNdW29zQrX)}!iv;S|cr)`ZF9RDQ_>yYV4OPyQ~yJdukkwXg+t z|KI`tbvV=>^*$q3l(7!6tLx~y|8yr2H8e;j5oYhnrtl@T{Wn#rJ&+udvJFtV5S$(c~?+KQSh zG$v2vj8~SVJCeNR$+p~fh-(GJ&g5C~pIb-TCQEBiVP*|Uw)Vd(VqhDkY-h14HXBjy z2V>a5xw;4{aEmEa4dh_ui~3hM%3NnB_Ey?`*r#*+7+{ALIMRuh52oGCb& zPm;X*5=kT#eitK&6FBbKC}4Nef$P;rlUfuXI+J2Jo_x5d%3cqU@>gu*P%YkosRROi z39=0N<&FO%(xCRM|JbIG*PiznD3pok{l}{PBdr1kfCT?s%;l-YLveWmysZ7Ff&53s z0H@S{nW;lDln@txzg+E&pK8phI0*s;+Lq~iuT31I40;6^<#56qQ;p}Oe0S6&B_-kG zS3w|p2P-Ri8dm8(5{Xo0mvU%-fRDp5YCZ7}x?oaK%he;p!|Hkc_qIfjfxf60Xe$BV zb~e%h{@42zc;J66&7t}NK0g2bAJhf65i`s5c~@3e7ANb2fZ4p12J&TB4_mCTAq&{^ zQxFZSjiaL~&?}Ig0!QK2{0{XO#RlBmT_x7IM11PyqY(SY!Twr(NeCRcO)IZogFeuk zv|k02@=-d`1Nl`8(Dd!FIRg){o$sOxoU97eq=ZGzQ9g8UlQvEqLW&zlkYYV0!v73b zuSt{hY&I1Y)d&_lm_pvS`e%0A1cKZ1=g$j|i2eYeJm_i|dH+5z8J$HY|0Ew;=CTaO zeRay@(w=iALjeN_YCE#wz<5VM=DrND^*nz9A4f<7ba03nfRCdv4QTVwm{U4Ggf*b< z|5*q3{vm#C&~eb0%x;^q&55rkDC3G#;!)=o8bhvm@2sV|ySvXx(SksHZ<3RlDXc&w z5;s`Rf{4g#Hf zP3bwe-^LoCAcczpsAx8U+;Z{f!B4f>0y(Y zw($2i0ciKnjX>W(JM|~9ormoU2w`^;G0Wyc}$zebV1WF137APOVviLQC zYHzKcMo;&!bw2k3c$P)V8(6bcjo-N0&8W^3|8)G}G0?=f zBawZ1;lhPZ3*yhg9#SX*BNB_%GaO7l=aJg!+jZWHfxY7(OW7@)=e0sNe^1!w{=Ly}UG z@6Oufmo>32LEdR`RYt7B?>(ACut-JXh%WE^khtZZbop~4Sr*sl6{aQ6{99kPwzh?n zI2!+*`fp*@3}}gGzU&kg4FY|M1c>~_w?h)-U~kVm79Z=B6wu^x`DkZ(-o2Z)*41nk zFsJA2|8~n?P1veMfV#1bq(@V7a8-Gh_hH}%HMaLNh0UVW4ESPS1?O|}{;)Tna-8`% zB`uo;s6XOM&z6xqXdp^@ip)|^=K1Zotk95kOJcb^x?8PDCEK})^=~!hR>eUP%%v?z zuzZRR`La^<-M!}>iyL5tAuT}*&a1)}Y}$R)4@Gn?D_+HLM$lN=j~{#9lRi@%8g;}Y z*Dm5WXnu2u4j7n+G4Aj3_LDxPV;uc7SCN!L{1&7LQ7EqI1^oA58@ zV`56DxZL3aeA;%2oKuSu=lYw66qB}&H9ZFQkIy^WFxClhd4O+D9KSc{$tVixWV^s` z?V-`Cb1&{PG51=D;)o?N(ppoc`ja<~M*)%Rdvheqlr07^5S?f~XHB#cHh>ho*B-Nr zxK-sW&g3#gUl)0~<;u5w6YXz`Io{v$RVpT$J4I-@v~Ddo-=${A;+2GH-ioFjh$-*Q ztrD5N65Fl?d3pN{EO$4G7Klg0MBO@Dh{cgSQO9AIl@TMXI(!lREvV_r)%? z7UXj7F{|pP|uc==4%r$kB_w*RnNNmXtXGDg$%u5z#8)OKWWth6)en~4@d0>M;65=X=!u6d9`lM9-M*SmSV4$lZ<8*dK#PLZXU)E zh3<7oQoda+BPr{+NnfAEg&FeEQd4SqtgRZVW-82&=4`fSO*9jxtFQhZTVO7f{uF~d zHEYup8N4g4-vWfX7ZO12NEn{@F<*_gmr6Y^lV_y zGE-(~dQM^aBo7rPI|ohO;c96iI?O%U`Q~Xh|g31 z8{;m%bh)si=uCCEg?&IqEWfZ3G1sDLD~_o$DN@3Y*Japg5-74<)ntm1vn@OJm>_ z+`3=R+b~Fcto{b`yth~8mT5N7^JyVwhQ3@oq0Wq_xoE@2-LfmeDP}KgE-)II>1o6R!Il+JC09Ze2RRZys|&a zM5iiW5Fsmo163}lJL@$mP|yPC#kqyMK*gQ?uv7@$a)YL7SiZ#V&rOi+6C%M3jRm@Q z)BB3k+ak^zoD};}$clq%?Pt)0E|CnEjJ;V!oz-6`*A_6{LW}@Z}CX%T?#*G-Hl{tKfO27EPniC022K-)`uQY7*bP1oqQA z!(9+n=;wYeJRdgv(yXyp!*?R|%jXXtL?%*o{UrE=A(9fWwwiiBAeb+%zRHb6Pg%>J zkral4lb^CuNzpF>Z+tCtM2EhG1Kaf{EL?ZKg1udfg-*3zPDLf{xo3p2g0Y04JD9mn z`s!D$W6z0&<9h>n-m@_}BT9-`Z`<`hC6+m=pahexCLL6^&J?zr{|+^>p%;IIBqpen z2c=X4Y;vJAy;GCzGN{}bUv&tu&-ZFxVv}C(CP+{B~H3)0ups8WJZhp*d&NgnW}wb1)P-0$fZ9qh z_Ob6GI*#Uhrl2 zd)^D0WFWeUbl(Hsfo-W}qiRo`z?R9Y*`o6K98;^lN*7cUJ}j?Usp;n>BNX8 z9<~igRaouydhyyZ3?lEnGp#T+gP=i9Ov0GHcDX5s@#gK_TuVuRkLX=EPWdXJv3s~V zKY;x>cQ5_*Fw^dVJNy1U>w>=8={T!FXXmFYPTB`I;%aMhXYNhEYf+i27IviaXF0UY z+|{`JsP>%iycTtU8n=a`>`+UxDNzi<=JDY|nU<>Y=d`+HQ$BpmeS~(Ng4&_R-&%6B z7h8xVHrD$f!bd91IJ+rvwP1cVTHy&S5j^x*hwP5LFa{%#X4wVsQ_^SCb-*Q zF}5q)vRw?tF&piUV6TTShhV!Su)FfmGRe+LBtAr9-1w*eKz|LtdHgJRHT6Y{;iqjfZ%(cK>T~tbDOL{QY{;h$S!L1cXRH6U=Aa)_$y4=Z9eO(Ot za+3~r}Vi8dtii za!sX+M{)JXGjzeS3Bp&&Wbdh=i8oYpwNpM9gTwZ6AE| z4i0Urt1xETSIcvJOj64eW}4qNI+zwi<|6#u8rI7ktq=HqeuEM%Y#(e4g#)@)Loyz@ z$5uDu;y=(Af$MNg8bx*6;_<6qd-khdhq~kt?Het4?ulUs=Hz?2w*2eT9HCoz-e%u8 zypYr2nm7MoYQP6szI$wKbx&-wY_Kq!)RWfOYu``CpRaTCs8&-1CsX2)Kj=12uzKq)8R7F zzV(cZG5TOnFEnMbYb7y6TB&}s;gyo}IyaLi(`GVh9GR2EtkaU%H7alRjKhpwO9D=F zEBlT`=JLI*OBWKkvUnPwX5}{oC)^SfpYPhHH!1Vg(B=UUy#`n_vWDYfy_PRF#ddS! zV49qsO!!Z)tz|j~u5mLsE6}u6$ZUlyN~<(T`*%Zc)f$95_QHv6FpmOwtL=}({FNu-9<(n8R{nr zkFTpr9_ww*>ERUpOEV@WNznmo+bId-i*7t?=TbzAzpHi2j9akh&ufb%=lh#S6r-=< z{Evwz2LznhMe=uTSY9TAyP|N!hXL4pbZO}Hbt_*=^dHzwple3edT%+w`uC=@G}G27 zWHW;(@VM`Xa>WDZO)%KZ3;yh=te9wKdzm>7qx`&t@D_o~xqqN5eC&Snph7Jh5?W&F z89th7&Kf>&C&r%0iqb$%$(gMwD&7uyJ>0D+k`is-L>uz4ILZrBr>5TRoOU1xR0zB4 zURYKfweBBFSU;l#ysW*WUCK!^{Q~ko9Vo>Az=86ls@9fy2hbuaz8>kx}8?*p6$XiauiuDwUczRY_J33s_`MP{LvrhHUTN36v z6N-0K)Pi0?*2rV18UzGDkD>?-4Z^B*ky9&eo9BDgxpdU3#yy7D?&9y-*)%#hidnW4 zbu4Iu1kI*AN2)SkME&jR?;Z@Jt>$U~oP)Z%gmRkA5m6h<3P6c0xuv4Z|N4?pCcC^!Fu4+>g zF!R>PGsAc0#{KRKt|3m1KSG5T>H7Dd`BVI*&I0;x)!(x?*^Pb#E_CN{Ee}Z@E0%$& zpb)beoRXRj*fwFc^k{V<)7BqNy_bldX=+=cnU69(K$^bgw+8VLm95nPgq&ddqi@pG zUrvyrp1HK#HroxP2etF`gb0~@ZhN<>#ca1@JZFE!G^|4@Ice%&uJe+ zBC~?we~Hj_h?i|(#OER3du;E7!^_uK!ggXF-9>6C`w^w`4UPN`3v`V26adz=RD~&w z4zo)R5)#zHl6b8e``_XFN~4#JtY_R$olEp;)QmAJIUS%cr;=6pnH?4mSgytROgr44 zwUO8B2NZF=QDd*JOR`Dl_myjodepCc$lQhlA16^4HL@$vkb#@8IbsOkvB-Ke|5UzK+p8 zXr5^;zU;oecJ+^dn??Xr*!W9B@vciyUUu{Ir$5yJwH#Fu>~=nC;N-ay=CV#l^iWV# zc#a7_SE34MvI=)p3rAG3dDar(lT0oj*QGu3Xmv05HuRc(ZRRb17*p^n?*_hfB$<<5 zROrOCb#29yK;>C@Fg%FBdp@yhf#rh~zOPkV3o%HHo$C%#+s)kh!r*Iq>lU~4U%=SO zSH@A-vl=Y%DsyoX<& zNxvd8J6Cca`M$?uC>ihJpC{KDo9xJST^JTV-ua#&*1Lp)T6EiSc^CHd04@m1z17o3 zzm;J0l%-F&xH@i|H4NUnnm0x_Y`HfCRmZ$?nJGR<1tew~@0!r%-ghsBy4H@oAbp*D z{ej3v_+_Z(r+`**ylc|$!l5voQ}dLyYE0^C2s6oJUSZ2vU4`fo8>Qy3fsI}oyVdVJ z6CW5F&)fkHV@n^pDmoIkz$BDksgd)DR?27En(U4}^fwlye|K2;VscJt2<*R9k11u7 z?A>_r$yq-(#sU3JZ7Z4+zQ9F&V)vy=e1U|GBs(6WEKkF+)G+%Anf5w4oMo?%{3SaT zkt_|n6Uh)WqRA9ssbJlvRea^gx4`1qUKea%?~lA3T`=4k6N3|h@Mh3?+*8e9HDgu1 z3()0?|DlRd&?^>>+1`2J)nBWjV)r*VZ1upF&6`Yf8t^f)+E?>eqOAUdru)SQ_d8mH zg%sp1+21CVUmpHGsfnD;OK?l0y5D%+BKKvjbJoH8ocJH+#*jfxHj7q)%RvOjt=v}j zf^E_1)>y9Aa{f^q`0IYNJ9*J3s!>znYyy|XmEsYzh+)pzJY(9DS|G3&#m}y@kQ=$2 z&lHsmxC6o+g4wfa&`^n1Ex>cAronc;d!X9yt5I&zR&FoRlEj747y#lVb?$p@+j+)D zZ?uRdV$2qb9Wa4w*{~34R$<7y@aaC{h;bJXuZ_JtT%6D`H7TVlzcSsz#BxzpK4N3Y zO0pCArm%ImvR(IamIe36ylg!Nw=PYSe!~Z`)-6s`ik39DK;-_t-MA%;pQ_@90L*SspbRlr1d-;DU*ngC$1bRFS=l^dHmK?ThAi3u#12ysA zn&aR6xId~?x8I+L>h>ot604DA^?31mv*Q!%ztj|v;75#(zC^C6ip{eSI&F8q$zb|c zR$fdy1ygSOl?;d%hXsmc0zl-01}}KuO|7j}h?>D&Wy@kk&Q#N@?Y-%3Er|eVWgYW^ z3j!rfi1!$8n>Y5i%GdSO3rF8Z|M7)VE)A^t1)I|yd>=O_Lr9ug&-tK2WOt_k%s5L; zT!p9B4ju5~>=XK5=2#Qm`#H7NzFFXLCO4@n%;gT{&P}CWDqfQvc;fYlGvQ}mv{9TZ zpeaph;qR_N6cUA~AG#w`Z`BFf64*ys+bZ^GlT~AuNX<6nfeHmBC zTPC5<_#{`AU0-bl?mY>;?HQd&U{TsghBvAwb8nCKe2?4LD8-nIy#JQv91F}*qw^5f zb7)DKwF=l3RMz3Fn&0X<|KM0)49v9SU1-v*2Lq41zz&S2ZUWB^ofd!vb{M*{>aeHB z#MBBYD9Q2U6!UZ17l_FT(ooa9 zXW9Hbc-?!v>$!H{$Mz+idnoSal?Kgv?LsLgk!Mtf^__V=Frj70cOjoCYxb#ovbg8i z{T_nrL7teu;9cZFfwwaE{9%IEO`f zR`B<(+WX}F-sQcvEo|O%;s??4XRfaf0*dx+N_it@Y5_l=|aGH!jTOs`ous#Hxy%5}^ z8(Zg4BrP%QaMD6NsB-L=hE$Ss0g%yrRESC!k6 zUeO)*kuf_q81Qqrh#Eu9W$Bi#Eq-bt-=2XJj*mc53-g`gOs(-N7x(-mVNH^8!-Raz zb?*TQ@2=i%UXF1Vk9HM~Wd0n{rV~Yho%;KxnoJdrTkQ_DSwoUYQNL=hyH_vxP?uOY&m~j*3GW<` z1Q%$z*i}DNPU5J+-nZqILFjxnvYamav%C0)@V2pl5X|omc{@{r1>;o9w6Oi&^WML0 z0+6*RUk`hB^%*Vas0`t?0=I#BoiWZJA-K>xg700$x?6uq7WJ*1@prN;2f$+Dmo6hcOSdIpOo#psh*OD8{QjPjP;^D+TgM+k41A8UdV#;>-rXg_v-zXOE&E?;x^P zhULw0H>7^qD;vU=6K~qwE_!NwxpaENk>vX~549^1vm8M7yM6V7mythczq4zrZp9v& z3Q+4}_VcGawV5gQj>$^kgZ)Gq)F0^Sgr|;<%jFfBT6k|8(mApjtU_=mna}RnbuJjg<%nO^Qfs%R{;mOLAD%;a zsa}44{xy}{R)gjn<=GY3=$VF*X?rqCrDu8EwqL;_#-xS&N(7*4*;iEtoKkvF=!EqwWq5tE{Dbk1L!7zQ^_SeDg?(AfBx<|6VxE`aa|6o9aYe^{~2IG zveS&v7QZ7jm$iVo>AMqv3ur?1o2K#g*yTB#qdbDiZ1SZ#Xpd4LONlomDT8BXbkc*w z8Guw(D(zt;$1N=*Sp&Jm92RD*9^Qle!@oObEg3a>vMO>WE{0+c3MK1H^Kb``*$ZN} z>r+oPX)3HQb7dqw3$$t1w#mFx5gTJqAAC)UVqR2R1ZnE+giON9Cu5@j-nK`q>RW%J1uei3Z0*K9q~nm|M*D%ifZP(s=M1kKn;6fJpd4{kv#Wj zM_N1DUA z)sQ3Cd-($RG-cqkh(QNu@E!3xAU^(I*1M{q_j94$Soms`O+$2{QK>5zX8giting4L z;iB+v#nwmG@%{)u@}oh2RAwIyF=Y;Uy=YCQpf-JUl-)l(ZpAay1+a_8zwF{hFxHhv+i+8nAEi!!c}P`_QffHq6` z9m)I&>ulO8V9xaOHc0W`n0JZrfg4Ga=elC{7FRT-PA}eMjwrbYtc2!gum3Nl8~@*; zx&NpW`5z4SbjfpR5Ym48pBQA8Zk+%2L$JY7Zo+EJ{Xvzp=49n^kXvR!hK(6QU^|df zm63c9cnoxoa-tAult|`MOpH+a&NF(!j~KG3c~)KsliES9P{5F! zTG?Xm*oek zGPI~&Py*mW(&b-asth0`Wo`i^sJRiACiCYKAR^xN)d>UmOy0S3QNRhH^egVSWRGdS*W)At1O$^90jQFj zK?!gKLSwF!J9j+);+}h!_TOt7Qs4X-20d5!XEzvCF|T-m6y>b^82eoS-O0yoNiHU> z@8(BpZ@Lu!aGQSST7}|d|FA&%LF+?u(C@L$&p3-ZSXr|VREBT`@S|vKIQ3eV=r8r? zh?un~#?h5^-tW)=yk>O~HCi5JrFZ6XneLny4zq5H!Pt_p%I{KtiMVpNil3pwxNnx) zu|+Y^E&CBgPFTXiuc$`Yqct;i)#1HdcDWZTV)WVqSD-YR}MSa2gJVT_sZ#xN(3;T3ClhupJ6exv@?olkAh>VqS+QR=1XU( z9L!oh?>*r;c%}Hj-8~da1!|`_XF!W>$N*djakLd|&!RD`K1fclDsV}!gt&ocD_loa zOh2pbt816Gn@Lj|yaG9y?8%5T3}np}v`KvEpwAdCvC+qmrji=~a@#Q+Z8D26xT%pf zcdFu_yZ@2Me>ocOKDUT3+Sy7gUX1>}SSs`}REQIZ{i;xo3{YygDDI5lu9T_^B|_UT zBdHmw6WM$1pX7V1%vJf!&%@)}Z#})IM1#(cAvmlv)0A*Qb@{Zc;!47H=H`v)Q21BZ>%rt?oZ3QgflE;PJg%)z6 z5`ryXH-)U<%iDt#%!K4tf1Q+4Mu)?DEQk*)B($=<2V#@+SW}>keKAUNS~O`&tM)Zy zQ(fTS?#N-}%(!~b^5`SpTWxxa#^sKQ)>~N1yU#>t-!RI+0^NW#8&@4<2uP6Yvp4jr zb=0Om!qSd?qMV}zis*l?-3u^~G10+pd~p#icg^JaQY)O5-(aZZ7=jyxTW5t8<9q5; zh58q#a^&oV#dlw-M`nB~tTp3;@#ZZmX>g#_wFd-eXCzfK2oME>VqqzoP%gNI-Xh0S zV0d07yt#3VyTk=X+04gEi#A;+(!URUsJz~%6aBe2*S*3C3>(nQN=nNUpq`=XaaTN} ziGSc4@)`&fr#$AE74LznP}#9(XPL7F2dR%1a4?Bkgl~Q30UaIiJj^E0sj{^oa^8o_ z7xlhvQJm2#q@%+%{1cE#6|sazBfNXCSwK9q{7{PonIKsyrCS#0k;y>?PAse8L!B7I zd8wzxQ4)|^m9Tv76?2GfbWE5*a3ghN{%dD+`D9LlYHPXOa5*pg$K|Ghs8tAKACLnE z0%hrsB^v@e(loRm%e6Qg=8-v%>`9`4xizQp8?(Ek#|${Jz<;2+f6lz>r24 zo)Tu3&(w|e8OQe_xXcn2XY!m+D4d<`4^bS=nmS3KKECwAbEL-c0Pi|>aO#D`Z;_TO zi0sN_O*6glo}8&1giUK?iO`eS91{qijzqw4dBBu4E`>M^)HCz_LNp~2aO6^Beq=c( zU^D1}+Ofa3I?a_T{u~uBx6I3>`yQOw!!~Z|EF0EoyPu$~QT{aW#;xD8Uw~KG3e*F( z=!*@w`Nu8oJ2Z$ld8Rz8SB`NBic3pWQQTGZxsyqWRj^z?g#n_~a$BZ?LKH^UvW<>b zZld$B8+O;&%^kdQ<6%_{UFLN7b@T^&bPS&;?WTSDYCoj;Hm!%<$E@_njgtF5V!?sy zToP=|^5JG}3pfyDi!glI~52$b1~ zE|l3qob2O+=im8m(gv4Cxs>WQZ61)_SUVPq4%GLG`A1o&2x^aJl(IazfS0MQ{3+_`;M3&c#3dma z_b^2to_MOk;!RkMt*+&NXBY$v_!Ry?{ij* zMVc6+zW!3f&E*CAwWrZmm_}67hHulLbI!b2h7arl-iPDnI-4e#4tQGLrAt+c`{YVH zvLS8)yYQ!fDU*YPS_Ei!FUk8a8bv%#(Gn3f(<|g`b8X)4kW^WCmM$ zm1H8u+dPwAMlj4in=*IgudA!ubcakX&IKmc%$D%C0P9wce2Gt&pO_PU)iZs5X7GG) z!FFGI9C?YdHAjcmh7OymS)^12!h~Ia+9EXueAHX;bJ8RKUjn#ok*- z#j*Zfz9$I@?(V^ZyEl;FPLKrm1b1ybxVu}E1b27o;0_@KcNz)qEtQMBolCqvs~gSN`*7wYXL}1xr0=VGiywT zg`lsXE_v>)^0$v@Om5rr4pFylC+BM8Ff!Ym8-Z<$YBar5zv_$r)#0gycM`#YCx>=X zF~oQWYy{W9>gV2t=^|#?Fm$W0bDREEKHBC zV;}5UQ*wm2^Cky}L}%W@vgilLuF1(c3^!zZp3KMC`8|kSxJeOWO|$hK7;EHS(d%FU zYCk^%7SQ(==1ry|qitnjWz}M2YxqYgZmhnSV}5BnG4*%O)jP`mNoQ7!zNm5dwQtp1 z&8cgZAn2Kx4DgL*{J0<(-nWUiJQ{Sy#9|q$kefQ6U1#ER54O!u=#bntwy;>jn|ZN4 z>*n8Qq~aj*)Bk;?JHd7YN!k`2oJlVnU4&+&NB(qJr2penFe33WYz`6_^V8) zcFlIC9yIoz``j0$JyuOiMXSIWRmWeA>Gz%eX^-mPDL-@aiQ4nt9TZA1kuTc2j#8Ul zkecZg-S~uWx^xG1|9fwe8hJSbzv3e%;uQ*MaNf3vB<{XOjcK}^Mq`Cwcyj#)$8;6$ zOo|>ly;v8_V96yuu(;jWnOvqPgJ5KMvcsMh;;!rDT;ZA`BFuXbPX)N42=G&ZV+ew@ ztciN^$@_v z6Z;dL!gh=|K1ET&72S7hfvA5I9Q%z3ql=)6FsT}hxXYA13&=f}a=UimV+=n&Q+cztBa5$Tjjyy|vW_Zv*6kCNgw=ZrZ zVv`cS90v`hrZ(j2RsS0r@ufZQ*LN8BAsOoW8rprAp(Co`zTXoQINe12{L=b>c>YsD z(^q>`(jt;J+jb#ACE=3oidO!nubS-f2i8{`gYiD9#9TXb|LU2$js<(zW@VmovE zW1HK>1yOxibM3KUH`#5ug?qn*iHIGb$9!$fM+u$Ln#pk`<;*xqVbT+^TQ$hkSK9E3 z?(_*FwL3KB(5OQf>hwqu>IX|V$C`|!0r4)Ag=Ogv=kt8F2Y6Cq;r4uy6PT+HzpdY- z$fC7vGPT_m9K)w~t5kC<2LJO2XFoJ;3ln5#^P8S=3g1RN=M%Vn%!wrm{C2qUa=bZ} zzMn|Csd?@2L-*jBuYK5x1a>@o`g-x-O?BYIx^w>|{K(VN+CorF)-8!+t8MtavY@{? zXdEna&8$F(pMugNdiO#~a)bNLzwNuC4(wTx569arI=R*&6F@WYVfe5lz53xyYWe%l z%AG)}FOH@zxXMB(3uL26Cpr?RpGNVA>QrL05=QCWte1VSMH^VmV{-|km_iYg+@Gz{+- zoCR|#L+1x+()AY3?BSucz?!-AbN^>~yMIC%Af84xWO%|}LdCH@+3~pYbAFdB=HrKj zC0_$R{=Mu6O#ike4i~AO$y#&4g~_N%7_W)0*wMB+=xGx_KK!Fvh(jvUz@8168OXqA zuAB`HUwY{j*C_ok1yDdE&Eb?49WhNY208dPaZPe)2M9&4)svR!K1glWL4|Rbto^Rn znBQWABgJgSoftHfzrMU)pg+3D#|eGOeB7zQT#R>Yux)G2KeS&K)JM!{dw2*x6WOn< z;asbq0Uz*UfhjTR$+Uj7Jt`Yba5KhgL^SAJ%4xEGRh# z^V7(X+#SVx#wQl0;;P7aau^4Qy}ZaiKZpB9!}q|cd{^*$7LoD~*HFHg0AK+Q**`B@ zH@v(0yrg1liGIhvH~su+$92g0XUFDn`P?&UM^f9z>7@5=MMMR$cM@X8KtZ9L!5)?* zQjz1=3EmaOS@^pBb8>&$bfZV+P-njMSg$qB)3AjCAjCqyv&)KzTh)vPl(!F8-zodaeLXita z3c;9?v3Gt2wGo4dG-AAvOCI49hpU2yyMTU6yT_!v3^z4iW7_45)N7%?w-@(+*1+*g{}8ugxLZMgU2lFHyQ~2+-hqY+^Y7KP3+rn$N|F#uMN|R{lSPp#PhY{03}QKnQMl{|m9Wr#3h6 z^FKTC->*m%{x9xxq5b^|TK2z9Gw<&MuFL;F1Frvr>)>ZHo{Hu)o7tk+V_-ZKn)9L5 zDUIhw4E!*P4Z2!a0pHK?V;hlmmwX4NntU!azbiOj9jz{N>2SYl7qf5ut4co^6!;9E3xQT+nyyVinH=kN*c7PG%H2F!+Rc}8)2*_LqW zn~1L9Y(sFMt?r-MCCUE7g0sigcGp^KL^ob1BTbq+cRMHB)tOiJ@G8RCvmj^VB>K@@$V`UmmGyI~Z-ZLdI|x7mqqSZwpoUz{uogB( zKR_lECm8cqokjE=HbOcK2`QXvHX*DtOR|a%AHIqZpcp=a7WS#7@`bY&O2;dPtt!cY z5mkf*Q%*r#yJAsI#!j3tB8K{Y|NAC8~{L&i|*!h=Li zq$q~52ESH+-tlhYn%D%1i*6N{NUDksIZ!Yj7%Oef6%%HoIQ@y`QUi_Zjs4u(_0g-W2(_?^)h;o*;zMnpEeE+~p6E3$LfBmX34x%X`{m2zDyqDhiiB!sYI^M7)yo#&2;7dAyZv8~ySPyp!ynxmY!{SGO>y^T z?2Y!O%Walgl2cL$E)N#^f$IhA?C!2#pTM$&Tq6z-?OIw|1ZI81rn6h;8eD~etHl~W zgp8KiTI4nO(hSe=yl=N6|G+#`<*=!U^`^MQc)BYeZ`4rS zR|;RynK167Xik#gnJh$K&SXaqM}8=r8KUI!4jH>yN^%PyH(fJ|yOGFznT1SHD##4K z$xK$3Mu2mPS3;bm({YE$WKxg2&m1cuE}W4Q)me?tm^iqHP&1Cxol`3EaBdJ6*qyqRgW-mHSj3bHIr{pqT2)lT%dfE8EoLQ$N5Cd-_uV&;MW5;ZlR z-;YtQ*ExKEr6(ax$+y=;2!ryWt1@%^`@csMea4fzBA#%DoCoaj`&))6%A=U2M*{q_ z?}Lmeox|=tmG=k8UAfBzWwVm9tA6V3951~FTC+gEx~gNyv-WLr0m}7b0$IL{A&*E+ zWpKAwqchmvZ~z403SUgc<#5YrfdC-Z&*hf%#LxwS8b4tMA$Mo6VJ&kWhU9NpsE*)7 zb0%(ftDr|yG%(P|zL<`Ru}E&BXzJLYfx>adV@})kX}cnL`?D|quJ7{ooxOIIKsqlvU7k7O+4{g8__*5I<20BQ zd_FUCdd5)M`w)9|99h`W-yZ87>P7L$C+2sr3py_)^|pvTZZ6B% zZ4?Msz~)kqHu5Jhk2lW5)>CqPvU48RbwSq~SIsa8Y12jF%Ib8EFRppsrZd!xiLl~_ za|ZI!7YBMpSB|RtPk1|3jRW9FgBamXp=&1Q}((<$= z8St=4;*|hC{D`9s7~M(RCq~d!Lu#Nkt)s{N6w{5D5!HzUfQ`g3H!)qB!M_0@6E?!U z$uX}K78yY-lrG|}F4|+tn}Gf55gs9=D(N-cb=m<6g|Dm-;t-^JMMnfJoMX;DBd1SB z;R8K*kdRJD81Ud^Ne4jnt^q-ujB)$r2XzZ3fI_dFsXxlRax*8``pNS=$}vc43(G{I za~wJnDbw2j)fJulUUSdHg%v`azKQ7As?Q`Eg4evm8q?%9brm|)&exOGxOE4lW zhodJ#%JFkWV-JM1U+Ewklw1+Sl~p_&Y$-|lBp7MJ&?h*!EkOOa{xkPdQjDJ#g+ZSN z{Y%8LnmF2>wDTu1@~&Ml<^N_1=@)zDrpmUMW}0UgP!tV9%`);$^QR zkr)b*p>Gn1g0s~*K3)s69X`UOe7rR_Q&wB-+GANIpOZ#P3z}*&);$y$wcji41kfe1 zmKAubq9;eDa{HY)m6T{!c~9wltXz=o4x#6>n-^D~1n>p{W%$H zYf@HL;kla6q)JMIWJMaEx9Lo}vu(xLi?ifM!2FkAQh^v6I;x=IJL99YzA*^ z)Tz{l2HUqPE5Y7KO|_P~m{a_{CnV8L)o-vDQJId3CzyYT1C<7hoHEsHu~C=XbTDU` zjp|D--{<3fWMwFHLbm*T7Cy$>oslG=rSr_1q|xVaW_0s!>j&`ufWkWntW#@3Rrz>f zSul3b-gkdtxePfLuBkz%rS&-L(;ct|*X=OOg^NR-0d)p6*;;{onQu2YrR<1-oPxV^MU&%u>n>K(-m1^?qQ z2?h9?;IQpV+75d6YImlxd4FbPY}#k`RwdQ*CWMRoO#mae?Ff=Sg&K4x{Nh7Hcj|eY0XlLhMQA( z5*b;cn<6`q5kwv+^3wVfK?ha!b>=#!FgM36E@yBd4oPCPh!Co&7MGd1&Whz^)u#Z7 zM5L-7Y%ClZ078IR0{AITQ-d5mKtGW57NF)|rYlF8`^5+(FpdmdQUgG3fUY@|PKhK{Bm~d*VBcsUC_CSK6jL~nM zg*qE-3U2y2N5x`x9#5``5|9Bxk!Fd1VT?|H7p`~_ZdO1Q&d8mcwvHRUUFQHGEbWkT zJgC@MF#|iiku%(~GrWy+Zip66^!z|OD$@qWdgSnEo)A34fWSS$o-yc;j3998;U$e% z*@pe4pY(CxX0K^~W)%K-1cwkRuK;B7^z;<)IHeU45y=vC4gsvaiHV7^wXwiD%GrKE z&CLCtl|7h$l`>OqIsq_1S7&&Uu3m$!{PSbY2No@Z;qUmR#TB~!r@VW`#rng)l1sHa ztXN&G`QJl*xk>qLzg0V;0t6B~I=569R&KDfEhx5R21b0Vt_}|gxv-h52?kWt{KA5u z&utxWLg#)rrr5^*T&?%s*biaI|iQrN!bm8Yl}PF#_mcq_j1_API(xk<#hOYcZnnRd^{D1CKP zLS0Sprx9&gK7R=-2>IdMRZU%4LXJ1iRJ19Q1rCuAde8q?<%4xWqRssr1A@;8g zjdmvEm!6uSr6x0MgG6{Ht1cne;n87Fk1`G2QqBXSro$gCa=+W*+_q~psF&caHAO!W=q&oCoU0C$)Z@fNPnmG$xs8|c%J_PiU_lw5u!_9toz43Cfc7j;3 zc9*%z^y`i1X0L>*Wj?LiN73^&r(t>Fa6j)lL5_Ic1Cjj7NFXMGC+a_OjUa8x!LVi? zMn_+b(8^6(N|X3Aj4X@urGP1ltYWr|+Pt?3?r?Y%D;1~(D^Vn{Y5=5G%jDRHhefOz zB*I1N3>H!ytPNAhQ4-%G%R+uR`@IG!aj0B1*t9%izHj6 zN(A4~lnkidM#j*};EE;`4I;O zUIzN!^q=R{DFI3hNV^uOUrK_UZ|OT_Qs>PN@aSr{`s!x8Z+hQ zJGHxU(_0eZ! zG(Z~ti&{L+%mBdb93E}~F~$?*Fh#FdfqePl%2Uwg4@axc!tC^7*Oo2oZ~OVKT>vqv zQ2*T)PeAr4^}bxI`|5=KGCA^11~jP4Bl3=IE{8j3WGwc+ep3Qlr{WJ;{rGPnCL zpQ!RQNYRW3C;})IeMg?!wjq2aXQtFR=+}^}A-cSAgST$ICh{fLi~vj~zT?x5X2|Hh z6D{|oBmH>N()ETa<+;L$GQ{?-zPt#Ll-|if^3tM%8$|+J^ z#%ArC0$T;!+=W9gZ8qCY@1C3??j=OMc$e217(LTZ zE)`%QEeki~KyvT&CR|s~FqT(~gaqb&=NYFu3)K-#c6$$#J*(3^*W{);R#p`I52c@E z&SN&IUh2uwO0z%UAI&ZN`Y~1@1>i%$=xd`8=U%WV;xtUT}0q&Y- zzuFuxwi>bo@y=|vwiY>Yn#81@vFmD$FYqEzp-EfU>@62{rqBX#Au1n42%%jy z59{TB6Y`fSsNtApK0>~(mj5)Rx=T1tC{Mj+N*r|M}}+Wt#Xdta$iWa5>J_Zp0N)NDIZ^T zu_JRPN#n1&&%&(>mlMm&oxoKf^{+mYH?_ZgsJDaOix8Y;pO7?F{p zU?GoTT-+Q~xQ&~vuV`by=y>zFhj4_x!-x-fMvFH_Ux6bW+ltbMz+o{58VvW3x!OWSkE ztjbZin=)Yk{9bF%60NE9yAzyij#Ur6awxd_!tCO9xa79nu7aqX2NA02#}^iM<9ED& z&nzNybWrn`wn~PT9XsSDa^dgOe(htZ4{;S=oMrWV+%CgRXc6eEA7IjxC06 zGhFF+k5k^UH7+@$i}{^#et+I!?|A3K?=-0b?Zh2l>K4IV>LI`KPF*-`gHWzGimX6yNILGiD-AEL z>FILOB1N#hz$nJpme&YDYotVDXkx-tDFRul>DQ!LBj@hx2Za7PR0N44(M8uLUDVEU zip>4aCBf;>R28$arQ;am2PY4%iPw=EXt_rj0{B-@)+_BtdKfqeR=x@ZC=P0M)f}HX zt`p+K_NGe#Y-t!ETRy4bm{=G)|01gxg9a*GkR2)O!Al9u!jbjDUFr_Z8TT#PM!xdO*1Zx9|f=sfiU#4~asshZR*b(~K3`MZb zv#lzZdx`aGp;{y!1{@0Aw^gjcJHFW0ulh~u@^L;X_mIR#R&vI_RbX27=e$N>FhU#s zF_ZQq>Z?{jSuv3f;O{2_!1`QbPy1N#>0TTseT#B5>Z?G(wIoMx{~%rtQrrFaW6mCq ziQ#}8st~zJTg42s&k>E;jNIbsJWG8+gH&zYy*;h!BW)rR1HeG>1Y>iw@!rF{<_1tb zId1DNtNs4`F+z^(2%*BlbFJ>|URQ?z4%+MXXQg0U6;ce>ns>2|ctU`BRnUa3rbW+0=UR7(>Y?h2@%TDKRaGiB!b z5A?gFB-+q#;pGc%HSix)%2@)vC$RpVot?FZs}=WlK@Am^agUSp+*r}?jaL#FK%Etn zUCzU6Z+;LWol;(0*kZ@}f!X@5Yv&h!5}Od5q7XpQKxGj%^n1yX(?g9smjd$uOX=(S zynv(xlmzopx@rpyvuD*FfM|iJOfNDeC@_T$veSWT|B{jJVE!&tixLj} zTj9V5pbAN0oQ8!rv}m6i2gN*5M@P==M!aV0V>~}JBWtLa7C#j?)o>mT_EBJAau5F9 z^WAAC{FlGN+1WNLRpa-Fwjm}ILY8k1oj534?8cYBK8zT&Bqa0>%ds)h(7O|ijZlAg z9+qXPparV8qO4!+r!!M@|A{&^#X_v71@ zoC5D}xVf9IZ3VGiCJ&_5ju5c2OaD0h0~1qL+eM0SvmiZ&TiNHy5P2aC9)~(p)T5l` z@#?^ZC#iH5+lYx$cqibq@mFCi+3Kh5n@(qk*?pm(PRoOnfHw_>gIo7ZpGfpnis9`R z+8%FHfN@JuRdNl8-m`=Jg#_{p?(23|hi^&698X=2k$?MtX|Xqdp-WPVjB+h3$Jjw@ zKJxmjau&f9yAz>+UjVh%k9r^uvv-D@uE3UMDz=MP z7Q2QkmwRiWaEkGmdr|g>9r{Dxee1=CKQrJ%_r{asN&b_Eg^oU-*!#Gg{rTm`zK76Iv#GfQWI#mF?+1a>AX%SJnr9zjJL zQIuvw{hgb0A%P>b0EZ$wbShpBXxyCPy@0#`kGgP-_WL&)3INIiFn}Jeu$8(GN9Z|d zA&sDDuyQ>Y_iGY+=$nE&X`tO=8_E9wQvE8C;J=)ot9y4H^Y?Q1GN2{W1fJjqo?t}K zb5*02)?$g7qCh6ez{>7M7~>|MZ)y9gG^i6J(h0DX6|In8>2ggE*hGCR2ArR8c}OrX zSLW(Zye=4OwE*`Ccduz(J{CcGU_Bhc%0iN_SUXv=_p1HogPzk)KZE=MqgEF;QUe`e zs7tu~VzI&2P9xtTI$*pe`kuav8^XvE{aOKMtV!HNeJD)v4Lz^9=vwv59@Fyl)YEf_#0wW}gEKCg!Hy~KfHZd{rlgtLF^PBkF2vXRm z3>AUI!Ug2&d=u31uHAt)z~m{^ukowS26-fmjVWVLfCf5z?&g|nlUa2es(rhqGct8& z=cfB0?RSFUKd)OC+-g5Bd?ews`82ib`n#;mbSlGhx_m`(sRgL9mVcD+l4>;r#!e}z zR=b%}q*n%n3yE#2{i52f05B{4U{nq2NXC}x`Mxp^h*St%M*P0O#X zUVq(6VSnv)392z4r!gP%t{Eas;52_`nV$^sA@RLH=AV6PlQVf)=JGrTV{|%&j|o5! z#h8BQrmnf3tyJtpO?f~kIo{;cj%O&i^-@O=vKD&x>JXGI z|7e?k1^jp9RrXzw7JrnAzA-3m5eJy}cw|xF3KmnXH|>i0-iWTG?`M1| z)RgzlPUz05Q>ras;_#PrlIDci5LH>A(mM%ue)62-4X$54Hni~kHyw23`3QkRFP>N4 z->5=dq0uW*Er|?%&bYacd(ZmXP7o%&9}_>g?&K9HZHqlR@L&Ffua!6Ez(yVI+V*aq z<1%yvbslR*MDBx?e1ccMLTlZ(t(NzeN5#g;)-CSb#>ngo3$6X&^E*32vMQR0BKnAW z46=x!WB!wQFHX*Z8f^~hjN6Y{?^JO27bQffCwy$F&D{p>k-AJd2h9e8GO;s*qCkn= z_pluX;OuVjGSCZ)Z4Sx-IkYp7I5<_a(j=%h`M{^3Ne{Co8Kt4A*mS%i1#e-Btry2P z9$zc)JHiuJHd0kq24W8%g<@lyf`QzN04TuF*`qsB%?%!@pyWQ>v7&zDm}2hem?F;T zn4k-EyOuMO4(H*Srp+TgY>yy~IINDphhuH&~ z$Ltmjm)n~K;iWJ#irYFRQOK1d_eU>K`~)#VsH6#x6gGLPgq}RMrJ(cRK(>sHlOufd zkrR9;oF+8c$74v^Kulu%PhS9OU26XVB6_dPv@PrYg%y8Bo?y!k3?PtdJHZs|YZFZ- zevH2+GC4*M?-YK6bM#f#?3D}{%Tj40U7C7dob?D-g*85DWQg$Ly+tE)EVcKQlBtK#Br0j8Hq{SE~&DG3&nJp z4O#;pH7rtAo}Gb(3$c|uGHmv_8W;01dPLvuz-z9GpRSa@uj}Rzv~f-_!@Kuo8F-iw zWfUn=j?px=c<0rT8uB?t$K@HaUVx=a9$AP?u+<-$ZSW_jl`2?fRln_py7tUZlD&zE^egdP| zkxmPhUVZ_Bl~pZz~rI%09%zp8Za^KSc)!3QG zx+P%q05>}?1mgM2OE#Ev9ax&Kboh`7I>lXH`s`aRbry^QT+kj) z*!>JpXs^}9@4_<$2%s(^cv@H%q70+RIWtl#=S{szby3SXqG-EEn!f z`K`S@TOt%=VsaAJV&ezME%3a@IZ?E3qpGf<%II!Ai(Yla&G5(f)h@)fslVU1fEjB` z02lek;H1A-HsEx=U`{hsvg@V(rNAu5mLVbT%NS35LyJH5RR7cxu$n6?k<(3;4ixK& zo2UwMHq%uo9I4AQ$pIQgKP5*4l)CX<@YAUFTkQ)bg7T%Fn&<_s$+pZ4bX`XMnuM(8 z4|&NNaT)@lvu$dc0_08JVm_D8XMpl#nTW~W4j&L%dW}?1M$<2;VJ$6P6`&^o&;>wt zBr}+sl~Bg>nW|vEjOBo1_^XLhj*rKx2<-A#L2YUwdSzfK6<7 zgf5`+pJm32ZL0WrAjN7P!Tgq8V6nM=G2FoUCU6(ZBgK1O_Sm-Q#uf6;9QY{_Y{k>R z8h&QoR?s1@+>*VX^+tz}9d`)eyfsy0Dx2|93m=5 z{as?o3t#;mdBsp#$T3qwWrD_s=sfbX2MYDhrfg)vUc&e(!YLeS-jf zZGiO3@y|~xAhwdZ^9P{f9VUUeU@2CW8gtq1Qg;OO+Tm-kU+LSO0x~ND>5E_Z8tkQ? zPillpO00`Z45ThtguWF&ZM}XK zwIwD(@tRpUEgTmf#&~Qy;(t`*G{`b`UIzqKh=mwOo4?n5vV^?9sArRB?Scjd$9#Zr zYO94|XVpQ-LHvAUjjsjs&?#GzoJ<(#{^KU~(|`B@@z77mp~dBO0EXnO|75Y@N05kE zmYrL+5V?2kWMuDTpcj9YizDB~o_vu3WQ5dSq_>sZuRE>LcM!(z8yjlS6pxq#7rnaQ z6@olGVBV@E`6kK$%OmFXhlIj=_mu&e4+D@;nHhLqd^9+23KyohC4pW~xr5K=D4nh( z0AskdV^HO&6(R$9d~`VK(Qis9U^Ij z6iq`5!WMHz=rnd5LBi->z=}|j74Y3cDtHMrs>v`ao|JTHMD_a-#VkweA0!H2dA}WP zSi&=vA50UlBe_X)Rt5T0(5OHaVSrBfHt`auP_~XBoozQU&!BOV;xx`rs)f4YOWnRl zp4kVW4Cx`ukXG{)RDEDjpLE(X#u#^y`t>IX=NBr0Nfkq48gFXd{mZ-O6B(P)DaE2dQvOt8Ev#ND3z77yb&zN^0L-C8? z#Dya_I;Y}U?2nbCC-V5G(0T`$BG=G!kBU7%`tb%(S4bGcKNhfJHQ%BodefxulMXh? z0bvxu(8gnq%1Pwz-NPe)w5NMUHa`Ob=iq|lTxI6)(`hqT4!h?!h3{2zL`RDg`#mbR z@!F4|{e!qmWMZCa5(i!uD>L#7hvaoOD?=ebTd%j`Rj~e8Q{?&bgMy~&2Ys2TUqS@z zdxlEodr<3-6{efJ7iBuF@$>bWT9Z}j^?TEkKYzYeSH~S49R>34P+SIO2cWOejEJ_d zkkIU0OC->PN2}HMMd@^f=?5Q?NX==rW*1`TQtLOmHAxANV4>^ZJ8yYd_3NTe^Gn|t zwnWtQ4kPN1L4&e@@cB(KZ8?~2rO^R zEb93>s#zjH6qKBuTEaMPcdB00k{iGMc5|B~^Z6?Dy!Q#gKdI`lJpTkOBh#J-1>xa5 ze}+@y$Uf zkMdrL9Q4!aXGoYc3j2oOYLXVWE=wLXGbfRY1(x0-?er$oHbsOF9(u=emmaGS7qaI- z@rot{rD$6s1S*(U7$|1edhbYGi{X?4)>AiP_2q1rJBmP4!-d z%$~zHnr<7x8^ws2z>UO?SAnjWz>|BzQ_Z+SrX`GyrH(Hj_WC)UOx(A8c%mF9y{cAo z-P7BPDECBjeq^8@)w*>PP5TMOB$vt@PcGAe?<&^sD9vhN{lWKjUV?&io=nW&}r0C%lRMciu)$7GLMcwheqdEOf;++zxd8TJ+ni+Ix zv8w7NqH?$hj*s_DG^F4;J2x;Nd|XNy23b}5#dqq!#j~c*nsWX7$&Ma!e6VfH|N5(q~O6Yu$(59EF6n1eiv@_Lrlwen&Smhj1EyWaqO> z@5>VuA>z+vIEvZr{qb#SXA(-UhHT=j3XoRma0!Z zB*G?22r)q*Nh?H?XmaOIB=O-lLH!$5KCy8xp0$iM{Dntjvh^iTs=QXL5XkX zMQ`SX!KF_|{oy=P?E(CI3y&uScxd$O5(Rw5$eR}k*o+@Q4-Xok!7eq$ev^w7FGKxa zdW{?>B8MXjD;U?_AK$N-ywV8Ofa)6i@@qFYiBd>ed(?5rO8LEkSJrMuE}5Wb04{@y^ZJG*n?akn!k(>;eZ6yT zb-MM;uAtW=b-xN^eYSWq3*_aWTR8S!*FB>I#=ux4^jo{eP+Q7On~wN%c6#9sUH0ZJ z0G3ZF^>wrLBe``}*$ zm1HC9v9CDow+?eKiN6!Phr_A$lFrBO0s|7*yJp(m3CfHSi0anh&v{Vs@}A zpubIyxqGwM85jIMKM;Pi$p^n`#5ioo+N2y80((NExAwOGShRGB`S}gh-tjlDc!u{M zXo6?mAbudbjhps8Q2R`eeXRY2j$aD=E>@;)S)f1BO9|Ar@B@Yz4f6Qe6WDqI@&YG@ zHddZ&D8EoS<k44_{Jn>56gJe#MC1e57M-3#W}Yf1mQv*zw5{5nqF_g!H-5@iE0Y`8kQtE0_G0 zul$A{j0B|>XoXA>Ck-lhf)acXzxUvyMls3hv3;yK=d->Um(AF0%3sAeQ_X=~Ou z3#IJk=p}JtQgcGEio=b<<6l=p-o{fLy?tr$$R(baJtK*NN*x?bc@>Jq!ioKc3+oNn z>SpEYmz=B@zD@x>($A${-HX?SO|2owqFp1^BTX5DQF#!C6vKGd5SUqlr1PnM1(`+; zoB4goIC6UlV@Hu9%~1SGixy0UA@=QMI@_!2`JFLw{9=>$nUn7`)sYhfex^;T5~_HssA;&R-LFe*;C+ZU{1{nU7SeXA zgTfRWr>Uy&&XV_Ya=nHI<+ty*NcA#%0v@;G+kcfLnhScD#Ylvzy!W{l2vyEnKQ68% z6ZDD6NGvP{xg~T-)Z>wt&{fuCjMO-B4G+n&m($ia1#EP2sYNmmloU}l-Xb+mWhd@9 zmtZ97Yb&@(u`&kt(ryyQtqw78R>o}vnBbhE$PF;lH&;bP)mS-M#U$u@1w@tP(h_K5 zA23l-(_kv7(cjJ{jZvu<104}QVrjltHc_Pum%^vrNLBURXQ?l&eDAvc{3f|SY@C&f zsq{-)8xGE?!T?LfYe2>=o=V_NQP4n32sEY8UrvP%vWiLCdGPku_X~Jmf$`t(*hb>_ z(nIL;JNvD2@6>$j74w~ptMqz@*SO~ACSwWDMs(+6drMz&c{!>~d-EkkXZF{8+I;PH zV9*ny(vM3{Dyx=2)NDiQG|0Da{0Q=Jh$$r;vTV{*de~&5SZsd#kZ<*Pa>eKC>ky3S z&W^R06rX6<`Srx?E+zKn!V%Yfp6%C!lRx5tCV&~pN{-txAnpK32oOz3Y^C*`%&^DU zO!CBp6NKSPD1T?^vJ~XAIMROU>FYb&HF?K>190vMd5$vex{zht<{ns#=M(o-?_AwM zO|Ho@2Qwa?mGMtBTX73+Wle2b0>|9hYJ$OcB<>mPPL&rmx>?KC?TY=QsEd}5nz56Y z1!r(C0gY};9n#$<0DYI4=EYDgg@tG#5_Zbm7M|!9(;JPCv~fB1@A4lY=!P+-saGaE z4U|aJKHZwFgf+$sXeoX|NpqzJ=96RY>8)EzedBw5Y3Y@mj$;c^8TYSp3)}mWq$;_6 z95MU+W|PwuTDhGq-RVbt5{pq=x&J({Dc)BhqH0E)Z1fzWkw4Hsgtm-KBNmKK`)=WnxC_zF>p;6B`Moq%OVv(uf%KaVm{g+Pl9PY#}IRa{35Rz*V z4_}bU3zOpTpH*P@9F1V1D6Dww_%8Xd--=(}t9%`JE9pWn?(v37jhjTB$K*3nUll^0 z6{(pnj+H4MmlA@!5A8b>npf5!rohCv@z4B60#czFO9ot*H*ZcbIoCD|jbl@zj2z!Q zKF8&%$BpKsXy!|J8xMKtz^U7M;~n?`A^ZYq(=5n|n@dSR&6S8sjfPt4%`JqbSL`sv-<`$M59MQGWd&e7$8*oNpB6`40(BaCdii*T&u5-Jv141gG)F zEx5ZRNN{%uf#4Dx0>NGP&FoC=Y}M>`J(cb*8d7}uan8Nx-iJbubUH+wL_&iI90-FX zC9Ggc86?SM@hQ$9JymN}KwQCEfkL?DL!n@Tt5?i9Zny_IeQMx48)o$gA6P?-3Jb&} z0jR?cV*KQQ(~NXYf^~g;-pi{@C(P8z#cbn^EQin?lK{Szd44_OSphrhz2VZC?J(cq zEr7Zovnj-)CL`^Ny7t|_`o47BwZHwwPz7d?(u>$ikH{u&OiiAOm0td~Zmu0a-JQ)X zEXWud5-IZ;wmoukUC-;IlGPVKjv_KT2oBl1KVTp!I*$2Ms5Zw|k1|x!cC^J@_k%fO z8An+e>3Y5$i?rz4heVdmcz<+AaXzm{d=^@~OCqQ=3&m=y zN=Q0n9L~#)r=f+_RN@?NL%HU#x62)?AcoNYMSSbCzd5@Y)%@R0tj|5$Zaul`NHB1n z2G^!le+{YAhG>rc)$8yHO`v{55gAbr;ne=w2#2M)?n3Yb>+0>~?^P1bdpC2mmb2{m zYVin})_4{}QLCFj?rTm}zw_VPrmqh0>|N`v7wfEjNQ}Z-?*ys0UFjKHED&${9YjWl zKc;XH-eF>Y&5}i%PD(8(sePbEJ2T!nh?)`(_KUh*AX;nxHM#TTEZpV~5&ByWgcI^o zsj;G}n|<8w1kuiT&UgEiPdDlgGU!@;m(*tlRu_HN)MuIjf7`WqIL-fZW8Q3-F4{iV zTT5i?>+_T?GW1SLb`}lbdw%B>ki+XN0{%;9G7VLVT2jPIJphF$t(9A+Dp}5)bKx{ zE}u3oX{^iw3?=xjPfAcw(C7LPz@6ycaZSHK;r|DgGfWqF;xgK!EkSXICU$tHCL9id1+nE>~Q#)AMo&z zP!=2b!XRF{h4OSikYDGTlGeGPXo^9DrfN!h>b&C+kRIGmL(kV$00%K-mHx8ISWGhX z%?w@HvC^GSQrD1n*)xwp&F|F?1klF_uC5xZtf6G+iM~z-BRM9fXsRnZ=};6lR^oqw z9DadRkU&PA-Q{X#qos<`qhwy-%YXHZ{GWa8i@F$YePD(F(_`b&Q)SHxe@y#?U-L!I zoql^ES+!_jlr&jSA6?F4(}*jtnBSB|{Y(H%c=f&4s#efib5i~-GX?#jrUR-#Wfjst7)Up*nUg}ZN3F@n8W-ye z?ZiUqgAd3N_pkwp1BH})YD6Ot!bhHMeiDE&M894_#XRQ%2Kdnf`+WG)l zcj~?N`{0R1_)l9OpyWus=YirK72t5s0c-2c@TMs6cpqUEI3M(-C6a5+MR)}G5Kx^v zW<3gaJFYTJ^;+u`pSaQdx{$x`wIg6q=bgUWlUl}B>fksaVBnftT)KrabyIFvC)QV+ zQ*QS?D6<-GqLLN3d_WN6+XZ}p^zpslNEGwquCeHEr=lNSQ5leTb~mW=D+rT?jfe3n z0WW*ut0_?W8W+SBeNk6xwG!D%Z*q-rO6{m(UKxs{tXX{v^+V$5G;_ekf+O|h z0VYgBdkAB+?8LVg`8! z8IRE;h>5=Djw*81?i@m7!B8PC@sjf0e`%?Ss=A)(b5)zekK4{iM!DTC7g6gMgl8+NqN0 z-GEy;ED_C&5+Y0t5ey}Vz>0-ngb3%F>Em0(hvj$fA*6cU-ZNgH&NeTq4qftWHm=I{ zi3S6F#e$BH-HAcYu?&`Xiu;&;i~=MS^J7?UR0Rxcs&mIsz&Do9#_(EBE8DT&ZuA{p z-%f59x-Yxsr@-oZ1`@uXSfUaa-Me1l#Kc}AZWDyKxw(I=ttkP*t+uvyt;>IrMgDBF zXXcBLx6kD+A}}kw1LU@ZeJ{i5RP)aNVefa}`|O;YcF!YB+Zp5E&k>5b0zl~vsL&mb zx+^d_jxyEtYHQuF*&C=y_yrLV!0wgcrT?>RU=u|7I!a6rWI6C2G}lyIA&6qk7nb_q zQ=R4|vOEhtWmiS`cyK1$BW^5yWW zCuNEzhhVYZ{g^{!eEw*(JXt|}G&wC-&eF4mWC|yOvfKzXS<1qT1F}3cSO$dSvs9H- zY`q+uTrd#pEbh#zziuOet5H+b4Wt8HFzknL0PLaX8_F4}kRk%V2p%>@Mv5$00#P9C zTStM* zu?>$4_txr9r^}?_Y^=58rpo0p%m#Y7#)$?cb+l^OUQIz0)WdDftn*3bF3 ztQ0ibN**2r`pXI}FWf0-!MWqYXwv0Kg3Fa^R=FzFg%MA}A={1DCx`x174i<7y zXL=Vr?#|v7#{PLe0&Z~MyPi)0jn=%TE?*KUPRMnl#CXg3R=t^jPt@Bq`b~klpTVS| zzyAt%dZ#5A>b5Oz^cE+`oVFStxXX%&ZFcn)-yWYb&u0`}t3Ta{-3SNzo|RfTy9&+# z)wO@lb>Hz5w`n!diGV$AF#-b{GWot70QI+j&;vffZ7d)$FjNeH?lnwUMA_p-KKnS) zz4?`$B|b{Pm-~zJCM#|4od*of@q^Qo-a>##_FjI%?p*Dhev3J`y|jT1OK_C_#HP*Z zh$~m{&8A*k3z-z1m-Wx*(@CR^FVe@4&9^ys4=$Tg%qD!%L&tCpCv$yD*-wHVy4^!d zS;mR}s%WQDtH zAOw>I3xKRtG#R~;0NNj;nuJ-n76(vDaW=!TRv>2Zni3}50I;TVS~?|v*a2&5VNEaD zo&{J|)O-00R4sB1y(C9x1S{Nt(0S1C9v}{X=v!cnOJOh#ut(5Q>O^9Y&to~LN)Qn$ zCe4S}i^onAMggZsE-_y%%DW*Oy&d+O0Abcbh@8Dt1p;09A-)7AGNUDmq%=Q_FFsNr zwx1)VM*REI*#|m|W451I)I5cp(uKUTRKH}%)xyE-a`AoXaf#wH3;8h12lf5BcD=F% zwoe=AEoUFigFnY~1tFor5iA{752@PinI$3Sqa(lDb_-Xa15{hnrs<4}D-U3N#ZJzf4Mz_NJzX--8;I%9v}T!O}i)eCNlov zDuc~*e>{yTSI9fz>R`s>?+VYK<70bQ*MqSXy64M@9)*{D5&vNTd~HE5f_QAkTmRT5 z7?@5)r=lKsk3Y2ct1V`HjIn~ex*&A&8T|87LH<)(5CVSJRHg{rwGH?E0OBPLd! zg@K~9ZIVUK6lpF)L@fnLL4J~rf}A4a{02F;oL1i5cgJp$~Xepa`NxKAUHN1rS@lfF83to%y*S?C7 z`u_R9yRQGUD)$!gjI(<**bY>QzF+1|1 zSUbH%Hjn$*L5V^N;LCQZPc@c z@|Tb8hvy46-ZXJhWnsebpEtm^~71t4i3u;A*HOvoOe_mKkwFA0gFo8_2_N>JDTr^tBvWs z?5){S+Xf2JYECQAd(eHWtM9aZexDXyN*lLt2Pm=BKW<iR7BYmN{#o+C=YkO693o&sd(e4+qFQ$!<1;KFjI?0r zpx*~htap+uFj)}t#tjyu2rw6t@dwN_9B6;2YXcJCR)HojP|^b^*@Mo~aT`ItxB`iu z2GxBl{vohN^NjT6eXRf-aDaXYKu;}aDa#mInrh;-J_sQ4suIMlqh+k4hn*B9DibBE zT0GdrQz zZY3S;Bh;9L`QbdGh>*TfQd6>F)tvFq7y}QFQGc0@Ul29-CvDcgR-zERklx<&7inlj zPccz)a^;W42|Gcu!iP$l+*;&E&_)0Y*lrI#JFUgRJ*E2GVmQsDNtu znnf})lN@Uex!}aFte5Pg{w$~>NP%}tJ}Z2{dAlBU@3Yp-yGl~m z2t=~d2Qh)VSC;=X)}DWLE#I%}rPq-SPL{eh9(6!!)`er175zC~eSsc>Xr^|4_dwOm z&ppSav_j{~}$ z8O0u0c8X`B8r=fL(p?A#+uDt@_{-t3Z0?HQDgZjY5LWl(4#vzxas=9YKgOMm_i`Bf zc=tO_>dz)3l64PV-kfm-nwvhN{2f0W>%xEO+r)p7aP_-6lic*~;0Q2cgNqADA$|FN zIo(k|`?r?$n)LEdR=L8b513gI>;6&*7=#Fka(#9Q(sd}di>e_$zKV#=G?q<+7VOd( zI4KYT?(~{mB<2PFnk~dkDa-YNV#;DJdRDQ>m0fZBXmY(OI=w2{5^ky_B97&41P@x^ z1;)5?rnCG9Nc@QaJ*}RFWZgHa)Tkn!k%H#IB3_xod09+)PIC2#9lRnMkb?|)vsuG% zA85YTP+aE|B5 zv)^Iuqvzw6)5AeH2>`sT-HOoSsc0ECjZe==DkL2f`Y@q!G?WDK41@sP^avt>(<2^b zF z16IMfAn+ZuX^Wn4!$`?f1b|fu(8~tTOmVt5D^E&EhqZB8U~q32Gvk<&by3>FM3f;y zx&*r$y<}*p1ScaYdy_#83vBc@t`JC}jD>_09ZcXWJ=pPz!!~5^sgoyU(Ihl+P|F|y zvf8y&ne0tYmC(`=osKgC!ExOVT3vg=`@avv=XDXrvYFnlCi7ws?2{~;GVKk|YR2dP zBl3t6n9(>_W*Hkhl9ver`Ju{7r!8rCxRvZSjHrU@-%*`oRAzO7NeE?$7gCu46WT~? zgPEQi&%(1vqP{E*q)n34)FdP&V1YN`<-nJcLs(dlWo1ZjJ@NM2xV3KiOLXWcJ*fNq zh+hAwby~sQBK$hRvF9iMwL`=8{}T{-IWNwux%Xs`T|_ZE`d-LvD3pqZcV{yknm1{> z5oPTNcRBmm7jXNRUi7g>ELP_&9+*qopExUT*l*@=TIR)zH%FUo#9XM&A6xUKda$~| zPG=>X`W~OMbos)}8^Do0(?c+Tw;2aqlrhreF#{uNAQBpH8gIL^;O=z4AGqK`I%aDq zbM>pGv1XY+iOfq`oZ5Ie!FcC>zvJ%SZ_(0P3q< ztmDCe#QCGGU3*Z>F`lD+o5@6cB%#W$y{&_%k4N@0)A?-T%p1esKWS!(__Lb^@+4~K z$C>|)Y@E!Ti&EuHF#9!J7|{KRn2GPB%|gs++?Uk|U&klTz=zGu#u7Fvx~{P#4p(*y z3pU&uzeH)r$OboO(~U3l@dOioT;^VE!!rRn7+4(~&Jw}H%E38>XFbEw7hU+A-|+^9 zZ>@e*EaD3k(oqfH70fi$U6X7?P*`@%xehvB6QBPHe)#4`$0?2fgc^+=9T$%9(e6gY zGm?JZ0N$bY{TB+Ptp4%Dj`wQzP9T1b==d25UQzh2SqNY;6)dGn8_kj8X(scc6KQw~>`{2aE{KZXB^OkCBrsL6LHfkt_qmS;dHIfn|MSc$frZzz3Pz zhwA0yMFvIhC;BC_0`u0yP;!0zR|{nLu$z-5wqd3py$OLDLDw1$tA<0OJ-TPU*-%4q zuON(wQXH*cqGF(SRWP z@$;vol+=6M>DXI`_0+N!yGRtXzqi z*G9RO%Y#o`aoVJZvEsR+$Oh8{Jq?J@eIhG%SaZ8sUK-S-*m1g>&>B?4qsL(85 zJtS*>P+R?;WTaluRg{Qj)V|HEQNy-B_z zU3!iexlHOm@LuV34a5z(UX0nEHQW7C!>tE`AY^Ek)7#yX`p>9WVt!G9eTsTlzvO~0 z^(Vgyi0Ho@@dt$QaczZdFzX2?+z=f!J3VO8CXkKC9Z_Y9_THU$i_6g&y+XJkt7$)I`_$cXCqQAXrJ8O?mw3uZ9N~cR2hR!x*1q>*M#kzx{?%-+y?x;cXmlMueR80Ab;J zla`)~=Dz_w>qKwjJbsqk8tphKGzn%Q8!W0*g%{M+dpmAr?muKDqt&9uFr^yAV}YKi zt7j1xh%!A}?U=G*1?z_au^bPsq?OY_$1jp9_AdGT*Fhe`tN@W^s#vPsCV^aKs8hz0y8aT^KCm|?ScS?4&) z`MglzmvU_wUhnv2T43AL0~g#F5%}ux4{Ccfd&gwY_d(tWFxDTyQYim`cB_8=q6!lv zSYdV$RM|24rp-{t4|4a#DNT#w_uS>DJ67@7`|~N=(BSCs@b~F@$G>9#X3*0VNzdDB zhfvVdU%uDZyPm7#`kw#M>IAm)1-}Y^`t)i3*Dv695X8F0&ELyxGrq5@Vs_3w6F^#| zQpg)JP(Gus;SpMs%&2jtC=bTL%GZ=rvLS^Y2`p(gH_+IcDa-XiQzN-(;+Nu>F`GQ( zC*7f$JK&7Nay;A=Z4DV0UmD*iAiKdt2NceLf?82ilbemrwhsnWU!T7TSZ%ZaET1gM z1zxATN!)Y=#2$V|3Y61f3^m+w{gTL1gw-?mxyZkYS|=%wz!;!4k7LWm&wm&=qL(c;07jX1I_si2_#Q9=xoIx8NOU`TsVU;B$U%I%+DBH~qHj zypgjIk(RSzeG9Y!*o)!k_HS)gayKT8g_9m8;2PbA%+hNK`s0Q~^xvlJ((4E&AE&S$ zybdsjRZmA6pdtjqB|-yHJyX$Jf%sft`m;p*-Y2TJVcCh{Chr+WuT#B2UDIi^tNpB# z&7Slyc)q5aa^HY%515>m_?_6=o#pFadZG_L^hE`#h)W%W_0CM^%iS^UnvYHH6Yv4A z1D>LrykBl|=+1Avxe(DdXQoLM@3))nPd2|L(^r$Bxqc}vJ`(meV0ACQ!30WPZgVT^REB;uGKWOv4+08Gp_t&&V{w${O6X<)Ml9mH7vu_Wo(#&1RFWVbN zBqXZl_hW`FJU0}5v*5*z<=Zk336Ff#)J%~K>L%$h9-WmUz&;RUKlb+6cY?v(6AW77 z%fcb@Z}u@ZO?M(5&qVV-pWVNR%emmQVIvvHWC$bR{^Km8dNi^7aK;Yw2LH7D2zsN+g((rRh1SbXSwA2M{p`)Q*Xxt#P#sgg7H`vKUby zK*ORCH$o8Q+jN4QjZ7JmRAn<3CC7I3H2GRy=umdtY-;p0dZG-Tq7R4`s)E-CgA6WB zVK=0mJ`B)Wv9m}p1`!6p;sR^~m4GpsV}14lH9y_+r}4;E0AmAl2W;-e z7qn9>&R<*Bi-1{hVEpHNqS-b$xqK#H?BL<*;Ga-CeW%Vw;~*;w|MBC;Q_{)|R^y_- z3(i3gHv&CxJB-IybpI<05Zrcmh^R|MDByp=D65)Z{(Q(_g!AoRcQe%xt^p-kh~T*&j!HQ)EGqJ?q6`8&YfUOP!*&HWJE*1I^;y^rCkdGZtD)cjx|OKg$y zQQrq!(&GbVGYNzSQ`!eb(3TPqam*J-dRSbIrThQPDg`a9vX$_7G(L8V-TbZIS16(# zCDuRk#Q@~X3LQ`X%t`r9--lTe@TrjqFx)z-Gym@_+xfY}zpg+LPd$h0o?}2;4N-o8 zXlkh=9EaB*$GH5BH2qlri#@ayz3*jcjy*n!sy$h~Wwn;~eg{6d0m7dJ6lFQgehZ-x zT(frhcTXjCix6Fe}% zK?P)gfz1I?mlxx&0bS-FOg5D%jJ{%ABs>tWai_gME^jh(Qng{mAHIei&~I?VX39t~ zACSd*u$Z#4V1a+wYOZ{4+j@WNnmO6HCg%c_$AU(12wieZN^gkyT=TYWr>;D?^A1#Y zd{22zcmGAz_>6bGb|S>2{pX|&>hiaMMc3RWqVkR}`oO!QzrzeJd|wJ59_8=8mv$#C zL<(lt=O4yJ?&MZYP)`1tkX0PnK6|10WsS&fEG9YdjW9bq0bG26@KO1jkz>uioiU>? z4P4NYPzF$GoY;5P%xpX)0sai)o+5MCQkDWGXDe70gs^yQvy12&zz|P+I?1?m6K1raSAXCt*Md(?PgDNb~UeTZ5VAKkxK1n`qYfE|v$it1pCxJLdC$96E;FaIqxKEQDzS#NQZlNAI;z%vDMV zu^cq{87=uaYY9pzP*PZsx_B_-mm`fVWolb3JZLQt;w9^lWi1mxMcfp+IgJ84h_Uy; zwXM2t*fuSvf#ywP5?1ojxnT%!C@t?SdwGYKhBM8;D&vK}{^WXSDX#y~nHE6)kUT06 z1EKFVBPw?vyq!GJET8ticw;@cnVGN49>^2K)6{&aHYg2ft=jmhd2H;;Xs;guq8o!K zC4tZFV4m(q(DABwe-!HNGIDX2qBcrOhw8}$B!~Kh#4LS)g@I;&C`3x3`B>SnR3jcT z_D6zzzJRYRnf@mRom$}nP0AmJ-W?VY`8+u^YizQv*X;7QGMfZ*D<<1KI!QgKh`m^C z6%vP0tYg@)EKH9BXJzrx#q=GAg@~6fE3StiCKNVeJVN0>qQn!OjvE8dwby)Rz~QP; zV^z&D7X(uH;h@Pu7+AsMLX8PuL`@`%8ViZjY4$J`&S{m!%(0`Du%eN0+S5zTHh#jw zP#{4lMb(P*q}=8qhNzz(z3QQYC`elVImfiKn zBc0Vx66ehnSc12@E33rhKS@zd9k7DmW-Wsr9~gokCQR@DjA3;@JTe8n{blF@LMNL+ zfsfvEWj(KtO#i0kAAtOD9(*MrHig7q@2T!iH%njkKe8GL&eRI=J#3YqJ^Y>Nxw>vO zeRy1Ty+64cS!?&sxYDh2zkHUiA~K|}s-x>__+Tr;tK$k+_SJK8!;_gHOD`ZxFEC4Q zuG!scKRMYDWFSFsRGMa$rVGU5r2XV^?4_+saMF{~-$q>K`z!xscrU@ysW$3qAGO+nt#Wn{#`AK$(qR z8Fy@zt=Hm?ln`@d^Lx$Xve+S+)C4f`h>gF(meOOmm*ao#NFPs$=jVk84oxLkV(>R# zxs@FJ9v$t4rbR60Oh4mP6L5Km!ef@mIlBzf;z0zNIFLxxIe9pcSYYA_AhVGE^ccbA zu!X&WKNADl(5U5%Fdh*!DF;C~Z#X}1L5FgptYyf2Ze0JVjQw3fLp$J9qT^J;1%(hD zkQnD-RLdN!MMQt#)NA4gqBi*MF`p2rhOqG9+#onp%-M5f)%)Zg2lq+L~ zF&TJ{px6etMf~@K?m2kqR~Jl9!H#fqbZ8c{x#SCx%4R#A3@7@WIfvfqm|ZRm$K~+g z=P&HMQ$!F&aJVa($)E?hm+eqG13T!vgRF>JJ-Cu(|DWHZ>>NW4;UvCyff`PnrdGAYgcqN&5-PT zk;x4`*?d5C#;a;y(iq?K*vl0$930ck8boMma-Ja~jtk1UF)Y7Y5gN#PlOZ>sfIxh@kMmP5NvasytI>C}< zx0H52C)n1w)JIaHNa9aWSm+&2j%_3FBnU}O!AEI8sAbX@CBgi z7IBf-C72{Cy0o-8@E!_+7PWhc#^oy5esuCkSd3Dfg0V!9m6-9v{_Sy4oksyLZ866Z zl>SrZ7g8luGzU#iz->duqt(hJDtU@|R(`CKP&1}RYx!YH8(47)!3EOtI#LJ*;wl&m zI#|LPDAIy!Q>fb^6(3+5C3zqk@7?7Itq6riEUBZhZ7d=j5@e#I<<+p5)Tp#qk}8Q2 zKycfbJaTEgm_ss{$)1NSCRT)ajFyBWmezxG_VTHR7!xS?ldSUwOq^M$P_+;xOB#(D z341vTc`I?&RtjA~jPcs&c~&a}KJX_-&h`}QEKKA5 ziy2N*2}q8p`0#$j@~fOy{Q>Fv|g_A-zM{4 zujvHIJTK2@rAS5nMpNp6+n>iLFZzre??8E zBnVGMiBchds*0+ON;JQ)Nls3Sm9Z;Y_XWNGtCu<>X1uA)vmZIa^+4d2M9@9EFMg-_yN^V}rk^LC2ScUpt_N#-q$* za#JcGI3b7uGNJ<)fW1cWdk#(!C??Am<=eET*#GwE!8@-<&#QZ}qplXiA9^yRZThrn zWMa${4qM+dInqJL;USMFy2g{*%IifX`Smke3w-mQ8^XlKaeu1xJ0+CkF<@XFftWMe zJnZpjkM4h(BR96sqpu%ey{sMVbiJIiNAji=5ePQYpzr;;1lf})!r<90_d&Q_g7Ijg ze({wlPmT0W^!DkNZ8uM&oFufX0dd$5L2>S@vofx9;5)(eaMay_%D$64&O9nj+GcA# z@~DH!-}gkZON~~%LYqdTvGFHS}`F*M$!5Pfqs^7Ej4GzK<3Q zWxN@Rbbf*Y^b-!o|I;^x?CF)e)mQ5w+!^@l8}0YDufI~C`+Il~?sUU${}o`~_l?mT z$8TRvs>;|`ClgKAcU2sz&|JQ$<=WCP{=pJmZ_E{m(rtD=S3gEm;d*Z*$wVaMi^ z`7qP_%yu{YLQQxs-vxY`L?Wf0LN*RFA3V53RB}57G@TkEV5~haE@w8@{wj){`<`Z> zm1wj={#{(|k2L7ccP{1G2;=6+XWa9n~?FvX8V&V5@${Xvq2&Rsi2kLc#nc2|( z_D|}<`1-1$(N3Pc^@|j13PdNSVPQZ)$#NqtUu5~+s8I{`RJGz#+wchl)50vbT6Y9b0A9hAQoizA0qReCZ{6CQd+?3>!*CK_AQ9=flK)HmKkIRZT2F+;I zOlaRYK0;O^l^i83y|&M-EWx6yX^iSQ&||0QRGDxv3+A_XX+tquZ%(dNv&jil>Yv3A zDb;s}wrgmb50MOS88D8((J8A-c&wlz@4~Ns9359bmI6Su_VPakA-a0}=nRwwR^k<& zw^^lA1U%t)SIM4*NJd zCWTxZACgibfSnPpW>2m|PG?dzo<~DsNCU zhL#E@+v4tqedln~Ytu%5tx}z4Jd(O{dp^XGgkYHR0T7=Vjov8kH zD~XeWV&0M}ZmX5Vy&o9@Q6DDRt%r{sFZ+^1Rqv4Q@8=LGEx1oMGJ5N}E{H{GX*lWGyBzWhy1`58PS@0;0xL!{`3+A=AeD-cnF`)@WYq_rgZ zy2;_^MAaC5J!NrQ>enI*;fSGdTqb9%$D|P@%ErwC4SvGMKS4OW?3pW}nSJg5}AZ%Y7pN z#Xbum4i!^*Y|#GiphL}|V=Y3wij^1NrI^C4Y^AZNXC=X*u)f`T*5O(f{fP@UDjJgQ zO7rHoGICAk_lY{ivAh~&BtV(`X9V~`l7!1GMjcWFz)h<+Xb>1??gm13?pT`s5 zH2^?XljZ!yMYtxrq5sl*xI(R~;jgAgBx+WLWA@H&%-0u!0y-eJVpDQh&8hjSqM15^3h!$D*59`nx7RdTc+;7=%Xq!Gc}cih>+wy1Z=HTwFF6V`JUBezAE;f> zTx;JL1fIT{)a-23;<^|)7hLTVtgtSCuf`Dt>wbB3bcLKa(LAAb4XqNDT~5nt`rf73 zGaGTFGF&~PbMMha#{ca^)~y$`l9(G$99f8*&JRF+S#e z1a#*;K1ZEUGaj04|76gNS4l$PQG~w?Ivov#N(`uoMumJwFZDC1F;TU9*Z#o$36Aq}5D#0NEmF(>@ep#EX6`Tnd$Qkfm=a z;PFwf(40N&%B<0+R!|=Oh>9%(k5o*Owj9E-9JXdAUBy+*z5+dRrml=bNb_?#RWj-h z;4Z^HsT9B`7F9ZBPEf=iJp4qgJ;qOti&g%$psCbDt3alpDW$@_;OnE>%1@4R9CEgqw#4A31l<+TK(RXCGNyrAT*DdeqGzuKWkA|UEN{H#AL-1f+4>8QBMlE}FzW|txI z8dz)#U}{bb=vuUfqioGQ78}%^Sw%b-q@q>yp?y}NMo*$f4$}Xd+N6j=qkvr9TB4!_ zgM|m3RSTn@9fOV!lZp$Sjt_%%o?J_aAGe-brGiSrO1uh;j!|v)hVf38iUu^yAVA7O zB`hO7B{p0Oe@DzU z13x~mgo(nM%CL+ub=rfd+WcC9^0k}U(_XZNL?A}=m$HKwu3&6}s+ZG#?alGM&y2~} zO3@NjG|0XdW*h@Gz7c{lL$tFC_LwL(E180>;CQO17Q+#}vFNS}8>cLxMihJ_4-S-O zPhbCyUJ(fqPH5HvYYR*w3sOL(9baZkYGixW{~MpuL?<&@XE!V6Ve}&PdOkn%|2)n% zfAmQDeBXW%2U@k$Kfi?mL$YkEiIWH4yx}h{HV~P8u4onlekQi^-t11rcV%`ne{Rrz z7niw`vVTmt5P%)WLX%LHjWVwAlb*#(&A@K(uN?ICD7?1SBN$qn|X_f9JxwyE+=&Uaf$Z3Ja5I{s_^;KBqGnJ!Kfa(d^a9#I*Z! z#1$Q9l`CGl3W5bV@jqJF4-HO(?2)h^*uTo^!rh!rM`MUAHJEdh!t&PT))##3mG{d| zxFsrY_dcL(6`BUu?+D+y<^q++P1BCI8MSLysh`scT>qq=iT}jacmLunp~alM#je|Q z+n(TKVsD{o_ZcR_Yav_jW#hxY{V*%>JHFm?o;ECm zqvt>V8=g8G7+8{PPMS%q|k-Tn7$LKQuji>vciQj^0ZZSgqu-puhc(Q zy9z*#85z0;DjJVoGm~{ym3CE?sp2W%SWY^MtBCX3g%bi7lSIshC^mp7t8OFi?D^Z%wt!1W05?tC$_R57(E^i(agdV* zvpw>VpF*$;a(JkRO~}I746(dGq-OX<|5fG|SdLT#4Ercix>Lf+BfUqY{0K$Vu)wrN zuy&x_#)K#)V`Wgwk}r^J8qVfuE(g=Ylnzh6N?{NS62{B8QmK#we=lg%OQ?kv#I>9- zVM5~WeHaiC!4{S@#G=F_TLbRILbT)*CK2rFik_(`5~1lOAQsBPgiLw{f3FBEESkWr zZUNsvoLS3zyLj4~I=;!s z3!13^?Jvo~+3NVyQ_IzDf-*`jcc?j6D71VDD)a?`1s9}4*JQ=lD9A*a69wD`#^Hz8 zlxh^N!zQo8Cz*q%4u;dXYev+H=fetP3lo{;&5}_vLf!K9faaT+|Fyi8J5^&TMN=C@-4LRq9}OIhY~V#+Fq@Ih z?`XM!Eoz>qaK_s~g(VCItJRC}gPXVP|D%-i?VwZKIGuVVk*HbbPPRTn`Td23qUO<# z`^@E|O<&G>R!`opLZVnQ8FtE$60dJ1=g*s1avd10R{PuF^t5~dkGB#+al7hMgt&Wd&4L2z_idK#PkNslnGZgfHP1O zN@EIJeM?!y5(j{lYV2Z3a7AO$gNc!|>CwH((Q8RDqkBR%?!V_&6mjsvlfCw=c+IjP za(aW+?1jn|@>w-zwGtJv&PH6h{)&-G1;KREqKj)01Etvv?QP6u64L?wX$e8SM*;<`qzPqptIF}z zF3?GP7WWt`RuE!AFik=sLd61AD*0-q3e*cDrm!qPTCq;#CZ!O~qJB#T(iDjqjR`=R zD)b&xArm@R6HE|zgR4k@06?609+Y~jD4`nuodjMB-zo&9O(awYBtWN@fJGseStwG# zNRn0-0UakuqDF)=I(s@XFi1{AvAAdqePS$i3@>;yRc&M_JoBz8sb}katWIuIVa+;L4 zJ-!3Pbb_1J=Fpb%kmcUy`buZJwAQxt{HvzxBbCtaEhEqWIpy->4ub#vE!n>NHJ3u) zx4&~r9Nf8uq%vc2IzOPWHc?Q4k*&2bF>wwEtT^Fxtj`!axK+vF5Vf?07-V%tQ(1^t zRufdSrW#KgHeX9?tOaINJb+`$<{~!R@73_LA6L^*83KT5?{B zFqWcV6?4iK6-}?MhLDsW%;@vrvUAi&I?tqd-i7FS6SBFK$wCRWW}7W1j2bZ^!Rpvn zgdmOYB`qJ%9hFiVLCSEu%C6~VLXFjbNhz!E@&qvxXq0why?sSp|Y384yz1>#h}N+Bnu}Zh7zJiFNt~& zq)cT=rV^5-65{4IWKCt{OkHSrITUzAqb9W-S2yrw#DYPRA_ji`?~}&n!@OauN)ccT zUfMASaMnSj@<1Umk=N0vSsZ$qfOu=(!QbQL@c*jEZ~yTYZT3)CiwAri-PRn0XE0{> z!=#?((v*hwcZL&X_jsA=cNnqb5>JqJ7$_2V zk`oRR6H-z|?Ea+h*sv~yV92GGIDqzu<^{G-PqQz&4K9Ph7E#%Z-r!)ph{nql9kqDcSZ5ipm@Z>-vtL_5 z?2=5MV7z30xZc=`VK{BdaCg1V#@m-%G}1y1{<1&x*f@i+@J9m$;{F2J{7Ta<1i?S+ z{mljD_0G+KN$VJ%F82uBG~EB-?^Zk?d`zA7+yCCOCikhU@RB!Q41UM|`INVPJh?dU z(wLjSYXz5cj@dT9D74mwlX=q6=3WtiN}+qkd4-dA25r1SVf<`xh!$AIwTDo4tVDSs%Z5hEW%r*N#$H43UVT6c^PTEDzt|o6tb%xf}cnR*9z#+Q*tmY48^Z zBLGaKBkhd<*)+>~Yr+G51@N7ba&jOA+-Clk28HAo-)o-N1!RHfwlqfj)`H z&3JSk|OAGDm|?J(4(r0wU6=E7DgEpC@IV zGO?Q*X2ntyk>O!Q9i>o;NpW3WTDC06iox*V-QH~nBQ|XZvJ#?{k@!(G4H~vaE#3>2 zpITJ}O+(=-W#aa=pyUcAG z#Q^|}E4W6Gp#8}SJl>io9V|@|i^d^yD?p5ri`gg?2g>wRDjUyQGL-IdOhT-L zuXp<8WV5h06`AVT@l6jZV|p%Mhu0AL%RAqa5%7Pc=J~zAfroACcK<%2%gd8g)N=sb z?ZMF#LUcM7yX$RitJUsKpC9Uf*|Wu~YaQOw<8!!UlMblJDcVDKcEtJ$lJTNgckUK; z?iQVRHYcWp>G?dp_E&kQa_viwCsfBOa3rOtDHgJV=u3WqZme9)xG$n@3r0y)@Is=%Tg+;wYbEMKdYyfj zdCf>^;ONBI@aZ@?DRUecY@MXXMyaSMxUKs)Fp?#rEKTU4Y3Ee)Wl z7D?Wbv8$emiJE$}tc+6Iwd} zoO4LaJOi3MB3T>YYao3-oZVZ3fgH8U8Kq2`d^KLEax|ppOyoeqP~V2d%%157$+}semMIf}8>VEc3Cbi@col&OBE6G14pTe$BnuhAik`6%G;knhB1;VBJ4Tab zI;Nzur=->iUll`&O^jH~K*?eQ7?@7xI7;of31pD@vk^U8M1uCDQkGk#5`&u>$gija zXVOTY%)<-(dq3sh-~OjQ5Z2*|H15M#?H6V9=xO;OTzig5phjuFiQYfL6fYfB1j^~so+aR(*_(Y;AwV0M7*LMu>-GkEMq%^&!6p??nA}9S$>d@W4Pf75 z@p~dFo6{I9Mw11{=np*2&SS9x!xQ?UnCxwc@H5K(67oxI{%P9l=)`%AR9|5-W7uhu zmRx)J>dD(QsF(8%*g22f+8kp*LB~fayg~#)VRD-zIQ4GulyFK z11F?N2#}yCYU>6GmJFNK{hqf+DGh38Rd#&XeZwisL<{5J334v*VuI&G^{A#myzR(8GT*9vNSf^KqO zLqrz<+|HJz?P7+b*i2D4l5+IJTN7lQ1>Yj3ChI&9SWDIziqMegW(=jN2M??y-_4pyb^GoBP3jE_a@IP*U&~I-4Sc;q}RqR{2#=sb(ivpF{Up1})@9@mem|OFDPi@YydNz#{C`>VJD<3v5%_odW$4^C~Kf zN@}XoW`c~lXFNP@&n6gYiQ0OSeyRwZDXQQ$afGIZsJ%WiIudqneEd2kB|%Y9(9QM! zcB}Dse!$L zt`yEfj%p}D-nT_EbVRbb1yI`EN*|kIEQ&D(QZs5%!+0@oCjth{&|gU&8|-ew2F8m< zCd|N&wFq)EGHdXaNih3k(!xw8Wf`dCecuVZk>@w(kv+rD}*Es$E zzazkx)gQhZwawf$z6`$}-9qYZ-jU3@ubGG&+EJJ)a8VEMjfWDq;eR3+JZBp8VSL|d zBqU?o!H+%n%^3)9sVjE}uVOKn#TzV+>Z#m_ll4a{A&zB<`W^-rCqHo96n0`YUc=*Z zCHF!E!QgR3vg>R2o?$n@z`&U99o0p{le`uKJ5Bje#2MC^>8?acel?5Q@R*-Evz5NnYk~dBD}YK+sF46 z6vwS@nORGjPd6W|OgdIBkq$s9oAp1svTD`o!U+{mTl0=!Wlv0mvll9pCsBYPFBZ;v z3Ni6l8UG?o@JP=eulz4n;b=W4c?|Nrzz@#-?rIyybp2diT1)!N6I=@QcV#={PZ>umbP3s?I{fK*x z%k$e89Jak^a=qG3`*-!UDO|1FA+=Uyt;6Y_5oJ#2(9o3AEWOm~e@eh!-8k!a4^?u4 zQ$|B~xL)S`SM{&+>5wj6qt4FUGn-Z>T~dmokftTrOV*f>qZZ5~IbJ=&Ve;ITywNTF zJgE&`MOFEHrEG*o{vi1`cuhydq7sm)8$9lcmu5Y}>xh%TGP=0?P0h~-DWo9#p1V-T z`;HrUX$f)>P1b)&#do9wP~9)X*3@37C;a?*s_8E3#m!PjRR5m}E-R+T()nb3WvOCP<^~S01|4Iv97&l=aN9bI0`*mrJyVdI*D#n~% zK|@m*%mS|z?N2}Csx2j|-_m@ct+XeqDNd~%lVSpb^N;CC3qaWuW3b@HQ38C^{wMP7 zg-c3~RcUiwWZ~Eh_7r!dx)O|(q1h)~bCJ{zm?``}<*QagH0qt9)gv_8JXv)i^o_J9 zFk&hDB2=PgpTUiykHndsiQG>xV*#cv>P_g4+HnIGM6;e>iY_U}5c&VBkM2tvPb&fja0yb<84BM2KJ~wQq?lz)kEyVT9k_;M(#ZL-EENtcgQl@~k>P)W(ND9-x?WJhYPKZ^p)_jhS2`_oT^ zOIeBjVoA`K|Gv4yzOlv~DXS!_Xw0mvw_+Nnc09yP%uEVf$cm+!jAC24p9Wj#;{RX6 zL^NdVLA|KyuqamdWhYXcTwE`R*~nlt|)E6ulBC>5Udf8}Z@m z&1j;)5C9=Q*P`v7+I0il4-v*_<-!1_hsh{iP{6IE(b%5mL?*^iB~?Q@2V45JU_Uhe zOjcDxN&M?9)L2?aZ-jcPa+3!cHuX}i^}2>pvHTF1IUBYi994EV{B)qHL>i6Z;hbkQ z_Ii?`@axq_rs;a;x{z>497{>|P^Jvi298sQmt9Ma4`0B`)*?2+y4Cg+_z>n{`-uil z89mS&)~wdI+S2oeqX057logE1sT(qd6)0SqjbEs1+|Ej<`Lje?-u__l(<16kf?{;u zX3+C=W78X-BSApjiCq`%8wjE~H8MdvW3=L^y^ z8tGty&)%cq@m=4cT+KBk)P+jAC&C?d(_c>*4!YSgVH$En3JWOiK%ZCD;IE2z8`94j z3w(JG>wfBfL*UdbEZ@^9uOa4MiDV+qEDR^LNZO&2a!vpxDrfH$0v3Y!1f|wLD4Xq< zM_()09DV%1UDmt=%bqqn8I0Qjwi9f$8lVJC@CZuc8cOK57}{&GbCNOD9P1xg#2@g@ zH!>forfByY)_!_A9rDH1G~E>5!|LlJ5VfOMi{X{4zVBUCg1GG@36_Mjl-I+f&w*-fu7ZFa7<`RiY?i`+iXN7}13 z8wZOqa$59F%1R27ihg8jQMmeA1Q^ah0(UmD!6pFt2;)%>)}5S-7B^Q6e$1+z>^=6` z1H6b4s+u?3!=BIjG5Sc8C7>k5Sf1ASvg>;!wS1i}B^i)EtndYB($s|4(6*dZYF48% zO;C{ITg^h!0XblvT05QCr`LcgYKf2-XeIJ|??d9)Ag?}!EKT}~K(Sm^wO?8l(fP+K zb~%&7!p@|oI(8!y=K&jM*}Bxc9hAs>K;CSDvuw*b&Sp!BYwBt*?}lNE6*&=*@tf_Y+Y{;-d(TPRB_!esgapbk<{f>K&s+x69`*& zaKg(c!GAAno@ozR=Q_5XV@1?ytuFg0RpFR!`R^6_(uM+OB}?avY}d ziV@11K3$E6;UL8j4JJ5-qC>-p2_Xx{TB}nou_^q?%|hRfx?@@qH&iQkC?#<&Cv$R= zs2^p!ni1z^(6n?Y(TGL}ZbmVPM$w2Q_iC}0GI+|^FzQ&G#kEc%cKfvxW5f{=q$s>F zUZ_7HXDc_}=(yu9Mb4$f&L2qXN)nZHB35%E7cDZSciRW~Xr{S%P0gd}4{P|4;HRg}elXmnwU8Y|^@jvX7C z2ajD7HC00CyP@snI$SkzK25WvApA^!`g$h3+pVYkn6uU9P+e^`XNyO#W}hc0Pd;A#&2ABMZ@3(P9*q09 z-qLOuMf;{)FFkxPf9%&5(0)F-Zf&1`D~4*03m3uH95HhBQ&MKVPuqI<_9HdoEKX}E zUD7w5!57IFqWyX`Q(@D?{X2M6ySK0q0Om=eC7r=+kea%lE^l_qsc{2!2rM4*U-4!1%myZ31e3g(JzTz^nj`$D zwU)`j6siI9&Uk1&wP2MEyK@iRql~g1Vj8v7^YNyv-%-b?{LhQ6#gXgM!fe{HT{B(U z$qa0lWR>gFkTs5<5zn_x6e3k?(_QRr&OYaKF0VT?XMB->>z=&G@m}e&rMNwu zI+QUcwN0zJnN0iVu=`>QHdL5{wQ@f`?l$zFj>A5;UYfjp+&--d-24U)^ZciSe&{P} zdS)gk+ek^vE2yZ9uQ)H2RofL;f8c@XTS^r~6Q>_mIbrA(?6=p=& z88IHx^xG4B5o}HIBYP|lg`V-bc7XEVzX}l9ksnyx%By^SGok3N^lS$LW6_st=hKEM zM)?r;Q&5#1Gh>Qnnzf`jkNEm~li|)9a`tO)QQF~UMPBV{*OmwT#x)UF=^d6GGtN)M z+)gr=K^6v47cA{~X&(A&(_WVNSuC_Zg*=nPnHY z0$|FDpwsG=Gj5BYtg<+>>X>DH-g0HOzco2U+)fnsqJ00CbprIbc-jd3a zY_KqeXU#KHO)0Rw6k6U98BEh0sz2RYpHh}qP?VHI*-LU#J&U&9L^|%F8%|CQC+CK3 zX2q=T3Z`X@-Ar0zVY4OTU$-w4cq63@2hHq>Wh918WQ34#Le$ZsC)}^dDS^Gi*_&dG zQ$o?bVjU}z9fOh`D*-(xM6)|YO4f&^eS)oHqLplr3B(y38F&rDy`j2<$VDsWUWo==78*md@XES|FDwoCly%0^d3Q&HWertDK!2xss96&*-&GX|uru>M_sjYct@ zQ`CISqFRDu`Nt&zZfWf!V*Z5i_Wxx#K~DO^VCYBx-`TsShH&KO=S%HD($|hhOC)Fg z)6q4;FeYhu=|IK-_N1-`#c%C&o57SYPWZei|y_ z_f_(T0vvy|v(XRJ@P-1-_{+RFQG>wFz@9Hq9qT#2iRl|`dToTnewshk=10T88m&J? z$Yk=QNG6pqSl*Zv%V&&D%s58luEwzzKpAPWgzbeiAj9K?`<|&JibWfbFC(eJABoR( ztVmGEim=cnU-bwC?+!Jz{}V7OncO=He6Gwy>Wg+HeR4VcamM|E%>B?g{IGFZYdy{N zaG^JRaej&9YeOxXfpMX4zcaca&11no9u(WKZqMJp(M*1!Yky#;jq0u?fBSovCWl?C zb!~BA16S6ikj;~vUv>c=i*-ZAjB(wW|50^O_JUTbqs*{6p)a2Mi>&3HlfO<2!p?{j)n z7izz)=(LN1F4&+KMlPJ&QGG`)92o*-N9a39z+q|Yf?$1PVD^(`d;-DnQmD_%%`R5O2#Ad>@g^Kg2BF5-L+IxcMVtdT@YaBuS?QaO1gskw zJ7awPUjZEFZ;qZmnaw+to57sd@47$q`Qw<_xTMUNzWf&qa7s|rUKCdz2$XV`rW~aP zl@|u4hN=OjD@MkF05YnW!U2{@IBH5@C4jl$SBX50qr=reKk0XFZ+#sekmF74@Ej|Y zcDDw?s_fOF$^CNJ(Qbmy~uQm`;Q2Nm+i+SnY=fXNkk;C3w~C=uYDe$>YtMI<9mA z|CsQFUwxwSU}st;dPewuK&;V3=fHBjGhsu#@=R$I=0Dybl+ZA@8l=VLigFF-l{mbp zl6$3MXZxiLVprJ2^1eRf2S3nlK0%73VBpJ7_dp99Ut-}A5OdH3$4;>c3B5(c!jf{b zLNZHJ8~rQ1J__L^W^~+3P2D|t&y4NzQ);LWmz3xk-9W%)*S6U>50{E2VIohAyn)Tc z)wV3PF7B*K10~`(!BtRJmzLC4MpnKV&D}ENjd`_!OlvS$xMR~Z>Ja3){7*nWA1~R((#wRDC z8Bssta@IYMw#Fd5F$tF24U7&acyYxEIR9MF%*G7MU8H-r8SfuXk+RcQuX#9555<|Y zZ7#2J>|EFkkIsv88am(%hZCIz_SM2c4|B6+j7<1!qNOCLt4a&1vT_!Yp{c7WC@PEU zX)H6|DRCuxJRea zeT30{@_VX%R!_08@=6(XU~Dzuhdfn-V;Xz~`zWZSJyupaIRQC0{O%5BLN%k0WYV&9 z1a{lX9alYTtyN2Zczd6Wr?O_(z%saM0bPdh$k0de$L%YogTE)Cx-+wzt=4d(rE)r( zC0^9u{aL-jkit@i2K0Re1qA_JW5mdY6h$>fVdq#3=Yt7BMKuCjSF)*6;7*6f*W7W8 z8ztQk?S{g(g7V&}viUY%cRu>2gWX00V)_MEhIxg<*hm!f!9mWN%83QmRUOV&Trx<- zDV&_G#B0Usjm6!U9AzH%?$DB9I2}A$7`R6B(vrlkW+ku8D6Er8gVvJB?Ofo?s`Rlf zb$&}{aBp>FH{rE?)%f!%<7X_2*Q)f-diA6KqXjs!p#qhWhdqRTgK8fem4-7ctw;}y z{$kWuIWl=qN;@3I8`h-Jq?ir4imF-Xh!dqIZ!~oyNjZ%vr00xh6-B|UubrNfWnSk| zMLEtcRls2W4JC3{aV9%B@IYjbb*O;D{9B|mIY|K%qG!yt1r3In?KWDW>QFw1ITNT} zXd)RyNX-<=>ee)!iao?qNod4M&V1d4m^}RBP5&db&?8bP=xAyj)XkAsSI)$@pgy0G zA!hExv@%6Ekj_UucZMAc_R@Y{NebnyF{$Z@Yigj_T6(7EaL0|7?RK#6#DJwBm1@~z z)VrkLHT5X=@1>!Di5^BC>75lU4qi?=Mt)Pc-w-U+tZM&d_xlI zp~ZlxPm6jZ!_`t+KscED`~1%Qlt1-cURi%Es!B_0x>APbq*kp?!Gl`!#+JOteo}b1 zM@BXVA$@g1U)^{3pV4y~OER{qw4EF8cW#Jt3iEQhvY6PKsv<*}JGcqs(o2*Ryr`|F z`*CIFEM9R{wbBz?|{Rkm%9T)(&j46`5M_MMct#5_&2Wh4(xq@cu6l$KG^r@PVt z4`CDzbi`rWmgqWH()~TmDcpkSI=5AamBx&Rx?`<7y3?9rD6yJ*4pVh_yje!@yf|&g z|3+adzQt;qIFEK_?y5oJHBE?5cSY~Ak>ND~_tIry{yd;(J63N6`hG3ZH+4F&cU?X^ zyyTf2p(EyG#q6(W8J(oxzCZo4+5HL55ku`4E?{AAnOR&F(-MR7{)taQ&KS^;MtA-6 z?EEGyJW5YX#>}7BnvACR18V1FHzufsx@$YY1br`2T}8mxmsC~NwXw-n`QMC`sVuYS zpelIRTzrbYjHfKGV#H|SAtuTzIYNWF+LNdVID++;yvTO~V&d;)fa|gTtY1$6ALAVu z?<6?|BUrhwz2C`-w=lDQxtqWfkCp|KmmsC5O9%*&)D#$9M@K$;dz>Jlg;x1fE`Ibb ze}AoAx`K|hHY2T|jarv7&Gq6017}p3Gi6-PH;=uuK~hZ2i!~0%wYl7^gXVRXmi^|U z_kT<7dYo^aGC4V($LB-76z#gRygUZzAXEv2>E)Q5Ga)f5HFX&HzVPj0JNM8dE zJx0mz-J<|D>agrcpw!6;WmQEns5&(A4-kAiN=*l-Ad0IDkAvw`{`x-^;4l0MyL~(->r}Z+-misE#iAB#95cnTc#%6%>}zDh z|GQ@lLCI!?HEn+!ZAS0+1P>>+%0Nk-)rAO~wYGzO0L9NyDLjz&l9SN3Y7u1r|vVi}{=LdOZ!M5BNg8-Tf-xR@3!Iy$-; zbs305d%tG8tQd@+Q=&3zIJ7W~@P}60jXqRzQHPHD!WltE^DDIEeU6GS7h`1xRfPdr z2R^x!Ku3LD1PE1A7xVE3X|Y7oaZCfRU6l3*JA(@;*9U_2;EG{po%LL&*9S|U^*m$y z*IyK7VpzENq@=9r?xZny?&=CkSkh`J1sPRc+nRq3H)Xghu9oW4G+Yt3aKZ#(qV2TYA_-EUQnyx(XE z687%0*)I+T+Pd}zo0xf6xgsVfm6L;4W{?hrLWh~T8bFrgl18<~(Nkkid~Wx1+Vc|T zng}r~o^P}KBHEHLy#yC32m4A1X~KF^urd4Sf6>xz&dX*z$4uO9n6e6XmNC-$LgOjr0OrQono~IgO40B0t=sB7WJ@G; zZK)0`RoSOq_c|_A`;q1dOM2`^XB)rj+#$pWnvS^BoQLw$r7sq;oq@Zxo`_x#WOyx9 zVoP1oNr?MLoT{Kpo!Bl{a&sCbMknA_r1RGoHGcm?OBEBIn$Gv@TLe&vd3Jhn3UV_1&v=LWn<$T@9BDH{#yb1Ca0#h{ zZE5FhU!UuU@E$UvUp-IXeT4l?8|bA|#)N2T`-Lg#>hX z_!t?VhRNQ#`;=dM7;N5zYH#2MxR#ST#ljR%gU;t ztSoFS3}I_)>*DG)Y7etfa3m?A8L~fMey~f39oJNWNj^>6_PEDc z10g&zLJc6T`E{4=qvU)eF)~5KN19WbYywgS?;&`5o_RO_e`4ki0@K87Zg1pyVku2V z&p}XPAH)U`yjA7rp-L|16 zxMifGdtk5gcf=O2s7UAMj_Yh<#FV!+-T0+o*!(?S(5(BOCON>7rt75(fB=ezm#4@K++QG&v1*g zpg&>Botwk)j^I@8!uDzt>iQq&(6BgqV_R>+D0OyELpvFbR)}rn*yZKTq2AG8ifMSy zj~&?QTwD}_V+nV8#{2tY7Iw4w4aL6pIPWyzte7NkMHy!4xJ3awU04EdJtBHZ+g@x;pl|hNi*i z9*jF3j+50TBfJa!_1OdSS>B4V(>;Oul-|(QIwa!d`ed7MSewfmVA%b9|LVb4BSSOc zu{eAu8wiZdECt#X6*mUW1wxHUXJQ?_jR>r9|2g^d%=nPd-9fmgtW9=#0{gV8GIfbR z`F6NW^pE@GS=pV|(vIH4(~Zzi-VWvXDw|_TU1TjQ;qoz3{iR*f*-y+@he7{j{AqDh zM9+l77d-`jX<=ShN5tNdxZiZJ!@9bpp**?fUDxO2ys)4?TEm~v3hw6Ew%ok2At`qV zDwLZW>-2b=-~Vlj-u~ab>e7IKG(~sUtB}7op+3J)Nw+x`CZ_#GN3Hp+9&cmZF=>+z zf^}@}-Z}(x?#p+lvk=I%KJd0_r2ejCz#U2hCvsYVoC!%*pYbwA-auEfi(JR(j*$

og)&}a=igvoW2-z| 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 literal 0 HcmV?d00001 diff --git a/nstock/shot-thumb.png b/nstock/shot-thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..d76c59ddb2687eb5e2de36f6ae658033b1a13b67 GIT binary patch literal 32567 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.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Source Sans Pro","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#555555;background-color:#ffffff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#158cba;text-decoration:none}a:hover,a:focus{color:#158cba;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:5px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#ffffff;border:1px solid #eeeeee;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eeeeee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role="button"]{cursor:pointer}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:400;line-height:1.1;color:#333333}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}mark,.mark{background-color:#ff851b;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#999999}.text-primary{color:#158cba}a.text-primary:hover,a.text-primary:focus{color:#106a8c}.text-success{color:#ffffff}a.text-success:hover,a.text-success:focus{color:#e6e6e6}.text-info{color:#ffffff}a.text-info:hover,a.text-info:focus{color:#e6e6e6}.text-warning{color:#ffffff}a.text-warning:hover,a.text-warning:focus{color:#e6e6e6}.text-danger{color:#ffffff}a.text-danger:hover,a.text-danger:focus{color:#e6e6e6}.bg-primary{color:#fff;background-color:#158cba}a.bg-primary:hover,a.bg-primary:focus{background-color:#106a8c}.bg-success{background-color:#28b62c}a.bg-success:hover,a.bg-success:focus{background-color:#1f8c22}.bg-info{background-color:#75caeb}a.bg-info:hover,a.bg-info:focus{background-color:#48b9e5}.bg-warning{background-color:#ff851b}a.bg-warning:hover,a.bg-warning:focus{background-color:#e76b00}.bg-danger{background-color:#ff4136}a.bg-danger:hover,a.bg-danger:focus{background-color:#ff1103}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eeeeee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eeeeee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#999999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eeeeee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#ffffff;background-color:#333333;border-radius:2px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}kbd kbd{padding:0;font-size:100%;font-weight:bold;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333333;background-color:#f5f5f5;border:1px solid #cccccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0%}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0%}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0%}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0%}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#999999;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #eeeeee}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #eeeeee}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #eeeeee}.table .table{background-color:#ffffff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #eeeeee}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #eeeeee}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#28b62c}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#23a127}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#75caeb}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#5fc1e8}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#ff851b}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#ff7701}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#ff4136}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ff291c}.table-responsive{overflow-x:auto;min-height:0.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #eeeeee}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:8px;font-size:14px;line-height:1.42857143;color:#555555}.form-control{display:block;width:100%;height:38px;padding:7px 12px;font-size:14px;line-height:1.42857143;color:#555555;background-color:#ffffff;background-image:none;border:1px solid #e7e7e7;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control::-moz-placeholder{color:#999999;opacity:1}.form-control:-ms-input-placeholder{color:#999999}.form-control::-webkit-input-placeholder{color:#999999}.form-control::-ms-expand{border:0;background-color:transparent}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eeeeee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{line-height:38px}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm,.input-group-sm input[type="date"],.input-group-sm input[type="time"],.input-group-sm input[type="datetime-local"],.input-group-sm input[type="month"]{line-height:28px}input[type="date"].input-lg,input[type="time"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg,.input-group-lg input[type="date"],.input-group-lg input[type="time"],.input-group-lg input[type="datetime-local"],.input-group-lg input[type="month"]{line-height:52px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-left:-20px;margin-top:4px \9}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:8px;padding-bottom:8px;margin-bottom:0;min-height:34px}.form-control-static.input-lg,.form-control-static.input-sm{padding-left:0;padding-right:0}.input-sm{height:28px;padding:4px 10px;font-size:12px;line-height:1.5;border-radius:2px}select.input-sm{height:28px;line-height:28px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:28px;padding:4px 10px;font-size:12px;line-height:1.5;border-radius:2px}.form-group-sm select.form-control{height:28px;line-height:28px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:28px;min-height:32px;padding:5px 10px;font-size:12px;line-height:1.5}.input-lg{height:52px;padding:13px 16px;font-size:18px;line-height:1.3333333;border-radius:5px}select.input-lg{height:52px;line-height:52px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:52px;padding:13px 16px;font-size:18px;line-height:1.3333333;border-radius:5px}.form-group-lg select.form-control{height:52px;line-height:52px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:52px;min-height:38px;padding:14px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:47.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:38px;height:38px;line-height:38px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback,.input-group-lg+.form-control-feedback,.form-group-lg .form-control+.form-control-feedback{width:52px;height:52px;line-height:52px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:28px;height:28px;line-height:28px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#ffffff}.has-success .form-control{border-color:#ffffff;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#e6e6e6;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff}.has-success .input-group-addon{color:#ffffff;border-color:#ffffff;background-color:#28b62c}.has-success .form-control-feedback{color:#ffffff}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#ffffff}.has-warning .form-control{border-color:#ffffff;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#e6e6e6;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff}.has-warning .input-group-addon{color:#ffffff;border-color:#ffffff;background-color:#ff851b}.has-warning .form-control-feedback{color:#ffffff}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#ffffff}.has-error .form-control{border-color:#ffffff;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#e6e6e6;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff}.has-error .input-group-addon{color:#ffffff;border-color:#ffffff;background-color:#ff4136}.has-error .form-control-feedback{color:#ffffff}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#959595}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:8px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:28px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:8px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:5px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:7px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#555555;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#555555;background-color:#eeeeee;border-color:#e2e2e2}.btn-default:focus,.btn-default.focus{color:#555555;background-color:#d5d5d5;border-color:#a2a2a2}.btn-default:hover{color:#555555;background-color:#d5d5d5;border-color:#c3c3c3}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#555555;background-color:#d5d5d5;border-color:#c3c3c3}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open>.dropdown-toggle.btn-default.focus{color:#555555;background-color:#c3c3c3;border-color:#a2a2a2}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#eeeeee;border-color:#e2e2e2}.btn-default .badge{color:#eeeeee;background-color:#555555}.btn-primary{color:#ffffff;background-color:#158cba;border-color:#127ba3}.btn-primary:focus,.btn-primary.focus{color:#ffffff;background-color:#106a8c;border-color:#052531}.btn-primary:hover{color:#ffffff;background-color:#106a8c;border-color:#0c516c}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#ffffff;background-color:#106a8c;border-color:#0c516c}.btn-primary:active:hover,.btn-primary.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#ffffff;background-color:#0c516c;border-color:#052531}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#158cba;border-color:#127ba3}.btn-primary .badge{color:#158cba;background-color:#ffffff}.btn-success{color:#ffffff;background-color:#28b62c;border-color:#23a127}.btn-success:focus,.btn-success.focus{color:#ffffff;background-color:#1f8c22;border-color:#0c390e}.btn-success:hover{color:#ffffff;background-color:#1f8c22;border-color:#186f1b}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#ffffff;background-color:#1f8c22;border-color:#186f1b}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#ffffff;background-color:#186f1b;border-color:#0c390e}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#28b62c;border-color:#23a127}.btn-success .badge{color:#28b62c;background-color:#ffffff}.btn-info{color:#ffffff;background-color:#75caeb;border-color:#5fc1e8}.btn-info:focus,.btn-info.focus{color:#ffffff;background-color:#48b9e5;border-color:#1984ae}.btn-info:hover{color:#ffffff;background-color:#48b9e5;border-color:#29ade0}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#ffffff;background-color:#48b9e5;border-color:#29ade0}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#ffffff;background-color:#29ade0;border-color:#1984ae}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{background-color:#75caeb;border-color:#5fc1e8}.btn-info .badge{color:#75caeb;background-color:#ffffff}.btn-warning{color:#ffffff;background-color:#ff851b;border-color:#ff7701}.btn-warning:focus,.btn-warning.focus{color:#ffffff;background-color:#e76b00;border-color:#813c00}.btn-warning:hover{color:#ffffff;background-color:#e76b00;border-color:#c35b00}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#ffffff;background-color:#e76b00;border-color:#c35b00}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#ffffff;background-color:#c35b00;border-color:#813c00}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#ff851b;border-color:#ff7701}.btn-warning .badge{color:#ff851b;background-color:#ffffff}.btn-danger{color:#ffffff;background-color:#ff4136;border-color:#ff291c}.btn-danger:focus,.btn-danger.focus{color:#ffffff;background-color:#ff1103;border-color:#9c0900}.btn-danger:hover{color:#ffffff;background-color:#ff1103;border-color:#de0c00}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#ffffff;background-color:#ff1103;border-color:#de0c00}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#ffffff;background-color:#de0c00;border-color:#9c0900}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#ff4136;border-color:#ff291c}.btn-danger .badge{color:#ff4136;background-color:#ffffff}.btn-link{color:#158cba;font-weight:normal;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#158cba;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999999;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:13px 16px;font-size:18px;line-height:1.3333333;border-radius:5px}.btn-sm,.btn-group-sm>.btn{padding:4px 10px;font-size:12px;line-height:1.5;border-radius:2px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:2px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;transition:opacity 0.15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height, visibility;-o-transition-property:height, visibility;transition-property:height, visibility;-webkit-transition-duration:0.35s;-o-transition-duration:0.35s;transition-duration:0.35s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid \9;border-right:4px solid transparent;border-left:4px solid transparent}.dropup,.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;text-align:left;background-color:#ffffff;border:1px solid #cccccc;border:1px solid #e7e7e7;border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);-webkit-background-clip:padding-box;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#eeeeee}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.42857143;color:#999999;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#333333;background-color:transparent}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#ffffff;text-decoration:none;outline:0;background-color:#158cba}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#eeeeee}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#999999;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px dashed;border-bottom:4px solid \9;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-top-left-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle="buttons"]>.btn input[type="radio"],[data-toggle="buttons"]>.btn-group>.btn input[type="radio"],[data-toggle="buttons"]>.btn input[type="checkbox"],[data-toggle="buttons"]>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:52px;padding:13px 16px;font-size:18px;line-height:1.3333333;border-radius:5px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:52px;line-height:52px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:28px;padding:4px 10px;font-size:12px;line-height:1.5;border-radius:2px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:28px;line-height:28px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:7px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555555;text-align:center;background-color:#eeeeee;border:1px solid #e7e7e7;border-radius:4px}.input-group-addon.input-sm{padding:4px 10px;font-size:12px;border-radius:2px}.input-group-addon.input-lg{padding:13px 16px;font-size:18px;border-radius:5px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#ffffff}.nav>li.disabled>a{color:#999999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999999;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#ffffff;border-color:#158cba}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #e7e7e7}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #e7e7e7}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555555;background-color:#ffffff;border:1px solid #e7e7e7;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #e7e7e7}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #e7e7e7;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#ffffff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#ffffff;background-color:#158cba}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #e7e7e7}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #e7e7e7;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#ffffff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:6px;margin-bottom:6px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:6px;margin-bottom:6px}.navbar-btn.btn-sm{margin-top:11px;margin-bottom:11px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#333333}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#333333;background-color:transparent}.navbar-default .navbar-text{color:#555555}.navbar-default .navbar-nav>li>a{color:#999999}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#333333;background-color:transparent}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#eeeeee;background-color:transparent}.navbar-default .navbar-toggle{border-color:#eeeeee}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ffffff}.navbar-default .navbar-toggle .icon-bar{background-color:#999999}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:transparent;color:#333333}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#999999}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#333333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#eeeeee;background-color:transparent}}.navbar-default .navbar-link{color:#999999}.navbar-default .navbar-link:hover{color:#333333}.navbar-default .btn-link{color:#999999}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#333333}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#eeeeee}.navbar-inverse{background-color:#ffffff;border-color:#e6e6e6}.navbar-inverse .navbar-brand{color:#999999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#333333;background-color:transparent}.navbar-inverse .navbar-text{color:#999999}.navbar-inverse .navbar-nav>li>a{color:#999999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#333333;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#333333;background-color:transparent}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#eeeeee;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#eeeeee}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#eeeeee}.navbar-inverse .navbar-toggle .icon-bar{background-color:#999999}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#ededed}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:transparent;color:#333333}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#e6e6e6}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#e6e6e6}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#333333;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#333333;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#eeeeee;background-color:transparent}}.navbar-inverse .navbar-link{color:#999999}.navbar-inverse .navbar-link:hover{color:#333333}.navbar-inverse .btn-link{color:#999999}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#333333}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#eeeeee}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#fafafa;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:">\00a0";padding:0 5px;color:#999999}.breadcrumb>.active{color:#999999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:7px 12px;line-height:1.42857143;text-decoration:none;color:#555555;background-color:#eeeeee;border:1px solid #e2e2e2;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{z-index:2;color:#555555;background-color:#eeeeee;border-color:#e2e2e2}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:3;color:#ffffff;background-color:#158cba;border-color:#127ba3;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999999;background-color:#eeeeee;border-color:#e2e2e2;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:13px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:5px;border-top-left-radius:5px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:5px;border-top-right-radius:5px}.pagination-sm>li>a,.pagination-sm>li>span{padding:4px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:2px;border-top-left-radius:2px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:2px;border-top-right-radius:2px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#eeeeee;border:1px solid #e2e2e2;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eeeeee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999999;background-color:#eeeeee;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#ffffff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#ffffff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#999999}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080}.label-primary{background-color:#158cba}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#106a8c}.label-success{background-color:#28b62c}.label-success[href]:hover,.label-success[href]:focus{background-color:#1f8c22}.label-info{background-color:#75caeb}.label-info[href]:hover,.label-info[href]:focus{background-color:#48b9e5}.label-warning{background-color:#ff851b}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#e76b00}.label-danger{background-color:#ff4136}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#ff1103}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:normal;color:#ffffff;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#158cba;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge,.btn-group-xs>.btn .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#ffffff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#158cba;background-color:#ffffff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#fafafa}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#e1e1e1}.container .jumbotron,.container-fluid .jumbotron{border-radius:5px;padding-left:15px;padding-right:15px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#ffffff;border:1px solid #eeeeee;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#158cba}.thumbnail .caption{padding:9px;color:#555555}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#28b62c;border-color:#24a528;color:#ffffff}.alert-success hr{border-top-color:#209023}.alert-success .alert-link{color:#e6e6e6}.alert-info{background-color:#75caeb;border-color:#40b5e3;color:#ffffff}.alert-info hr{border-top-color:#29ade0}.alert-info .alert-link{color:#e6e6e6}.alert-warning{background-color:#ff851b;border-color:#ff7701;color:#ffffff}.alert-warning hr{border-top-color:#e76b00}.alert-warning .alert-link{color:#e6e6e6}.alert-danger{background-color:#ff4136;border-color:#ff1103;color:#ffffff}.alert-danger hr{border-top-color:#e90d00}.alert-danger .alert-link{color:#e6e6e6}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#fafafa;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#ffffff;text-align:center;background-color:#158cba;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width 0.6s ease;-o-transition:width 0.6s ease;transition:width 0.6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#28b62c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-info{background-color:#75caeb}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#ff851b}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#ff4136}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{zoom:1;overflow:hidden}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-left,.media-right,.media-body{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#ffffff;border:1px solid #eeeeee}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333333}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{text-decoration:none;color:#555555;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{background-color:#eeeeee;color:#999999;cursor:not-allowed}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#999999}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#ffffff;background-color:#158cba;border-color:#158cba}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#a6dff5}.list-group-item-success{color:#ffffff;background-color:#28b62c}a.list-group-item-success,button.list-group-item-success{color:#ffffff}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,button.list-group-item-success:hover,a.list-group-item-success:focus,button.list-group-item-success:focus{color:#ffffff;background-color:#23a127}a.list-group-item-success.active,button.list-group-item-success.active,a.list-group-item-success.active:hover,button.list-group-item-success.active:hover,a.list-group-item-success.active:focus,button.list-group-item-success.active:focus{color:#fff;background-color:#ffffff;border-color:#ffffff}.list-group-item-info{color:#ffffff;background-color:#75caeb}a.list-group-item-info,button.list-group-item-info{color:#ffffff}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,button.list-group-item-info:hover,a.list-group-item-info:focus,button.list-group-item-info:focus{color:#ffffff;background-color:#5fc1e8}a.list-group-item-info.active,button.list-group-item-info.active,a.list-group-item-info.active:hover,button.list-group-item-info.active:hover,a.list-group-item-info.active:focus,button.list-group-item-info.active:focus{color:#fff;background-color:#ffffff;border-color:#ffffff}.list-group-item-warning{color:#ffffff;background-color:#ff851b}a.list-group-item-warning,button.list-group-item-warning{color:#ffffff}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,button.list-group-item-warning:hover,a.list-group-item-warning:focus,button.list-group-item-warning:focus{color:#ffffff;background-color:#ff7701}a.list-group-item-warning.active,button.list-group-item-warning.active,a.list-group-item-warning.active:hover,button.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus,button.list-group-item-warning.active:focus{color:#fff;background-color:#ffffff;border-color:#ffffff}.list-group-item-danger{color:#ffffff;background-color:#ff4136}a.list-group-item-danger,button.list-group-item-danger{color:#ffffff}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,button.list-group-item-danger:hover,a.list-group-item-danger:focus,button.list-group-item-danger:focus{color:#ffffff;background-color:#ff291c}a.list-group-item-danger.active,button.list-group-item-danger.active,a.list-group-item-danger.active:hover,button.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus,button.list-group-item-danger.active:focus{color:#fff;background-color:#ffffff;border-color:#ffffff}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#ffffff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a,.panel-title>small,.panel-title>.small,.panel-title>small>a,.panel-title>.small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid transparent;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-left:15px;padding-right:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #eeeeee}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid transparent}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid transparent}.panel-default{border-color:transparent}.panel-default>.panel-heading{color:#333333;background-color:#f5f5f5;border-color:transparent}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:transparent}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:transparent}.panel-primary{border-color:transparent}.panel-primary>.panel-heading{color:#ffffff;background-color:#158cba;border-color:transparent}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:transparent}.panel-primary>.panel-heading .badge{color:#158cba;background-color:#ffffff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:transparent}.panel-success{border-color:transparent}.panel-success>.panel-heading{color:#ffffff;background-color:#28b62c;border-color:transparent}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:transparent}.panel-success>.panel-heading .badge{color:#28b62c;background-color:#ffffff}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:transparent}.panel-info{border-color:transparent}.panel-info>.panel-heading{color:#ffffff;background-color:#75caeb;border-color:transparent}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:transparent}.panel-info>.panel-heading .badge{color:#75caeb;background-color:#ffffff}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:transparent}.panel-warning{border-color:transparent}.panel-warning>.panel-heading{color:#ffffff;background-color:#ff851b;border-color:transparent}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:transparent}.panel-warning>.panel-heading .badge{color:#ff851b;background-color:#ffffff}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:transparent}.panel-danger{border-color:transparent}.panel-danger>.panel-heading{color:#ffffff;background-color:#ff4136;border-color:transparent}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:transparent}.panel-danger>.panel-heading .badge{color:#ff4136;background-color:#ffffff}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:transparent}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;left:0;bottom:0;height:100%;width:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#fafafa;border:1px solid #e8e8e8;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:5px}.well-sm{padding:9px;border-radius:2px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#ffffff;text-shadow:0 1px 0 #ffffff;opacity:0.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#ffffff;text-decoration:none;cursor:pointer;opacity:0.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:hidden;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);-o-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);-o-transform:translate(0, 0);transform:translate(0, 0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#ffffff;border:1px solid #eeeeee;border:1px solid rgba(0,0,0,0.05);border-radius:5px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);-webkit-background-clip:padding-box;background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:0.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:20px}.modal-footer{padding:20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Source Sans Pro","Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:12px;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:0.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;background-color:#000000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000000}.tooltip.top-left .tooltip-arrow{bottom:0;right:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Source Sans Pro","Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:14px;background-color:#ffffff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #cccccc;border:1px solid rgba(0,0,0,0.2);border-radius:5px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:4px 4px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999999;border-top-color:rgba(0,0,0,0.25);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#ffffff}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999999;border-right-color:rgba(0,0,0,0.25)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#ffffff}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999999;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#ffffff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999999;border-left-color:rgba(0,0,0,0.25)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#ffffff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.next,.carousel-inner>.item.active.right{-webkit-transform:translate3d(100%, 0, 0);transform:translate3d(100%, 0, 0);left:0}.carousel-inner>.item.prev,.carousel-inner>.item.active.left{-webkit-transform:translate3d(-100%, 0, 0);transform:translate3d(-100%, 0, 0);left:0}.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right,.carousel-inner>.item.active{-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:0.5;filter:alpha(opacity=50);font-size:20px;color:#ffffff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6);background-color:rgba(0,0,0,0)}.carousel-control.left{background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-webkit-gradient(linear, left top, right top, from(rgba(0,0,0,0.5)), to(rgba(0,0,0,0.0001)));background-image:linear-gradient(to right, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-webkit-gradient(linear, left top, right top, from(rgba(0,0,0,0.0001)), to(rgba(0,0,0,0.5)));background-image:linear-gradient(to right, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#ffffff;text-decoration:none;opacity:0.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;margin-top:-10px;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;line-height:1;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #ffffff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#ffffff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#ffffff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-header:before,.modal-header:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-header:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table !important}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table !important}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table !important}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table !important}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1200px){.visible-lg-block{display:block !important}}@media (min-width:1200px){.visible-lg-inline{display:inline !important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table !important}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}}.navbar{border-width:0 1px 4px 1px}.btn{padding:9px 12px 7px;border-width:0 1px 4px 1px;font-size:12px;font-weight:bold;line-height:1.5;text-transform:uppercase}.btn:hover{margin-top:1px;border-bottom-width:3px}.btn:active{margin-top:2px;border-bottom-width:2px;-webkit-box-shadow:none;box-shadow:none}.btn-lg,.btn-group-lg>.btn{padding:15px 16px 13px;line-height:15px}.btn-sm,.btn-group-sm>.btn{padding:6px 10px 4px}.btn-xs,.btn-group-xs>.btn{padding:3px 5px 1px}.btn-default:hover,.btn-default:focus,.btn-group.open .dropdown-toggle.btn-default{background-color:#eeeeee;border-color:#e2e2e2}.btn-primary:hover,.btn-primary:focus,.btn-group.open .dropdown-toggle.btn-primary{background-color:#158cba;border-color:#127ba3}.btn-success:hover,.btn-success:focus,.btn-group.open .dropdown-toggle.btn-success{background-color:#28b62c;border-color:#23a127}.btn-info:hover,.btn-info:focus,.btn-group.open .dropdown-toggle.btn-info{background-color:#75caeb;border-color:#5fc1e8}.btn-warning:hover,.btn-warning:focus,.btn-group.open .dropdown-toggle.btn-warning{background-color:#ff851b;border-color:#ff7701}.btn-danger:hover,.btn-danger:focus,.btn-group.open .dropdown-toggle.btn-danger{background-color:#ff4136;border-color:#ff291c}.btn-group.open .dropdown-toggle{-webkit-box-shadow:none;box-shadow:none}.navbar-btn:hover{margin-top:8px}.navbar-btn:active{margin-top:9px}.navbar-btn.btn-sm:hover{margin-top:11px}.navbar-btn.btn-sm:active{margin-top:12px}.navbar-btn.btn-xs:hover{margin-top:15px}.navbar-btn.btn-xs:active{margin-top:16px}.btn-group-vertical .btn+.btn:hover{border-top-width:1px}.btn-group-vertical .btn+.btn:active{border-top-width:2px}.text-primary,.text-primary:hover{color:#158cba}.text-success,.text-success:hover{color:#28b62c}.text-danger,.text-danger:hover{color:#ff4136}.text-warning,.text-warning:hover{color:#ff851b}.text-info,.text-info:hover{color:#75caeb}table a:not(.btn),.table a:not(.btn){text-decoration:underline}table .dropdown-menu a,.table .dropdown-menu a{text-decoration:none}table .success,.table .success,table .warning,.table .warning,table .danger,.table .danger,table .info,.table .info{color:#fff}table .success a:not(.btn),.table .success a:not(.btn),table .warning a:not(.btn),.table .warning a:not(.btn),table .danger a:not(.btn),.table .danger a:not(.btn),table .info a:not(.btn),.table .info a:not(.btn){color:#fff}table:not(.table-bordered)>thead>tr>th,.table:not(.table-bordered)>thead>tr>th,table:not(.table-bordered)>tbody>tr>th,.table:not(.table-bordered)>tbody>tr>th,table:not(.table-bordered)>tfoot>tr>th,.table:not(.table-bordered)>tfoot>tr>th,table:not(.table-bordered)>thead>tr>td,.table:not(.table-bordered)>thead>tr>td,table:not(.table-bordered)>tbody>tr>td,.table:not(.table-bordered)>tbody>tr>td,table:not(.table-bordered)>tfoot>tr>td,.table:not(.table-bordered)>tfoot>tr>td{border-color:transparent}.form-control{-webkit-box-shadow:inset 0 2px 0 rgba(0,0,0,0.075);box-shadow:inset 0 2px 0 rgba(0,0,0,0.075)}label{font-weight:normal}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label,.has-warning .form-control-feedback{color:#ff851b}.has-warning .form-control,.has-warning .form-control:focus{border:1px solid #ff851b;-webkit-box-shadow:inset 0 2px 0 rgba(0,0,0,0.075);box-shadow:inset 0 2px 0 rgba(0,0,0,0.075)}.has-warning .input-group-addon{border:1px solid #ff851b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label,.has-error .form-control-feedback{color:#ff4136}.has-error .form-control,.has-error .form-control:focus{border:1px solid #ff4136;-webkit-box-shadow:inset 0 2px 0 rgba(0,0,0,0.075);box-shadow:inset 0 2px 0 rgba(0,0,0,0.075)}.has-error .input-group-addon{border:1px solid #ff4136}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label,.has-success .form-control-feedback{color:#28b62c}.has-success .form-control,.has-success .form-control:focus{border:1px solid #28b62c;-webkit-box-shadow:inset 0 2px 0 rgba(0,0,0,0.075);box-shadow:inset 0 2px 0 rgba(0,0,0,0.075)}.has-success .input-group-addon{border:1px solid #28b62c}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{border-color:transparent}.nav-tabs>li>a{margin-top:6px;border-color:#e7e7e7;color:#333333;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.nav-tabs>li>a:hover,.nav-tabs>li>a:focus,.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus,.nav-tabs .open>a,.nav-tabs .open>a:hover,.nav-tabs .open>a:focus{padding-bottom:16px;margin-top:0}.nav-tabs .open>a,.nav-tabs .open>a:hover,.nav-tabs .open>a:focus{border-color:#e7e7e7}.nav-tabs>li.disabled>a:hover,.nav-tabs>li.disabled>a:focus{padding-top:10px;padding-bottom:10px;margin-top:6px}.nav-tabs.nav-justified>li{vertical-align:bottom}.dropdown-menu{margin-top:0;border-width:0 1px 4px 1px;border-top-width:1px;-webkit-box-shadow:none;box-shadow:none}.breadcrumb{border-color:#ededed;border-style:solid;border-width:0 1px 4px 1px}.pagination>li>a,.pager>li>a,.pagination>li>span,.pager>li>span{position:relative;top:0;border-width:0 1px 4px 1px;color:#555555;font-size:12px;font-weight:bold;text-transform:uppercase}.pagination>li>a:hover,.pager>li>a:hover,.pagination>li>span:hover,.pager>li>span:hover{top:1px;border-bottom-width:3px}.pagination>li>a:active,.pager>li>a:active,.pagination>li>span:active,.pager>li>span:active{top:2px;border-bottom-width:2px}.pagination>.disabled>a:hover,.pager>.disabled>a:hover,.pagination>.disabled>span:hover,.pager>.disabled>span:hover{top:0;border-width:0 1px 4px 1px}.pagination>.disabled>a:active,.pager>.disabled>a:active,.pagination>.disabled>span:active,.pager>.disabled>span:active{top:0;border-width:0 1px 4px 1px}.pager>li>a,.pager>li>span,.pager>.disabled>a,.pager>.disabled>span,.pager>li>a:hover,.pager>li>span:hover,.pager>.disabled>a:hover,.pager>.disabled>span:hover,.pager>li>a:active,.pager>li>span:active,.pager>.disabled>a:active,.pager>.disabled>span:active{border-left-width:2px;border-right-width:2px}.close{color:#fff;text-decoration:none;opacity:0.4}.close:hover,.close:focus{color:#fff;opacity:1}.alert{border-width:0 1px 4px 1px}.alert .alert-link{font-weight:normal;color:#fff;text-decoration:underline}.label{font-weight:normal}.progress{border:1px solid #e7e7e7;-webkit-box-shadow:inset 0 2px 0 rgba(0,0,0,0.1);box-shadow:inset 0 2px 0 rgba(0,0,0,0.1)}.progress-bar{-webkit-box-shadow:inset 0 -4px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -4px 0 rgba(0,0,0,0.15)}.well{border:1px solid #e7e7e7;-webkit-box-shadow:inset 0 2px 0 rgba(0,0,0,0.05);box-shadow:inset 0 2px 0 rgba(0,0,0,0.05)}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{border-color:#eeeeee}a.list-group-item-success.active{background-color:#28b62c}a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{background-color:#23a127}a.list-group-item-warning.active{background-color:#ff851b}a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{background-color:#ff7701}a.list-group-item-danger.active{background-color:#ff4136}a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{background-color:#ff291c}.jumbotron{border:1px solid #e7e7e7;-webkit-box-shadow:inset 0 2px 0 rgba(0,0,0,0.05);box-shadow:inset 0 2px 0 rgba(0,0,0,0.05)}.panel{border:1px solid #e7e7e7;border-width:0 1px 4px 1px}.panel-default .close{color:#555555}.modal .close{color:#555555}.popover{color:#555555} \ No newline at end of file diff --git a/nstock/static/css/bootstrap.min.css.map b/nstock/static/css/bootstrap.min.css.map new file mode 100644 index 0000000..6c7fa40 --- /dev/null +++ b/nstock/static/css/bootstrap.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["less/normalize.less","less/print.less","bootstrap.css","dist/css/bootstrap.css","less/glyphicons.less","less/scaffolding.less","less/mixins/vendor-prefixes.less","less/mixins/tab-focus.less","less/mixins/image.less","less/type.less","less/mixins/text-emphasis.less","less/mixins/background-variant.less","less/mixins/text-overflow.less","less/code.less","less/grid.less","less/mixins/grid.less","less/mixins/grid-framework.less","less/tables.less","less/mixins/table-row.less","less/forms.less","less/mixins/forms.less","less/buttons.less","less/mixins/buttons.less","less/mixins/opacity.less","less/component-animations.less","less/dropdowns.less","less/mixins/nav-divider.less","less/mixins/reset-filter.less","less/button-groups.less","less/mixins/border-radius.less","less/input-groups.less","less/navs.less","less/navbar.less","less/mixins/nav-vertical-align.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/mixins/pagination.less","less/pager.less","less/labels.less","less/mixins/labels.less","less/badges.less","less/jumbotron.less","less/thumbnails.less","less/alerts.less","less/mixins/alerts.less","less/progress-bars.less","less/mixins/gradients.less","less/mixins/progress-bar.less","less/media.less","less/list-group.less","less/mixins/list-group.less","less/panels.less","less/mixins/panels.less","less/responsive-embed.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/mixins/reset-text.less","less/popovers.less","less/carousel.less","less/mixins/clearfix.less","less/mixins/center-block.less","less/mixins/hide-text.less","less/responsive-utilities.less","less/mixins/responsive-visibility.less"],"names":[],"mappings":"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kDG,edokDH,MAAA,acpkDG,edukDH,MAAA,IcvkDG,ed0kDH,MAAA,ac1kDG,ed6kDH,MAAA,ac7kDG,edglDH,MAAA,IchlDG,edmlDH,MAAA,ac9kDG,edilDH,MAAA,YchmDG,edmmDH,MAAA,KcnmDG,gBdsmDH,KAAA,KctmDG,gBdymDH,KAAA,aczmDG,gBd4mDH,KAAA,ac5mDG,ed+mDH,KAAA,Ic/mDG,edknDH,KAAA,aclnDG,edqnDH,KAAA,acrnDG,edwnDH,KAAA,IcxnDG,ed2nDH,KAAA,ac3nDG,ed8nDH,KAAA,ac9nDG,edioDH,KAAA,IcjoDG,edooDH,KAAA,ac/nDG,edkoDH,KAAA,YcnnDG,edsnDH,KAAA,KctnDG,kBdynDH,YAAA,KcznDG,kBd4nDH,YAAA,ac5nDG,kBd+nDH,YAAA,ac/nDG,iBdkoDH,YAAA,IcloDG,iBdqoDH,YAAA,acroDG,iBdwoDH,YAAA,acxoDG,iBd2oDH,YAAA,Ic3oDG,iBd8oDH,YAAA,ac9oDG,iBdipDH,YAAA,acjpDG,iBdopDH,YAAA,IcppDG,iBdupDH,YAAA,acvpDG,iBd0pDH,YAAA,Yc5rDG,iBACE,YAAA,EAOJ,yBACE,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,Ud0rDD,MAAA,Kc1rDC,Wd6rDD,MAAA,Kc7rDC,WdgsDD,MAAA,achsDC,WdmsDD,MAAA,acnsDC,UdssDD,MAAA,IctsDC,UdysDD,MAAA,aczsDC,Ud4sDD,MAAA,ac5sDC,Ud+sDD,MAAA,Ic/sDC,UdktDD,MAAA,acltDC,UdqtDD,MAAA,acrtDC,UdwtDD,MAAA,IcxtDC,Ud2tDD,MAAA,ac5sDC,Ud+sDD,MAAA,Yc/sDC,gBdktDD,MAAA,KcltDC,gBdqtDD,MAAA,acrtDC,gBdwtDD,MAAA,acxtDC,ed2tDD,MAAA,Ic3tDC,ed8tDD,MAAA,ac9tDC,ediuDD,MAAA,acjuDC,edouDD,MAAA,IcpuDC,eduuDD,MAAA,acvuDC,ed0uDD,MAAA,ac1uDC,ed6uDD,MAAA,Ic7uDC,edgvDD,MAAA,ac3uDC,ed8uDD,MAAA,Yc7vDC,edgwDD,MAAA,KchwDC,gBdmwDD,KAAA,KcnwDC,gBdswDD,KAAA,actwDC,gBdywDD,KAAA,aczwDC,ed4wDD,KAAA,Ic5wDC,ed+wDD,KAAA,ac/wDC,edkxDD,KAAA,aclxDC,edqxDD,KAAA,IcrxDC,edwxDD,KAAA,acxxDC,ed2xDD,KAAA,ac3xDC,ed8xDD,KAAA,Ic9xDC,ediyDD,KAAA,ac5xDC,ed+xDD,KAAA,YchxDC,edmxDD,KAAA,KcnxDC,kBdsxDD,YAAA,KctxDC,kBdyxDD,YAAA,aczxDC,kBd4xDD,YAAA,ac5xDC,iBd+xDD,YAAA,Ic/xDC,iBdkyDD,YAAA,aclyDC,iBdqyDD,YAAA,acryDC,iBdwyDD,YAAA,IcxyDC,iBd2yDD,YAAA,ac3yDC,iBd8yDD,YAAA,ac9yDC,iBdizDD,YAAA,IcjzDC,iBdozDD,YAAA,acpzDC,iBduzDD,YAAA,YY9yDD,iBE3CE,YAAA,GAQF,yBACE,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,Udw1DD,MAAA,Kcx1DC,Wd21DD,MAAA,Kc31DC,Wd81DD,MAAA,ac91DC,Wdi2DD,MAAA,acj2DC,Udo2DD,MAAA,Icp2DC,Udu2DD,MAAA,acv2DC,Ud02DD,MAAA,ac12DC,Ud62DD,MAAA,Ic72DC,Udg3DD,MAAA,ach3DC,Udm3DD,MAAA,acn3DC,Uds3DD,MAAA,Ict3DC,Udy3DD,MAAA,ac12DC,Ud62DD,MAAA,Yc72DC,gBdg3DD,MAAA,Kch3DC,gBdm3DD,MAAA,acn3DC,gBds3DD,MAAA,act3DC,edy3DD,MAAA,Icz3DC,ed43DD,MAAA,ac53DC,ed+3DD,MAAA,ac/3DC,edk4DD,MAAA,Icl4DC,edq4DD,MAAA,acr4DC,edw4DD,MAAA,acx4DC,ed24DD,MAAA,Ic34DC,ed84DD,MAAA,acz4DC,ed44DD,MAAA,Yc35DC,ed85DD,MAAA,Kc95DC,gBdi6DD,KAAA,Kcj6DC,gBdo6DD,KAAA,acp6DC,gBdu6DD,KAAA,acv6DC,ed06DD,KAAA,Ic16DC,ed66DD,KAAA,ac76DC,edg7DD,KAAA,ach7DC,edm7DD,KAAA,Icn7DC,eds7DD,KAAA,act7DC,edy7DD,KAAA,acz7DC,ed47DD,KAAA,Ic57DC,ed+7DD,KAAA,ac17DC,ed67DD,KAAA,Yc96DC,edi7DD,KAAA,Kcj7DC,kBdo7DD,YAAA,Kcp7DC,kBdu7DD,YAAA,acv7DC,kBd07DD,YAAA,ac17DC,iBd67DD,YAAA,Ic77DC,iBdg8DD,YAAA,ach8DC,iBdm8DD,YAAA,acn8DC,iBds8DD,YAAA,Ict8DC,iBdy8DD,YAAA,acz8DC,iBd48DD,YAAA,ac58DC,iBd+8DD,YAAA,Ic/8DC,iBdk9DD,YAAA,acl9DC,iBdq9DD,YAAA,YYz8DD,iBE9CE,YAAA,GAQF,0BACE,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,Uds/DD,MAAA,Kct/DC,Wdy/DD,MAAA,Kcz/DC,Wd4/DD,MAAA,ac5/DC,Wd+/DD,MAAA,ac//DC,UdkgED,MAAA,IclgEC,UdqgED,MAAA,acrgEC,UdwgED,MAAA,acxgEC,Ud2gED,MAAA,Ic3gEC,Ud8gED,MAAA,ac9gEC,UdihED,MAAA,acjhEC,UdohED,MAAA,IcphEC,UduhED,MAAA,acxgEC,Ud2gED,MAAA,Yc3gEC,gBd8gED,MAAA,Kc9gEC,gBdihED,MAAA,acjhEC,gBdohED,MAAA,acphEC,eduhED,MAAA,IcvhEC,ed0hED,MAAA,ac1hEC,ed6hED,MAAA,ac7hEC,edgiED,MAAA,IchiEC,edmiED,MAAA,acniEC,edsiED,MAAA,actiEC,edyiED,MAAA,IcziEC,ed4iED,MAAA,acviEC,ed0iED,MAAA,YczjEC,ed4jED,MAAA,Kc5jEC,gBd+jED,KAAA,Kc/jEC,gBdkkED,KAAA,aclkEC,gBdqkED,KAAA,acrkEC,edwkED,KAAA,IcxkEC,ed2kED,KAAA,ac3kEC,ed8kED,KAAA,ac9kEC,edilED,KAAA,IcjlEC,edolED,KAAA,acplEC,edulED,KAAA,acvlEC,ed0lED,KAAA,Ic1lEC,ed6lED,KAAA,acxlEC,ed2lED,KAAA,Yc5kEC,ed+kED,KAAA,Kc/kEC,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A,KlBq7FM,WAAY,KkBn7FhB,QAAA,IASN,eC3DE,yBACA,eAAA,KpBi+FD,aoB99FC,MAAA,KnB0+FA,iBAAkB,KmBx+FhB,aAAA,KpBk+FH,mBoBh+FO,mBAEN,MAAA,KACE,iBAAA,QACA,aAAA,QpBi+FH,mBoB99FC,MAAA,KnB0+FA,iBAAkB,QAClB,aAAc,QmBt+FR,oBADJ,oBpBi+FH,mCoB99FG,MAAA,KnB0+FF,iBAAkB,QAClB,aAAc,QmBt+FN,0BnB4+FV,0BAHA,0BmB1+FM,0BnB4+FN,0BAHA,0BDFC,yCoBx+FK,yCnB4+FN,yCmBv+FE,MAAA,KnB++FA,iBAAkB,QAClB,aAAc,QmBx+FZ,oBpBg+FH,oBoBh+FG,mCnB6+FF,iBAAkB,KmBz+FV,4BnB8+FV,4BAHA,4BDHC,6BCOD,6BAHA,6BkB39FA,sCClBM,sCnB8+FN,sCmBx+FI,iBAAA,KACA,aAAA,KDcJ,oBC9DE,MAAA,KACA,iBAAA,KpB0hGD,aoBvhGC,MAAA,KnBmiGA,iBAAkB,QmBjiGhB,aAAA,QpB2hGH,mBoBzhGO,mBAEN,MAAA,KACE,iBAAA,QACA,aAAA,QpB0hGH,mBoBvhGC,MAAA,KnBmiGA,iBAAkB,QAClB,aAAc,QmB/hGR,oBADJ,oBpB0hGH,mCoBvhGG,MAAA,KnBmiGF,iBAAkB,QAClB,aAAc,QmB/hGN,0BnBqiGV,0BAHA,0BmBniGM,0BnBqiGN,0BAHA,0BDFC,yCoBjiGK,yCnBqiGN,yCmBhiGE,MAAA,KnBwiGA,iBAAkB,QAClB,aAAc,QmBjiGZ,oBpByhGH,oBoBzhGG,mCnBsiGF,iBAAkB,KmBliGV,4BnBuiGV,4BAHA,4BDHC,6BCOD,6BAHA,6BkBjhGA,sCCrBM,sCnBuiGN,sCmBjiGI,iBAAA,QACA,aAAA,QDkBJ,oBClEE,MAAA,QACA,iBAAA,KpBmlGD,aoBhlGC,MAAA,KnB4lGA,iBAAkB,QmB1lGhB,aAAA,QpBolGH,mBoBllGO,mBAEN,MAAA,KACE,iBAAA,QACA,aAAA,QpBmlGH,mBoBhlGC,MAAA,KnB4lGA,iBAAkB,QAClB,aAAc,QmBxlGR,oBADJ,oBpBmlGH,mCoBhlGG,MAAA,KnB4lGF,iBAAkB,QAClB,aAAc,QmBxlGN,0BnB8lGV,0BAHA,0BmB5lGM,0BnB8lGN,0BAHA,0BDFC,yCoB1lGK,yCnB8lGN,yCmBzlGE,MAAA,KnBimGA,iBAAkB,QAClB,aAAc,QmB1lGZ,oBpBklGH,oBoBllGG,mCnB+lGF,iBAAkB,KmB3lGV,4BnBgmGV,4BAHA,4BDHC,6BCOD,6BAHA,6BkBtkGA,sCCzBM,sCnBgmGN,sCmB1lGI,iBAAA,QACA,aAAA,QDsBJ,oBCtEE,MAAA,QACA,iBAAA,KpB4oGD,UoBzoGC,MAAA,KnBqpGA,iBAAkB,QmBnpGhB,aAAA,QpB6oGH,gBoB3oGO,gBAEN,MAAA,KACE,iBAAA,QACA,aAAA,QpB4oGH,gBoBzoGC,MAAA,KnBqpGA,iBAAkB,QAClB,aAAc,QmBjpGR,iBADJ,iBpB4oGH,gCoBzoGG,MAAA,KnBqpGF,iBAAkB,QAClB,aAAc,QmBjpGN,uBnBupGV,uBAHA,uBmBrpGM,uBnBupGN,uBAHA,uBDFC,sCoBnpGK,sCnBupGN,sCmBlpGE,MAAA,KnB0pGA,iBAAkB,QAClB,aAAc,QmBnpGZ,iBpB2oGH,iBoB3oGG,gCnBwpGF,iBAAkB,KmBppGV,yBnBypGV,yBAHA,yBDHC,0BCOD,0BAHA,0BkB3nGA,mCC7BM,mCnBypGN,mCmBnpGI,iBAAA,QACA,aAAA,QD0BJ,iBC1EE,MAAA,QACA,iBAAA,KpBqsGD,aoBlsGC,MAAA,KnB8sGA,iBAAkB,QmB5sGhB,aAAA,QpBssGH,mBoBpsGO,mBAEN,MAAA,KACE,iBAAA,QACA,aAAA,QpBqsGH,mBoBlsGC,MAAA,KnB8sGA,iBAAkB,QAClB,aAAc,QmB1sGR,oBADJ,oBpBqsGH,mCoBlsGG,MAAA,KnB8sGF,iBAAkB,QAClB,aAAc,QmB1sGN,0BnBgtGV,0BAHA,0BmB9sGM,0BnBgtGN,0BAHA,0BDFC,yCoB5sGK,yCnBgtGN,yCmB3sGE,MAAA,KnBmtGA,iBAAkB,QAClB,aAAc,QmB5sGZ,oBpBosGH,oBoBpsGG,mCnBitGF,iBAAkB,KmB7sGV,4BnBktGV,4BAHA,4BDHC,6BCOD,6BAHA,6BkBhrGA,sCCjC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A,QkDrxKC,WAAY,IAAI,MAAM,KjDizKtB,2BAA4B,IiD9yK1B,0BAAA,IAHJ,mBAAA,mCAMM,cAAA,ElDwxKL,oCkDnxKG,oDjD+yKF,aAAc,IAAI,EiD7yKZ,cAAA,EvBtEL,4D3B61KF,4EkDjxKG,WAAA,EjD6yKF,uBAAwB,IiD3yKlB,wBAAA,IvBtEL,0D3B21KF,0EkD1yKC,cAAe,EvB1Df,2BAAA,IACC,0BAAA,IuB0FH,+EAEI,uBAAA,ElD8wKH,wBAAA,EkD1wKC,wDlD6wKD,iBAAA,EC4BD,0BACE,iBAAkB,EiDlyKpB,8BlD0wKC,ckD1wKD,gCjDuyKE,cAAe,EiDvyKjB,sCAQM,sBlDwwKL,wCC4BC,cAAe,K0Br5Kf,aAAA,KuByGF,wDlDqxKC,0BC4BC,uBAAwB,IACxB,wBAAyB,IiDlzK3B,yFAoBQ,yFlDwwKP,2DkDzwKO,2DjDqyKN,uBAAwB,IACxB,wBAAyB,IAK3B,wGiD9zKA,wGjD4zKA,wGDtBC,wGCuBD,0EiD7zKA,0EjD2zKA,0EiDnyKU,0EjD2yKR,uBAAwB,IAK1B,uGiDx0KA,uGjDs0KA,uGDtBC,uGCuBD,yEiDv0KA,yEjDq0KA,yEiDzyKU,yEvB7HR,wBAAA,IuBiGF,sDlDqzKC,yBC4BC,2BAA4B,IAC5B,0BAA2B,IiDxyKrB,qFA1CR,qFAyCQ,wDlDmxKP,wDC4BC,2BAA4B,IAC5B,0BAA2B,IAG7B,oGDtBC,oGCwBD,oGiD91KA,oGjD21KA,uEiD7yKU,uEjD+yKV,uEiD71KA,uEjDm2KE,0BAA2B,IAG7B,mGDtBC,mGCwBD,mGiDx2KA,mGjDq2KA,sEiDnzKU,sEjDqzKV,sEiDv2KA,sEjD62KE,2BAA4B,IiDlzK1B,0BlD2xKH,qCkDt1KD,0BAAA,qCA+DI,WAAA,IAAA,MAAA,KA/DJ,kDAAA,kDAmEI,WAAA,EAnEJ,uBAAA,yCjD23KE,OAAQ,EiDjzKA,+CjDqzKV,+CiD/3KA,+CjDi4KA,+CAEA,+CANA,+CDjBC,iECoBD,iEiDh4KA,iEjDk4KA,iEAEA,iEANA,iEAWE,YAAa,EiD3zKL,8CjD+zKV,8CiD74KA,8CjD+4KA,8CAEA,8CANA,8CDjBC,gECo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Dk2MD,kBACF,QAAA,iB+D91MG,yB/Dk2MD,mBACF,QAAA,kBgEh6MC,yBhEo6MC,yBgEn6MD,QAAA,wBACA,+CAAU,YhEw6MT,QAAA,gBC4BD,iB+Dl8MU,QAAA,gBhE26MX,c+Dr2MG,QAAS,oB/Dy2MV,c+D32MC,c/D42MH,QAAA,sB+Dv2MG,+C/D22MD,kBACF,QAAA,iB+Dv2MG,+C/D22MD,mBACF,QAAA,kBgE97MC,+ChEk8MC,yBgEj8MD,QAAA,wBACA,gDAAU,YhEs8MT,QAAA,gBC4BD,iB+Dh+MU,QAAA,gBhEy8MX,c+D92MG,QAAS,oB/Dk3MV,c+Dp3MC,c/Dq3MH,QAAA,sB+Dh3MG,gD/Do3MD,kBACF,QAAA,iB+Dh3MG,gD/Do3MD,mBACF,QAAA,kBgE59MC,gDhEg+MC,yBgE/9MD,QAAA,wBACA,0BAAU,YhEo+MT,QAAA,gBC4BD,iB+D9/MU,QAAA,gBhEu+MX,c+Dv3MG,QAAS,oB/D23MV,c+D73MC,c/D83MH,QAAA,sB+Dz3MG,0B/D63MD,kBACF,QAAA,iB+Dz3MG,0B/D63MD,mBACF,QAAA,kBgEl/MC,0BhEs/MC,yBACF,QAAA,wBgEv/MC,yBhE2/MC,WACF,QAAA,gBgE5/MC,+ChEggNC,WACF,QAAA,gBgEjgNC,gDhEqgNC,WACF,QAAA,gBAGA,0B+Dh3MC,WA4BE,QAAS,gBC5LX,eAAU,QAAA,eACV,aAAU,ehEyhNT,QAAA,gBC4BD,oB+DnjNU,QAAA,gBhE4hNX,iB+D93MG,QAAS,oBAMX,iB/D23MD,iB+Dt2MG,QAAS,sB/D22MZ,qB+D/3MC,QAAS,e/Dk4MV,a+D53MC,qBAcE,QAAS,iB/Dm3MZ,sB+Dh4MC,QAAS,e/Dm4MV,a+D73MC,sBAOE,QAAS,kB/D23MZ,4B+D53MC,QAAS,eCpLT,ahEojNC,4BACF,QAAA,wBC6BD,aACE,cACE,QAAS","sourcesContent":["/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS and IE text size adjust after device orientation change,\n// without disabling user zoom.\n//\n\nhtml {\n font-family: sans-serif; // 1\n -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined for any HTML5 element in IE 8/9.\n// Correct `block` display not defined for `details` or `summary` in IE 10/11\n// and Firefox.\n// Correct `block` display not defined for `main` in IE 11.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9/10.\n// Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background-color: transparent;\n}\n\n//\n// Improve readability of focused elements when they are also in an\n// active/hover state.\n//\n\na:active,\na:hover {\n outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n//\n\nabbr[title] {\n border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n//\n\nb,\nstrong {\n font-weight: bold;\n}\n\n//\n// Address styling not present in Safari and Chrome.\n//\n\ndfn {\n font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari, and Chrome.\n//\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9/10.\n//\n\nimg {\n border: 0;\n}\n\n//\n// Correct overflow not hidden in IE 9/10/11.\n//\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari.\n//\n\nfigure {\n margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n box-sizing: content-box;\n height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10/11.\n//\n\nbutton {\n overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n// and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n// `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; // 2\n cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari and Chrome.\n//\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; // 1\n box-sizing: content-box; //2\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9/10/11.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n border: 0; // 1\n padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9/10/11.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}\n","/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n\n// ==========================================================================\n// Print styles.\n// Inlined to avoid the additional HTTP request: h5bp.com/r\n// ==========================================================================\n\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important; // Black prints faster: h5bp.com/s\n box-shadow: none !important;\n text-shadow: none !important;\n }\n\n a,\n a:visited {\n text-decoration: underline;\n }\n\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n\n // Don't show links that are fragment identifiers,\n // or use the `javascript:` pseudo protocol\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n\n thead {\n display: table-header-group; // h5bp.com/t\n }\n\n tr,\n img {\n page-break-inside: avoid;\n }\n\n img {\n max-width: 100% !important;\n }\n\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n\n h2,\n h3 {\n page-break-after: avoid;\n }\n\n // Bootstrap specific changes start\n\n // Bootstrap components\n .navbar {\n display: none;\n }\n .btn,\n .dropup > .btn {\n > .caret {\n border-top-color: #000 !important;\n }\n }\n .label {\n border: 1px solid #000;\n }\n\n .table {\n border-collapse: collapse !important;\n\n td,\n th {\n background-color: #fff !important;\n }\n }\n .table-bordered {\n th,\n td {\n border: 1px solid #ddd !important;\n }\n }\n\n // Bootstrap specific changes end\n}\n","/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\nhtml {\n font-family: sans-serif;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: 1px dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\nmark {\n background: #ff0;\n color: #000;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\nsup {\n top: -0.5em;\n}\nsub {\n bottom: -0.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n box-sizing: content-box;\n height: 0;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit;\n font: inherit;\n margin: 0;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: textfield;\n box-sizing: content-box;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\nlegend {\n border: 0;\n padding: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important;\n box-shadow: none !important;\n text-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('../fonts/glyphicons-halflings-regular.eot');\n src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\002a\";\n}\n.glyphicon-plus:before {\n content: \"\\002b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333333;\n background-color: #fff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n padding: 4px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: all 0.2s ease-in-out;\n -o-transition: all 0.2s ease-in-out;\n transition: all 0.2s ease-in-out;\n display: inline-block;\n max-width: 100%;\n height: auto;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eeeeee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: normal;\n line-height: 1;\n color: #777777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n background-color: #fcf8e3;\n padding: .2em;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover,\na.text-primary:focus {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover,\na.text-success:focus {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover,\na.text-info:focus {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover,\na.text-warning:focus {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover,\na.text-danger:focus {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover,\na.bg-primary:focus {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover,\na.bg-success:focus {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover,\na.bg-info:focus {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover,\na.bg-warning:focus {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover,\na.bg-danger:focus {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eeeeee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n list-style: none;\n margin-left: -5px;\n}\n.list-inline > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n clear: left;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted #777777;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eeeeee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: '\\2014 \\00A0';\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid #eeeeee;\n border-left: 0;\n text-align: right;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: '';\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: '\\00A0 \\2014';\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #fff;\n background-color: #333;\n border-radius: 3px;\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n word-break: break-all;\n word-wrap: break-word;\n color: #333333;\n background-color: #f5f5f5;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n.row {\n margin-left: -15px;\n margin-right: -15px;\n}\n.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0%;\n}\n@media (min-width: 768px) {\n .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 992px) {\n .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0%;\n }\n}\ntable {\n background-color: transparent;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #ddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #ddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #ddd;\n}\n.table .table {\n background-color: #fff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\ntable col[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-column;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-cell;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #ddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n min-width: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: bold;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n background-color: #fff;\n background-image: none;\n border: 1px solid #ccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.form-control::-moz-placeholder {\n color: #999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999;\n}\n.form-control::-ms-expand {\n border: 0;\n background-color: transparent;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eeeeee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"].form-control,\n input[type=\"time\"].form-control,\n input[type=\"datetime-local\"].form-control,\n input[type=\"month\"].form-control {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-left: -20px;\n margin-top: 4px \\9;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.form-control-static {\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n min-height: 34px;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-left: 0;\n padding-right: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.form-group-sm select.form-control {\n height: 30px;\n line-height: 30px;\n}\n.form-group-sm textarea.form-control,\n.form-group-sm select[multiple].form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n min-height: 32px;\n padding: 6px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.form-group-lg select.form-control {\n height: 46px;\n line-height: 46px;\n}\n.form-group-lg textarea.form-control,\n.form-group-lg select[multiple].form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n min-height: 38px;\n padding: 11px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n border-color: #3c763d;\n background-color: #dff0d8;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n border-color: #8a6d3b;\n background-color: #fcf8e3;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n border-color: #a94442;\n background-color: #f2dede;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: 7px;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-left: -15px;\n margin-right: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n text-align: right;\n margin-bottom: 0;\n padding-top: 7px;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 11px;\n font-size: 18px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n font-size: 12px;\n }\n}\n.btn {\n display: inline-block;\n margin-bottom: 0;\n font-weight: normal;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none;\n border: 1px solid transparent;\n white-space: nowrap;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n border-radius: 4px;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n outline: 0;\n background-image: none;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n cursor: not-allowed;\n opacity: 0.65;\n filter: alpha(opacity=65);\n -webkit-box-shadow: none;\n box-shadow: none;\n}\na.btn.disabled,\nfieldset[disabled] a.btn {\n pointer-events: none;\n}\n.btn-default {\n color: #333;\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default:focus,\n.btn-default.focus {\n color: #333;\n background-color: #e6e6e6;\n border-color: #8c8c8c;\n}\n.btn-default:hover {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active:hover,\n.btn-default.active:hover,\n.open > .dropdown-toggle.btn-default:hover,\n.btn-default:active:focus,\n.btn-default.active:focus,\n.open > .dropdown-toggle.btn-default:focus,\n.btn-default:active.focus,\n.btn-default.active.focus,\n.open > .dropdown-toggle.btn-default.focus {\n color: #333;\n background-color: #d4d4d4;\n border-color: #8c8c8c;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n background-image: none;\n}\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus {\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default .badge {\n color: #fff;\n background-color: #333;\n}\n.btn-primary {\n color: #fff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:focus,\n.btn-primary.focus {\n color: #fff;\n background-color: #286090;\n border-color: #122b40;\n}\n.btn-primary:hover {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active:hover,\n.btn-primary.active:hover,\n.open > .dropdown-toggle.btn-primary:hover,\n.btn-primary:active:focus,\n.btn-primary.active:focus,\n.open > .dropdown-toggle.btn-primary:focus,\n.btn-primary:active.focus,\n.btn-primary.active.focus,\n.open > .dropdown-toggle.btn-primary.focus {\n color: #fff;\n background-color: #204d74;\n border-color: #122b40;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n background-image: none;\n}\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.btn-success {\n color: #fff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:focus,\n.btn-success.focus {\n color: #fff;\n background-color: #449d44;\n border-color: #255625;\n}\n.btn-success:hover {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active:hover,\n.btn-success.active:hover,\n.open > .dropdown-toggle.btn-success:hover,\n.btn-success:active:focus,\n.btn-success.active:focus,\n.open > .dropdown-toggle.btn-success:focus,\n.btn-success:active.focus,\n.btn-success.active.focus,\n.open > .dropdown-toggle.btn-success.focus {\n color: #fff;\n background-color: #398439;\n border-color: #255625;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n background-image: none;\n}\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #fff;\n}\n.btn-info {\n color: #fff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:focus,\n.btn-info.focus {\n color: #fff;\n background-color: #31b0d5;\n border-color: #1b6d85;\n}\n.btn-info:hover {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active:hover,\n.btn-info.active:hover,\n.open > .dropdown-toggle.btn-info:hover,\n.btn-info:active:focus,\n.btn-info.active:focus,\n.open > .dropdown-toggle.btn-info:focus,\n.btn-info:active.focus,\n.btn-info.active.focus,\n.open > .dropdown-toggle.btn-info.focus {\n color: #fff;\n background-color: #269abc;\n border-color: #1b6d85;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n background-image: none;\n}\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #fff;\n}\n.btn-warning {\n color: #fff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:focus,\n.btn-warning.focus {\n color: #fff;\n background-color: #ec971f;\n border-color: #985f0d;\n}\n.btn-warning:hover {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active:hover,\n.btn-warning.active:hover,\n.open > .dropdown-toggle.btn-warning:hover,\n.btn-warning:active:focus,\n.btn-warning.active:focus,\n.open > .dropdown-toggle.btn-warning:focus,\n.btn-warning:active.focus,\n.btn-warning.active.focus,\n.open > .dropdown-toggle.btn-warning.focus {\n color: #fff;\n background-color: #d58512;\n border-color: #985f0d;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n background-image: none;\n}\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #fff;\n}\n.btn-danger {\n color: #fff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:focus,\n.btn-danger.focus {\n color: #fff;\n background-color: #c9302c;\n border-color: #761c19;\n}\n.btn-danger:hover {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active:hover,\n.btn-danger.active:hover,\n.open > .dropdown-toggle.btn-danger:hover,\n.btn-danger:active:focus,\n.btn-danger.active:focus,\n.open > .dropdown-toggle.btn-danger:focus,\n.btn-danger:active.focus,\n.btn-danger.active.focus,\n.open > .dropdown-toggle.btn-danger.focus {\n color: #fff;\n background-color: #ac2925;\n border-color: #761c19;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n background-image: none;\n}\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #fff;\n}\n.btn-link {\n color: #337ab7;\n font-weight: normal;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity 0.15s linear;\n -o-transition: opacity 0.15s linear;\n transition: opacity 0.15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-property: height, visibility;\n transition-property: height, visibility;\n -webkit-transition-duration: 0.35s;\n transition-duration: 0.35s;\n -webkit-transition-timing-function: ease;\n transition-timing-function: ease;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-top: 4px solid \\9;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n list-style: none;\n font-size: 14px;\n text-align: left;\n background-color: #fff;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n background-clip: padding-box;\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: 1.42857143;\n color: #333333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n text-decoration: none;\n color: #262626;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #fff;\n text-decoration: none;\n outline: 0;\n background-color: #337ab7;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n cursor: not-allowed;\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n left: auto;\n right: 0;\n}\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n border-top: 0;\n border-bottom: 4px dashed;\n border-bottom: 4px solid \\9;\n content: \"\";\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n left: auto;\n right: 0;\n }\n .navbar-right .dropdown-menu-left {\n left: 0;\n right: auto;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn,\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group .form-control:focus {\n z-index: 3;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: normal;\n line-height: 1;\n color: #555555;\n text-align: center;\n background-color: #eeeeee;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n z-index: 2;\n margin-left: -1px;\n}\n.nav {\n margin-bottom: 0;\n padding-left: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.nav > li.disabled > a {\n color: #777777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777777;\n text-decoration: none;\n background-color: transparent;\n cursor: not-allowed;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eeeeee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eeeeee #eeeeee #ddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555555;\n background-color: #fff;\n border: 1px solid #ddd;\n border-bottom-color: transparent;\n cursor: default;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #fff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n overflow-x: visible;\n padding-right: 15px;\n padding-left: 15px;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n -webkit-overflow-scrolling: touch;\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-left: 0;\n padding-right: 0;\n }\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.navbar-brand {\n float: left;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n height: 50px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: 15px;\n padding: 9px 10px;\n margin-top: 8px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n margin-left: -15px;\n margin-right: -15px;\n padding: 10px 15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n margin-top: 8px;\n margin-bottom: 8px;\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-left: 15px;\n margin-right: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n border-color: #ddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #ddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n background-color: #e7e7e7;\n color: #555;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-link {\n color: #777;\n}\n.navbar-default .navbar-link:hover {\n color: #333;\n}\n.navbar-default .btn-link {\n color: #777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #ccc;\n}\n.navbar-inverse {\n background-color: #222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #fff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #fff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n background-color: #080808;\n color: #fff;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #fff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #fff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #fff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n content: \"/\\00a0\";\n padding: 0 5px;\n color: #ccc;\n}\n.breadcrumb > .active {\n color: #777777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n line-height: 1.42857143;\n text-decoration: none;\n color: #337ab7;\n background-color: #fff;\n border: 1px solid #ddd;\n margin-left: -1px;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-bottom-left-radius: 4px;\n border-top-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-bottom-right-radius: 4px;\n border-top-right-radius: 4px;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n z-index: 2;\n color: #23527c;\n background-color: #eeeeee;\n border-color: #ddd;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 3;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n cursor: default;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777777;\n background-color: #fff;\n border-color: #ddd;\n cursor: not-allowed;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-bottom-left-radius: 6px;\n border-top-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-bottom-right-radius: 6px;\n border-top-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-bottom-left-radius: 3px;\n border-top-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-bottom-right-radius: 3px;\n border-top-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n list-style: none;\n text-align: center;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777777;\n background-color: #fff;\n cursor: not-allowed;\n}\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n}\na.label:hover,\na.label:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n color: #fff;\n line-height: 1;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: #777777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding-top: 30px;\n padding-bottom: 30px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eeeeee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n border-radius: 6px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding-top: 48px;\n padding-bottom: 48px;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-left: 60px;\n padding-right: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: border 0.2s ease-in-out;\n -o-transition: border 0.2s ease-in-out;\n transition: border 0.2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-left: auto;\n margin-right: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n background-color: #dff0d8;\n border-color: #d6e9c6;\n color: #3c763d;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n background-color: #d9edf7;\n border-color: #bce8f1;\n color: #31708f;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n background-color: #fcf8e3;\n border-color: #faebcc;\n color: #8a6d3b;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n background-color: #f2dede;\n border-color: #ebccd1;\n color: #a94442;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n overflow: hidden;\n height: 20px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #fff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n -webkit-transition: width 0.6s ease;\n -o-transition: width 0.6s ease;\n transition: width 0.6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-object.img-thumbnail {\n max-width: none;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n margin-bottom: 20px;\n padding-left: 0;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.list-group-item:first-child {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\na.list-group-item,\nbutton.list-group-item {\n color: #555;\n}\na.list-group-item .list-group-item-heading,\nbutton.list-group-item .list-group-item-heading {\n color: #333;\n}\na.list-group-item:hover,\nbutton.list-group-item:hover,\na.list-group-item:focus,\nbutton.list-group-item:focus {\n text-decoration: none;\n color: #555;\n background-color: #f5f5f5;\n}\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n background-color: #eeeeee;\n color: #777777;\n cursor: not-allowed;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success,\nbutton.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading,\nbutton.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\nbutton.list-group-item-success:hover,\na.list-group-item-success:focus,\nbutton.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\nbutton.list-group-item-success.active,\na.list-group-item-success.active:hover,\nbutton.list-group-item-success.active:hover,\na.list-group-item-success.active:focus,\nbutton.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info,\nbutton.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading,\nbutton.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\nbutton.list-group-item-info:hover,\na.list-group-item-info:focus,\nbutton.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\nbutton.list-group-item-info.active,\na.list-group-item-info.active:hover,\nbutton.list-group-item-info.active:hover,\na.list-group-item-info.active:focus,\nbutton.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning,\nbutton.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading,\nbutton.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\nbutton.list-group-item-warning:hover,\na.list-group-item-warning:focus,\nbutton.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\nbutton.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus,\nbutton.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger,\nbutton.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading,\nbutton.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\nbutton.list-group-item-danger:hover,\na.list-group-item-danger:focus,\nbutton.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\nbutton.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus,\nbutton.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #fff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #ddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-left: 15px;\n padding-right: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-left-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #ddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n border: 0;\n margin-bottom: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #ddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #ddd;\n}\n.panel-default {\n border-color: #ddd;\n}\n.panel-default > .panel-heading {\n color: #333333;\n background-color: #f5f5f5;\n border-color: #ddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n height: 100%;\n width: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, 0.15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n opacity: 0.2;\n filter: alpha(opacity=20);\n}\n.close:hover,\n.close:focus {\n color: #000;\n text-decoration: none;\n cursor: pointer;\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\nbutton.close {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n display: none;\n overflow: hidden;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n -webkit-transition: -webkit-transform 0.3s ease-out;\n -moz-transition: -moz-transform 0.3s ease-out;\n -o-transition: -o-transform 0.3s ease-out;\n transition: transform 0.3s ease-out;\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #fff;\n border: 1px solid #999;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n background-clip: padding-box;\n outline: 0;\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000;\n}\n.modal-backdrop.fade {\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.modal-backdrop.in {\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-left: 5px;\n margin-bottom: 0;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 12px;\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.tooltip.in {\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.tooltip.top {\n margin-top: -3px;\n padding: 5px 0;\n}\n.tooltip.right {\n margin-left: 3px;\n padding: 0 5px;\n}\n.tooltip.bottom {\n margin-top: 3px;\n padding: 5px 0;\n}\n.tooltip.left {\n margin-left: -3px;\n padding: 0 5px;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-left .tooltip-arrow {\n bottom: 0;\n right: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 14px;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover-title {\n margin: 0;\n padding: 8px 14px;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow:after {\n border-width: 10px;\n content: \"\";\n}\n.popover.top > .arrow {\n left: 50%;\n margin-left: -11px;\n border-bottom-width: 0;\n border-top-color: #999999;\n border-top-color: rgba(0, 0, 0, 0.25);\n bottom: -11px;\n}\n.popover.top > .arrow:after {\n content: \" \";\n bottom: 1px;\n margin-left: -10px;\n border-bottom-width: 0;\n border-top-color: #fff;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-left-width: 0;\n border-right-color: #999999;\n border-right-color: rgba(0, 0, 0, 0.25);\n}\n.popover.right > .arrow:after {\n content: \" \";\n left: 1px;\n bottom: -10px;\n border-left-width: 0;\n border-right-color: #fff;\n}\n.popover.bottom > .arrow {\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999999;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n top: -11px;\n}\n.popover.bottom > .arrow:after {\n content: \" \";\n top: 1px;\n margin-left: -10px;\n border-top-width: 0;\n border-bottom-color: #fff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999999;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n.popover.left > .arrow:after {\n content: \" \";\n right: 1px;\n border-right-width: 0;\n border-left-color: #fff;\n bottom: -10px;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n overflow: hidden;\n width: 100%;\n}\n.carousel-inner > .item {\n display: none;\n position: relative;\n -webkit-transition: 0.6s ease-in-out left;\n -o-transition: 0.6s ease-in-out left;\n transition: 0.6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform 0.6s ease-in-out;\n -moz-transition: -moz-transform 0.6s ease-in-out;\n -o-transition: -o-transform 0.6s ease-in-out;\n transition: transform 0.6s ease-in-out;\n -webkit-backface-visibility: hidden;\n -moz-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000px;\n -moz-perspective: 1000px;\n perspective: 1000px;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n left: 0;\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: 15%;\n opacity: 0.5;\n filter: alpha(opacity=50);\n font-size: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n}\n.carousel-control.right {\n left: auto;\n right: 0;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n}\n.carousel-control:hover,\n.carousel-control:focus {\n outline: 0;\n color: #fff;\n text-decoration: none;\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n margin-top: -10px;\n z-index: 5;\n display: inline-block;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n line-height: 1;\n font-family: serif;\n}\n.carousel-control .icon-prev:before {\n content: '\\2039';\n}\n.carousel-control .icon-next:before {\n content: '\\203a';\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n margin-left: -30%;\n padding-left: 0;\n list-style: none;\n text-align: center;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n border: 1px solid #fff;\n border-radius: 10px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-indicators .active {\n margin: 0;\n width: 12px;\n height: 12px;\n background-color: #fff;\n}\n.carousel-caption {\n position: absolute;\n left: 15%;\n right: 15%;\n bottom: 20px;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -10px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -10px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -10px;\n }\n .carousel-caption {\n left: 20%;\n right: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-header:before,\n.modal-header:after,\n.modal-footer:before,\n.modal-footer:after {\n content: \" \";\n display: table;\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-header:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table !important;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table !important;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table !important;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table !important;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table !important;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */","/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\nhtml {\n font-family: sans-serif;\n -webkit-text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: 1px dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n margin: .67em 0;\n font-size: 2em;\n}\nmark {\n color: #000;\n background: #ff0;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\nsup {\n top: -.5em;\n}\nsub {\n bottom: -.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n height: 0;\n -webkit-box-sizing: content-box;\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n margin: 0;\n font: inherit;\n color: inherit;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n padding: 0;\n border: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: content-box;\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n -webkit-appearance: textfield;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n padding: .35em .625em .75em;\n margin: 0 2px;\n border: 1px solid #c0c0c0;\n}\nlegend {\n padding: 0;\n border: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-spacing: 0;\n border-collapse: collapse;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n color: #000 !important;\n text-shadow: none !important;\n background: transparent !important;\n -webkit-box-shadow: none !important;\n box-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: 'Glyphicons Halflings';\n\n src: url('../fonts/glyphicons-halflings-regular.eot');\n src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\002a\";\n}\n.glyphicon-plus:before {\n content: \"\\002b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333;\n background-color: #fff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n display: inline-block;\n max-width: 100%;\n height: auto;\n padding: 4px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: all .2s ease-in-out;\n -o-transition: all .2s ease-in-out;\n transition: all .2s ease-in-out;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: normal;\n line-height: 1;\n color: #777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n padding: .2em;\n background-color: #fcf8e3;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover,\na.text-primary:focus {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover,\na.text-success:focus {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover,\na.text-info:focus {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover,\na.text-warning:focus {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover,\na.text-danger:focus {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover,\na.bg-primary:focus {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover,\na.bg-success:focus {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover,\na.bg-info:focus {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover,\na.bg-warning:focus {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover,\na.bg-danger:focus {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n margin-left: -5px;\n list-style: none;\n}\n.list-inline > li {\n display: inline-block;\n padding-right: 5px;\n padding-left: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n overflow: hidden;\n clear: left;\n text-align: right;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted #777;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: '\\2014 \\00A0';\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n text-align: right;\n border-right: 5px solid #eee;\n border-left: 0;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: '';\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: '\\00A0 \\2014';\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #fff;\n background-color: #333;\n border-radius: 3px;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n color: #333;\n word-break: break-all;\n word-wrap: break-word;\n background-color: #f5f5f5;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n.row {\n margin-right: -15px;\n margin-left: -15px;\n}\n.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-right: 15px;\n padding-left: 15px;\n}\n.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0;\n }\n}\n@media (min-width: 992px) {\n .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0;\n }\n}\ntable {\n background-color: transparent;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #ddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #ddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #ddd;\n}\n.table .table {\n background-color: #fff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\ntable col[class*=\"col-\"] {\n position: static;\n display: table-column;\n float: none;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n display: table-cell;\n float: none;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n min-height: .01%;\n overflow-x: auto;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #ddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: bold;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555;\n background-color: #fff;\n background-image: none;\n border: 1px solid #ccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);\n box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);\n}\n.form-control::-moz-placeholder {\n color: #999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999;\n}\n.form-control::-ms-expand {\n background-color: transparent;\n border: 0;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"].form-control,\n input[type=\"time\"].form-control,\n input[type=\"datetime-local\"].form-control,\n input[type=\"month\"].form-control {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-top: 4px \\9;\n margin-left: -20px;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n vertical-align: middle;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.form-control-static {\n min-height: 34px;\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-right: 0;\n padding-left: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.form-group-sm select.form-control {\n height: 30px;\n line-height: 30px;\n}\n.form-group-sm textarea.form-control,\n.form-group-sm select[multiple].form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n min-height: 32px;\n padding: 6px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.form-group-lg select.form-control {\n height: 46px;\n line-height: 46px;\n}\n.form-group-lg textarea.form-control,\n.form-group-lg select[multiple].form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n min-height: 38px;\n padding: 11px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #3c763d;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #8a6d3b;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n background-color: #f2dede;\n border-color: #a94442;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n padding-top: 7px;\n margin-top: 0;\n margin-bottom: 0;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n padding-top: 7px;\n margin-bottom: 0;\n text-align: right;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 11px;\n font-size: 18px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n font-size: 12px;\n }\n}\n.btn {\n display: inline-block;\n padding: 6px 12px;\n margin-bottom: 0;\n font-size: 14px;\n font-weight: normal;\n line-height: 1.42857143;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n -ms-touch-action: manipulation;\n touch-action: manipulation;\n cursor: pointer;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n outline: 0;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n cursor: not-allowed;\n filter: alpha(opacity=65);\n -webkit-box-shadow: none;\n box-shadow: none;\n opacity: .65;\n}\na.btn.disabled,\nfieldset[disabled] a.btn {\n pointer-events: none;\n}\n.btn-default {\n color: #333;\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default:focus,\n.btn-default.focus {\n color: #333;\n background-color: #e6e6e6;\n border-color: #8c8c8c;\n}\n.btn-default:hover {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active:hover,\n.btn-default.active:hover,\n.open > .dropdown-toggle.btn-default:hover,\n.btn-default:active:focus,\n.btn-default.active:focus,\n.open > .dropdown-toggle.btn-default:focus,\n.btn-default:active.focus,\n.btn-default.active.focus,\n.open > .dropdown-toggle.btn-default.focus {\n color: #333;\n background-color: #d4d4d4;\n border-color: #8c8c8c;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n background-image: none;\n}\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus {\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default .badge {\n color: #fff;\n background-color: #333;\n}\n.btn-primary {\n color: #fff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:focus,\n.btn-primary.focus {\n color: #fff;\n background-color: #286090;\n border-color: #122b40;\n}\n.btn-primary:hover {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active:hover,\n.btn-primary.active:hover,\n.open > .dropdown-toggle.btn-primary:hover,\n.btn-primary:active:focus,\n.btn-primary.active:focus,\n.open > .dropdown-toggle.btn-primary:focus,\n.btn-primary:active.focus,\n.btn-primary.active.focus,\n.open > .dropdown-toggle.btn-primary.focus {\n color: #fff;\n background-color: #204d74;\n border-color: #122b40;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n background-image: none;\n}\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.btn-success {\n color: #fff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:focus,\n.btn-success.focus {\n color: #fff;\n background-color: #449d44;\n border-color: #255625;\n}\n.btn-success:hover {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active:hover,\n.btn-success.active:hover,\n.open > .dropdown-toggle.btn-success:hover,\n.btn-success:active:focus,\n.btn-success.active:focus,\n.open > .dropdown-toggle.btn-success:focus,\n.btn-success:active.focus,\n.btn-success.active.focus,\n.open > .dropdown-toggle.btn-success.focus {\n color: #fff;\n background-color: #398439;\n border-color: #255625;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n background-image: none;\n}\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #fff;\n}\n.btn-info {\n color: #fff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:focus,\n.btn-info.focus {\n color: #fff;\n background-color: #31b0d5;\n border-color: #1b6d85;\n}\n.btn-info:hover {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active:hover,\n.btn-info.active:hover,\n.open > .dropdown-toggle.btn-info:hover,\n.btn-info:active:focus,\n.btn-info.active:focus,\n.open > .dropdown-toggle.btn-info:focus,\n.btn-info:active.focus,\n.btn-info.active.focus,\n.open > .dropdown-toggle.btn-info.focus {\n color: #fff;\n background-color: #269abc;\n border-color: #1b6d85;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n background-image: none;\n}\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #fff;\n}\n.btn-warning {\n color: #fff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:focus,\n.btn-warning.focus {\n color: #fff;\n background-color: #ec971f;\n border-color: #985f0d;\n}\n.btn-warning:hover {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active:hover,\n.btn-warning.active:hover,\n.open > .dropdown-toggle.btn-warning:hover,\n.btn-warning:active:focus,\n.btn-warning.active:focus,\n.open > .dropdown-toggle.btn-warning:focus,\n.btn-warning:active.focus,\n.btn-warning.active.focus,\n.open > .dropdown-toggle.btn-warning.focus {\n color: #fff;\n background-color: #d58512;\n border-color: #985f0d;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n background-image: none;\n}\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #fff;\n}\n.btn-danger {\n color: #fff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:focus,\n.btn-danger.focus {\n color: #fff;\n background-color: #c9302c;\n border-color: #761c19;\n}\n.btn-danger:hover {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active:hover,\n.btn-danger.active:hover,\n.open > .dropdown-toggle.btn-danger:hover,\n.btn-danger:active:focus,\n.btn-danger.active:focus,\n.open > .dropdown-toggle.btn-danger:focus,\n.btn-danger:active.focus,\n.btn-danger.active.focus,\n.open > .dropdown-toggle.btn-danger.focus {\n color: #fff;\n background-color: #ac2925;\n border-color: #761c19;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n background-image: none;\n}\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #fff;\n}\n.btn-link {\n font-weight: normal;\n color: #337ab7;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity .15s linear;\n -o-transition: opacity .15s linear;\n transition: opacity .15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-timing-function: ease;\n -o-transition-timing-function: ease;\n transition-timing-function: ease;\n -webkit-transition-duration: .35s;\n -o-transition-duration: .35s;\n transition-duration: .35s;\n -webkit-transition-property: height, visibility;\n -o-transition-property: height, visibility;\n transition-property: height, visibility;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-top: 4px solid \\9;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n font-size: 14px;\n text-align: left;\n list-style: none;\n background-color: #fff;\n -webkit-background-clip: padding-box;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, .15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, .175);\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: 1.42857143;\n color: #333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n color: #262626;\n text-decoration: none;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #fff;\n text-decoration: none;\n background-color: #337ab7;\n outline: 0;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n cursor: not-allowed;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu-left {\n right: auto;\n left: 0;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n content: \"\";\n border-top: 0;\n border-bottom: 4px dashed;\n border-bottom: 4px solid \\9;\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n right: 0;\n left: auto;\n }\n .navbar-right .dropdown-menu-left {\n right: auto;\n left: 0;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn,\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-right: 8px;\n padding-left: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-right: 12px;\n padding-left: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n display: table-cell;\n float: none;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-right: 0;\n padding-left: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group .form-control:focus {\n z-index: 3;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: normal;\n line-height: 1;\n color: #555;\n text-align: center;\n background-color: #eee;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n z-index: 2;\n margin-left: -1px;\n}\n.nav {\n padding-left: 0;\n margin-bottom: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eee;\n}\n.nav > li.disabled > a {\n color: #777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777;\n text-decoration: none;\n cursor: not-allowed;\n background-color: transparent;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eee #eee #ddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555;\n cursor: default;\n background-color: #fff;\n border: 1px solid #ddd;\n border-bottom-color: transparent;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n margin-bottom: 5px;\n text-align: center;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #fff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n margin-bottom: 5px;\n text-align: center;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n padding-right: 15px;\n padding-left: 15px;\n overflow-x: visible;\n -webkit-overflow-scrolling: touch;\n border-top: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-right: 0;\n padding-left: 0;\n }\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.navbar-brand {\n float: left;\n height: 50px;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n padding: 9px 10px;\n margin-top: 8px;\n margin-right: 15px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n padding: 10px 15px;\n margin-top: 8px;\n margin-right: -15px;\n margin-bottom: 8px;\n margin-left: -15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n padding-top: 0;\n padding-bottom: 0;\n margin-right: 0;\n margin-left: 0;\n border: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-right: 15px;\n margin-left: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n border-color: #ddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #ddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-link {\n color: #777;\n}\n.navbar-default .navbar-link:hover {\n color: #333;\n}\n.navbar-default .btn-link {\n color: #777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #ccc;\n}\n.navbar-inverse {\n background-color: #222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #fff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #fff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n color: #fff;\n background-color: #080808;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #fff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #fff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #fff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n padding: 0 5px;\n color: #ccc;\n content: \"/\\00a0\";\n}\n.breadcrumb > .active {\n color: #777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n margin-left: -1px;\n line-height: 1.42857143;\n color: #337ab7;\n text-decoration: none;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-top-left-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-top-right-radius: 4px;\n border-bottom-right-radius: 4px;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n z-index: 2;\n color: #23527c;\n background-color: #eee;\n border-color: #ddd;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 3;\n color: #fff;\n cursor: default;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777;\n cursor: not-allowed;\n background-color: #fff;\n border-color: #ddd;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-top-left-radius: 6px;\n border-bottom-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-top-right-radius: 6px;\n border-bottom-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-top-left-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-top-right-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n text-align: center;\n list-style: none;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777;\n cursor: not-allowed;\n background-color: #fff;\n}\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n}\na.label:hover,\na.label:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n background-color: #777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding-top: 30px;\n padding-bottom: 30px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n padding-right: 15px;\n padding-left: 15px;\n border-radius: 6px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding-top: 48px;\n padding-bottom: 48px;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-right: 60px;\n padding-left: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: border .2s ease-in-out;\n -o-transition: border .2s ease-in-out;\n transition: border .2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-right: auto;\n margin-left: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@-o-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n height: 20px;\n margin-bottom: 20px;\n overflow: hidden;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);\n}\n.progress-bar {\n float: left;\n width: 0;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #fff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);\n -webkit-transition: width .6s ease;\n -o-transition: width .6s ease;\n transition: width .6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n -webkit-background-size: 40px 40px;\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n overflow: hidden;\n zoom: 1;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-object.img-thumbnail {\n max-width: none;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n padding-left: 0;\n margin-bottom: 20px;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.list-group-item:first-child {\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\na.list-group-item,\nbutton.list-group-item {\n color: #555;\n}\na.list-group-item .list-group-item-heading,\nbutton.list-group-item .list-group-item-heading {\n color: #333;\n}\na.list-group-item:hover,\nbutton.list-group-item:hover,\na.list-group-item:focus,\nbutton.list-group-item:focus {\n color: #555;\n text-decoration: none;\n background-color: #f5f5f5;\n}\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n color: #777;\n cursor: not-allowed;\n background-color: #eee;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success,\nbutton.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading,\nbutton.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\nbutton.list-group-item-success:hover,\na.list-group-item-success:focus,\nbutton.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\nbutton.list-group-item-success.active,\na.list-group-item-success.active:hover,\nbutton.list-group-item-success.active:hover,\na.list-group-item-success.active:focus,\nbutton.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info,\nbutton.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading,\nbutton.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\nbutton.list-group-item-info:hover,\na.list-group-item-info:focus,\nbutton.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\nbutton.list-group-item-info.active,\na.list-group-item-info.active:hover,\nbutton.list-group-item-info.active:hover,\na.list-group-item-info.active:focus,\nbutton.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning,\nbutton.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading,\nbutton.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\nbutton.list-group-item-warning:hover,\na.list-group-item-warning:focus,\nbutton.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\nbutton.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus,\nbutton.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger,\nbutton.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading,\nbutton.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\nbutton.list-group-item-danger:hover,\na.list-group-item-danger:focus,\nbutton.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\nbutton.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus,\nbutton.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #fff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, .05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #ddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-right: 15px;\n padding-left: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #ddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n margin-bottom: 0;\n border: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #ddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #ddd;\n}\n.panel-default {\n border-color: #ddd;\n}\n.panel-default > .panel-heading {\n color: #333;\n background-color: #f5f5f5;\n border-color: #ddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, .15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n filter: alpha(opacity=20);\n opacity: .2;\n}\n.close:hover,\n.close:focus {\n color: #000;\n text-decoration: none;\n cursor: pointer;\n filter: alpha(opacity=50);\n opacity: .5;\n}\nbutton.close {\n -webkit-appearance: none;\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n display: none;\n overflow: hidden;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transition: -webkit-transform .3s ease-out;\n -o-transition: -o-transform .3s ease-out;\n transition: transform .3s ease-out;\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #fff;\n -webkit-background-clip: padding-box;\n background-clip: padding-box;\n border: 1px solid #999;\n border: 1px solid rgba(0, 0, 0, .2);\n border-radius: 6px;\n outline: 0;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, .5);\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000;\n}\n.modal-backdrop.fade {\n filter: alpha(opacity=0);\n opacity: 0;\n}\n.modal-backdrop.in {\n filter: alpha(opacity=50);\n opacity: .5;\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-bottom: 0;\n margin-left: 5px;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, .5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 12px;\n font-style: normal;\n font-weight: normal;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n white-space: normal;\n filter: alpha(opacity=0);\n opacity: 0;\n\n line-break: auto;\n}\n.tooltip.in {\n filter: alpha(opacity=90);\n opacity: .9;\n}\n.tooltip.top {\n padding: 5px 0;\n margin-top: -3px;\n}\n.tooltip.right {\n padding: 0 5px;\n margin-left: 3px;\n}\n.tooltip.bottom {\n padding: 5px 0;\n margin-top: 3px;\n}\n.tooltip.left {\n padding: 0 5px;\n margin-left: -3px;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-left .tooltip-arrow {\n right: 5px;\n bottom: 0;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n font-style: normal;\n font-weight: normal;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n white-space: normal;\n background-color: #fff;\n -webkit-background-clip: padding-box;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, .2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, .2);\n\n line-break: auto;\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover-title {\n padding: 8px 14px;\n margin: 0;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow:after {\n content: \"\";\n border-width: 10px;\n}\n.popover.top > .arrow {\n bottom: -11px;\n left: 50%;\n margin-left: -11px;\n border-top-color: #999;\n border-top-color: rgba(0, 0, 0, .25);\n border-bottom-width: 0;\n}\n.popover.top > .arrow:after {\n bottom: 1px;\n margin-left: -10px;\n content: \" \";\n border-top-color: #fff;\n border-bottom-width: 0;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-right-color: #999;\n border-right-color: rgba(0, 0, 0, .25);\n border-left-width: 0;\n}\n.popover.right > .arrow:after {\n bottom: -10px;\n left: 1px;\n content: \" \";\n border-right-color: #fff;\n border-left-width: 0;\n}\n.popover.bottom > .arrow {\n top: -11px;\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999;\n border-bottom-color: rgba(0, 0, 0, .25);\n}\n.popover.bottom > .arrow:after {\n top: 1px;\n margin-left: -10px;\n content: \" \";\n border-top-width: 0;\n border-bottom-color: #fff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999;\n border-left-color: rgba(0, 0, 0, .25);\n}\n.popover.left > .arrow:after {\n right: 1px;\n bottom: -10px;\n content: \" \";\n border-right-width: 0;\n border-left-color: #fff;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n width: 100%;\n overflow: hidden;\n}\n.carousel-inner > .item {\n position: relative;\n display: none;\n -webkit-transition: .6s ease-in-out left;\n -o-transition: .6s ease-in-out left;\n transition: .6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform .6s ease-in-out;\n -o-transition: -o-transform .6s ease-in-out;\n transition: transform .6s ease-in-out;\n\n -webkit-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000px;\n perspective: 1000px;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n left: 0;\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n left: 0;\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n left: 0;\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 15%;\n font-size: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, .6);\n background-color: rgba(0, 0, 0, 0);\n filter: alpha(opacity=50);\n opacity: .5;\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);\n background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001)));\n background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n background-repeat: repeat-x;\n}\n.carousel-control.right {\n right: 0;\n left: auto;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);\n background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5)));\n background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n background-repeat: repeat-x;\n}\n.carousel-control:hover,\n.carousel-control:focus {\n color: #fff;\n text-decoration: none;\n filter: alpha(opacity=90);\n outline: 0;\n opacity: .9;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n z-index: 5;\n display: inline-block;\n margin-top: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n font-family: serif;\n line-height: 1;\n}\n.carousel-control .icon-prev:before {\n content: '\\2039';\n}\n.carousel-control .icon-next:before {\n content: '\\203a';\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n padding-left: 0;\n margin-left: -30%;\n text-align: center;\n list-style: none;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n border: 1px solid #fff;\n border-radius: 10px;\n}\n.carousel-indicators .active {\n width: 12px;\n height: 12px;\n margin: 0;\n background-color: #fff;\n}\n.carousel-caption {\n position: absolute;\n right: 15%;\n bottom: 20px;\n left: 15%;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, .6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -10px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -10px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -10px;\n }\n .carousel-caption {\n right: 20%;\n left: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-header:before,\n.modal-header:after,\n.modal-footer:before,\n.modal-footer:after {\n display: table;\n content: \" \";\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-header:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-right: auto;\n margin-left: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table !important;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table !important;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table !important;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table !important;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table !important;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// Star\n\n// Import the fonts\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('@{icon-font-path}@{icon-font-name}.eot');\n src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'),\n url('@{icon-font-path}@{icon-font-name}.woff2') format('woff2'),\n url('@{icon-font-path}@{icon-font-name}.woff') format('woff'),\n url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'),\n url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg');\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\002a\"; } }\n.glyphicon-plus { &:before { content: \"\\002b\"; } }\n.glyphicon-euro,\n.glyphicon-eur { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n.glyphicon-cd { &:before { content: \"\\e201\"; } }\n.glyphicon-save-file { &:before { content: \"\\e202\"; } }\n.glyphicon-open-file { &:before { content: \"\\e203\"; } }\n.glyphicon-level-up { &:before { content: \"\\e204\"; } }\n.glyphicon-copy { &:before { content: \"\\e205\"; } }\n.glyphicon-paste { &:before { content: \"\\e206\"; } }\n// The following 2 Glyphicons are omitted for the time being because\n// they currently use Unicode codepoints that are outside the\n// Basic Multilingual Plane (BMP). Older buggy versions of WebKit can't handle\n// non-BMP codepoints in CSS string escapes, and thus can't display these two icons.\n// Notably, the bug affects some older versions of the Android Browser.\n// More info: https://github.com/twbs/bootstrap/issues/10106\n// .glyphicon-door { &:before { content: \"\\1f6aa\"; } }\n// .glyphicon-key { &:before { content: \"\\1f511\"; } }\n.glyphicon-alert { &:before { content: \"\\e209\"; } }\n.glyphicon-equalizer { &:before { content: \"\\e210\"; } }\n.glyphicon-king { &:before { content: \"\\e211\"; } }\n.glyphicon-queen { &:before { content: \"\\e212\"; } }\n.glyphicon-pawn { &:before { content: \"\\e213\"; } }\n.glyphicon-bishop { &:before { content: \"\\e214\"; } }\n.glyphicon-knight { &:before { content: \"\\e215\"; } }\n.glyphicon-baby-formula { &:before { content: \"\\e216\"; } }\n.glyphicon-tent { &:before { content: \"\\26fa\"; } }\n.glyphicon-blackboard { &:before { content: \"\\e218\"; } }\n.glyphicon-bed { &:before { content: \"\\e219\"; } }\n.glyphicon-apple { &:before { content: \"\\f8ff\"; } }\n.glyphicon-erase { &:before { content: \"\\e221\"; } }\n.glyphicon-hourglass { &:before { content: \"\\231b\"; } }\n.glyphicon-lamp { &:before { content: \"\\e223\"; } }\n.glyphicon-duplicate { &:before { content: \"\\e224\"; } }\n.glyphicon-piggy-bank { &:before { content: \"\\e225\"; } }\n.glyphicon-scissors { &:before { content: \"\\e226\"; } }\n.glyphicon-bitcoin { &:before { content: \"\\e227\"; } }\n.glyphicon-btc { &:before { content: \"\\e227\"; } }\n.glyphicon-xbt { &:before { content: \"\\e227\"; } }\n.glyphicon-yen { &:before { content: \"\\00a5\"; } }\n.glyphicon-jpy { &:before { content: \"\\00a5\"; } }\n.glyphicon-ruble { &:before { content: \"\\20bd\"; } }\n.glyphicon-rub { &:before { content: \"\\20bd\"; } }\n.glyphicon-scale { &:before { content: \"\\e230\"; } }\n.glyphicon-ice-lolly { &:before { content: \"\\e231\"; } }\n.glyphicon-ice-lolly-tasted { &:before { content: \"\\e232\"; } }\n.glyphicon-education { &:before { content: \"\\e233\"; } }\n.glyphicon-option-horizontal { &:before { content: \"\\e234\"; } }\n.glyphicon-option-vertical { &:before { content: \"\\e235\"; } }\n.glyphicon-menu-hamburger { &:before { content: \"\\e236\"; } }\n.glyphicon-modal-window { &:before { content: \"\\e237\"; } }\n.glyphicon-oil { &:before { content: \"\\e238\"; } }\n.glyphicon-grain { &:before { content: \"\\e239\"; } }\n.glyphicon-sunglasses { &:before { content: \"\\e240\"; } }\n.glyphicon-text-size { &:before { content: \"\\e241\"; } }\n.glyphicon-text-color { &:before { content: \"\\e242\"; } }\n.glyphicon-text-background { &:before { content: \"\\e243\"; } }\n.glyphicon-object-align-top { &:before { content: \"\\e244\"; } }\n.glyphicon-object-align-bottom { &:before { content: \"\\e245\"; } }\n.glyphicon-object-align-horizontal{ &:before { content: \"\\e246\"; } }\n.glyphicon-object-align-left { &:before { content: \"\\e247\"; } }\n.glyphicon-object-align-vertical { &:before { content: \"\\e248\"; } }\n.glyphicon-object-align-right { &:before { content: \"\\e249\"; } }\n.glyphicon-triangle-right { &:before { content: \"\\e250\"; } }\n.glyphicon-triangle-left { &:before { content: \"\\e251\"; } }\n.glyphicon-triangle-bottom { &:before { content: \"\\e252\"; } }\n.glyphicon-triangle-top { &:before { content: \"\\e253\"; } }\n.glyphicon-console { &:before { content: \"\\e254\"; } }\n.glyphicon-superscript { &:before { content: \"\\e255\"; } }\n.glyphicon-subscript { &:before { content: \"\\e256\"; } }\n.glyphicon-menu-left { &:before { content: \"\\e257\"; } }\n.glyphicon-menu-right { &:before { content: \"\\e258\"; } }\n.glyphicon-menu-down { &:before { content: \"\\e259\"; } }\n.glyphicon-menu-up { &:before { content: \"\\e260\"; } }\n","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\n}\n*:before,\n*:after {\n .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n font-family: @font-family-base;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @text-color;\n background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n\n// Links\n\na {\n color: @link-color;\n text-decoration: none;\n\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n }\n\n &:focus {\n .tab-focus();\n }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\n}\n\n\n// Images\n\nimg {\n vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n padding: @thumbnail-padding;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n // Keep them at most 100% wide\n .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n margin-top: @line-height-computed;\n margin-bottom: @line-height-computed;\n border: 0;\n border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: http://a11yproject.com/posts/how-to-hide-content\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0,0,0,0);\n border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n// Useful for \"Skip to main content\" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n// Credit: HTML5 Boilerplate\n\n.sr-only-focusable {\n &:active,\n &:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n }\n}\n\n\n// iOS \"clickable elements\" fix for role=\"button\"\n//\n// Fixes \"clickability\" issue (and more generally, the firing of events such as focus as well)\n// for traditionally non-focusable elements with role=\"button\"\n// see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n\n[role=\"button\"] {\n cursor: pointer;\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// WebKit-style focus\n\n.tab-focus() {\n // WebKit-specific. Other browsers will keep their default outline style.\n // (Initially tried to also force default via `outline: initial`,\n // but that seems to erroneously remove the outline in Firefox altogether.)\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n.img-responsive(@display: block) {\n display: @display;\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size. Note that the\n// spelling of `min--moz-device-pixel-ratio` is intentional.\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 300;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: (12px small font / 14px base font) * 100% = about 85%\nsmall,\n.small {\n font-size: floor((100% * @font-size-small / @font-size-base));\n}\n\nmark,\n.mark {\n background-color: @state-warning-bg;\n padding: .2em;\n}\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n.text-nowrap { white-space: nowrap; }\n\n// Transformation\n.text-lowercase { text-transform: lowercase; }\n.text-uppercase { text-transform: uppercase; }\n.text-capitalize { text-transform: capitalize; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// -------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n.dl-horizontal {\n dd {\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n\n @media (min-width: @dl-horizontal-breakpoint) {\n dt {\n float: left;\n width: (@dl-horizontal-offset - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @dl-horizontal-offset;\n }\n }\n}\n\n\n// Misc\n// -------------------------\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n font-size: 90%;\n .text-uppercase();\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","// Typography\n\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover,\n a&:focus {\n color: darken(@color, 10%);\n }\n}\n","// Contextual backgrounds\n\n.bg-variant(@color) {\n background-color: @color;\n a&:hover,\n a&:focus {\n background-color: darken(@color, 10%);\n }\n}\n","// Text overflow\n// Requires inline-block or block for proper styling\n\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n\n kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n }\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n word-break: break-all;\n word-wrap: break-word;\n color: @pre-color;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n","// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n// Centered container element\n.container-fixed(@gutter: @grid-gutter-width) {\n margin-right: auto;\n margin-left: auto;\n padding-left: floor((@gutter / 2));\n padding-right: ceil((@gutter / 2));\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-left: ceil((@gutter / -2));\n margin-right: floor((@gutter / -2));\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n margin-left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-push(@columns) {\n left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-pull(@columns) {\n right: percentage((@columns / @grid-columns));\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-left: ceil((@grid-gutter-width / 2));\n padding-right: floor((@grid-gutter-width / 2));\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {\n .col-@{class}-push-0 {\n left: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {\n .col-@{class}-pull-0 {\n right: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n background-color: @table-bg;\n}\ncaption {\n padding-top: @table-cell-padding;\n padding-bottom: @table-cell-padding;\n color: @text-muted;\n text-align: left;\n}\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-of-type(odd) {\n background-color: @table-bg-accent;\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n background-color: @table-bg-hover;\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-cell;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837)\n\n @media screen and (max-width: @screen-xs-max) {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","// Tables\n\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &:hover > .@{state},\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n // Chrome and Firefox set a `min-width: min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)\n margin-bottom: 5px;\n font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; // IE8-9\n line-height: normal;\n}\n\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n display: block;\n width: 100%;\n height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid @input-border;\n border-radius: @input-border-radius; // Note: This has no effect on s in CSS.\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n // Customize the `:focus` state to imitate native WebKit styles.\n .form-control-focus();\n\n // Placeholder\n .placeholder();\n\n // Unstyle the caret on ``\n// element gets special love because it's special, and that's a fact!\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n height: @input-height;\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n\n select& {\n height: @input-height;\n line-height: @input-height;\n }\n\n textarea&,\n select[multiple]& {\n height: auto;\n }\n}\n","//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n display: inline-block;\n margin-bottom: 0; // For input.btn\n font-weight: @btn-font-weight;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n white-space: nowrap;\n .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @btn-border-radius-base);\n .user-select(none);\n\n &,\n &:active,\n &.active {\n &:focus,\n &.focus {\n .tab-focus();\n }\n }\n\n &:hover,\n &:focus,\n &.focus {\n color: @btn-default-color;\n text-decoration: none;\n }\n\n &:active,\n &.active {\n outline: 0;\n background-image: none;\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n .opacity(.65);\n .box-shadow(none);\n }\n\n a& {\n &.disabled,\n fieldset[disabled] & {\n pointer-events: none; // Future-proof disabling of clicks on `` elements\n }\n }\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Success appears as green\n.btn-success {\n .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n// Warning appears as orange\n.btn-warning {\n .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n color: @link-color;\n font-weight: normal;\n border-radius: 0;\n\n &,\n &:active,\n &.active,\n &[disabled],\n fieldset[disabled] & {\n background-color: transparent;\n .box-shadow(none);\n }\n &,\n &:hover,\n &:focus,\n &:active {\n border-color: transparent;\n }\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n background-color: transparent;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @btn-link-disabled-color;\n text-decoration: none;\n }\n }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n // line-height: ensure even-numbered height of button next to large input\n .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @btn-border-radius-large);\n}\n.btn-sm {\n // line-height: ensure proper height of button next to small input\n .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n.btn-xs {\n .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n display: block;\n width: 100%;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n &.btn-block {\n width: 100%;\n }\n}\n","// Button variants\n//\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n\n.button-variant(@color; @background; @border) {\n color: @color;\n background-color: @background;\n border-color: @border;\n\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 25%);\n }\n &:hover {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n\n &:hover,\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 17%);\n border-color: darken(@border, 25%);\n }\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n background-image: none;\n }\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus,\n &.focus {\n background-color: @background;\n border-color: @border;\n }\n }\n\n .badge {\n color: @background;\n background-color: @color;\n }\n}\n\n// Button sizes\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n}\n","// Opacity\n\n.opacity(@opacity) {\n opacity: @opacity;\n // IE8 filter\n @opacity-ie: (@opacity * 100);\n filter: ~\"alpha(opacity=@{opacity-ie})\";\n}\n","//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552.\n\n.fade {\n opacity: 0;\n .transition(opacity .15s linear);\n &.in {\n opacity: 1;\n }\n}\n\n.collapse {\n display: none;\n\n &.in { display: block; }\n tr&.in { display: table-row; }\n tbody&.in { display: table-row-group; }\n}\n\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n .transition-property(~\"height, visibility\");\n .transition-duration(.35s);\n .transition-timing-function(ease);\n}\n","//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: @caret-width-base dashed;\n border-top: @caret-width-base solid ~\"\\9\"; // IE8\n border-right: @caret-width-base solid transparent;\n border-left: @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropup,\n.dropdown {\n position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: @zindex-dropdown;\n display: none; // none by default, but block on \"open\" of the menu\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0; // override default ul\n list-style: none;\n font-size: @font-size-base;\n text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)\n background-color: @dropdown-bg;\n border: 1px solid @dropdown-fallback-border; // IE8 fallback\n border: 1px solid @dropdown-border;\n border-radius: @border-radius-base;\n .box-shadow(0 6px 12px rgba(0,0,0,.175));\n background-clip: padding-box;\n\n // Aligns the dropdown menu to right\n //\n // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n &.pull-right {\n right: 0;\n left: auto;\n }\n\n // Dividers (basically an hr) within the dropdown\n .divider {\n .nav-divider(@dropdown-divider-bg);\n }\n\n // Links within the dropdown menu\n > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: @line-height-base;\n color: @dropdown-link-color;\n white-space: nowrap; // prevent links from randomly breaking onto new lines\n }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n &:hover,\n &:focus {\n text-decoration: none;\n color: @dropdown-link-hover-color;\n background-color: @dropdown-link-hover-bg;\n }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-active-color;\n text-decoration: none;\n outline: 0;\n background-color: @dropdown-link-active-bg;\n }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-disabled-color;\n }\n\n // Nuke hover/focus effects\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none; // Remove CSS gradient\n .reset-filter();\n cursor: @cursor-disabled;\n }\n}\n\n// Open state for the dropdown\n.open {\n // Show the menu\n > .dropdown-menu {\n display: block;\n }\n\n // Remove the outline when :focus is triggered\n > a {\n outline: 0;\n }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n left: auto; // Reset the default from `.dropdown-menu`\n right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n\n// Dropdown section headers\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: @font-size-small;\n line-height: @line-height-base;\n color: @dropdown-header-color;\n white-space: nowrap; // as with > li > a\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n // Reverse the caret\n .caret {\n border-top: 0;\n border-bottom: @caret-width-base dashed;\n border-bottom: @caret-width-base solid ~\"\\9\"; // IE8\n content: \"\";\n }\n // Different positioning for bottom up menu\n .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-right {\n .dropdown-menu {\n .dropdown-menu-right();\n }\n // Necessary for overrides of the default right aligned menu.\n // Will remove come v4 in all likelihood.\n .dropdown-menu-left {\n .dropdown-menu-left();\n }\n }\n}\n","// Horizontal dividers\n//\n// Dividers (basically an hr) within dropdowns and nav lists\n\n.nav-divider(@color: #e5e5e5) {\n height: 1px;\n margin: ((@line-height-computed / 2) - 1) 0;\n overflow: hidden;\n background-color: @color;\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n","//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle; // match .btn alignment given font-size hack above\n > .btn {\n position: relative;\n float: left;\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active,\n &.active {\n z-index: 2;\n }\n }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n .btn + .btn,\n .btn + .btn-group,\n .btn-group + .btn,\n .btn-group + .btn-group {\n margin-left: -1px;\n }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n margin-left: -5px; // Offset the first child's margin\n &:extend(.clearfix all);\n\n .btn,\n .btn-group,\n .input-group {\n float: left;\n }\n > .btn,\n > .btn-group,\n > .input-group {\n margin-left: 5px;\n }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n margin-left: 0;\n &:not(:last-child):not(.dropdown-toggle) {\n .border-right-radius(0);\n }\n}\n// Need .dropdown-toggle since :last-child doesn't apply, given that a .dropdown-menu is used immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-right-radius(0);\n }\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { &:extend(.btn-xs); }\n.btn-group-sm > .btn { &:extend(.btn-sm); }\n.btn-group-lg > .btn { &:extend(.btn-lg); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n .box-shadow(none);\n }\n}\n\n\n// Reposition the caret\n.btn .caret {\n margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n border-width: @caret-width-large @caret-width-large 0;\n border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n border-width: 0 @caret-width-large @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n > .btn,\n > .btn-group,\n > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n }\n\n // Clear floats so dropdown menus can be properly placed\n > .btn-group {\n &:extend(.clearfix all);\n > .btn {\n float: none;\n }\n }\n\n > .btn + .btn,\n > .btn + .btn-group,\n > .btn-group + .btn,\n > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n }\n}\n\n.btn-group-vertical > .btn {\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n &:first-child:not(:last-child) {\n .border-top-radius(@btn-border-radius-base);\n .border-bottom-radius(0);\n }\n &:last-child:not(:first-child) {\n .border-top-radius(0);\n .border-bottom-radius(@btn-border-radius-base);\n }\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-bottom-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-top-radius(0);\n}\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n > .btn,\n > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n }\n > .btn-group .btn {\n width: 100%;\n }\n\n > .btn-group .dropdown-menu {\n left: auto;\n }\n}\n\n\n// Checkbox and radio options\n//\n// In order to support the browser's form validation feedback, powered by the\n// `required` attribute, we have to \"hide\" the inputs via `clip`. We cannot use\n// `display: none;` or `visibility: hidden;` as that also hides the popover.\n// Simply visually hiding the inputs via `opacity` would leave them clickable in\n// certain cases which is prevented by using `clip` and `pointer-events`.\n// This way, we ensure a DOM element is visible to position the popover from.\n//\n// See https://github.com/twbs/bootstrap/pull/12794 and\n// https://github.com/twbs/bootstrap/pull/14559 for more information.\n\n[data-toggle=\"buttons\"] {\n > .btn,\n > .btn-group > .btn {\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0,0,0,0);\n pointer-events: none;\n }\n }\n}\n","// Single side border-radius\n\n.border-top-radius(@radius) {\n border-top-right-radius: @radius;\n border-top-left-radius: @radius;\n}\n.border-right-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-top-right-radius: @radius;\n}\n.border-bottom-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-bottom-left-radius: @radius;\n}\n.border-left-radius(@radius) {\n border-bottom-left-radius: @radius;\n border-top-left-radius: @radius;\n}\n","//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n position: relative; // For dropdowns\n display: table;\n border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n // Undo padding and float of grid classes\n &[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n }\n\n .form-control {\n // Ensure that the input is always above the *appended* addon button for\n // proper border colors.\n position: relative;\n z-index: 2;\n\n // IE9 fubars the placeholder attribute in text inputs and the arrows on\n // select elements in input groups. To fix it, we float the input. Details:\n // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n float: left;\n\n width: 100%;\n margin-bottom: 0;\n\n &:focus {\n z-index: 3;\n }\n }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n .input-lg();\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n .input-sm();\n}\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: 1;\n color: @input-color;\n text-align: center;\n background-color: @input-group-addon-bg;\n border: 1px solid @input-group-addon-border-color;\n border-radius: @input-border-radius;\n\n // Sizing\n &.input-sm {\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n border-radius: @input-border-radius-small;\n }\n &.input-lg {\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n border-radius: @input-border-radius-large;\n }\n\n // Nuke default margins from checkboxes and radios to vertically center within.\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n margin-top: 0;\n }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n .border-right-radius(0);\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n .border-left-radius(0);\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n position: relative;\n // Jankily prevent input button groups from wrapping with `white-space` and\n // `font-size` in combination with `inline-block` on buttons.\n font-size: 0;\n white-space: nowrap;\n\n // Negative margin for spacing, position for bringing hovered/focused/actived\n // element above the siblings.\n > .btn {\n position: relative;\n + .btn {\n margin-left: -1px;\n }\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active {\n z-index: 2;\n }\n }\n\n // Negative margin to only have a 1px border between the two\n &:first-child {\n > .btn,\n > .btn-group {\n margin-right: -1px;\n }\n }\n &:last-child {\n > .btn,\n > .btn-group {\n z-index: 2;\n margin-left: -1px;\n }\n }\n}\n","//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n margin-bottom: 0;\n padding-left: 0; // Override default ul/ol\n list-style: none;\n &:extend(.clearfix all);\n\n > li {\n position: relative;\n display: block;\n\n > a {\n position: relative;\n display: block;\n padding: @nav-link-padding;\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: @nav-link-hover-bg;\n }\n }\n\n // Disabled state sets text to gray and nukes hover/tab effects\n &.disabled > a {\n color: @nav-disabled-link-color;\n\n &:hover,\n &:focus {\n color: @nav-disabled-link-hover-color;\n text-decoration: none;\n background-color: transparent;\n cursor: @cursor-disabled;\n }\n }\n }\n\n // Open dropdowns\n .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @nav-link-hover-bg;\n border-color: @link-color;\n }\n }\n\n // Nav dividers (deprecated with v3.0.1)\n //\n // This should have been removed in v3 with the dropping of `.nav-list`, but\n // we missed it. We don't currently support this anywhere, but in the interest\n // of maintaining backward compatibility in case you use it, it's deprecated.\n .nav-divider {\n .nav-divider();\n }\n\n // Prevent IE8 from misplacing imgs\n //\n // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n > li > a > img {\n max-width: none;\n }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n border-bottom: 1px solid @nav-tabs-border-color;\n > li {\n float: left;\n // Make the list-items overlay the bottom border\n margin-bottom: -1px;\n\n // Actual tabs (as links)\n > a {\n margin-right: 2px;\n line-height: @line-height-base;\n border: 1px solid transparent;\n border-radius: @border-radius-base @border-radius-base 0 0;\n &:hover {\n border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n }\n }\n\n // Active state, and its :hover to override normal :hover\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-tabs-active-link-hover-color;\n background-color: @nav-tabs-active-link-hover-bg;\n border: 1px solid @nav-tabs-active-link-hover-border-color;\n border-bottom-color: transparent;\n cursor: default;\n }\n }\n }\n // pulling this in mainly for less shorthand\n &.nav-justified {\n .nav-justified();\n .nav-tabs-justified();\n }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n > li {\n float: left;\n\n // Links rendered as pills\n > a {\n border-radius: @nav-pills-border-radius;\n }\n + li {\n margin-left: 2px;\n }\n\n // Active state\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-pills-active-link-hover-color;\n background-color: @nav-pills-active-link-hover-bg;\n }\n }\n }\n}\n\n\n// Stacked pills\n.nav-stacked {\n > li {\n float: none;\n + li {\n margin-top: 2px;\n margin-left: 0; // no need for this gap between nav items\n }\n }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n width: 100%;\n\n > li {\n float: none;\n > a {\n text-align: center;\n margin-bottom: 5px;\n }\n }\n\n > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n }\n\n @media (min-width: @screen-sm-min) {\n > li {\n display: table-cell;\n width: 1%;\n > a {\n margin-bottom: 0;\n }\n }\n }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n border-bottom: 0;\n\n > li > a {\n // Override margin from .nav-tabs\n margin-right: 0;\n border-radius: @border-radius-base;\n }\n\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border: 1px solid @nav-tabs-justified-link-border-color;\n }\n\n @media (min-width: @screen-sm-min) {\n > li > a {\n border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n border-radius: @border-radius-base @border-radius-base 0 0;\n }\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border-bottom-color: @nav-tabs-justified-active-link-border-color;\n }\n }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n // make dropdown border overlap tab border\n margin-top: -1px;\n // Remove the top rounded corners here since there is a hard edge above the menu\n .border-top-radius(0);\n}\n","//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n position: relative;\n min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n margin-bottom: @navbar-margin-bottom;\n border: 1px solid transparent;\n\n // Prevent floats from breaking the navbar\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: @navbar-border-radius;\n }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n overflow-x: visible;\n padding-right: @navbar-padding-horizontal;\n padding-left: @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n &:extend(.clearfix all);\n -webkit-overflow-scrolling: touch;\n\n &.in {\n overflow-y: auto;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border-top: 0;\n box-shadow: none;\n\n &.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0; // Override default setting\n overflow: visible !important;\n }\n\n &.in {\n overflow-y: visible;\n }\n\n // Undo the collapse side padding for navbars with containers to ensure\n // alignment of right-aligned contents.\n .navbar-fixed-top &,\n .navbar-static-top &,\n .navbar-fixed-bottom & {\n padding-left: 0;\n padding-right: 0;\n }\n }\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n .navbar-collapse {\n max-height: @navbar-collapse-max-height;\n\n @media (max-device-width: @screen-xs-min) and (orientation: landscape) {\n max-height: 200px;\n }\n }\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n > .navbar-header,\n > .navbar-collapse {\n margin-right: -@navbar-padding-horizontal;\n margin-left: -@navbar-padding-horizontal;\n\n @media (min-width: @grid-float-breakpoint) {\n margin-right: 0;\n margin-left: 0;\n }\n }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n z-index: @zindex-navbar;\n border-width: 0 0 1px;\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: @zindex-navbar-fixed;\n\n // Undo the rounded corners\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0; // override .navbar defaults\n border-width: 1px 0 0;\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n float: left;\n padding: @navbar-padding-vertical @navbar-padding-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-computed;\n height: @navbar-height;\n\n &:hover,\n &:focus {\n text-decoration: none;\n }\n\n > img {\n display: block;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n .navbar > .container &,\n .navbar > .container-fluid & {\n margin-left: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: @navbar-padding-horizontal;\n padding: 9px 10px;\n .navbar-vertical-align(34px);\n background-color: transparent;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n border-radius: @border-radius-base;\n\n // We remove the `outline` here, but later compensate by attaching `:hover`\n // styles to `:focus`.\n &:focus {\n outline: 0;\n }\n\n // Bars\n .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n }\n .icon-bar + .icon-bar {\n margin-top: 4px;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n display: none;\n }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: @line-height-computed;\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n > li > a,\n .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n > li > a {\n line-height: @line-height-computed;\n &:hover,\n &:focus {\n background-image: none;\n }\n }\n }\n }\n\n // Uncollapse the nav\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin: 0;\n\n > li {\n float: left;\n > a {\n padding-top: @navbar-padding-vertical;\n padding-bottom: @navbar-padding-vertical;\n }\n }\n }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n margin-left: -@navbar-padding-horizontal;\n margin-right: -@navbar-padding-horizontal;\n padding: 10px @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n\n // Mixin behavior for optimum display\n .form-inline();\n\n .form-group {\n @media (max-width: @grid-float-breakpoint-max) {\n margin-bottom: 5px;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n }\n\n // Vertically center in expanded, horizontal navbar\n .navbar-vertical-align(@input-height-base);\n\n // Undo 100% width for pull classes\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n .box-shadow(none);\n }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n .border-top-radius(@navbar-border-radius);\n .border-bottom-radius(0);\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n .navbar-vertical-align(@input-height-base);\n\n &.btn-sm {\n .navbar-vertical-align(@input-height-small);\n }\n &.btn-xs {\n .navbar-vertical-align(22);\n }\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n .navbar-vertical-align(@line-height-computed);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin-left: @navbar-padding-horizontal;\n margin-right: @navbar-padding-horizontal;\n }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n//\n// Declared after the navbar components to ensure more specificity on the margins.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-left { .pull-left(); }\n .navbar-right {\n .pull-right();\n margin-right: -@navbar-padding-horizontal;\n\n ~ .navbar-right {\n margin-right: 0;\n }\n }\n}\n\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n background-color: @navbar-default-bg;\n border-color: @navbar-default-border;\n\n .navbar-brand {\n color: @navbar-default-brand-color;\n &:hover,\n &:focus {\n color: @navbar-default-brand-hover-color;\n background-color: @navbar-default-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-default-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-default-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n\n .navbar-toggle {\n border-color: @navbar-default-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-default-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-default-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: @navbar-default-border;\n }\n\n // Dropdown menu items\n .navbar-nav {\n // Remove background color from open dropdown\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-default-link-active-bg;\n color: @navbar-default-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n > li > a {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n }\n }\n\n\n // Links in navbars\n //\n // Add a class to ensure links outside the navbar nav are colored correctly.\n\n .navbar-link {\n color: @navbar-default-link-color;\n &:hover {\n color: @navbar-default-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n }\n }\n }\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n background-color: @navbar-inverse-bg;\n border-color: @navbar-inverse-border;\n\n .navbar-brand {\n color: @navbar-inverse-brand-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-brand-hover-color;\n background-color: @navbar-inverse-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-inverse-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-inverse-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n\n // Darken the responsive nav toggle\n .navbar-toggle {\n border-color: @navbar-inverse-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-inverse-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-inverse-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: darken(@navbar-inverse-bg, 7%);\n }\n\n // Dropdowns\n .navbar-nav {\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-inverse-link-active-bg;\n color: @navbar-inverse-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display\n .open .dropdown-menu {\n > .dropdown-header {\n border-color: @navbar-inverse-border;\n }\n .divider {\n background-color: @navbar-inverse-border;\n }\n > li > a {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n }\n }\n\n .navbar-link {\n color: @navbar-inverse-link-color;\n &:hover {\n color: @navbar-inverse-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n }\n }\n }\n}\n","// Navbar vertical align\n//\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n\n.navbar-vertical-align(@element-height) {\n margin-top: ((@navbar-height - @element-height) / 2);\n margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n","//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n .clearfix();\n}\n.center-block {\n .center-block();\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n display: none !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n position: fixed;\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n margin-bottom: @line-height-computed;\n list-style: none;\n background-color: @breadcrumb-bg;\n border-radius: @border-radius-base;\n\n > li {\n display: inline-block;\n\n + li:before {\n content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n padding: 0 5px;\n color: @breadcrumb-color;\n }\n }\n\n > .active {\n color: @breadcrumb-active-color;\n }\n}\n","//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: @line-height-computed 0;\n border-radius: @border-radius-base;\n\n > li {\n display: inline; // Remove list-style and block-level defaults\n > a,\n > span {\n position: relative;\n float: left; // Collapse white-space\n padding: @padding-base-vertical @padding-base-horizontal;\n line-height: @line-height-base;\n text-decoration: none;\n color: @pagination-color;\n background-color: @pagination-bg;\n border: 1px solid @pagination-border;\n margin-left: -1px;\n }\n &:first-child {\n > a,\n > span {\n margin-left: 0;\n .border-left-radius(@border-radius-base);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius-base);\n }\n }\n }\n\n > li > a,\n > li > span {\n &:hover,\n &:focus {\n z-index: 2;\n color: @pagination-hover-color;\n background-color: @pagination-hover-bg;\n border-color: @pagination-hover-border;\n }\n }\n\n > .active > a,\n > .active > span {\n &,\n &:hover,\n &:focus {\n z-index: 3;\n color: @pagination-active-color;\n background-color: @pagination-active-bg;\n border-color: @pagination-active-border;\n cursor: default;\n }\n }\n\n > .disabled {\n > span,\n > span:hover,\n > span:focus,\n > a,\n > a:hover,\n > a:focus {\n color: @pagination-disabled-color;\n background-color: @pagination-disabled-bg;\n border-color: @pagination-disabled-border;\n cursor: @cursor-disabled;\n }\n }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n","// Pagination\n\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n > li {\n > a,\n > span {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n }\n &:first-child {\n > a,\n > span {\n .border-left-radius(@border-radius);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius);\n }\n }\n }\n}\n","//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n padding-left: 0;\n margin: @line-height-computed 0;\n list-style: none;\n text-align: center;\n &:extend(.clearfix all);\n li {\n display: inline;\n > a,\n > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: @pager-bg;\n border: 1px solid @pager-border;\n border-radius: @pager-border-radius;\n }\n\n > a:hover,\n > a:focus {\n text-decoration: none;\n background-color: @pager-hover-bg;\n }\n }\n\n .next {\n > a,\n > span {\n float: right;\n }\n }\n\n .previous {\n > a,\n > span {\n float: left;\n }\n }\n\n .disabled {\n > a,\n > a:hover,\n > a:focus,\n > span {\n color: @pager-disabled-color;\n background-color: @pager-bg;\n cursor: @cursor-disabled;\n }\n }\n}\n","//\n// Labels\n// --------------------------------------------------\n\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: @label-color;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n\n // Add hover effects, but only for links\n a& {\n &:hover,\n &:focus {\n color: @label-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Empty labels collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for labels in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n .label-variant(@label-default-bg);\n}\n\n.label-primary {\n .label-variant(@label-primary-bg);\n}\n\n.label-success {\n .label-variant(@label-success-bg);\n}\n\n.label-info {\n .label-variant(@label-info-bg);\n}\n\n.label-warning {\n .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n .label-variant(@label-danger-bg);\n}\n","// Labels\n\n.label-variant(@color) {\n background-color: @color;\n\n &[href] {\n &:hover,\n &:focus {\n background-color: darken(@color, 10%);\n }\n }\n}\n","//\n// Badges\n// --------------------------------------------------\n\n\n// Base class\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: @font-size-small;\n font-weight: @badge-font-weight;\n color: @badge-color;\n line-height: @badge-line-height;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: @badge-bg;\n border-radius: @badge-border-radius;\n\n // Empty badges collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for badges in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n\n .btn-xs &,\n .btn-group-xs > .btn & {\n top: 0;\n padding: 1px 5px;\n }\n\n // Hover state, but only for links\n a& {\n &:hover,\n &:focus {\n color: @badge-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Account for badges in navs\n .list-group-item.active > &,\n .nav-pills > .active > a > & {\n color: @badge-active-color;\n background-color: @badge-active-bg;\n }\n\n .list-group-item > & {\n float: right;\n }\n\n .list-group-item > & + & {\n margin-right: 5px;\n }\n\n .nav-pills > li > a > & {\n margin-left: 3px;\n }\n}\n","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n padding-top: @jumbotron-padding;\n padding-bottom: @jumbotron-padding;\n margin-bottom: @jumbotron-padding;\n color: @jumbotron-color;\n background-color: @jumbotron-bg;\n\n h1,\n .h1 {\n color: @jumbotron-heading-color;\n }\n\n p {\n margin-bottom: (@jumbotron-padding / 2);\n font-size: @jumbotron-font-size;\n font-weight: 200;\n }\n\n > hr {\n border-top-color: darken(@jumbotron-bg, 10%);\n }\n\n .container &,\n .container-fluid & {\n border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n padding-left: (@grid-gutter-width / 2);\n padding-right: (@grid-gutter-width / 2);\n }\n\n .container {\n max-width: 100%;\n }\n\n @media screen and (min-width: @screen-sm-min) {\n padding-top: (@jumbotron-padding * 1.6);\n padding-bottom: (@jumbotron-padding * 1.6);\n\n .container &,\n .container-fluid & {\n padding-left: (@jumbotron-padding * 2);\n padding-right: (@jumbotron-padding * 2);\n }\n\n h1,\n .h1 {\n font-size: @jumbotron-heading-font-size;\n }\n }\n}\n","//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n display: block;\n padding: @thumbnail-padding;\n margin-bottom: @line-height-computed;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(border .2s ease-in-out);\n\n > img,\n a > img {\n &:extend(.img-responsive);\n margin-left: auto;\n margin-right: auto;\n }\n\n // Add a hover state for linked versions only\n a&:hover,\n a&:focus,\n a&.active {\n border-color: @link-color;\n }\n\n // Image captions\n .caption {\n padding: @thumbnail-caption-padding;\n color: @thumbnail-caption-color;\n }\n}\n","//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n padding: @alert-padding;\n margin-bottom: @line-height-computed;\n border: 1px solid transparent;\n border-radius: @alert-border-radius;\n\n // Headings for larger alerts\n h4 {\n margin-top: 0;\n // Specified for the h4 to prevent conflicts of changing @headings-color\n color: inherit;\n }\n\n // Provide class for links that match alerts\n .alert-link {\n font-weight: @alert-link-font-weight;\n }\n\n // Improve alignment and spacing of inner content\n > p,\n > ul {\n margin-bottom: 0;\n }\n\n > p + p {\n margin-top: 5px;\n }\n}\n\n// Dismissible alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0.\n.alert-dismissible {\n padding-right: (@alert-padding + 20);\n\n // Adjust close link position\n .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n\n.alert-info {\n .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n\n.alert-warning {\n .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n\n.alert-danger {\n .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n","// Alerts\n\n.alert-variant(@background; @border; @text-color) {\n background-color: @background;\n border-color: @border;\n color: @text-color;\n\n hr {\n border-top-color: darken(@border, 5%);\n }\n .alert-link {\n color: darken(@text-color, 10%);\n }\n}\n","//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n overflow: hidden;\n height: @line-height-computed;\n margin-bottom: @line-height-computed;\n background-color: @progress-bg;\n border-radius: @progress-border-radius;\n .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: @font-size-small;\n line-height: @line-height-computed;\n color: @progress-bar-color;\n text-align: center;\n background-color: @progress-bar-bg;\n .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n .transition(width .6s ease);\n}\n\n// Striped bars\n//\n// `.progress-striped .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar-striped` class, which you just add to an existing\n// `.progress-bar`.\n.progress-striped .progress-bar,\n.progress-bar-striped {\n #gradient > .striped();\n background-size: 40px 40px;\n}\n\n// Call animation for the active one\n//\n// `.progress.active .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar.active` approach.\n.progress.active .progress-bar,\n.progress-bar.active {\n .animation(progress-bar-stripes 2s linear infinite);\n}\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n .progress-bar-variant(@progress-bar-danger-bg);\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Progress bars\n\n.progress-bar-variant(@color) {\n background-color: @color;\n\n // Deprecated parent class requirement as of v3.2.0\n .progress-striped & {\n #gradient > .striped();\n }\n}\n",".media {\n // Proper spacing between instances of .media\n margin-top: 15px;\n\n &:first-child {\n margin-top: 0;\n }\n}\n\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n\n.media-body {\n width: 10000px;\n}\n\n.media-object {\n display: block;\n\n // Fix collapse in webkit from max-width: 100% and display: table-cell.\n &.img-thumbnail {\n max-width: none;\n }\n}\n\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n\n.media-middle {\n vertical-align: middle;\n}\n\n.media-bottom {\n vertical-align: bottom;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n\n// Media list variation\n//\n// Undo default ul/ol styles\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n","//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on

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 literal 0 HcmV?d00001 diff --git a/nstock/static/fonts/Raleway-Regular.ttf b/nstock/static/fonts/Raleway-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e570a2d5c39b2841b5753350a3822bd2b685e771 GIT binary patch literal 178520 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 literal 0 HcmV?d00001 diff --git a/nstock/static/fonts/fontawesome-webfont.eot b/nstock/static/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..e9f60ca953f93e35eab4108bd414bc02ddcf3928 GIT binary patch literal 165742 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 G*yFsbY~cLNXLP73aA74Mq6M9f^&YV`isWW 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

5q!RY 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 + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nstock/static/fonts/fontawesome-webfont.ttf b/nstock/static/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..35acda2fa1196aad98c2adf4378a7611dd713aa3 GIT binary patch literal 165548 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 z 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 d0mRO}xo^G_%I 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 SdSQM28?+M|D(2r_;{O0|uQ74} literal 0 HcmV?d00001 diff --git a/nstock/static/fonts/fontawesome-webfont.woff2 b/nstock/static/fonts/fontawesome-webfont.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..4d13fc60404b91e398a37200c4a77b645cfd9586 GIT binary patch literal 77160 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 literal 0 HcmV?d00001 diff --git a/nstock/static/fonts/glyphicons-halflings-regular.eot b/nstock/static/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000000000000000000000000000000000000..b93a4953fff68df523aa7656497ee339d6026d64 GIT binary patch literal 20127 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nstock/static/fonts/glyphicons-halflings-regular.ttf b/nstock/static/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..1413fc609ab6f21774de0cb7e01360095584f65b GIT binary patch literal 45404 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 G`u_lkUM?>H literal 0 HcmV?d00001 diff --git a/nstock/static/fonts/glyphicons-halflings-regular.woff2 b/nstock/static/fonts/glyphicons-halflings-regular.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..64539b54c3751a6d9adb44c8e3a45ba5a73b77f0 GIT binary patch literal 18028 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 literal 0 HcmV?d00001 diff --git a/nstock/static/images/background.jpg b/nstock/static/images/background.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8add8fa741e8e784b49114b46dc362f7f9854538 GIT binary patch literal 740881 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

Lw}aX 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

(f?|uVo*`(IGEYs!0SXeLHXkaLD!#c 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

Wssoeu}gI9V> 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

E_XdeEtDSpUnD+Ee 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

1o_Kg`5hQ=?YQ$O4WXuD^H7IX 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

i`;Aaofd$#;-$kg#05m?Wi!*v5Ti; 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

wAO;E@S0 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 N002ovPDHLkV1lDZ(&+#I literal 0 HcmV?d00001 diff --git a/nstock/static/images/favicon.ico b/nstock/static/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..d2296d5e893eeef0d9c23629b93fc15f0c07de6e GIT binary patch literal 198 zcmZQzU<5(|0VW0z*Z{<0K&%180zj+)#2|SPZ~&7K0-_qiW}p8IF5}98KWZe literal 0 HcmV?d00001 diff --git a/nstock/static/images/favicon.png b/nstock/static/images/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..bd0a414ec86d9994b46676a8d399955a211da224 GIT binary patch literal 323 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b zK-vS0-A-oPfdtD69Mgd`SU*F|v9*VRoE%RV#}JFt$q5VCD$M5pwKtPGcI;St=SBge z2(6Fm%2v{mJ)H9yZQYu1}7PYx)% z@f?oav8UOWC*MSf`N75p?Scu5d6r8U#vMo%JQ^oa!N723Q>lXa!beMh_Ntb+MwFx^ zmZVxG7o`Fz1|tJQLtO(4T_cka14}DoLn{MwT?11q1A~nj7xtiN$jwj5OsmAL;ecrd QP(1^Kr>mdKI;Vst0O;yt8UO$Q literal 0 HcmV?d00001 diff --git a/nstock/static/images/gplus-32.png b/nstock/static/images/gplus-32.png new file mode 100644 index 0000000000000000000000000000000000000000..c42eab784578bf4e827722400f125760ebab527a GIT binary patch literal 1513 zcmV~mL-d9E}6-eW&UBZZ2My_Cfm%i zR~F|3K~NBsXK5*=D3)i1wty(22(yB`TUx&RokMTe)+&h3CZC-4{C@YG-#z!-d&`WO zGS-!qz^GkB4wEK=|ACn(NH+1}^K$G@-wCy z0;G7yEEQ9(4no!1aNNo}0oZK9SWg%F&gWvdMeFGE#5OSwZT4>7=WNp!v>pB&nq6C< ze0`nBxsnntCUn;FS~TQt1(Z_(Qe0=pMhw?5W1SYR?%xf?>OeHnUTCEOc*}pQcWi=X z_`V}=;&v}o8LJ(6o;0ULd0YW0-e$*UEEaIq(NVfaeqzuTI#|+7zvZ+)8V`O1DVMud zkR$d@vpugu=KqlDG`9lW;+2HW&?e$0dT)r0#3yvukQ|26SYM17+9Bmn4-cU{F$7mA z#&Z;Ilg;85BjW5K2>{ar;8Phz&JpAg9TdRG24xRXBc2dwLg0 zaS1Dt1>wf2zhE`pb1~J|3zMc6!_8Vp-#xVw@)UZ+(o)U`-%swOSe3nHmDE`jxdIB> zV8&mL!c?ckkhWg5(}Vr6-Ww1mdpc2>5`#)Qi)W$2-ZD{Hj2}v(R*6CiBUa#i#B!8n zB*97#CrMvn9_@`)v>*JQiBfyZ`0g$vrA~Mu)$eY`^uQg5v5q!eppAGbdX-D=(_$BC zKzF==qBUWdyxxWB{@V_NiVBpZ#)`Yd({XbtacU*3ByuIV3w-Irm!lwT8P0|-Ltf}o zXg>J>)AZ_fHp*|oots5&F&+1`SRoCRPm|?_EJaaLB-H!&K>O8aF#h@@ZqdJ@$?HZ~ z`fj?Iy3vKYkM|*;iY=nT7oyPKvUBw0YdmxirrK&)dV3s3ni?=DFBSNA=a{4}doS{+ zaK0LaPw2cI8*gug^kR3*sZ}FL+C1UXT$O&4E zv$9~ARC1WR90=>T`dVjeH1J4JnS9Y<8;0P&*v_?+xtd)gw|EW3ec P00000NkvXXu0mjf1Z(LN literal 0 HcmV?d00001 diff --git a/nstock/static/images/twitter.png b/nstock/static/images/twitter.png new file mode 100644 index 0000000000000000000000000000000000000000..d94419a4b1011554746d666a133235679dec04a3 GIT binary patch literal 1120 zcmV-m1fTnfP)9nfCllPH zmZqC+wkFx^ZD!6n{%3cR&89Q6O>_C#pV=8^&-b10zn#_K+WSBMHIXvS{6I39!yek5 zN@aefUeAB<{8LjK4?nzo{oJ>+C3&~OB^Po}U13}-EJ=l_u(fx8oSqmx^6>fbBN<3~ z(ByJ21wcgCpwacGxe}&t-act0BH{ew11Z!T0c(%Jl{Fk7Oe97I)0ioh^G3>y<`_|` z*&O?2v{xuhg>4u*BiRLX^<*E7@&O9lFf;*cdx8&MiDZ@8~3GZGw}WG z<$@prt^$5$5V(rfy2*GX@cnHOXe+=2cVve2ZbD4oMFofe?-2rh)9#hoH4Ec!|Il;s z1SRa5i4lw(O$Stha2230z9C@U1XwJB{@g=730Rhc)8G7!3vV6op#Tq7fNdo}x70j( zw_GB+Tx+7VW}!bG@>YPm3J59SM?r20!FDX$7f0GuIU~H(MUw`#nmE?4X1Xb zfM7}i4z@W7y?pFYqMeAYv#^0Oi{SKyIb2()Vzue`{x-;ErxC4(z&i&{WTUwBZ?)@L zdN75##Z|m_@s{rnV_}9Cvo{!hXf-f1`qa8*kr5Y zc`oj7OkG>S*l^stx*)q15I$vCt~c@elWE*;aLg`STjs>Q!>Y?d2CBA%srxIyT3xC~ zyb3GJ_~=9iPY=eR(eCfpvwbnd49#=RHm2xwLMLFxtCo5F&JxZX%Rr^WSA`0GDb@qC zJZUg|@=OMWyCt6xxJk&VQ`wHwiirq3L~>kNSVSfo!5dE;z{kf20twhOXs#?2sc+o7 zF?AMHn0)<6X3LrC@ zQH|qyCIrv_e&Z&p)iq>eQOa0qHg0@&(^b-`wH1cKQkV+6HECY_?CW!;89q6B_z;FO z{Zu_6a${F_tzvFFHvU;E<2M4YHLUaBz53FrjZyc)*)J!AhCJ6;js{g=LOzHoRW+%m mAjvL~|Nga?TYu007hnJ&oPNBq52Shk0000').tag("https",'');Clicky.prototype.initialize=function(page){var user=this.analytics.user();window.clicky_site_ids=window.clicky_site_ids||[this.options.siteId];this.identify(new Identify({userId:user.id(),traits:user.traits()}));this.load(this.ready)};Clicky.prototype.loaded=function(){return is.object(window.clicky)};Clicky.prototype.page=function(page){var properties=page.properties();var category=page.category();var name=page.fullName();window.clicky.log(properties.path,name||properties.title)};Clicky.prototype.identify=function(identify){window.clicky_custom=window.clicky_custom||{};window.clicky_custom.session=window.clicky_custom.session||{};var traits=identify.traits();var username=identify.username();var email=identify.email();var name=identify.name();if(username||email||name)traits.username=username||email||name;extend(window.clicky_custom.session,traits)};Clicky.prototype.track=function(track){window.clicky.goal(track.event(),track.revenue())}},{facade:147,extend:145,"analytics.js-integration":88,is:91}],25:[function(require,module,exports){var integration=require("analytics.js-integration");var useHttps=require("use-https");var Comscore=module.exports=integration("comScore").assumesPageview().global("_comscore").global("COMSCORE").option("c1","2").option("c2","").tag("http",'")}},{bind:101,domify:119,each:4,extend:145,"analytics.js-integration":88,json:179}],179:[function(require,module,exports){var json=window.JSON||{};var stringify=json.stringify;var parse=json.parse;module.exports=parse&&stringify?JSON:require("json-fallback")},{"json-fallback":180}],180:[function(require,module,exports){(function(){"use strict";var JSON=module.exports={};function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()}}var cx,escapable,gap,indent,meta,rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i').mapping("events");Facebook.prototype.initialize=function(page){window._fbq=window._fbq||[];this.load(this.ready);window._fbq.loaded=true};Facebook.prototype.loaded=function(){return!!(window._fbq&&window._fbq.loaded)};Facebook.prototype.track=function(track){var event=track.event();var events=this.events(event);var revenue=track.revenue()||0;var self=this;each(events,function(event){push("track",event,{value:String(revenue.toFixed(2)),currency:self.options.currency})});if(!events.length){var data=track.properties();push("track",event,data)}}},{"analytics.js-integration":88,"global-queue":173,each:4}],34:[function(require,module,exports){var push=require("global-queue")("_fxm");var integration=require("analytics.js-integration");var Track=require("facade").Track;var each=require("each");var FoxMetrics=module.exports=integration("FoxMetrics").assumesPageview().global("_fxm").option("appId","").tag('');FullStory.prototype.initialize=function(){var self=this;window._fs_debug=this.options.debug;window._fs_host="www.fullstory.com";window._fs_org=this.options.org;(function(m,n,e,t,l,o,g,y){g=m[e]=function(a,b){g.q?g.q.push([a,b]):g._api(a,b)};g.q=[];g.identify=function(i,v){g(l,{uid:i});if(v)g(l,v)};g.setUserVars=function(v){FS(l,v)};g.setSessionVars=function(v){FS("session",v)};g.setPageVars=function(v){FS("page",v)};self.ready();self.load()})(window,document,"FS","script","user")};FullStory.prototype.loaded=function(){return!!window.FS};FullStory.prototype.identify=function(identify){var id=identify.userId()||identify.anonymousId();var traits=identify.traits();del(traits,"id");if(identify.name()){traits.displayName=identify.name();del(traits,"name")}each(traits,function(trait,value){if(trait!=="displayName"&&trait!=="email"){var newTrait=convert(trait,value);traits[newTrait]=value;del(traits,trait)}});if(typeof id!=="string")id=""+id;window.FS.identify(id,traits)};function convert(trait,value){if(is.string(value))return trait+="_str";if(isInt(value))return trait+="_int";if(isFloat(value))return trait+="_real";if(is.date(value))return trait+="_date";if(is.boolean(value))return trait+="_bool"}function isFloat(n){return n===+n&&n!==(n|0)}function isInt(n){return n===+n&&n===(n|0)}},{each:4,is:91,"obj-case":92,"analytics.js-integration":88}],37:[function(require,module,exports){var integration=require("analytics.js-integration");var push=require("global-queue")("_gauges");var Gauges=module.exports=integration("Gauges").assumesPageview().global("_gauges").option("siteId","").tag(' + +**/ + +jQuery(function(){ + var script_source = jQuery('script[src*="share.js"]').attr('src'); + var params = function(name,default_value) { + var match = RegExp('[?&]' + name + '=([^&]*)').exec(script_source); + return match && decodeURIComponent(match[1].replace(/\+/g, ' '))||default_value; + } + var path = params('static','social'); + var url = encodeURIComponent(window.location.href); + var host = window.location.hostname; + var title = escape(jQuery('title').text()); + var twit = 'http://twitter.com/home?status='+title+'%20'+url; + var facebook = 'http://www.facebook.com/sharer.php?u='+url; + var gplus = 'https://plus.google.com/share?url='+url; + var tbar = ''; + // Add the share tool bar. + jQuery('body').append(tbar); + var st = jQuery('#socialdrawer'); + st.css({'opacity':'.7','z-index':'3000','background':'#FFF','border':'solid 1px #666','border-width':' 1px 0 0 1px','height':'20px','width':'40px','position':'fixed','bottom':'0','right':'0','padding':'2px 5px','overflow':'hidden','-webkit-border-top-left-radius':' 12px','-moz-border-radius-topleft':' 12px','border-top-left-radius':' 12px','-moz-box-shadow':' -3px -3px 3px rgba(0,0,0,0.5)','-webkit-box-shadow':' -3px -3px 3px rgba(0,0,0,0.5)','box-shadow':' -3px -3px 3px rgba(0,0,0,0.5)'}); + jQuery('#socialdrawer a').css({'float':'left','width':'32px','margin':'3px 2px 2px 2px','padding':'0','cursor':'pointer'}); + jQuery('#socialdrawer span').css({'float':'left','margin':'2px 3px','text-shadow':' 1px 1px 1px #FFF','color':'#444','font-size':'12px','line-height':'1em'}); + jQuery('#socialdrawer img').hide(); + // hover + st.click(function(){ + jQuery(this).animate({height:'40px', width:'160px', opacity: 0.95}, 300); + jQuery('#socialdrawer img').show(); + }); + //leave + st.mouseleave(function(){ + st.animate({height:'20px', width: '40px', opacity: .7}, 300); + jQuery('#socialdrawer img').hide(); + return false; + } ); + }); diff --git a/nstock/static/js/vue.min.js b/nstock/static/js/vue.min.js new file mode 100644 index 0000000..9ac23c4 --- /dev/null +++ b/nstock/static/js/vue.min.js @@ -0,0 +1,8 @@ +/*! + * Vue.js v2.1.10 + * (c) 2014-2017 Evan You + * Released under the MIT License. + */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Vue=t()}(this,function(){"use strict";function e(e){return null==e?"":"object"==typeof e?JSON.stringify(e,null,2):String(e)}function t(e){var t=parseFloat(e);return isNaN(t)?e:t}function n(e,t){for(var n=Object.create(null),r=e.split(","),i=0;i-1)return e.splice(n,1)}}function i(e,t){return ii.call(e,t)}function o(e){return"string"==typeof e||"number"==typeof e}function a(e){var t=Object.create(null);return function(n){var r=t[n];return r||(t[n]=e(n))}}function s(e,t){function n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}return n._length=e.length,n}function c(e,t){t=t||0;for(var n=e.length-t,r=new Array(n);n--;)r[n]=e[n+t];return r}function u(e,t){for(var n in t)e[n]=t[n];return e}function l(e){return null!==e&&"object"==typeof e}function f(e){return li.call(e)===fi}function p(e){for(var t={},n=0;n1?c(n):n;for(var r=c(arguments,1),i=0,o=n.length;i=0&&Gi[n].id>e.id;)n--;Gi.splice(Math.max(n,eo)+1,0,e)}else Gi.push(e);Qi||(Qi=!0,Ai(xe))}}function Ae(e){ro.clear(),Oe(e,ro)}function Oe(e,t){var n,r,i=Array.isArray(e);if((i||l(e))&&Object.isExtensible(e)){if(e.__ob__){var o=e.__ob__.dep.id;if(t.has(o))return;t.add(o)}if(i)for(n=e.length;n--;)Oe(e[n],t);else for(r=Object.keys(e),n=r.length;n--;)Oe(e[r[n]],t)}}function Se(e){e._watchers=[];var t=e.$options;t.props&&Te(e,t.props),t.methods&&Ne(e,t.methods),t.data?Ee(e):k(e._data={},!0),t.computed&&Ie(e,t.computed),t.watch&&Le(e,t.watch)}function Te(e,t){var n=e.$options.propsData||{},r=e.$options._propKeys=Object.keys(t),i=!e.$parent;Mi.shouldConvert=i;for(var o=function(i){var o=r[i];A(e,o,P(o,t,n,e))},a=0;a-1:e.test(t)}function We(e,t){for(var n in e){var r=e[n];if(r){var i=Ke(r.componentOptions);i&&!t(i)&&(Ze(r),e[n]=null)}}}function Ze(e){e&&(e.componentInstance._inactive||we(e.componentInstance,"deactivated"),e.componentInstance.$destroy())}function Ge(e){var t={};t.get=function(){return vi},Object.defineProperty(e,"config",t),e.util=Fi,e.set=O,e.delete=S,e.nextTick=Ai,e.options=Object.create(null),vi._assetTypes.forEach(function(t){e.options[t+"s"]=Object.create(null)}),e.options._base=e,u(e.options.components,co),Be(e),ze(e),Ve(e),Je(e)}function Ye(e){for(var t=e.data,n=e,r=e;r.componentInstance;)r=r.componentInstance._vnode,r.data&&(t=Qe(r.data,t));for(;n=n.parent;)n.data&&(t=Qe(t,n.data));return Xe(t)}function Qe(e,t){return{staticClass:et(e.staticClass,t.staticClass),class:e.class?[e.class,t.class]:t.class}}function Xe(e){var t=e.class,n=e.staticClass;return n||t?et(n,tt(t)):""}function et(e,t){return e?t?e+" "+t:e:t||""}function tt(e){var t="";if(!e)return t;if("string"==typeof e)return e;if(Array.isArray(e)){for(var n,r=0,i=e.length;r-1?ko[e]=t.constructor===window.HTMLUnknownElement||t.constructor===window.HTMLElement:ko[e]=/HTMLUnknownElement/.test(t.toString())}function it(e){if("string"==typeof e){if(e=document.querySelector(e),!e)return document.createElement("div")}return e}function ot(e,t){var n=document.createElement(e);return"select"!==e?n:(t.data&&t.data.attrs&&"multiple"in t.data.attrs&&n.setAttribute("multiple","multiple"),n)}function at(e,t){return document.createElementNS(bo[e],t)}function st(e){return document.createTextNode(e)}function ct(e){return document.createComment(e)}function ut(e,t,n){e.insertBefore(t,n)}function lt(e,t){e.removeChild(t)}function ft(e,t){e.appendChild(t)}function pt(e){return e.parentNode}function dt(e){return e.nextSibling}function vt(e){return e.tagName}function ht(e,t){e.textContent=t}function mt(e,t,n){e.setAttribute(t,n)}function gt(e,t){var n=e.data.ref;if(n){var i=e.context,o=e.componentInstance||e.elm,a=i.$refs;t?Array.isArray(a[n])?r(a[n],o):a[n]===o&&(a[n]=void 0):e.data.refInFor?Array.isArray(a[n])&&a[n].indexOf(o)<0?a[n].push(o):a[n]=[o]:a[n]=o}}function yt(e){return null==e}function _t(e){return null!=e}function bt(e,t){return e.key===t.key&&e.tag===t.tag&&e.isComment===t.isComment&&!e.data==!t.data}function $t(e,t,n){var r,i,o={};for(r=t;r<=n;++r)i=e[r].key,_t(i)&&(o[i]=r);return o}function wt(e){function t(e){return new Hi(O.tagName(e).toLowerCase(),{},[],void 0,e)}function r(e,t){function n(){0===--n.listeners&&i(e)}return n.listeners=t,n}function i(e){var t=O.parentNode(e);t&&O.removeChild(t,e)}function a(e,t,n,r,i){if(e.isRootInsert=!i,!s(e,t,n,r)){var o=e.data,a=e.children,c=e.tag;_t(c)?(e.elm=e.ns?O.createElementNS(e.ns,c):O.createElement(c,e),v(e),f(e,a,t),_t(o)&&d(e,t),l(n,e.elm,r)):e.isComment?(e.elm=O.createComment(e.text),l(n,e.elm,r)):(e.elm=O.createTextNode(e.text),l(n,e.elm,r))}}function s(e,t,n,r){var i=e.data;if(_t(i)){var o=_t(e.componentInstance)&&i.keepAlive;if(_t(i=i.hook)&&_t(i=i.init)&&i(e,!1,n,r),_t(e.componentInstance))return c(e,t),o&&u(e,t,n,r),!0}}function c(e,t){e.data.pendingInsert&&t.push.apply(t,e.data.pendingInsert),e.elm=e.componentInstance.$el,p(e)?(d(e,t),v(e)):(gt(e),t.push(e))}function u(e,t,n,r){for(var i,o=e;o.componentInstance;)if(o=o.componentInstance._vnode,_t(i=o.data)&&_t(i=i.transition)){for(i=0;ip?(u=yt(n[m+1])?null:n[m+1].elm,h(e,u,n,f,m,r)):f>m&&g(e,t,l,p)}function b(e,t,n,r){if(e!==t){if(t.isStatic&&e.isStatic&&t.key===e.key&&(t.isCloned||t.isOnce))return t.elm=e.elm,void(t.componentInstance=e.componentInstance);var i,o=t.data,a=_t(o);a&&_t(i=o.hook)&&_t(i=i.prepatch)&&i(e,t);var s=t.elm=e.elm,c=e.children,u=t.children;if(a&&p(t)){for(i=0;i-1?t.split(/\s+/).forEach(function(t){return e.classList.add(t)}):e.classList.add(t);else{var n=" "+e.getAttribute("class")+" ";n.indexOf(" "+t+" ")<0&&e.setAttribute("class",(n+t).trim())}}function zt(e,t){if(t&&t.trim())if(e.classList)t.indexOf(" ")>-1?t.split(/\s+/).forEach(function(t){return e.classList.remove(t)}):e.classList.remove(t);else{for(var n=" "+e.getAttribute("class")+" ",r=" "+t+" ";n.indexOf(r)>=0;)n=n.replace(r," ");e.setAttribute("class",n.trim())}}function Vt(e){Yo(function(){Yo(e)})}function Jt(e,t){(e._transitionClasses||(e._transitionClasses=[])).push(t),Bt(e,t)}function Kt(e,t){e._transitionClasses&&r(e._transitionClasses,t),zt(e,t)}function qt(e,t,n){var r=Wt(e,t),i=r.type,o=r.timeout,a=r.propCount;if(!i)return n();var s=i===Jo?Wo:Go,c=0,u=function(){e.removeEventListener(s,l),n()},l=function(t){t.target===e&&++c>=a&&u()};setTimeout(function(){c0&&(n=Jo,l=a,f=o.length):t===Ko?u>0&&(n=Ko,l=u,f=c.length):(l=Math.max(a,u),n=l>0?a>u?Jo:Ko:null,f=n?n===Jo?o.length:c.length:0);var p=n===Jo&&Qo.test(r[qo+"Property"]);return{type:n,timeout:l,propCount:f,hasTransform:p}}function Zt(e,t){for(;e.length1,j=n._enterCb=en(function(){E&&(Kt(n,k),Kt(n,x)),j.cancelled?(E&&Kt(n,C),T&&T(n)):S&&S(n),n._enterCb=null});e.data.show||ne(e.data.hook||(e.data.hook={}),"insert",function(){var t=n.parentNode,r=t&&t._pending&&t._pending[e.key];r&&r.tag===e.tag&&r.elm._leaveCb&&r.elm._leaveCb(),O&&O(n,j)},"transition-insert"),A&&A(n),E&&(Jt(n,C),Jt(n,x),Vt(function(){Jt(n,k),Kt(n,C),j.cancelled||I||qt(n,o,j)})),e.data.show&&(t&&t(),O&&O(n,j)),E||I||j()}}}function Qt(e,t){function n(){g.cancelled||(e.data.show||((r.parentNode._pending||(r.parentNode._pending={}))[e.key]=e),l&&l(r),h&&(Jt(r,s),Jt(r,u),Vt(function(){Jt(r,c),Kt(r,s),g.cancelled||m||qt(r,a,g)})),f&&f(r,g),h||m||g())}var r=e.elm;r._enterCb&&(r._enterCb.cancelled=!0,r._enterCb());var i=Xt(e.data.transition);if(!i)return t();if(!r._leaveCb&&1===r.nodeType){var o=i.css,a=i.type,s=i.leaveClass,c=i.leaveToClass,u=i.leaveActiveClass,l=i.beforeLeave,f=i.leave,p=i.afterLeave,d=i.leaveCancelled,v=i.delayLeave,h=o!==!1&&!bi,m=f&&(f._length||f.length)>1,g=r._leaveCb=en(function(){r.parentNode&&r.parentNode._pending&&(r.parentNode._pending[e.key]=null),h&&(Kt(r,c),Kt(r,u)),g.cancelled?(h&&Kt(r,s),d&&d(r)):(t(),p&&p(r)),r._leaveCb=null});v?v(n):n()}}function Xt(e){if(e){if("object"==typeof e){var t={};return e.css!==!1&&u(t,Xo(e.name||"v")),u(t,e),t}return"string"==typeof e?Xo(e):void 0}}function en(e){var t=!1;return function(){t||(t=!0,e())}}function tn(e,t){t.data.show||Yt(t)}function nn(e,t,n){var r=t.value,i=e.multiple;if(!i||Array.isArray(r)){for(var o,a,s=0,c=e.options.length;s-1,a.selected!==o&&(a.selected=o);else if(h(on(a),r))return void(e.selectedIndex!==s&&(e.selectedIndex=s));i||(e.selectedIndex=-1)}}function rn(e,t){for(var n=0,r=t.length;n',n.innerHTML.indexOf(t)>0}function _n(e){return pa=pa||document.createElement("div"),pa.innerHTML=e,pa.textContent}function bn(e,t){return t&&(e=e.replace(os,"\n")),e.replace(rs,"<").replace(is,">").replace(as,"&").replace(ss,'"')}function $n(e,t){function n(t){f+=t,e=e.substring(t)}function r(){var t=e.match(Ca);if(t){var r={tagName:t[1],attrs:[],start:f};n(t[0].length);for(var i,o;!(i=e.match(xa))&&(o=e.match(ba));)n(o[0].length),r.attrs.push(o);if(i)return r.unarySlash=i[1],n(i[0].length),r.end=f,r}}function i(e){var n=e.tagName,r=e.unarySlash;u&&("p"===s&&ma(n)&&o(s),ha(n)&&s===n&&o(n));for(var i=l(n)||"html"===n&&"head"===s||!!r,a=e.attrs.length,f=new Array(a),p=0;p=0&&c[i].lowerCasedTag!==o;i--);else i=0;if(i>=0){for(var a=c.length-1;a>=i;a--)t.end&&t.end(c[a].tag,n,r);c.length=i,s=i&&c[i-1].tag}else"br"===o?t.start&&t.start(e,[],!0,n,r):"p"===o&&(t.start&&t.start(e,[],!1,n,r),t.end&&t.end(e,n,r))}for(var a,s,c=[],u=t.expectHTML,l=t.isUnaryTag||pi,f=0;e;){if(a=e,s&&ts(s)){var p=s.toLowerCase(),d=ns[p]||(ns[p]=new RegExp("([\\s\\S]*?)(]*>)","i")),v=0,h=e.replace(d,function(e,n,r){return v=r.length,"script"!==p&&"style"!==p&&"noscript"!==p&&(n=n.replace(//g,"$1").replace(//g,"$1")),t.chars&&t.chars(n),""});f+=e.length-h.length,e=h,o(p,f-v,f)}else{var m=e.indexOf("<");if(0===m){if(Oa.test(e)){var g=e.indexOf("-->");if(g>=0){n(g+3);continue}}if(Sa.test(e)){var y=e.indexOf("]>");if(y>=0){n(y+2);continue}}var _=e.match(Aa);if(_){n(_[0].length);continue}var b=e.match(ka);if(b){var $=f;n(b[0].length),o(b[1],$,f);continue}var w=r();if(w){i(w);continue}}var C=void 0,x=void 0,k=void 0;if(m>0){for(x=e.slice(m);!(ka.test(x)||Ca.test(x)||Oa.test(x)||Sa.test(x)||(k=x.indexOf("<",1),k<0));)m+=k,x=e.slice(m);C=e.substring(0,m),n(m)}m<0&&(C=e,e=""),t.chars&&C&&t.chars(C)}if(e===a&&t.chars){t.chars(e);break}}o()}function wn(e){function t(){(a||(a=[])).push(e.slice(v,i).trim()),v=i+1}var n,r,i,o,a,s=!1,c=!1,u=!1,l=!1,f=0,p=0,d=0,v=0;for(i=0;i=0&&(m=e.charAt(h)," "===m);h--);m&&/[\w$]/.test(m)||(l=!0)}}else void 0===o?(v=i+1,o=e.slice(0,i).trim()):t();if(void 0===o?o=e.slice(0,i).trim():0!==v&&t(),a)for(i=0;ia&&o.push(JSON.stringify(e.slice(a,i)));var s=wn(r[1].trim());o.push("_s("+s+")"),a=i+r[0].length}return a=Ea}function Dn(e){return 34===e||39===e}function Pn(e){var t=1;for(La=Na;!Mn();)if(e=Ln(),Dn(e))Rn(e);else if(91===e&&t++,93===e&&t--,0===t){Ma=Na;break}}function Rn(e){for(var t=e;!Mn()&&(e=Ln(),e!==t););}function Fn(e,t){Da=t.warn||kn,Pa=t.getTagNamespace||pi,Ra=t.mustUseProp||pi,Fa=t.isPreTag||pi,Ha=An(t.modules,"preTransformNode"),Ua=An(t.modules,"transformNode"),Ba=An(t.modules,"postTransformNode"),za=t.delimiters;var n,r,i=[],o=t.preserveWhitespace!==!1,a=!1,s=!1;return $n(e,{expectHTML:t.expectHTML,isUnaryTag:t.isUnaryTag,shouldDecodeNewlines:t.shouldDecodeNewlines,start:function(e,o,c){function u(e){}var l=r&&r.ns||Pa(e);_i&&"svg"===l&&(o=rr(o));var f={type:1,tag:e,attrsList:o,attrsMap:tr(o),parent:r,children:[]};l&&(f.ns=l),nr(f)&&!xi()&&(f.forbidden=!0);for(var p=0;p-1"+("true"===o?":("+t+")":":_q("+t+","+o+")")),En(e,"click","var $$a="+t+",$$el=$event.target,$$c=$$el.checked?("+o+"):("+a+");if(Array.isArray($$a)){var $$v="+(r?"_n("+i+")":i)+",$$i=_i($$a,$$v);if($$c){$$i<0&&("+t+"=$$a.concat($$v))}else{$$i>-1&&("+t+"=$$a.slice(0,$$i).concat($$a.slice($$i+1)))}}else{"+t+"=$$c}",null,!0)}function Jr(e,t,n){var r=n&&n.number,i=In(e,"value")||"null";i=r?"_n("+i+")":i,On(e,"checked","_q("+t+","+i+")"),En(e,"click",Wr(t,i),null,!0)}function Kr(e,t,n){var r=e.attrsMap.type,i=n||{},o=i.lazy,a=i.number,s=i.trim,c=o||_i&&"range"===r?"change":"input",u=!o&&"range"!==r,l="input"===e.tag||"textarea"===e.tag,f=l?"$event.target.value"+(s?".trim()":""):s?"(typeof $event === 'string' ? $event.trim() : $event)":"$event";f=a||"number"===r?"_n("+f+")":f;var p=Wr(t,f);l&&u&&(p="if($event.target.composing)return;"+p),On(e,"value",l?"_s("+t+")":"("+t+")"),En(e,c,p,null,!0),(s||a||"number"===r)&&En(e,"blur","$forceUpdate()")}function qr(e,t,n){var r=n&&n.number,i='Array.prototype.filter.call($event.target.options,function(o){return o.selected}).map(function(o){var val = "_value" in o ? o._value : o.value;return '+(r?"_n(val)":"val")+"})"+(null==e.attrsMap.multiple?"[0]":""),o=Wr(t,i);En(e,"change",o,null,!0)}function Wr(e,t){var n=Nn(e);return null===n.idx?e+"="+t:"var $$exp = "+n.exp+", $$idx = "+n.idx+";if (!Array.isArray($$exp)){"+e+"="+t+"}else{$$exp.splice($$idx, 1, "+t+")}"}function Zr(e,t){t.value&&On(e,"textContent","_s("+t.value+")")}function Gr(e,t){t.value&&On(e,"innerHTML","_s("+t.value+")")}function Yr(e,t){return t=t?u(u({},js),t):js,Rr(e,t)}function Qr(e,t,n){var r=(t&&t.warn||Si,t&&t.delimiters?String(t.delimiters)+e:e);if(Is[r])return Is[r];var i={},o=Yr(e,t);i.render=Xr(o.render);var a=o.staticRenderFns.length;i.staticRenderFns=new Array(a);for(var s=0;s0,$i=yi&&yi.indexOf("edge/")>0,wi=yi&&yi.indexOf("android")>0,Ci=yi&&/iphone|ipad|ipod|ios/.test(yi),xi=function(){return void 0===ti&&(ti=!gi&&"undefined"!=typeof global&&"server"===global.process.env.VUE_ENV),ti},ki=gi&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__,Ai=function(){function e(){r=!1;var e=n.slice(0);n.length=0;for(var t=0;t1&&(t[n[0].trim()]=n[1].trim())}}),t}),Ro=/^--/,Fo=/\s*!important$/,Ho=function(e,t,n){Ro.test(t)?e.style.setProperty(t,n):Fo.test(n)?e.style.setProperty(t,n.replace(Fo,""),"important"):e.style[Bo(t)]=n},Uo=["Webkit","Moz","ms"],Bo=a(function(e){if(lo=lo||document.createElement("div"),e=ai(e),"filter"!==e&&e in lo.style)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=0;n\/=]+)/,ya=/(?:=)/,_a=[/"([^"]*)"+/.source,/'([^']*)'+/.source,/([^\s"'=<>`]+)/.source],ba=new RegExp("^\\s*"+ga.source+"(?:\\s*("+ya.source+")\\s*(?:"+_a.join("|")+"))?"),$a="[a-zA-Z_][\\w\\-\\.]*",wa="((?:"+$a+"\\:)?"+$a+")",Ca=new RegExp("^<"+wa),xa=/^\s*(\/?)>/,ka=new RegExp("^<\\/"+wa+"[^>]*>"),Aa=/^]+>/i,Oa=/^ + + + + + + +

+ diff --git a/nstock/static/plugin_ckeditor/plugins/wsc/dialogs/tmpFrameset.html b/nstock/static/plugin_ckeditor/plugins/wsc/dialogs/tmpFrameset.html new file mode 100644 index 0000000..d5fc6bb --- /dev/null +++ b/nstock/static/plugin_ckeditor/plugins/wsc/dialogs/tmpFrameset.html @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + diff --git a/nstock/static/plugin_ckeditor/plugins/wsc/dialogs/wsc.css b/nstock/static/plugin_ckeditor/plugins/wsc/dialogs/wsc.css new file mode 100644 index 0000000..2a622f2 --- /dev/null +++ b/nstock/static/plugin_ckeditor/plugins/wsc/dialogs/wsc.css @@ -0,0 +1,82 @@ +/* +Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.html or http://ckeditor.com/license +*/ + +html, body +{ + background-color: transparent; + margin: 0px; + padding: 0px; +} + +body +{ + padding: 10px; +} + +body, td, input, select, textarea +{ + font-size: 11px; + font-family: 'Microsoft Sans Serif' , Arial, Helvetica, Verdana; +} + +.midtext +{ + padding:0px; + margin:10px; +} + +.midtext p +{ + padding:0px; + margin:10px; +} + +.Button +{ + border: #737357 1px solid; + color: #3b3b1f; + background-color: #c7c78f; +} + +.PopupTabArea +{ + color: #737357; + background-color: #e3e3c7; +} + +.PopupTitleBorder +{ + border-bottom: #d5d59d 1px solid; +} +.PopupTabEmptyArea +{ + padding-left: 10px; + border-bottom: #d5d59d 1px solid; +} + +.PopupTab, .PopupTabSelected +{ + border-right: #d5d59d 1px solid; + border-top: #d5d59d 1px solid; + border-left: #d5d59d 1px solid; + padding: 3px 5px 3px 5px; + color: #737357; +} + +.PopupTab +{ + margin-top: 1px; + border-bottom: #d5d59d 1px solid; + cursor: pointer; +} + +.PopupTabSelected +{ + font-weight: bold; + cursor: default; + padding-top: 4px; + border-bottom: #f1f1e3 1px solid; + background-color: #f1f1e3; +} diff --git a/nstock/static/plugin_ckeditor/plugins/wsc/dialogs/wsc.js b/nstock/static/plugin_ckeditor/plugins/wsc/dialogs/wsc.js new file mode 100644 index 0000000..5ef1d39 --- /dev/null +++ b/nstock/static/plugin_ckeditor/plugins/wsc/dialogs/wsc.js @@ -0,0 +1,92 @@ +/* + Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.html or http://ckeditor.com/license +*/ +(function(){function z(a){return a&&a.domId&&a.getInputElement().$?a.getInputElement():a&&a.$?a:!1}function I(a){if(!a)throw"Languages-by-groups list are required for construct selectbox";var c=[],e="",d;for(d in a)for(var f in a[d]){var h=a[d][f];"en_US"==h?e=h:c.push(h)}c.sort();e&&c.unshift(e);return{getCurrentLangGroup:function(c){a:{for(var d in a)for(var e in a[d])if(e.toUpperCase()===c.toUpperCase()){c=d;break a}c=""}return c},setLangList:function(){var c={},d;for(d in a)for(var e in a[d])c[a[d][e]]= +e;return c}()}}var g=function(){var a=function(a,b,d){d=d||{};var f=d.expires;if("number"==typeof f&&f){var h=new Date;h.setTime(h.getTime()+1E3*f);f=d.expires=h}f&&f.toUTCString&&(d.expires=f.toUTCString());b=encodeURIComponent(b);a=a+"\x3d"+b;for(var k in d)b=d[k],a+="; "+k,!0!==b&&(a+="\x3d"+b);document.cookie=a};return{postMessage:{init:function(a){window.addEventListener?window.addEventListener("message",a,!1):window.attachEvent("onmessage",a)},send:function(a){var b=Object.prototype.toString, +d=a.fn||null,f=a.id||"",h=a.target||window,k=a.message||{id:f};a.message&&"[object Object]"==b.call(a.message)&&(a.message.id?a.message.id:a.message.id=f,k=a.message);a=window.JSON.stringify(k,d);h.postMessage(a,"*")},unbindHandler:function(a){window.removeEventListener?window.removeEventListener("message",a,!1):window.detachEvent("onmessage",a)}},hash:{create:function(){},parse:function(){}},cookie:{set:a,get:function(a){return(a=document.cookie.match(new RegExp("(?:^|; )"+a.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, +"\\$1")+"\x3d([^;]*)")))?decodeURIComponent(a[1]):void 0},remove:function(c){a(c,"",{expires:-1})}},misc:{findFocusable:function(a){var b=null;a&&(b=a.find("a[href], area[href], input, select, textarea, button, *[tabindex], *[contenteditable]"));return b},isVisible:function(a){var b;(b=0===a.offsetWidth||0==a.offsetHeight)||(b="none"===(document.defaultView&&document.defaultView.getComputedStyle?document.defaultView.getComputedStyle(a,null).display:a.currentStyle?a.currentStyle.display:a.style.display)); +return!b},hasClass:function(a,b){return!(!a.className||!a.className.match(new RegExp("(\\s|^)"+b+"(\\s|$)")))}}}}(),a=a||{};a.TextAreaNumber=null;a.load=!0;a.cmd={SpellTab:"spell",Thesaurus:"thes",GrammTab:"grammar"};a.dialog=null;a.optionNode=null;a.selectNode=null;a.grammerSuggest=null;a.textNode={};a.iframeMain=null;a.dataTemp="";a.div_overlay=null;a.textNodeInfo={};a.selectNode={};a.selectNodeResponce={};a.langList=null;a.langSelectbox=null;a.banner="";a.show_grammar=null;a.div_overlay_no_check= +null;a.targetFromFrame={};a.onLoadOverlay=null;a.LocalizationComing={};a.OverlayPlace=null;a.sessionid="";a.LocalizationButton={ChangeTo_button:{instance:null,text:"Change to",localizationID:"ChangeTo"},ChangeAll:{instance:null,text:"Change All"},IgnoreWord:{instance:null,text:"Ignore word"},IgnoreAllWords:{instance:null,text:"Ignore all words"},Options:{instance:null,text:"Options",optionsDialog:{instance:null}},AddWord:{instance:null,text:"Add word"},FinishChecking_button:{instance:null,text:"Finish Checking", +localizationID:"FinishChecking"},FinishChecking_button_block:{instance:null,text:"Finish Checking",localizationID:"FinishChecking"}};a.LocalizationLabel={ChangeTo_label:{instance:null,text:"Change to",localizationID:"ChangeTo"},Suggestions:{instance:null,text:"Suggestions"},Categories:{instance:null,text:"Categories"},Synonyms:{instance:null,text:"Synonyms"}};var J=function(b){var c,e,d;for(d in b)c=(c=a.dialog.getContentElement(a.dialog._.currentTabId,d))?c.getElement():b[d].instance.getElement().getFirst()|| +b[d].instance.getElement(),e=b[d].localizationID||d,c.setText(a.LocalizationComing[e])},K=function(b){var c,e,d;for(d in b)c=a.dialog.getContentElement(a.dialog._.currentTabId,d),c||(c=b[d].instance),c.setLabel&&(e=b[d].localizationID||d,c.setLabel(a.LocalizationComing[e]+":"))},r,A;a.framesetHtml=function(b){return"\x3ciframe id\x3d"+a.iframeNumber+"_"+b+' frameborder\x3d"0" allowtransparency\x3d"1" style\x3d"width:100%;border: 1px solid #AEB3B9;overflow: auto;background:#fff; border-radius: 3px;"\x3e\x3c/iframe\x3e'}; +a.setIframe=function(b,c){var e;e=a.framesetHtml(c);var d=a.iframeNumber+"_"+c;b.getElement().setHtml(e);e=document.getElementById(d);e=e.contentWindow?e.contentWindow:e.contentDocument.document?e.contentDocument.document:e.contentDocument;e.document.open();e.document.write('\x3c!DOCTYPE html\x3e\x3chtml\x3e\x3chead\x3e\x3cmeta charset\x3d"UTF-8"\x3e\x3ctitle\x3eiframe\x3c/title\x3e\x3cstyle\x3ehtml,body{margin: 0;height: 100%;font: 13px/1.555 "Trebuchet MS", sans-serif;}a{color: #888;font-weight: bold;text-decoration: none;border-bottom: 1px solid #888;}.main-box {color:#252525;padding: 3px 5px;text-align: justify;}.main-box p{margin: 0 0 14px;}.main-box .cerr{color: #f00000;border-bottom-color: #f00000;}\x3c/style\x3e\x3c/head\x3e\x3cbody\x3e\x3cdiv id\x3d"content" class\x3d"main-box"\x3e\x3c/div\x3e\x3ciframe src\x3d"" frameborder\x3d"0" id\x3d"spelltext" name\x3d"spelltext" style\x3d"display:none; width: 100%" \x3e\x3c/iframe\x3e\x3ciframe src\x3d"" frameborder\x3d"0" id\x3d"loadsuggestfirst" name\x3d"loadsuggestfirst" style\x3d"display:none; width: 100%" \x3e\x3c/iframe\x3e\x3ciframe src\x3d"" frameborder\x3d"0" id\x3d"loadspellsuggestall" name\x3d"loadspellsuggestall" style\x3d"display:none; width: 100%" \x3e\x3c/iframe\x3e\x3ciframe src\x3d"" frameborder\x3d"0" id\x3d"loadOptionsForm" name\x3d"loadOptionsForm" style\x3d"display:none; width: 100%" \x3e\x3c/iframe\x3e\x3cscript\x3e(function(window) {var ManagerPostMessage \x3d function() {var _init \x3d function(handler) {if (document.addEventListener) {window.addEventListener("message", handler, false);} else {window.attachEvent("onmessage", handler);};};var _sendCmd \x3d function(o) {var str,type \x3d Object.prototype.toString,fn \x3d o.fn || null,id \x3d o.id || "",target \x3d o.target || window,message \x3d o.message || { "id": id };if (o.message \x26\x26 type.call(o.message) \x3d\x3d "[object Object]") {(o.message["id"]) ? o.message["id"] : o.message["id"] \x3d id;message \x3d o.message;};str \x3d JSON.stringify(message, fn);target.postMessage(str, "*");};return {init: _init,send: _sendCmd};};var manageMessageTmp \x3d new ManagerPostMessage;var appString \x3d (function(){var spell \x3d parent.CKEDITOR.config.wsc.DefaultParams.scriptPath;var serverUrl \x3d parent.CKEDITOR.config.wsc.DefaultParams.serviceHost;return serverUrl + spell;})();function loadScript(src, callback) {var scriptTag \x3d document.createElement("script");scriptTag.type \x3d "text/javascript";callback ? callback : callback \x3d function() {};if(scriptTag.readyState) {scriptTag.onreadystatechange \x3d function() {if (scriptTag.readyState \x3d\x3d "loaded" ||scriptTag.readyState \x3d\x3d "complete") {scriptTag.onreadystatechange \x3d null;setTimeout(function(){scriptTag.parentNode.removeChild(scriptTag)},1);callback();}};}else{scriptTag.onload \x3d function() {setTimeout(function(){scriptTag.parentNode.removeChild(scriptTag)},1);callback();};};scriptTag.src \x3d src;document.getElementsByTagName("head")[0].appendChild(scriptTag);};window.onload \x3d function(){loadScript(appString, function(){manageMessageTmp.send({"id": "iframeOnload","target": window.parent});});}})(this);\x3c/script\x3e\x3c/body\x3e\x3c/html\x3e'); +e.document.close()};a.setCurrentIframe=function(b){a.setIframe(a.dialog._.contents[b].Content,b)};a.setHeightBannerFrame=function(){var b=a.dialog.getContentElement("SpellTab","banner").getElement(),c=a.dialog.getContentElement("GrammTab","banner").getElement(),e=a.dialog.getContentElement("Thesaurus","banner").getElement();b.setStyle("height","90px");c.setStyle("height","90px");e.setStyle("height","90px")};a.setHeightFrame=function(){document.getElementById(a.iframeNumber+"_"+a.dialog._.currentTabId).style.height= +"240px"};a.sendData=function(b){var c=b._.currentTabId,e=b._.contents[c].Content,d,f;a.previousTab=c;a.setIframe(e,c);var h=function(h){c=b._.currentTabId;h=h||window.event;h.data.getTarget().is("a")&&c!==a.previousTab&&(a.previousTab=c,e=b._.contents[c].Content,d=a.iframeNumber+"_"+c,a.div_overlay.setEnable(),e.getElement().getChildCount()?E(a.targetFromFrame[d],a.cmd[c]):(a.setIframe(e,c),f=document.getElementById(d),a.targetFromFrame[d]=f.contentWindow))};b.parts.tabs.removeListener("click",h); +b.parts.tabs.on("click",h)};a.buildSelectLang=function(a){var c=new CKEDITOR.dom.element("div"),e=new CKEDITOR.dom.element("select");a="wscLang"+a;c.addClass("cke_dialog_ui_input_select");c.setAttribute("role","presentation");c.setStyles({height:"auto",position:"absolute",right:"0",top:"-1px",width:"160px","white-space":"normal"});e.setAttribute("id",a);e.addClass("cke_dialog_ui_input_select");e.setStyles({width:"160px"});c.append(e);return c};a.buildOptionLang=function(b,c){var e=document.getElementById("wscLang"+ +c),d=document.createDocumentFragment(),f,h,k=[];if(0===e.options.length){for(f in b)k.push([f,b[f]]);k.sort();for(var p=0;pm.width-D&&(e=m.width-D);if(gm.height-q&&(g=m.height-q);n.width=e+D;n.height=g+q;a._.fromResizeEvent=!1;a.resize(e,g);setTimeout(function(){a._.fromResizeEvent=!1;CKEDITOR.dialog.fire("resize",{dialog:a,width:e,height:g},b)},300)}a._.moved||(q=isNaN(c)&&isNaN(d)?0:1,isNaN(c)&&(c=(m.width-n.width)/2),0>c&&(c=0),c>m.width-n.width&&(c=m.width-n.width),isNaN(d)&&(d=(m.height-n.height)/2),0>d&&(d=0),d>m.height-n.height&&(d=m.height-n.height),a.move(c, +d,q))}function e(){b.wsc={};(function(a){var b={separator:"\x3c$\x3e",getDataType:function(a){return"undefined"===typeof a?"undefined":null===a?"null":Object.prototype.toString.call(a).slice(8,-1)},convertDataToString:function(a){return this.getDataType(a).toLowerCase()+this.separator+a},restoreDataFromString:function(a){var b=a,c;a=this.backCompatibility(a);if("string"===typeof a)switch(b=a.indexOf(this.separator),c=a.substring(0,b),b=a.substring(b+this.separator.length),c){case "boolean":b="true"=== +b;break;case "number":b=parseFloat(b);break;case "array":b=""===b?[]:b.split(",");break;case "null":b=null;break;case "undefined":b=void 0}return b},backCompatibility:function(a){var b=a,c;"string"===typeof a&&(c=a.indexOf(this.separator),0>c&&(b=parseFloat(a),isNaN(b)&&("["===a[0]&&"]"===a[a.length-1]?(a=a.replace("[",""),a=a.replace("]",""),b=""===a?[]:a.split(",")):b="true"===a||"false"===a?"true"===a:a),b=this.convertDataToString(b)));return b}},c={get:function(a){return b.restoreDataFromString(window.localStorage.getItem(a))}, +set:function(a,c){var d=b.convertDataToString(c);window.localStorage.setItem(a,d)},del:function(a){window.localStorage.removeItem(a)},clear:function(){window.localStorage.clear()}},d={expiration:31622400,get:function(a){return b.restoreDataFromString(this.getCookie(a))},set:function(a,c){var d=b.convertDataToString(c);this.setCookie(a,d,{expires:this.expiration})},del:function(a){this.deleteCookie(a)},getCookie:function(a){return(a=document.cookie.match(new RegExp("(?:^|; )"+a.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, +"\\$1")+"\x3d([^;]*)")))?decodeURIComponent(a[1]):void 0},setCookie:function(a,b,c){c=c||{};var d=c.expires;if("number"===typeof d&&d){var e=new Date;e.setTime(e.getTime()+1E3*d);d=c.expires=e}d&&d.toUTCString&&(c.expires=d.toUTCString());b=encodeURIComponent(b);a=a+"\x3d"+b;for(var h in c)b=c[h],a+="; "+h,!0!==b&&(a+="\x3d"+b);document.cookie=a},deleteCookie:function(a){this.setCookie(a,null,{expires:-1})},clear:function(){for(var a=document.cookie.split(";"),b=0;b * { + vertical-align: middle; +} +.ie8 .switch input[type="radio"] { + margin: 0 0.25em; + display: inline-block; +} +.ie8 .switch label { + margin-left: 0 !important; + margin-right: 0 !important; +} +.ie8 .switch label[data-for="1"] { + float: left; +} +.ie8 .switch label[data-for="2"] { + float: right; +} +.ie8 .switch .switch-inner { + display: none; +} +.switch { + font-size: 14px; + font-size: 0.875rem; + line-height: 25.2px; + line-height: 1.57rem; + font-weight: bold; + background-color: #27c0d8; + overflow: hidden; + display: inline-block; + padding: 0.75em 0.25em; + color: #fff; + -webkit-border-radius: 3px; + -webkit-background-clip: padding-box; + -moz-border-radius: 3px; + -moz-background-clip: padding; + border-radius: 3px; + background-clip: padding-box; + position: relative; +} +.switch input[type="radio"] { + display: none; +} +.switch label { + position: relative; + z-index: 2; + float: left; + cursor: pointer; + padding: 0 0.75em; +} +.switch label:hover { + text-decoration: underline; +} +.switch .switch-inner { + float: left; + background-color: #FFF; + height: 1.5em; + width: 4.125em; + padding: 2px; + margin: 0 0.25em; + -webkit-border-radius: 5.5px; + -webkit-background-clip: padding-box; + -moz-border-radius: 5.5px; + -moz-background-clip: padding; + border-radius: 5.5px; + background-clip: padding-box; +} +.switch .switch-inner .handler { + overflow: hidden; + position: relative; + display: block; + height: 1.5em; + width: 1.5em; + background: #25b4cb; + -webkit-border-radius: 4.5px; + -webkit-background-clip: padding-box; + -moz-border-radius: 4.5px; + -moz-background-clip: padding; + border-radius: 4.5px; + background-clip: padding-box; +} +.switch .switch-inner .handler:before { + content: ''; + display: block; + position: absolute; + top: 0; + right: 0; + bottom: 3px; + left: 0; + background-color: #34c4da; + -webkit-border-bottom-left-radius: 4.5px; + -moz-border-radius-bottomleft: 4.5px; + border-bottom-left-radius: 4.5px; + -webkit-border-bottom-right-radius: 4.5px; + -webkit-background-clip: padding-box; + -moz-border-radius-bottomright: 4.5px; + -moz-background-clip: padding; + border-bottom-right-radius: 4.5px; + background-clip: padding-box; +} +.switch:hover .switch-inner .handler:before { + background: #45c9dd; +} +.switch input[data-num="2"]:checked ~ .switch-inner > .handler { + margin-left: auto; +} +.switch input[data-num="2"]:checked ~ label[data-for="1"] { + padding-right: 5.125em; + margin-right: -4.375em; +} +.switch input[data-num="1"]:checked ~ label[data-for="2"] { + padding-left: 5.125em; + margin-left: -4.375em; +} +.toggler { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.toggler label { + cursor: pointer; +} +.toggler [data-collapse] { + display: inherit; +} +.toggler [data-expand] { + display: none; +} +.toggler.collapsed [data-collapse] { + display: none; +} +.toggler.collapsed [data-expand] { + display: inherit; +} +.toggler-container { + overflow: hidden; +} +.toggler-container.collapsed { + height: 0; +} +.icon-toggler-expanded:before, +.icon-toggler-collapsed:before, +.icon-toggler-expanded:after, +.icon-toggler-collapsed:after { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAByCAYAAABeOoENAAAAAXNSR0IArs4c6QAAAbxJREFUaAXtmT1KBEEQhRdFQdBEMfQEBoaGopl3MfECXsFERLyBh/AUIuwJDEUQM//eB11Dz1A1uzotGFTBY2rr58306+kNpmazP7Z98V8Kj8JrAT4xcgttXRVXwofwFYAcNdS6RuJegOBTuBUOhc0CfGLkqKHWJeMuFDwJJ0Jk5Kihlp6esW4embuNkVgTNdTS09MMEbkDj76sUUsPvZ2xIwTRATsQuBuxGsTIYdSSo7cztpggwprdyKlJ8ImZUUuM3s48ol1lXwQjwydm5hINl2bF53KMCL82d2mR2GvqnBfg1+aKPbb9p+oGtYXbT1GTFxKiZkfEyHgy7x0y0clR454zSGpDMzaA3fzV30hNln4qkAqkAqlAKpAKpAKpQCqQCqQCqUAqkAqkAqlAKpAKpAKpQCrw3xWY/GGcz++TP9U3Gx40GWdEAxabXA33NBywRCOfdzFcCztDJv12Rz7REMpmIc9qPBNWK0J3COWNxegxIrs+KHZcyHpjsZUSXPaypcLtseJFS3tT84WwUZG4S4vEZkl3wl5FYK4rdrT9R9Y1uIbbT12TFxKiZkfEyCYfWojMJv+NGNGPr99GI9DP7P9TCgAAAABJRU5ErkJggg=="); +} +.icon-toggler-expanded.icon-light:before, +.icon-toggler-collapsed.icon-light:before, +.icon-toggler-expanded.icon-light:after, +.icon-toggler-collapsed.icon-light:after { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAByCAYAAABeOoENAAAAAXNSR0IArs4c6QAAAcVJREFUaAXtmT9KA1EQxhMlASE2SkpPkCJlStHOu3gGwRPYBAm5gYfwFBKwtrARRAh26vr7ljfx7TrLChtBcAa+zOSbPy/7vcTC6fV+04qimIArsALrBMXiJq1nUzQEc/AOmkw51QzdgUqAWyD7AEswA6MExeKUk6n2+zBInSJ7BKfuaZDKpRpcMa/UQUgTfWSd1jjEmlSTatXzpRlvJKJsacVtXrVlB72bWgjdiGwmEj8FOq1u4qapRprJVvkgXbFsZCTxomSqL4ssr0uQrY3TJ/AGjeFfVJlM8diaiCuDdlLiIfmNcP1+/wnu0hoVJ84oq7XeUhNXbE4dgPuEgU2Qh3PFbrx+Gs6E2hD/+tMJ3b+QadB2fiLZsG4/2poG3f6M5MMiDgVCgVAgFAgFQoFQIBQIBUKBUCAUCAVCgVAgFAgFQoFQIBQIBf66AiwLuv1jnAH/Zb/Go5abq/qdwvsLFhJNK583ctfg0Bnmrnwq+zVrYoDZM8E52M1yP9uvqcGmZP6O+CTl3LWYHdTm9yk4aCzilLZHe6XmAuzZEGL30ZrEpr64AUc2wDycK7a7X6P42BpzD+9fv4pIxn4tWznnwm0r/gQpiG1tFshTowAAAABJRU5ErkJggg=="); +} +.icon-toggler-expanded:before, +.icon-toggler-expanded:after { + background-position: top left; +} +.icon-toggler-collapsed:before, +.icon-toggler-collapsed:after { + background-position: bottom left; +} +.modal { + padding: 20px; + border-radius: 3px; + background-color: white; + max-width: 700px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + width: 80% !important; + top: 50% !important; + -webkit-transform: translate(-50%, -50%) !important; + -moz-transform: translate(-50%, -50%) !important; + -o-transform: translate(-50%, -50%) !important; + -ms-transform: translate(-50%, -50%) !important; + transform: translate(-50%, -50%) !important; +} +.modal-close { + -webkit-border-radius: 100px; + -webkit-background-clip: padding-box; + -moz-border-radius: 100px; + -moz-background-clip: padding; + border-radius: 100px; + background-clip: padding-box; + cursor: pointer; + height: 18px; + width: 18px; + position: absolute; + top: 10px; + right: 10px; + font-size: 17px; + text-align: center; + line-height: 19px; + background: #cccccc; +} +main .grid-container, +header .grid-container, +.navigation-a > div, +footer > div { + max-width: 968px; +} +.header-a { + margin-top: 30px; +} +.footer-a { + border-top: 1px solid #d9d9d9; +} +.adjoined-top { + background-color: #27c0d8; + color: #fff; +} +.adjoined-top .content h1, +.adjoined-top .content h2, +.adjoined-top .content h3, +.adjoined-top .content h4, +.adjoined-top .content h5 { + color: #fff; +} +.adjoined-top .content p { + font-size: 18px; + font-size: 1.125rem; + line-height: 32.4px; + line-height: 2.02rem; + font-weight: 100; +} +.adjoined-top .content p a { + text-decoration: none; + border-bottom: 1px dotted #fff; + color: inherit; +} +.adjoined-top .content p a:hover { + color: #e6e6e6; +} +.adjoined-top .content button { + color: #fff; +} +.adjoined-top .content strong { + color: #fff; +} +.adjoined-top .content code { + font-size: inherit; + color: #27c0d8; +} +.adjoined-bottom { + position: relative; +} +.adjoined-bottom:before { + z-index: -1; + content: ''; + background: #27c0d8; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 50%; +} +main .grid-container, +header .grid-container, +.navigation-a > div, +footer > div { + max-width: 1052px; +} +main .grid-container.freed-width { + max-width: none; +} +.switch { + background: #25b4cb; + float: right; + overflow: visible; +} +.switch .balloon-a { + position: absolute; + top: -40px; + right: 50%; + margin-right: -15px; + background: #FFEFC1; + border-bottom-color: #DCDCA4; +} +.switch .balloon-a:before { + border-color: #FFEFC1 transparent transparent transparent; +} +#toolbar .editors-container { + overflow: hidden; + height: 0; + transition: height 200ms; +} +#toolbar .editors-container.active { + height: auto; +} +#main #editor { + background: #FFF; + padding: 2% 4%; + border: dashed 5px #27c0d8; +} +div.cke a.cke_button, +div.cke .cke_combo_button { + border-bottom: none; +} +div.cke a.cke_button.cke_combo_button, +div.cke .cke_combo_button.cke_combo_button { + border-bottom: 1px solid #a6a6a6; +} +#main .adjoined-top:before { + height: 335px; +} +#toolbar .adjoined-top:before { + height: 219px; +} +#toolbar .adjoined-top .grid-container-nested { + height: 147px; +} +.content .grid-switch-magic { + margin: 3.5em 0 0; +} +#info-box { + padding-bottom: 0; +} +#info-box > div { + width: 100%; + text-align: right; +} +#info-box > div .toggler { + padding-right: 0; +} +#info-box > div .toggler:hover { + background: transparent; + color: #000; +} +#info-box > div .toggler:hover > label { + text-decoration: underline; +} +#info-box > div h2 { + float: left; + margin-top: 0; +} +#info-box > div#instructions-container { + text-align: left; +} +#toolbarModifierWrapper { + overflow: hidden; + height: 0; + opacity: 0; + transition: height 200ms; +} +#toolbarModifierWrapper.active { + height: auto; + opacity: 1; +} +header { + overflow: visible; +} +header div.grid-container { + overflow: visible; +} +header .navigation-b { + overflow: visible; +} +header .navigation-b ul { + overflow: visible; +} +header .navigation-b a { + position: relative; +} +header .balloon-a { + position: absolute; + top: 48px; + left: 50%; + margin-left: -35px; +} +@media (max-width: 1140px) { + header .balloon-a { + left: auto; + margin-left: auto; + right: 50%; + margin-right: -35px; + } + header .balloon-a:before { + left: auto; + right: 22px; + } +} +@media (max-width: 900px) { + header .balloon-a { + display: none; + } +} +#toolbar .cke_toolbar { + pointer-events: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: default; +} +.some-toolbar-active .cke_toolbar { + zoom: 1; + filter: alpha(opacity=50); + -webkit-opacity: 0.5; + -moz-opacity: 0.5; + opacity: 0.5; +} +.cke_toolbar.active { + position: relative; + zoom: 1; + filter: alpha(opacity=100); + -webkit-opacity: 1; + -moz-opacity: 1; + opacity: 1; +} +.cke_toolbar.active:after { + content: ''; + display: block; + position: absolute; + top: 0; + right: 6px; + bottom: 5px; + left: 0; + -webkit-border-radius: 5px; + -webkit-background-clip: padding-box; + -moz-border-radius: 5px; + -moz-background-clip: padding; + border-radius: 5px; + background-clip: padding-box; + -webkit-box-shadow: 0px 0px 15px 3px #fff4b0; + -moz-box-shadow: 0px 0px 15px 3px #fff4b0; + box-shadow: 0px 0px 15px 3px #fff4b0; +} +.cke_toolbar.active .cke_toolgroup { + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + border-color: #e3c300; +} +.cke_toolbar.active .cke_combo, +.cke_toolbar.active .cke_toolgroup { + position: relative; + z-index: 2; +} +.cke_toolbar.active .cke_combo_button { + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.unselectable { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.toolbar { + padding: 5px 0; + margin-bottom: 2.4em; + overflow: hidden; + background: #fff; +} +.toolbar button.button-a.cke_button { + cursor: pointer; + display: inline-block; + padding: 4px 6px; + outline: 0; + border: 1px solid #a6a6a6; +} +.toolbar button.button-a.hidden { + display: none; +} +.toolbar button.button-a.left { + float: left; + margin-right: 8px; +} +.toolbar button.button-a.right { + float: right; + margin-left: 8px; +} +.toolbar button.button-a .highlight { + color: #ffefc1; +} +.configContainer.hidden, +.toolbarModifier.hidden, +.toolbarModifier-hints.hidden { + display: none; +} +.toolbarModifier :focus, +.toolbar button:focus, +.configContainer textarea.configCode:focus { + outline: none; +} +div.toolbarModifier { + padding: 0; + overflow: hidden; + width: 100%; + position: relative; + display: table; + border-collapse: collapse; +} +div.toolbarModifier ::-moz-focus-inner { + border: 0; +} +div.toolbarModifier .empty { + display: none; +} +div.toolbarModifier.empty-visible .empty { + display: table-row; + zoom: 1; + filter: alpha(opacity=60); + -webkit-opacity: 0.6; + -moz-opacity: 0.6; + opacity: 0.6; +} +div.toolbarModifier .empty > p { + line-height: 31px; +} +div.toolbarModifier > ul { + padding: 0; + margin: 0; + border-top: 1px solid #cccccc; + width: 100%; +} +div.toolbarModifier > ul[data-type="table-header"] { + display: table-header-group; +} +div.toolbarModifier > ul[data-type="table-body"] { + display: table-row-group; +} +div.toolbarModifier > ul p { + padding: 0; + margin: 0; +} +div.toolbarModifier > ul > li { + display: table-row; +} +div.toolbarModifier > ul > li[data-type="header"] { + font-weight: bold; + user-select: none; + cursor: default; +} +div.toolbarModifier > ul > li[data-type="group"], +div.toolbarModifier > ul > li[data-type="separator"] { + border-bottom: 1px solid #cccccc; +} +div.toolbarModifier > ul > li[data-type="subgroup"] { + border-top: 1px solid #eee; +} +div.toolbarModifier > ul > li[data-type="subgroup"]:first-child { + border-top: none; +} +div.toolbarModifier > ul > li[data-type="group"].active, +div.toolbarModifier > ul > li[data-type="group"]:hover, +div.toolbarModifier > ul > li[data-type="separator"].active, +div.toolbarModifier > ul > li[data-type="separator"]:hover { + overflow: hidden; + z-index: 2; +} +div.toolbarModifier > ul > li[data-type="group"].active, +div.toolbarModifier > ul > li[data-type="separator"].active, +div.toolbarModifier > ul > li[data-type="group"].active:hover, +div.toolbarModifier > ul > li[data-type="separator"].active:hover { + background: #f0fafb; +} +div.toolbarModifier > ul > li[data-type="group"]:hover, +div.toolbarModifier > ul > li[data-type="separator"]:hover { + background: #fffbe3; +} +div.toolbarModifier > ul > li[data-type="separator"] { + background: #f5f5f5; +} +div.toolbarModifier > ul > li[data-type="separator"]:after { + content: ''; + width: 100%; +} +div.toolbarModifier > ul > li[data-type="separator"] > p { + padding: 2px 5px; +} +div.toolbarModifier > ul > li > p, +div.toolbarModifier > ul > li > ul { + display: table-cell; + vertical-align: middle; +} +div.toolbarModifier > ul > li p { + padding-left: 5px; + min-width: 200px; +} +div.toolbarModifier > ul > li p span { + white-space: nowrap; + cursor: default; +} +div.toolbarModifier > ul > li p span button { + font-size: 12.666px; + margin-right: 5px; + cursor: pointer; + background: #fff; + -webkit-border-radius: 5px; + -webkit-background-clip: padding-box; + -moz-border-radius: 5px; + -moz-background-clip: padding; + border-radius: 5px; + background-clip: padding-box; + border: 1px solid #bbb; + padding: 0 7px; + line-height: 12px; + height: 20px; +} +div.toolbarModifier > ul > li p span button:not(.disabled):hover, +div.toolbarModifier > ul > li p span button:not(.disabled):focus { + color: #fff; + background-color: #454545; + border-color: transparent; +} +div.toolbarModifier > ul > li p span button.move.disabled { + cursor: default; + zoom: 1; + filter: alpha(opacity=20); + -webkit-opacity: 0.2; + -moz-opacity: 0.2; + opacity: 0.2; +} +div.toolbarModifier > ul > li ul { + border-collapse: collapse; + padding: 0; + width: 100%; +} +div.toolbarModifier > ul > li ul li { + display: table-row; + list-style-type: none; + line-height: 1; +} +div.toolbarModifier > ul > li ul li[data-type="subgroup"] { + border-top: 1px solid #dddddd; +} +div.toolbarModifier > ul > li ul li[data-type="subgroup"]:first-child { + border-top: 0; +} +div.toolbarModifier > ul > li ul li[data-type="subgroup"] [data-type="button"] { + -webkit-border-radius: 3px; + -webkit-background-clip: padding-box; + -moz-border-radius: 3px; + -moz-background-clip: padding; + border-radius: 3px; + background-clip: padding-box; + padding: 0 2px; +} +div.toolbarModifier > ul > li ul li[data-type="subgroup"] [data-type="button"]:focus { + background: rgba(0, 0, 0, 0.04); +} +div.toolbarModifier > ul > li ul li[data-type="subgroup"] [data-type="button"] input { + vertical-align: middle; +} +div.toolbarModifier > ul > li ul li > p, +div.toolbarModifier > ul > li ul li > ul { + display: table-cell; + vertical-align: middle; +} +div.toolbarModifier > ul > li ul li ul { + padding: 0; +} +div.toolbarModifier > ul > li ul li ul li { + padding: 0; + display: inline-block; + cursor: pointer; + margin: 2px 5px 2px 0; +} +div.toolbarModifier > ul > li ul li ul li .cke_combo_text { + cursor: pointer; + white-space: nowrap; +} +div.toolbarModifier > ul > li ul li ul li .cke_toolgroup, +div.toolbarModifier > ul > li ul li ul li .cke_combo_button { + cursor: pointer; + margin: 0; + vertical-align: middle; + border: 1px solid #ddd; + font-size: 11.41px; + font-size: 0.713rem; + line-height: 20.54px; + line-height: 1.28rem; +} +div.toolbarModifier > .codemirror-wrapper { + overflow-y: auto; +} +div.toolbarModifier-hints { + float: right; + width: 350px; + min-width: 150px; + overflow-y: auto; + margin-left: 1.5em; +} +div.toolbarModifier-hints h3 { + font-size: 18.08px; + font-size: 1.13rem; + line-height: 32.54px; + line-height: 2.03rem; + padding: 0.36em 1.5em; + background: #f5f5f5; + border-bottom: 1px solid #dddddd; + margin-top: 0; + margin-bottom: 1.2em; +} +div.toolbarModifier-hints dl { + margin-bottom: 1.2em; + overflow: hidden; +} +div.toolbarModifier-hints dl .list-header { + font-weight: bold; + border: 0; + padding-bottom: 0.6em; +} +div.toolbarModifier-hints dl > p { + text-align: center; +} +div.toolbarModifier-hints dl dt { + float: left; + width: 9em; + clear: both; + text-align: right; + border-top: 1px solid #dddddd; + padding-left: 1.5em; + padding-right: .1em; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +div.toolbarModifier-hints dl dt code { + background: none; + border: none; + vertical-align: middle; +} +div.toolbarModifier-hints dl dd { + margin-left: 10em; + clear: right; + padding-right: 1.5em; +} +div.toolbarModifier-hints dl dd code { + line-height: 2.2em; +} +div.toolbarModifier-hints dl dd:after { + content: '\00a0'; + display: block; + clear: left; + float: right; + height: 0; + width: 0; +} +.toolbarModifier-hints, +.configContainer textarea.configCode, +.CodeMirror { + -webkit-border-radius: 3px; + -webkit-background-clip: padding-box; + -moz-border-radius: 3px; + -moz-background-clip: padding; + border-radius: 3px; + background-clip: padding-box; + border: 1px solid #ccc; + font-size: 13.01px; + font-size: 0.813rem; + line-height: 23.42px; + line-height: 1.46rem; +} +.configContainer textarea.configCode, +.CodeMirror pre, +.CodeMirror-linenumber { + font-size: 13.01px; + font-size: 0.813rem; + line-height: 23.42px; + line-height: 1.46rem; + font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif; +} +.CodeMirror pre { + border: none; + padding: 0; + margin: 0; +} +.configContainer textarea.configCode { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + color: #575757; + padding: 10px; + width: 100%; + min-height: 500px; + margin: 0; + resize: none; + outline: none; + -moz-tab-size: 4; + tab-size: 4; + white-space: pre; + word-wrap: normal; + overflow: auto; +} +.CodeMirror-hints.toolbar-modifier { + padding: 0; + color: #575757; + font-size: 14px; + font-size: 0.875rem; + line-height: 25.2px; + line-height: 1.57rem; + font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif; +} +.CodeMirror-hints.toolbar-modifier .CodeMirror-hint-active { + color: #575757; + background: #f0fafb; +} +.CodeMirror-hints.toolbar-modifier > li:hover { + background: #fffbe3; +} +/* Text modifier */ +#toolbarModifierWrapper { + margin-bottom: 1.2em; +} +#toolbarModifierWrapper .invalid .CodeMirror { + background: #fff8f8; + border-color: red; +} +#toolbarModifierWrapper .CodeMirror { + height: auto; + padding: 0 0.6em; +} +.staticContainer { + position: fixed; + top: 0; + width: 100%; + z-index: 10; +} +.staticContainer > .grid-container { + max-width: 1052px; +} +.staticContainer > .grid-container .inner { + background: #fff; +} +.staticContainer > .grid-container .inner .toolbar { + margin-bottom: 0; +} +#help { + position: relative; + top: -15px; + left: -5px; +} +#help-content { + display: none; +} +/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2dsb2JhbC9nbG9iYWwubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2NvcmUvY29yZS5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvZ3JpZC9ncmlkLmxlc3MiLCIuLi8uLi9ub2RlX21vZHVsZXMvY2tzb3VyY2Utc2FtcGxlcy1mcmFtZXdvcmsvbm9kZV9tb2R1bGVzL2xlc3NoYXQvYnVpbGQvbGVzc2hhdC5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvaGVhZGVyLWEvaGVhZGVyLWEubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL25hdmlnYXRpb24tYS9uYXZpZ2F0aW9uLWEubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL25hdmlnYXRpb24tYi9uYXZpZ2F0aW9uLWIubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2Zvb3Rlci1hL2Zvb3Rlci1hLmxlc3MiLCIuLi8uLi9ub2RlX21vZHVsZXMvY2tzb3VyY2Utc2FtcGxlcy1mcmFtZXdvcmsvY29tcG9uZW50cy9jb250ZW50L2NvbnRlbnQubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2J1dHRvbi1hL2J1dHRvbi1hLmxlc3MiLCIuLi8uLi9ub2RlX21vZHVsZXMvY2tzb3VyY2Utc2FtcGxlcy1mcmFtZXdvcmsvY29tcG9uZW50cy9iYWxsb29uLWEvYmFsbG9vbi1hLmxlc3MiLCIuLi8uLi9ub2RlX21vZHVsZXMvY2tzb3VyY2Utc2FtcGxlcy1mcmFtZXdvcmsvY29tcG9uZW50cy9pY29uL2ljb24ubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL3N3aXRjaC9zd2l0Y2gubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL3RvZ2dsZXIvdG9nZ2xlci5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvbW9kYWwvbW9kYWwubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2Jhc2ljc2FtcGxlL2NvcmUubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2Jhc2ljc2FtcGxlL2Fkam9pbmVkLmxlc3MiLCIuLi8uLi9zYW1wbGVzL2xlc3MvY3VzdG9tLmxlc3MiLCIuLi8uLi9zYW1wbGVzL3Rvb2xiYXJjb25maWd1cmF0b3IvbGVzcy90b29sYmFybW9kaWZpZXIubGVzcyIsIi4uLy4uL3NhbXBsZXMvdG9vbGJhcmNvbmZpZ3VyYXRvci9sZXNzL2Jhc2UubGVzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBc0RBLFFBSGlDO0VBeUNoQztJQUNDLHdCQUFBOzs7QUMxRkY7QUFBUztBQUFPO0FBQVM7QUFBWTtBQUFRO0FBQVE7QUFBUTtBQUFRO0FBQU07QUFBTTtBQUFLO0VBQ3JGLGNBQUE7O0FBR0Q7QUFBTTtFQUNMLFNBQUE7RUFDQSxVQUFBO0VBQ0Esd0JETitCLHVDQ00vQjtFQUNBLGdCQUFBO0VBQ0EsY0FBQTs7QUNIQSxZQUFZO0VBQ1gsVUFBQTs7QUFERCxZQUFZO0VBQ1gsVUFBQTs7QUFERCxZ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 */ diff --git a/nstock/static/plugin_ckeditor/samples/img/github-top.png b/nstock/static/plugin_ckeditor/samples/img/github-top.png new file mode 100644 index 0000000000000000000000000000000000000000..7b9cbb10fdd09f8db9c14c268d654c36c4c364bc GIT binary patch literal 383 zcmeAS@N?(olHy`uVBq!ia0vp^!ayvU?E9J6vh>Mva&n!ameNi2P6c|6 ztHa*vK6_ueXY16sg#qkk%~2CpbMJONYng4c(c0B^@i&<&(X9_Jthgd&>9V#n>)^To z<+%@2L*p8}BU!gDUi&)n%Ub4Lx31nf^uQu@K4-+A(2cMD>YWyz5c4%>-xpIx&%Y1i hPt9r2OzFJJe@8}Wo=4@+)j;Pmc)I$ztaD0e0sv2I+6@2z literal 0 HcmV?d00001 diff --git a/nstock/static/plugin_ckeditor/samples/img/header-bg.png b/nstock/static/plugin_ckeditor/samples/img/header-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..a14166a8f5af8474352f9a22b63b06d9868665e6 GIT binary patch literal 13086 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 OfZRuA=~_wSkpBmZ6+5Q@ literal 0 HcmV?d00001 diff --git a/nstock/static/plugin_ckeditor/samples/img/header-separator.png b/nstock/static/plugin_ckeditor/samples/img/header-separator.png new file mode 100644 index 0000000000000000000000000000000000000000..8c4fb9b569c381b28e9edda2786f3fa2c67f73d2 GIT binary patch literal 123 zcmeAS@N?(olHy`uVBq!ia0y~yV15B)Gjgy2NneH*V<6?^>EaktaqG=RZ$1VE4(EeK z|D6}RPv}>iWq#W%w!zbA?(28A*dxE_&HVRP7O0$Ib4|u^?w{I`&&+iHf6%=Y&&0zp We;NOO*LmhWAZbrmKbLh*2~7Zl1Sr%1 literal 0 HcmV?d00001 diff --git a/nstock/static/plugin_ckeditor/samples/img/logo.png b/nstock/static/plugin_ckeditor/samples/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..96d86e27c137e248693721e35485b590b7ab805e GIT binary patch literal 5891 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 literal 0 HcmV?d00001 diff --git a/nstock/static/plugin_ckeditor/samples/index.html b/nstock/static/plugin_ckeditor/samples/index.html new file mode 100644 index 0000000..0b154b7 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/index.html @@ -0,0 +1,128 @@ + + + + + + CKEditor Sample + + + + + + + + + +
+ +
+ +
+
+
+
+

Congratulations!

+

+ If you can see CKEditor below, it means that the installation succeeded. + You can now try out your new editor version, see its features, and when you are ready to move on, check some of the most useful resources recommended below. +

+
+
+
+
+
+
+
+

Hello world!

+

I'm an instance of CKEditor.

+
+
+
+
+ +
+
+
+

Customize Your Editor

+

Modular build and numerous configuration options give you nearly endless possibilities to customize CKEditor. Replace the content of your config.js file with the following code and refresh this page (remember to clear the browser cache)!

+
CKEDITOR.editorConfig = function( config ) {
+	config.language = 'es';
+	config.uiColor = '#F7B42C';
+	config.height = 300;
+	config.toolbarCanCollapse = true;
+};
+
+ +
+

Toolbar Configuration

+

If you want to reorder toolbar buttons or remove some of them, check this handy tool!

+
+ +
+

More Samples!

+

Visit the CKEditor SDK for a huge collection of samples showcasing editor features, with source code readily available to copy and use in your own implementation.

+
+ +
+

Developer's Guide

+

The most important resource for all developers working with CKEditor, integrating it with their websites and applications, and customizing to their needs. You can start from here:

+
    +
  • Getting Started – Explains most crucial editor concepts and practices as well as the installation process and integration with your website.
  • +
  • Advanced Installation Concepts – Describes how to upgrade, install additional components (plugins, skins), or create a custom build.
  • +
+

When you have the basics sorted out, feel free to browse some more advanced sections like:

+ +
+ +
+

CKEditor JavaScript API

+

CKEditor boasts a rich JavaScript API that you can use to adjust the editor to your needs and integrate it with your website or application.

+
+
+
+
+ +
+
+

+ CKEditor – The text editor for the Internet – http://ckeditor.com +

+

+ Copyright © 2003-2016, CKSource – Frederico Knabben. All rights reserved. +

+
+
+ + + + diff --git a/nstock/static/plugin_ckeditor/samples/js/sample.js b/nstock/static/plugin_ckeditor/samples/js/sample.js new file mode 100644 index 0000000..80f1c2b --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/js/sample.js @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or http://ckeditor.com/license + */ + +/* exported initSample */ + +if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) + CKEDITOR.tools.enableHtml5Elements( document ); + +// The trick to keep the editor in the sample quite small +// unless user specified own height. +CKEDITOR.config.height = 150; +CKEDITOR.config.width = 'auto'; + +var initSample = ( function() { + var wysiwygareaAvailable = isWysiwygareaAvailable(), + isBBCodeBuiltIn = !!CKEDITOR.plugins.get( 'bbcode' ); + + return function() { + var editorElement = CKEDITOR.document.getById( 'editor' ); + + // :((( + if ( isBBCodeBuiltIn ) { + editorElement.setHtml( + 'Hello world!\n\n' + + 'I\'m an instance of [url=http://ckeditor.com]CKEditor[/url].' + ); + } + + // Depending on the wysiwygare plugin availability initialize classic or inline editor. + if ( wysiwygareaAvailable ) { + CKEDITOR.replace( 'editor' ); + } else { + editorElement.setAttribute( 'contenteditable', 'true' ); + CKEDITOR.inline( 'editor' ); + + // TODO we can consider displaying some info box that + // without wysiwygarea the classic editor may not work. + } + }; + + function isWysiwygareaAvailable() { + // If in development mode, then the wysiwygarea must be available. + // Split REV into two strings so builder does not replace it :D. + if ( CKEDITOR.revision == ( '%RE' + 'V%' ) ) { + return true; + } + + return !!CKEDITOR.plugins.get( 'wysiwygarea' ); + } +} )(); + diff --git a/nstock/static/plugin_ckeditor/samples/js/sf.js b/nstock/static/plugin_ckeditor/samples/js/sf.js new file mode 100644 index 0000000..72edbde --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/js/sf.js @@ -0,0 +1,17 @@ +/* + Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +var SF=function(){function d(a){return(a=a.attributes?a.attributes.getNamedItem("class"):null)?a.value.split(" "):[]}function c(a){var e=document.createAttribute("class");e.value=a.join(" ");return e}var b={attachListener:function(a,e,b){if(a.addEventListener)a.addEventListener(e,b,!1);else if(a.attachEvent)a.attachEvent("on"+e,function(){b.apply(a,arguments)});else throw Error("Could not attach event.");}};b.indexOf=function(){var a=Array.prototype.indexOf;return"function"===a?function(e,b){return a.call(e, +b)}:function(a,b){for(var c=a.length,d=0;d + + + + + Ajax — CKEditor Sample + + + + + +

+ CKEditor Samples » Create and Destroy Editor Instances for Ajax Applications +

+
+ This sample is not maintained anymore. Check out its brand new version in CKEditor SDK. +
+
+

+ This sample shows how to create and destroy CKEditor instances on the fly. After the removal of CKEditor the content created inside the editing + area will be displayed in a <div> element. +

+

+ For details of how to create this setup check the source code of this sample page + for JavaScript code responsible for the creation and destruction of a CKEditor instance. +

+
+

Click the buttons to create and remove a CKEditor instance.

+

+ + +

+ +
+
+ + + + diff --git a/nstock/static/plugin_ckeditor/samples/old/api.html b/nstock/static/plugin_ckeditor/samples/old/api.html new file mode 100644 index 0000000..d01f0ee --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/api.html @@ -0,0 +1,210 @@ + + + + + + API Usage — CKEditor Sample + + + + + + +

+ CKEditor Samples » Using CKEditor JavaScript API +

+
+ This sample is not maintained anymore. Check out its brand new version in CKEditor SDK. +
+
+

+ This sample shows how to use the + CKEditor JavaScript API + to interact with the editor at runtime. +

+

+ For details on how to create this setup check the source code of this sample page. +

+
+ + +
+ +
+
+ + + + +

+

+ + +
+ + + diff --git a/nstock/static/plugin_ckeditor/samples/old/appendto.html b/nstock/static/plugin_ckeditor/samples/old/appendto.html new file mode 100644 index 0000000..51e2d62 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/appendto.html @@ -0,0 +1,59 @@ + + + + + + Append To Page Element Using JavaScript Code — CKEditor Sample + + + + +

+ CKEditor Samples » Append To Page Element Using JavaScript Code +

+
+ This sample is not maintained anymore. Check out the brand new samples in CKEditor SDK. +
+
+
+

+ The CKEDITOR.appendTo() method serves to to place editors inside existing DOM elements. Unlike CKEDITOR.replace(), + a target container to be replaced is no longer necessary. A new editor + instance is inserted directly wherever it is desired. +

+
CKEDITOR.appendTo( 'container_id',
+	{ /* Configuration options to be used. */ }
+	'Editor content to be used.'
+);
+
+ +
+
+ + + diff --git a/nstock/static/plugin_ckeditor/samples/old/assets/inlineall/logo.png b/nstock/static/plugin_ckeditor/samples/old/assets/inlineall/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b4d5979e3451d76d72e8b9337ee208d7275abb15 GIT binary patch literal 4283 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 literal 0 HcmV?d00001 diff --git a/nstock/static/plugin_ckeditor/samples/old/assets/outputxhtml/outputxhtml.css b/nstock/static/plugin_ckeditor/samples/old/assets/outputxhtml/outputxhtml.css new file mode 100644 index 0000000..09ca048 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/assets/outputxhtml/outputxhtml.css @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or http://ckeditor.com/license + * + * Styles used by the XHTML 1.1 sample page (xhtml.html). + */ + +/** + * Basic definitions for the editing area. + */ +body +{ + font-family: Arial, Verdana, sans-serif; + font-size: 80%; + color: #000000; + background-color: #ffffff; + padding: 5px; + margin: 0px; +} + +/** + * Core styles. + */ + +.Bold +{ + font-weight: bold; +} + +.Italic +{ + font-style: italic; +} + +.Underline +{ + text-decoration: underline; +} + +.StrikeThrough +{ + text-decoration: line-through; +} + +.Subscript +{ + vertical-align: sub; + font-size: smaller; +} + +.Superscript +{ + vertical-align: super; + font-size: smaller; +} + +/** + * Font faces. + */ + +.FontComic +{ + font-family: 'Comic Sans MS'; +} + +.FontCourier +{ + font-family: 'Courier New'; +} + +.FontTimes +{ + font-family: 'Times New Roman'; +} + +/** + * Font sizes. + */ + +.FontSmaller +{ + font-size: smaller; +} + +.FontLarger +{ + font-size: larger; +} + +.FontSmall +{ + font-size: 8pt; +} + +.FontBig +{ + font-size: 14pt; +} + +.FontDouble +{ + font-size: 200%; +} + +/** + * Font colors. + */ +.FontColor1 +{ + color: #ff9900; +} + +.FontColor2 +{ + color: #0066cc; +} + +.FontColor3 +{ + color: #ff0000; +} + +.FontColor1BG +{ + background-color: #ff9900; +} + +.FontColor2BG +{ + background-color: #0066cc; +} + +.FontColor3BG +{ + background-color: #ff0000; +} + +/** + * Indentation. + */ + +.Indent1 +{ + margin-left: 40px; +} + +.Indent2 +{ + margin-left: 80px; +} + +.Indent3 +{ + margin-left: 120px; +} + +/** + * Alignment. + */ + +.JustifyLeft +{ + text-align: left; +} + +.JustifyRight +{ + text-align: right; +} + +.JustifyCenter +{ + text-align: center; +} + +.JustifyFull +{ + text-align: justify; +} + +/** + * Other. + */ + +code +{ + font-family: courier, monospace; + background-color: #eeeeee; + padding-left: 1px; + padding-right: 1px; + border: #c0c0c0 1px solid; +} + +kbd +{ + padding: 0px 1px 0px 1px; + border-width: 1px 2px 2px 1px; + border-style: solid; +} + +blockquote +{ + color: #808080; +} diff --git a/nstock/static/plugin_ckeditor/samples/old/assets/posteddata.php b/nstock/static/plugin_ckeditor/samples/old/assets/posteddata.php new file mode 100644 index 0000000..568dbfb --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/assets/posteddata.php @@ -0,0 +1,59 @@ + + + + + + Sample — CKEditor + + + +

+ CKEditor — Posted Data +

+ + + + + + + + + $value ) + { + if ( ( !is_string($value) && !is_numeric($value) ) || !is_string($key) ) + continue; + + if ( get_magic_quotes_gpc() ) + $value = htmlspecialchars( stripslashes((string)$value) ); + else + $value = htmlspecialchars( (string)$value ); +?> + + + + + +
Field NameValue
+ + + diff --git a/nstock/static/plugin_ckeditor/samples/old/assets/sample.jpg b/nstock/static/plugin_ckeditor/samples/old/assets/sample.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9498271c6032eafda487c0428ad5b26eff35985a GIT binary patch literal 14449 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 literal 0 HcmV?d00001 diff --git a/nstock/static/plugin_ckeditor/samples/old/assets/uilanguages/languages.js b/nstock/static/plugin_ckeditor/samples/old/assets/uilanguages/languages.js new file mode 100644 index 0000000..3bd1248 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/assets/uilanguages/languages.js @@ -0,0 +1,7 @@ +/* + Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +var CKEDITOR_LANGS=function(){var c={af:"Afrikaans",ar:"Arabic",bg:"Bulgarian",bn:"Bengali/Bangla",bs:"Bosnian",ca:"Catalan",cs:"Czech",cy:"Welsh",da:"Danish",de:"German","de-ch":"German (Switzerland)",el:"Greek",en:"English","en-au":"English (Australia)","en-ca":"English (Canadian)","en-gb":"English (United Kingdom)",eo:"Esperanto",es:"Spanish",et:"Estonian",eu:"Basque",fa:"Persian",fi:"Finnish",fo:"Faroese",fr:"French","fr-ca":"French (Canada)",gl:"Galician",gu:"Gujarati",he:"Hebrew",hi:"Hindi", +hr:"Croatian",hu:"Hungarian",id:"Indonesian",is:"Icelandic",it:"Italian",ja:"Japanese",ka:"Georgian",km:"Khmer",ko:"Korean",ku:"Kurdish",lt:"Lithuanian",lv:"Latvian",mk:"Macedonian",mn:"Mongolian",ms:"Malay",nb:"Norwegian Bokmal",nl:"Dutch",no:"Norwegian",pl:"Polish",pt:"Portuguese (Portugal)","pt-br":"Portuguese (Brazil)",ro:"Romanian",ru:"Russian",si:"Sinhala",sk:"Slovak",sq:"Albanian",sl:"Slovenian",sr:"Serbian (Cyrillic)","sr-latn":"Serbian (Latin)",sv:"Swedish",th:"Thai",tr:"Turkish",tt:"Tatar", +ug:"Uighur",uk:"Ukrainian",vi:"Vietnamese",zh:"Chinese Traditional","zh-cn":"Chinese Simplified"},b=[],a;for(a in CKEDITOR.lang.languages)b.push({code:a,name:c[a]||a});b.sort(function(a,b){return a.name + + + + + Data Filtering — CKEditor Sample + + + + + +

+ CKEditor Samples » Data Filtering and Features Activation +

+
+ This sample is not maintained anymore. Check out its brand new version in CKEditor SDK. +
+
+

+ This sample page demonstrates the idea of Advanced Content Filter + (ACF), a sophisticated + tool that takes control over what kind of data is accepted by the editor and what + kind of output is produced. +

+

When and what is being filtered?

+

+ ACF controls + every single source of data that comes to the editor. + It process both HTML that is inserted manually (i.e. pasted by the user) + and programmatically like: +

+
+editor.setData( '<p>Hello world!</p>' );
+
+

+ ACF discards invalid, + useless HTML tags and attributes so the editor remains "clean" during + runtime. ACF behaviour + can be configured and adjusted for a particular case to prevent the + output HTML (i.e. in CMS systems) from being polluted. + + This kind of filtering is a first, client-side line of defense + against "tag soups", + the tool that precisely restricts which tags, attributes and styles + are allowed (desired). When properly configured, ACF + is an easy and fast way to produce a high-quality, intentionally filtered HTML. +

+ +

How to configure or disable ACF?

+

+ Advanced Content Filter is enabled by default, working in "automatic mode", yet + it provides a set of easy rules that allow adjusting filtering rules + and disabling the entire feature when necessary. The config property + responsible for this feature is config.allowedContent. +

+

+ By "automatic mode" is meant that loaded plugins decide which kind + of content is enabled and which is not. For example, if the link + plugin is loaded it implies that <a> tag is + automatically allowed. Each plugin is given a set + of predefined ACF rules + that control the editor until + config.allowedContent + is defined manually. +

+

+ Let's assume our intention is to restrict the editor to accept (produce) paragraphs + only: no attributes, no styles, no other tags. + With ACF + this is very simple. Basically set + config.allowedContent to 'p': +

+
+var editor = CKEDITOR.replace( textarea_id, {
+	allowedContent: 'p'
+} );
+
+

+ Now try to play with allowed content: +

+
+// Trying to insert disallowed tag and attribute.
+editor.setData( '<p style="color: red">Hello <em>world</em>!</p>' );
+alert( editor.getData() );
+
+// Filtered data is returned.
+"<p>Hello world!</p>"
+
+

+ What happened? Since config.allowedContent: 'p' is set the editor assumes + that only plain <p> are accepted. Nothing more. This is why + style attribute and <em> tag are gone. The same + filtering would happen if we pasted disallowed HTML into this editor. +

+

+ This is just a small sample of what ACF + can do. To know more, please refer to the sample section below and + the official Advanced Content Filter guide. +

+

+ You may, of course, want CKEditor to avoid filtering of any kind. + To get rid of ACF, + basically set + config.allowedContent to true like this: +

+
+CKEDITOR.replace( textarea_id, {
+	allowedContent: true
+} );
+
+ +

Beyond data flow: Features activation

+

+ ACF is far more than + I/O control: the entire + UI of the editor is adjusted to what + filters restrict. For example: if <a> tag is + disallowed + by ACF, + then accordingly link command, toolbar button and link dialog + are also disabled. Editor is smart: it knows which features must be + removed from the interface to match filtering rules. +

+

+ CKEditor can be far more specific. If <a> tag is + allowed by filtering rules to be used but it is restricted + to have only one attribute (href) + config.allowedContent = 'a[!href]', then + "Target" tab of the link dialog is automatically disabled as target + attribute isn't included in ACF rules + for <a>. This behaviour applies to dialog fields, context + menus and toolbar buttons. +

+ +

Sample configurations

+

+ There are several editor instances below that present different + ACF setups. All of them, + except the inline instance, share the same HTML content to visualize + how different filtering rules affect the same input data. +

+
+ +
+ +
+

+ This editor is using default configuration ("automatic mode"). It means that + + config.allowedContent is defined by loaded plugins. + Each plugin extends filtering rules to make it's own associated content + available for the user. +

+
+ + + +
+ +
+ +
+ +
+

+ This editor is using a custom configuration for + ACF: +

+
+CKEDITOR.replace( 'editor2', {
+	allowedContent:
+		'h1 h2 h3 p blockquote strong em;' +
+		'a[!href];' +
+		'img(left,right)[!src,alt,width,height];' +
+		'table tr th td caption;' +
+		'span{!font-family};' +'
+		'span{!color};' +
+		'span(!marker);' +
+		'del ins'
+} );
+
+

+ The following rules may require additional explanation: +

+
    +
  • + h1 h2 h3 p blockquote strong em - These tags + are accepted by the editor. Any tag attributes will be discarded. +
  • +
  • + a[!href] - href attribute is obligatory + for <a> tag. Tags without this attribute + are disarded. No other attribute will be accepted. +
  • +
  • + img(left,right)[!src,alt,width,height] - src + attribute is obligatory for <img> tag. + alt, width, height + and class attributes are accepted but + class must be either class="left" + or class="right" +
  • +
  • + table tr th td caption - These tags + are accepted by the editor. Any tag attributes will be discarded. +
  • +
  • + span{!font-family}, span{!color}, + span(!marker) - <span> tags + will be accepted if either font-family or + color style is set or class="marker" + is present. +
  • +
  • + del ins - These tags + are accepted by the editor. Any tag attributes will be discarded. +
  • +
+

+ Please note that UI of the + editor is different. It's a response to what happened to the filters. + Since text-align isn't allowed, the align toolbar is gone. + The same thing happened to subscript/superscript, strike, underline + (<u>, <sub>, <sup> + are disallowed by + config.allowedContent) and many other buttons. +

+
+ + +
+ +
+ +
+ +
+

+ This editor is using a custom configuration for + ACF. + Note that filters can be configured as an object literal + as an alternative to a string-based definition. +

+
+CKEDITOR.replace( 'editor3', {
+	allowedContent: {
+		'b i ul ol big small': true,
+		'h1 h2 h3 p blockquote li': {
+			styles: 'text-align'
+		},
+		a: { attributes: '!href,target' },
+		img: {
+			attributes: '!src,alt',
+			styles: 'width,height',
+			classes: 'left,right'
+		}
+	}
+} );
+
+
+ + +
+ +
+ +
+ +
+

+ This editor is using a custom set of plugins and buttons. +

+
+CKEDITOR.replace( 'editor4', {
+	removePlugins: 'bidi,font,forms,flash,horizontalrule,iframe,justify,table,tabletools,smiley',
+	removeButtons: 'Anchor,Underline,Strike,Subscript,Superscript,Image',
+	format_tags: 'p;h1;h2;h3;pre;address'
+} );
+
+

+ As you can see, removing plugins and buttons implies filtering. + Several tags are not allowed in the editor because there's no + plugin/button that is responsible for creating and editing this + kind of content (for example: the image is missing because + of removeButtons: 'Image'). The conclusion is that + ACF works "backwards" + as well: modifying UI + elements is changing allowed content rules. +

+
+ + +
+ +
+ +
+ +
+

+ This editor is built on editable <h1> element. + ACF takes care of + what can be included in <h1>. Note that there + are no block styles in Styles combo. Also why lists, indentation, + blockquote, div, form and other buttons are missing. +

+

+ ACF makes sure that + no disallowed tags will come to <h1> so the final + markup is valid. If the user tried to paste some invalid HTML + into this editor (let's say a list), it would be automatically + converted into plain text. +

+
+

+ Apollo 11 was the spaceflight that landed the first humans, Americans Neil Armstrong and Buzz Aldrin, on the Moon on July 20, 1969, at 20:18 UTC. +

+
+ +
+ +
+ +
+

+ This editor is using a custom configuration for ACF. + It's using the + Disallowed Content property of the filter to eliminate all title attributes. +

+ +
+CKEDITOR.replace( 'editor6', {
+	allowedContent: {
+		'b i ul ol big small': true,
+		'h1 h2 h3 p blockquote li': {
+			styles: 'text-align'
+		},
+		a: {attributes: '!href,target'},
+		img: {
+			attributes: '!src,alt',
+			styles: 'width,height',
+			classes: 'left,right'
+		}
+	},
+	disallowedContent: '*{title*}'
+} );
+
+
+ + +
+ +
+ +
+ +
+

+ This editor is using a custom configuration for ACF. + It's using the + Disallowed Content property of the filter to eliminate all a and img tags, + while allowing all other tags. +

+
+CKEDITOR.replace( 'editor7', {
+	allowedContent: {
+		// Allow all content.
+		$1: {
+			elements: CKEDITOR.dtd,
+			attributes: true,
+			styles: true,
+			classes: true
+		}
+	},
+	disallowedContent: 'img a'
+} );
+
+
+ + +
+ + + + diff --git a/nstock/static/plugin_ckeditor/samples/old/dialog/assets/my_dialog.js b/nstock/static/plugin_ckeditor/samples/old/dialog/assets/my_dialog.js new file mode 100644 index 0000000..f85af78 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/dialog/assets/my_dialog.js @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or http://ckeditor.com/license + */ + +CKEDITOR.dialog.add( 'myDialog', function() { + return { + title: 'My Dialog', + minWidth: 400, + minHeight: 200, + contents: [ + { + id: 'tab1', + label: 'First Tab', + title: 'First Tab', + elements: [ + { + id: 'input1', + type: 'text', + label: 'Text Field' + }, + { + id: 'select1', + type: 'select', + label: 'Select Field', + items: [ + [ 'option1', 'value1' ], + [ 'option2', 'value2' ] + ] + } + ] + }, + { + id: 'tab2', + label: 'Second Tab', + title: 'Second Tab', + elements: [ + { + id: 'button1', + type: 'button', + label: 'Button Field' + } + ] + } + ] + }; +} ); + diff --git a/nstock/static/plugin_ckeditor/samples/old/dialog/dialog.html b/nstock/static/plugin_ckeditor/samples/old/dialog/dialog.html new file mode 100644 index 0000000..4064b71 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/dialog/dialog.html @@ -0,0 +1,190 @@ + + + + + + Using API to Customize Dialog Windows — CKEditor Sample + + + + + + + + + +

+ CKEditor Samples » Using CKEditor Dialog API +

+
+ This sample is not maintained anymore. Check out the brand new samples in CKEditor SDK. +
+
+

+ This sample shows how to use the + CKEditor Dialog API + to customize CKEditor dialog windows without changing the original editor code. + The following customizations are being done in the example below: +

+

+ For details on how to create this setup check the source code of this sample page. +

+
+

A custom dialog is added to the editors using the pluginsLoaded event, from an external dialog definition file:

+
    +
  1. Creating a custom dialog window – "My Dialog" dialog window opened with the "My Dialog" toolbar button.
  2. +
  3. Creating a custom button – Add button to open the dialog with "My Dialog" toolbar button.
  4. +
+ + +

The below editor modify the dialog definition of the above added dialog using the dialogDefinition event:

+
    +
  1. Adding dialog tab – Add new tab "My Tab" to dialog window.
  2. +
  3. Removing a dialog window tab – Remove "Second Tab" page from the dialog window.
  4. +
  5. Adding dialog window fields – Add "My Custom Field" to the dialog window.
  6. +
  7. Removing dialog window field – Remove "Select Field" selection field from the dialog window.
  8. +
  9. Setting default values for dialog window fields – Set default value of "Text Field" text field.
  10. +
  11. Setup initial focus for dialog window – Put initial focus on "My Custom Field" text field.
  12. +
+ + + + + diff --git a/nstock/static/plugin_ckeditor/samples/old/divreplace.html b/nstock/static/plugin_ckeditor/samples/old/divreplace.html new file mode 100644 index 0000000..91008c8 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/divreplace.html @@ -0,0 +1,144 @@ + + + + + + Replace DIV — CKEditor Sample + + + + + + +

+ CKEditor Samples » Replace DIV with CKEditor on the Fly +

+
+ This sample is not maintained anymore. Check out the brand new samples in CKEditor SDK. +
+
+

+ This sample shows how to automatically replace <div> elements + with a CKEditor instance on the fly, following user's doubleclick. The content + that was previously placed inside the <div> element will now + be moved into CKEditor editing area. +

+

+ For details on how to create this setup check the source code of this sample page. +

+
+

+ Double-click any of the following <div> elements to transform them into + editor instances. +

+
+

+ Part 1 +

+

+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras et ipsum quis mi + semper accumsan. Integer pretium dui id massa. Suspendisse in nisl sit amet urna + rutrum imperdiet. Nulla eu tellus. Donec ante nisi, ullamcorper quis, fringilla + nec, sagittis eleifend, pede. Nulla commodo interdum massa. Donec id metus. Fusce + eu ipsum. Suspendisse auctor. Phasellus fermentum porttitor risus. +

+
+
+

+ Part 2 +

+

+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras et ipsum quis mi + semper accumsan. Integer pretium dui id massa. Suspendisse in nisl sit amet urna + rutrum imperdiet. Nulla eu tellus. Donec ante nisi, ullamcorper quis, fringilla + nec, sagittis eleifend, pede. Nulla commodo interdum massa. Donec id metus. Fusce + eu ipsum. Suspendisse auctor. Phasellus fermentum porttitor risus. +

+

+ Donec velit. Mauris massa. Vestibulum non nulla. Nam suscipit arcu nec elit. Phasellus + sollicitudin iaculis ante. Ut non mauris et sapien tincidunt adipiscing. Vestibulum + vitae leo. Suspendisse nec mi tristique nulla laoreet vulputate. +

+
+
+

+ Part 3 +

+

+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras et ipsum quis mi + semper accumsan. Integer pretium dui id massa. Suspendisse in nisl sit amet urna + rutrum imperdiet. Nulla eu tellus. Donec ante nisi, ullamcorper quis, fringilla + nec, sagittis eleifend, pede. Nulla commodo interdum massa. Donec id metus. Fusce + eu ipsum. Suspendisse auctor. Phasellus fermentum porttitor risus. +

+
+ + + diff --git a/nstock/static/plugin_ckeditor/samples/old/enterkey/enterkey.html b/nstock/static/plugin_ckeditor/samples/old/enterkey/enterkey.html new file mode 100644 index 0000000..dc7295f --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/enterkey/enterkey.html @@ -0,0 +1,106 @@ + + + + + + ENTER Key Configuration — CKEditor Sample + + + + + + + + +

+ CKEditor Samples » ENTER Key Configuration +

+
+ This sample is not maintained anymore. Check out its brand new version in CKEditor SDK. +
+
+

+ This sample shows how to configure the Enter and Shift+Enter keys + to perform actions specified in the + enterMode + and shiftEnterMode + parameters, respectively. + You can choose from the following options: +

+
    +
  • ENTER_P – new <p> paragraphs are created;
  • +
  • ENTER_BR – lines are broken with <br> elements;
  • +
  • ENTER_DIV – new <div> blocks are created.
  • +
+

+ The sample code below shows how to configure CKEditor to create a <div> block when Enter key is pressed. +

+
+CKEDITOR.replace( 'textarea_id', {
+	enterMode: CKEDITOR.ENTER_DIV
+});
+

+ Note that textarea_id in the code above is the id attribute of + the <textarea> element to be replaced. +

+
+
+ When Enter is pressed:
+ +
+
+ When Shift+Enter is pressed:
+ +
+
+
+

+
+ +

+

+ +

+
+ + + diff --git a/nstock/static/plugin_ckeditor/samples/old/htmlwriter/assets/outputforflash/outputforflash.fla b/nstock/static/plugin_ckeditor/samples/old/htmlwriter/assets/outputforflash/outputforflash.fla new file mode 100644 index 0000000000000000000000000000000000000000..27e68ccd1cb7192c8bda2418d198d90f1aff10a7 GIT binary patch literal 85504 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 literal 0 HcmV?d00001 diff --git a/nstock/static/plugin_ckeditor/samples/old/htmlwriter/assets/outputforflash/swfobject.js b/nstock/static/plugin_ckeditor/samples/old/htmlwriter/assets/outputforflash/swfobject.js new file mode 100644 index 0000000..0700921 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/htmlwriter/assets/outputforflash/swfobject.js @@ -0,0 +1,19 @@ +var swfobject=function(){function w(){if(!u){try{var a=d.getElementsByTagName("body")[0].appendChild(d.createElement("span"));a.parentNode.removeChild(a)}catch(b){return}u=!0;for(var a=z.length,c=0;cf){f++;setTimeout(arguments.callee,10);return}a.removeChild(b);c=null;E()})()}else E()} +function E(){var a=r.length;if(0e.wk)if(r[b].expressInstall&&F()){g={};g.data=r[b].expressInstall;g.width=d.getAttribute("width")||"0";g.height=d.getAttribute("height")||"0";d.getAttribute("class")&&(g.styleclass=d.getAttribute("class"));d.getAttribute("align")&&(g.align=d.getAttribute("align"));for(var h={},d=d.getElementsByTagName("param"),k=d.length,l=0;l< +k;l++)"movie"!=d[l].getAttribute("name").toLowerCase()&&(h[d[l].getAttribute("name")]=d[l].getAttribute("value"));G(g,h,c,f)}else W(d),f&&f(g);else v(c,!0),f&&(g.success=!0,g.ref=H(c),f(g))}else v(c,!0),f&&((c=H(c))&&"undefined"!=typeof c.SetVariable&&(g.success=!0,g.ref=c),f(g))}}function H(a){var b=null;(a=p(a))&&"OBJECT"==a.nodeName&&("undefined"!=typeof a.SetVariable?b=a:(a=a.getElementsByTagName("object")[0])&&(b=a));return b}function F(){return!B&&A("6.0.65")&&(e.win||e.mac)&&!(e.wk&&312>e.wk)} +function G(a,b,c,f){B=!0;I=f||null;O={success:!1,id:c};var g=p(c);if(g){"OBJECT"==g.nodeName?(y=J(g),C=null):(y=g,C=c);a.id="SWFObjectExprInst";if("undefined"==typeof a.width||!/%$/.test(a.width)&&310>parseInt(a.width,10))a.width="310";if("undefined"==typeof a.height||!/%$/.test(a.height)&&137>parseInt(a.height,10))a.height="137";d.title=d.title.slice(0,47)+" - Flash Player Installation";f=e.ie&&e.win?"ActiveX":"PlugIn";f="MMredirectURL\x3d"+n.location.toString().replace(/&/g,"%26")+"\x26MMplayerType\x3d"+ +f+"\x26MMdoctitle\x3d"+d.title;b.flashvars="undefined"!=typeof b.flashvars?b.flashvars+("\x26"+f):f;e.ie&&e.win&&4!=g.readyState&&(f=d.createElement("div"),c+="SWFObjectNew",f.setAttribute("id",c),g.parentNode.insertBefore(f,g),g.style.display="none",function(){4==g.readyState?g.parentNode.removeChild(g):setTimeout(arguments.callee,10)}());K(a,b,c)}}function W(a){if(e.ie&&e.win&&4!=a.readyState){var b=d.createElement("div");a.parentNode.insertBefore(b,a);b.parentNode.replaceChild(J(a),b);a.style.display= +"none";(function(){4==a.readyState?a.parentNode.removeChild(a):setTimeout(arguments.callee,10)})()}else a.parentNode.replaceChild(J(a),a)}function J(a){var b=d.createElement("div");if(e.win&&e.ie)b.innerHTML=a.innerHTML;else if(a=a.getElementsByTagName("object")[0])if(a=a.childNodes)for(var c=a.length,f=0;fe.wk)return f;if(g)if("undefined"==typeof a.id&& +(a.id=c),e.ie&&e.win){var q="",h;for(h in a)a[h]!=Object.prototype[h]&&("data"==h.toLowerCase()?b.movie=a[h]:"styleclass"==h.toLowerCase()?q+=' class\x3d"'+a[h]+'"':"classid"!=h.toLowerCase()&&(q+=" "+h+'\x3d"'+a[h]+'"'));h="";for(var k in b)b[k]!=Object.prototype[k]&&(h+='\x3cparam name\x3d"'+k+'" value\x3d"'+b[k]+'" /\x3e');g.outerHTML='\x3cobject classid\x3d"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+q+"\x3e"+h+"\x3c/object\x3e";D[D.length]=a.id;f=p(a.id)}else{k=d.createElement("object");k.setAttribute("type", +"application/x-shockwave-flash");for(var l in a)a[l]!=Object.prototype[l]&&("styleclass"==l.toLowerCase()?k.setAttribute("class",a[l]):"classid"!=l.toLowerCase()&&k.setAttribute(l,a[l]));for(q in b)b[q]!=Object.prototype[q]&&"movie"!=q.toLowerCase()&&(a=k,h=q,l=b[q],c=d.createElement("param"),c.setAttribute("name",h),c.setAttribute("value",l),a.appendChild(c));g.parentNode.replaceChild(k,g);f=k}return f}function P(a){var b=p(a);b&&"OBJECT"==b.nodeName&&(e.ie&&e.win?(b.style.display="none",function(){if(4== +b.readyState){var c=p(a);if(c){for(var f in c)"function"==typeof c[f]&&(c[f]=null);c.parentNode.removeChild(c)}}else setTimeout(arguments.callee,10)}()):b.parentNode.removeChild(b))}function p(a){var b=null;try{b=d.getElementById(a)}catch(c){}return b}function U(a,b,c){a.attachEvent(b,c);x[x.length]=[a,b,c]}function A(a){var b=e.pv;a=a.split(".");a[0]=parseInt(a[0],10);a[1]=parseInt(a[1],10)||0;a[2]=parseInt(a[2],10)||0;return b[0]>a[0]||b[0]==a[0]&&b[1]>a[1]||b[0]==a[0]&&b[1]==a[1]&&b[2]>=a[2]?!0: +!1}function Q(a,b,c,f){if(!e.ie||!e.mac){var g=d.getElementsByTagName("head")[0];g&&(c=c&&"string"==typeof c?c:"screen",f&&(L=m=null),m&&L==c||(f=d.createElement("style"),f.setAttribute("type","text/css"),f.setAttribute("media",c),m=g.appendChild(f),e.ie&&e.win&&"undefined"!=typeof d.styleSheets&&0\.;]/.exec(a)&&"undefined"!=typeof encodeURIComponent?encodeURIComponent(a):a}var n=window,d=document,t=navigator,T=!1,z=[function(){T?V():E()}],r=[],D=[],x=[],y,C,I,O,u=!1,B=!1,m,L,R=!0,e=function(){var a="undefined"!=typeof d.getElementById&&"undefined"!=typeof d.getElementsByTagName&&"undefined"!=typeof d.createElement,b=t.userAgent.toLowerCase(), +c=t.platform.toLowerCase(),f=c?/win/.test(c):/win/.test(b),c=c?/mac/.test(c):/mac/.test(b),b=/webkit/.test(b)?parseFloat(b.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):!1,g=!+"\v1",e=[0,0,0],h=null;if("undefined"!=typeof t.plugins&&"object"==typeof t.plugins["Shockwave Flash"])!(h=t.plugins["Shockwave Flash"].description)||"undefined"!=typeof t.mimeTypes&&t.mimeTypes["application/x-shockwave-flash"]&&!t.mimeTypes["application/x-shockwave-flash"].enabledPlugin||(T=!0,g=!1,h=h.replace(/^.*\s+(\S+\s+\S+$)/, +"$1"),e[0]=parseInt(h.replace(/^(.*)\..*$/,"$1"),10),e[1]=parseInt(h.replace(/^.*\.(.*)\s.*$/,"$1"),10),e[2]=/[a-zA-Z]/.test(h)?parseInt(h.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0);else if("undefined"!=typeof n.ActiveXObject)try{var k=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");k&&(h=k.GetVariable("$version"))&&(g=!0,h=h.split(" ")[1].split(","),e=[parseInt(h[0],10),parseInt(h[1],10),parseInt(h[2],10)])}catch(l){}return{w3:a,pv:e,wk:b,ie:g,win:f,mac:c}}();(function(){e.w3&&(("undefined"!=typeof d.readyState&& +"complete"==d.readyState||"undefined"==typeof d.readyState&&(d.getElementsByTagName("body")[0]||d.body))&&w(),u||("undefined"!=typeof d.addEventListener&&d.addEventListener("DOMContentLoaded",w,!1),e.ie&&e.win&&(d.attachEvent("onreadystatechange",function(){"complete"==d.readyState&&(d.detachEvent("onreadystatechange",arguments.callee),w())}),n==top&&function(){if(!u){try{d.documentElement.doScroll("left")}catch(a){setTimeout(arguments.callee,0);return}w()}}()),e.wk&&function(){u||(/loaded|complete/.test(d.readyState)? +w():setTimeout(arguments.callee,0))}(),N(w)))})();(function(){e.ie&&e.win&&window.attachEvent("onunload",function(){for(var a=x.length,b=0;be.wk)&&a&&b&&c&&d&&g?(v(b,!1),M(function(){c+="";d+="";var e={};if(l&&"object"===typeof l)for(var m in l)e[m]=l[m];e.data=a;e.width=c;e.height=d;m={};if(k&&"object"===typeof k)for(var r in k)m[r]=k[r];if(h&&"object"===typeof h)for(var t in h)m.flashvars="undefined"!=typeof m.flashvars?m.flashvars+("\x26"+t+"\x3d"+h[t]):t+"\x3d"+h[t];if(A(g))r=K(e,m,b),e.id==b&&v(b,!0),p.success=!0,p.ref=r;else{if(q&&F()){e.data=q;G(e, +m,b,n);return}v(b,!0)}n&&n(p)})):n&&n(p)},switchOffAutoHideShow:function(){R=!1},ua:e,getFlashPlayerVersion:function(){return{major:e.pv[0],minor:e.pv[1],release:e.pv[2]}},hasFlashPlayerVersion:A,createSWF:function(a,b,c){if(e.w3)return K(a,b,c)},showExpressInstall:function(a,b,c,d){e.w3&&F()&&G(a,b,c,d)},removeSWF:function(a){e.w3&&P(a)},createCSS:function(a,b,c,d){e.w3&&Q(a,b,c,d)},addDomLoadEvent:M,addLoadEvent:N,getQueryParamValue:function(a){var b=d.location.search||d.location.hash;if(b){/\?/.test(b)&& +(b=b.split("?")[1]);if(null==a)return S(b);for(var b=b.split("\x26"),c=0;c + + + + + Output for Flash — CKEditor Sample + + + + + + + + + + + +

+ CKEditor Samples » Producing Flash Compliant HTML Output +

+
+ This sample is not maintained anymore. Check out the brand new samples in CKEditor SDK. +
+
+

+ This sample shows how to configure CKEditor to output + HTML code that can be used with + + Adobe Flash. + The code will contain a subset of standard HTML elements like <b>, + <i>, and <p> as well as HTML attributes. +

+

+ To add a CKEditor instance outputting Flash compliant HTML code, load the editor using a standard + JavaScript call, and define CKEditor features to use HTML elements and attributes. +

+

+ For details on how to create this setup check the source code of this sample page. +

+
+

+ To see how it works, create some content in the editing area of CKEditor on the left + and send it to the Flash object on the right side of the page by using the + Send to Flash button. +

+ + + + + +
+ + +

+ +

+
+
+
+ + + diff --git a/nstock/static/plugin_ckeditor/samples/old/htmlwriter/outputhtml.html b/nstock/static/plugin_ckeditor/samples/old/htmlwriter/outputhtml.html new file mode 100644 index 0000000..bcf1eca --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/htmlwriter/outputhtml.html @@ -0,0 +1,224 @@ + + + + + + HTML Compliant Output — CKEditor Sample + + + + + + + + + +

+ CKEditor Samples » Producing HTML Compliant Output +

+
+ This sample is not maintained anymore. Check out the brand new samples in CKEditor SDK. +
+
+

+ This sample shows how to configure CKEditor to output valid + HTML 4.01 code. + Traditional HTML elements like <b>, + <i>, and <font> are used in place of + <strong>, <em>, and CSS styles. +

+

+ To add a CKEditor instance outputting legacy HTML 4.01 code, load the editor using a standard + JavaScript call, and define CKEditor features to use the HTML compliant elements and attributes. +

+

+ A snippet of the configuration code can be seen below; check the source of this page for + full definition: +

+
+CKEDITOR.replace( 'textarea_id', {
+	coreStyles_bold: { element: 'b' },
+	coreStyles_italic: { element: 'i' },
+
+	fontSize_style: {
+		element: 'font',
+		attributes: { 'size': '#(size)' }
+	}
+
+	...
+});
+
+
+

+ + + +

+

+ +

+
+ + + diff --git a/nstock/static/plugin_ckeditor/samples/old/index.html b/nstock/static/plugin_ckeditor/samples/old/index.html new file mode 100644 index 0000000..fc26eda --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/index.html @@ -0,0 +1,131 @@ + + + + + + CKEditor Samples + + + +

+ CKEditor Samples +

+
+ These samples are not maintained anymore. Check out the brand new samples in CKEditor SDK. +
+
+
+

+ Basic Samples +

+
+
Replace textarea elements by class name
+
Automatic replacement of all textarea elements of a given class with a CKEditor instance.
+ +
Replace textarea elements by code
+
Replacement of textarea elements with CKEditor instances by using a JavaScript call.
+ +
Create editors with jQuery
+
Creating standard and inline CKEditor instances with jQuery adapter.
+
+ +

+ Basic Customization +

+
+
User Interface color
+
Changing CKEditor User Interface color and adding a toolbar button that lets the user set the UI color.
+ +
User Interface languages
+
Changing CKEditor User Interface language and adding a drop-down list that lets the user choose the UI language.
+
+ + +

Plugins

+
+
Magicline plugin
+
Using the Magicline plugin to access difficult focus spaces.
+ +
Full page support
+
CKEditor inserted with a JavaScript call and used to edit the whole page from <html> to </html>.
+
+
+
+

+ Inline Editing +

+
+
Massive inline editor creation
+
Turn all elements with contentEditable = true attribute into inline editors.
+ +
Convert element into an inline editor by code
+
Conversion of DOM elements into inline CKEditor instances by using a JavaScript call.
+ +
Replace textarea with inline editor New!
+
A form with a textarea that is replaced by an inline editor at runtime.
+ + +
+ +

+ Advanced Samples +

+
+
Data filtering and features activation New!
+
Data filtering and automatic features activation basing on configuration.
+ +
Replace DIV elements on the fly
+
Transforming a div element into an instance of CKEditor with a mouse click.
+ +
Append editor instances
+
Appending editor instances to existing DOM elements.
+ +
Create and destroy editor instances for Ajax applications
+
Creating and destroying CKEditor instances on the fly and saving the contents entered into the editor window.
+ +
Basic usage of the API
+
Using the CKEditor JavaScript API to interact with the editor at runtime.
+ +
XHTML-compliant style
+
Configuring CKEditor to produce XHTML 1.1 compliant attributes and styles.
+ +
Read-only mode
+
Using the readOnly API to block introducing changes to the editor contents.
+ +
"Tab" key-based navigation
+
Navigating among editor instances with tab key.
+ + + +
Using the JavaScript API to customize dialog windows
+
Using the dialog windows API to customize dialog windows without changing the original editor code.
+ +
Using the "Enter" key in CKEditor
+
Configuring the behavior of Enter and Shift+Enter keys.
+ +
Output for Flash
+
Configuring CKEditor to produce HTML code that can be used with Adobe Flash.
+ +
Output HTML
+
Configuring CKEditor to produce legacy HTML 4 code.
+ +
Toolbar Configurations
+
Configuring CKEditor to display full or custom toolbar layout.
+ +
+
+
+ + + diff --git a/nstock/static/plugin_ckeditor/samples/old/inlineall.html b/nstock/static/plugin_ckeditor/samples/old/inlineall.html new file mode 100644 index 0000000..6fbd9ef --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/inlineall.html @@ -0,0 +1,314 @@ + + + + + + Massive inline editing — CKEditor Sample + + + + + + +
+

CKEditor Samples » Massive inline editing

+
+ This sample is not maintained anymore. Check out its brand new version in CKEditor SDK. +
+
+

This sample page demonstrates the inline editing feature - CKEditor instances will be created automatically from page elements with contentEditable attribute set to value true:

+
<div contenteditable="true" > ... </div>
+

Click inside of any element below to start editing.

+
+
+
+ +
+
+
+

+ Fusce vitae porttitor +

+

+ + Lorem ipsum dolor sit amet dolor. Duis blandit vestibulum faucibus a, tortor. + +

+

+ Proin nunc justo felis mollis tincidunt, risus risus pede, posuere cubilia Curae, Nullam euismod, enim. Etiam nibh ultricies dolor ac dignissim erat volutpat. Vivamus fermentum nisl nulla sem in metus. Maecenas wisi. Donec nec erat volutpat. +

+
+

+ Fusce vitae porttitor a, euismod convallis nisl, blandit risus tortor, pretium. + Vehicula vitae, imperdiet vel, ornare enim vel sodales rutrum +

+
+
+

+ Libero nunc, rhoncus ante ipsum non ipsum. Nunc eleifend pede turpis id sollicitudin fringilla. Phasellus ultrices, velit ac arcu. +

+
+

Pellentesque nunc. Donec suscipit erat. Pellentesque habitant morbi tristique ullamcorper.

+

Mauris mattis feugiat lectus nec mauris. Nullam vitae ante.

+
+
+
+
+

+ Integer condimentum sit amet +

+

+ Aenean nonummy a, mattis varius. Cras aliquet. + Praesent magna non mattis ac, rhoncus nunc, rhoncus eget, cursus pulvinar mollis.

+

Proin id nibh. Sed eu libero posuere sed, lectus. Phasellus dui gravida gravida feugiat mattis ac, felis.

+

Integer condimentum sit amet, tempor elit odio, a dolor non ante at sapien. Sed ac lectus. Nulla ligula quis eleifend mi, id leo velit pede cursus arcu id nulla ac lectus. Phasellus vestibulum. Nunc viverra enim quis diam.

+
+
+

+ Praesent wisi accumsan sit amet nibh +

+

Donec ullamcorper, risus tortor, pretium porttitor. Morbi quam quis lectus non leo.

+

Integer faucibus scelerisque. Proin faucibus at, aliquet vulputate, odio at eros. Fusce gravida, erat vitae augue. Fusce urna fringilla gravida.

+

In hac habitasse platea dictumst. Praesent wisi accumsan sit amet nibh. Maecenas orci luctus a, lacinia quam sem, posuere commodo, odio condimentum tempor, pede semper risus. Suspendisse pede. In hac habitasse platea dictumst. Nam sed laoreet sit amet erat. Integer.

+
+
+
+
+

+ CKEditor logo +

+

Quisque justo neque, mattis sed, fermentum ultrices posuere cubilia Curae, Vestibulum elit metus, quis placerat ut, lectus. Ut sagittis, nunc libero, egestas consequat lobortis velit rutrum ut, faucibus turpis. Fusce porttitor, nulla quis turpis. Nullam laoreet vel, consectetuer tellus suscipit ultricies, hendrerit wisi. Donec odio nec velit ac nunc sit amet, accumsan cursus aliquet. Vestibulum ante sit amet sagittis mi.

+

+ Nullam laoreet vel consectetuer tellus suscipit +

+
    +
  • Ut sagittis, nunc libero, egestas consequat lobortis velit rutrum ut, faucibus turpis.
  • +
  • Fusce porttitor, nulla quis turpis. Nullam laoreet vel, consectetuer tellus suscipit ultricies, hendrerit wisi.
  • +
  • Mauris eget tellus. Donec non felis. Nam eget dolor. Vestibulum enim. Donec.
  • +
+

Quisque justo neque, mattis sed, fermentum ultrices posuere cubilia Curae, Vestibulum elit metus, quis placerat ut, lectus.

+

Nullam laoreet vel, consectetuer tellus suscipit ultricies, hendrerit wisi. Ut sagittis, nunc libero, egestas consequat lobortis velit rutrum ut, faucibus turpis. Fusce porttitor, nulla quis turpis.

+

Donec odio nec velit ac nunc sit amet, accumsan cursus aliquet. Vestibulum ante sit amet sagittis mi. Sed in nonummy faucibus turpis. Mauris eget tellus. Donec non felis. Nam eget dolor. Vestibulum enim. Donec.

+
+
+
+
+ Tags of this article: +

+ inline, editing, floating, CKEditor +

+
+
+ + + diff --git a/nstock/static/plugin_ckeditor/samples/old/inlinebycode.html b/nstock/static/plugin_ckeditor/samples/old/inlinebycode.html new file mode 100644 index 0000000..390b142 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/inlinebycode.html @@ -0,0 +1,124 @@ + + + + + + Inline Editing by Code — CKEditor Sample + + + + + +

+ CKEditor Samples » Inline Editing by Code +

+
+ This sample is not maintained anymore. Check out its brand new version in CKEditor SDK. +
+
+

+ This sample shows how to create an inline editor instance of CKEditor. It is created + with a JavaScript call using the following code: +

+
+// This property tells CKEditor to not activate every element with contenteditable=true element.
+CKEDITOR.disableAutoInline = true;
+
+var editor = CKEDITOR.inline( document.getElementById( 'editable' ) );
+
+

+ Note that editable in the code above is the id + attribute of the <div> element to be converted into an inline instance. +

+
+
+

Saturn V carrying Apollo 11 Apollo 11

+ +

Apollo 11 was the spaceflight that landed the first humans, Americans Neil Armstrong and Buzz Aldrin, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.

+ +

Armstrong spent about three and a half two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5 kg) of lunar material for return to Earth. A third member of the mission, Michael Collins, piloted the command spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth.

+ +

Broadcasting and quotes

+ +

Broadcast on live TV to a world-wide audience, Armstrong stepped onto the lunar surface and described the event as:

+ +
+

One small step for [a] man, one giant leap for mankind.

+
+ +

Apollo 11 effectively ended the Space Race and fulfilled a national goal proposed in 1961 by the late U.S. President John F. Kennedy in a speech before the United States Congress:

+ +
+

[...] before this decade is out, of landing a man on the Moon and returning him safely to the Earth.

+
+ +

Technical details

+ + + + + + + + + + + + + + + + + + + + + + + +
Mission crew
PositionAstronaut
CommanderNeil A. Armstrong
Command Module PilotMichael Collins
Lunar Module PilotEdwin "Buzz" E. Aldrin, Jr.
+ +

Launched by a Saturn V rocket from Kennedy Space Center in Merritt Island, Florida on July 16, Apollo 11 was the fifth manned mission of NASA's Apollo program. The Apollo spacecraft had three parts:

+ +
    +
  1. Command Module with a cabin for the three astronauts which was the only part which landed back on Earth
  2. +
  3. Service Module which supported the Command Module with propulsion, electrical power, oxygen and water
  4. +
  5. Lunar Module for landing on the Moon.
  6. +
+ +

After being sent to the Moon by the Saturn V's upper stage, the astronauts separated the spacecraft from it and travelled for three days until they entered into lunar orbit. Armstrong and Aldrin then moved into the Lunar Module and landed in the Sea of Tranquility. They stayed a total of about 21 and a half hours on the lunar surface. After lifting off in the upper part of the Lunar Module and rejoining Collins in the Command Module, they returned to Earth and landed in the Pacific Ocean on July 24.

+ +
+

Source: Wikipedia.org

+
+ + + + + diff --git a/nstock/static/plugin_ckeditor/samples/old/inlinetextarea.html b/nstock/static/plugin_ckeditor/samples/old/inlinetextarea.html new file mode 100644 index 0000000..99ac241 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/inlinetextarea.html @@ -0,0 +1,113 @@ + + + + + + Replace Textarea with Inline Editor — CKEditor Sample + + + + + +

+ CKEditor Samples » Replace Textarea with Inline Editor +

+
+ This sample is not maintained anymore. Check out its brand new version in CKEditor SDK. +
+
+

+ You can also create an inline editor from a textarea + element. In this case the textarea will be replaced + by a div element with inline editing enabled. +

+
+// "article-body" is the name of a textarea element.
+var editor = CKEDITOR.inline( 'article-body' );
+
+
+
+

This is a sample form with some fields

+

+ Title:
+

+

+ Article Body (Textarea converted to CKEditor):
+ +

+

+ +

+
+ + + + + diff --git a/nstock/static/plugin_ckeditor/samples/old/jquery.html b/nstock/static/plugin_ckeditor/samples/old/jquery.html new file mode 100644 index 0000000..75bffa9 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/jquery.html @@ -0,0 +1,103 @@ + + + + + + jQuery Adapter — CKEditor Sample + + + + + + + + +

+ CKEditor Samples » Create Editors with jQuery +

+
+ This sample is not maintained anymore. Check out the brand new samples in CKEditor SDK. +
+
+
+

+ This sample shows how to use the jQuery adapter. + Note that you have to include both CKEditor and jQuery scripts before including the adapter. +

+ +
+<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
+<script src="/ckedit../../ckeditor.js"></script>
+<script src="/ckeditor/adapters/jquery.js"></script>
+
+ +

Then you can replace HTML elements with a CKEditor instance using the ckeditor() method.

+ +
+$( document ).ready( function() {
+	$( 'textarea#editor1' ).ckeditor();
+} );
+
+
+ +

Inline Example

+ +
+

Saturn V carrying Apollo 11Apollo 11 was the spaceflight that landed the first humans, Americans Neil Armstrong and Buzz Aldrin, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.

+

Armstrong spent about three and a half two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5 kg) of lunar material for return to Earth. A third member of the mission, Michael Collins, piloted the command spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth. +

Broadcast on live TV to a world-wide audience, Armstrong stepped onto the lunar surface and described the event as:

+

One small step for [a] man, one giant leap for mankind.

Apollo 11 effectively ended the Space Race and fulfilled a national goal proposed in 1961 by the late U.S. President John F. Kennedy in a speech before the United States Congress:

[...] before this decade is out, of landing a man on the Moon and returning him safely to the Earth.

+
+ +
+ +

Classic (iframe-based) Example

+ + + +

+ + + + + +

+
+ + + diff --git a/nstock/static/plugin_ckeditor/samples/old/magicline/magicline.html b/nstock/static/plugin_ckeditor/samples/old/magicline/magicline.html new file mode 100644 index 0000000..d769b7f --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/magicline/magicline.html @@ -0,0 +1,209 @@ + + + + + + Using Magicline plugin — CKEditor Sample + + + + + + + +

+ CKEditor Samples » Using Magicline plugin +

+
+ This sample is not maintained anymore. Check out its brand new version in CKEditor SDK. +
+
+

+ This sample shows the advantages of Magicline plugin + which is to enhance the editing process. Thanks to this plugin, + a number of difficult focus spaces which are inaccessible due to + browser issues can now be focused. +

+

+ Magicline plugin shows a red line with a handler + which, when clicked, inserts a paragraph and allows typing. To see this, + focus an editor and move your mouse above the focus space you want + to access. The plugin is enabled by default so no additional + configuration is necessary. +

+
+
+ +
+

+ This editor uses a default Magicline setup. +

+
+ + +
+
+
+ +
+

+ This editor is using a blue line. +

+
+CKEDITOR.replace( 'editor2', {
+	magicline_color: 'blue'
+});
+
+ + +
+ + + diff --git a/nstock/static/plugin_ckeditor/samples/old/readonly.html b/nstock/static/plugin_ckeditor/samples/old/readonly.html new file mode 100644 index 0000000..086e7b4 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/readonly.html @@ -0,0 +1,76 @@ + + + + + + Using the CKEditor Read-Only API — CKEditor Sample + + + + + +

+ CKEditor Samples » Using the CKEditor Read-Only API +

+
+ This sample is not maintained anymore. Check out its brand new version in CKEditor SDK. +
+
+

+ This sample shows how to use the + setReadOnly + API to put editor into the read-only state that makes it impossible for users to change the editor contents. +

+

+ For details on how to create this setup check the source code of this sample page. +

+
+
+

+ +

+

+ + +

+
+ + + diff --git a/nstock/static/plugin_ckeditor/samples/old/replacebyclass.html b/nstock/static/plugin_ckeditor/samples/old/replacebyclass.html new file mode 100644 index 0000000..e2eaa35 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/replacebyclass.html @@ -0,0 +1,60 @@ + + + + + + Replace Textareas by Class Name — CKEditor Sample + + + + +

+ CKEditor Samples » Replace Textarea Elements by Class Name +

+
+ This sample is not maintained anymore. Check out the brand new samples in CKEditor SDK. +
+
+

+ This sample shows how to automatically replace all <textarea> elements + of a given class with a CKEditor instance. +

+

+ To replace a <textarea> element, simply assign it the ckeditor + class, as in the code below: +

+
+<textarea class="ckeditor" name="editor1"></textarea>
+
+

+ Note that other <textarea> attributes (like id or name) need to be adjusted to your document. +

+
+
+

+ + +

+

+ +

+
+ + + diff --git a/nstock/static/plugin_ckeditor/samples/old/replacebycode.html b/nstock/static/plugin_ckeditor/samples/old/replacebycode.html new file mode 100644 index 0000000..a447c4e --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/replacebycode.html @@ -0,0 +1,59 @@ + + + + + + Replace Textarea by Code — CKEditor Sample + + + + +

+ CKEditor Samples » Replace Textarea Elements Using JavaScript Code +

+
+ This sample is not maintained anymore. Check out its brand new version in CKEditor SDK. +
+
+
+

+ This editor is using an <iframe> element-based editing area, provided by the Wysiwygarea plugin. +

+
+CKEDITOR.replace( 'textarea_id' )
+
+
+ + +

+ +

+
+ + + diff --git a/nstock/static/plugin_ckeditor/samples/old/sample.css b/nstock/static/plugin_ckeditor/samples/old/sample.css new file mode 100644 index 0000000..dee8855 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/sample.css @@ -0,0 +1,357 @@ +/* +Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ + +html, body, h1, h2, h3, h4, h5, h6, div, span, blockquote, p, address, form, fieldset, img, ul, ol, dl, dt, dd, li, hr, table, td, th, strong, em, sup, sub, dfn, ins, del, q, cite, var, samp, code, kbd, tt, pre +{ + line-height: 1.5; +} + +body +{ + padding: 10px 30px; +} + +input, textarea, select, option, optgroup, button, td, th +{ + font-size: 100%; +} + +pre +{ + -moz-tab-size: 4; + tab-size: 4; +} + +pre, code, kbd, samp, tt +{ + font-family: monospace,monospace; + font-size: 1em; +} + +body { + width: 960px; + margin: 0 auto; +} + +code +{ + background: #f3f3f3; + border: 1px solid #ddd; + padding: 1px 4px; + border-radius: 3px; +} + +abbr +{ + border-bottom: 1px dotted #555; + cursor: pointer; +} + +.new, .beta +{ + text-transform: uppercase; + font-size: 10px; + font-weight: bold; + padding: 1px 4px; + margin: 0 0 0 5px; + color: #fff; + float: right; + border-radius: 3px; +} + +.new +{ + background: #FF7E00; + border: 1px solid #DA8028; + text-shadow: 0 1px 0 #C97626; + + box-shadow: 0 2px 3px 0 #FFA54E inset; +} + +.beta +{ + background: #18C0DF; + border: 1px solid #19AAD8; + text-shadow: 0 1px 0 #048CAD; + font-style: italic; + + box-shadow: 0 2px 3px 0 #50D4FD inset; +} + +h1.samples +{ + color: #0782C1; + font-size: 200%; + font-weight: normal; + margin: 0; + padding: 0; +} + +h1.samples a +{ + color: #0782C1; + text-decoration: none; + border-bottom: 1px dotted #0782C1; +} + +.samples a:hover +{ + border-bottom: 1px dotted #0782C1; +} + +h2.samples +{ + color: #000000; + font-size: 130%; + margin: 15px 0 0 0; + padding: 0; +} + +p, blockquote, address, form, pre, dl, h1.samples, h2.samples +{ + margin-bottom: 15px; +} + +ul.samples +{ + margin-bottom: 15px; +} + +.clear +{ + clear: both; +} + +fieldset +{ + margin: 0; + padding: 10px; +} + +body, input, textarea +{ + color: #333333; + font-family: Arial, Helvetica, sans-serif; +} + +body +{ + font-size: 75%; +} + +a.samples +{ + color: #189DE1; + text-decoration: none; +} + +form +{ + margin: 0; + padding: 0; +} + +pre.samples +{ + background-color: #F7F7F7; + border: 1px solid #D7D7D7; + overflow: auto; + padding: 0.25em; + white-space: pre-wrap; /* CSS 2.1 */ + word-wrap: break-word; /* IE7 */ +} + +#footer +{ + clear: both; + padding-top: 10px; +} + +#footer hr +{ + margin: 10px 0 15px 0; + height: 1px; + border: solid 1px gray; + border-bottom: none; +} + +#footer p +{ + margin: 0 10px 10px 10px; + float: left; +} + +#footer #copy +{ + float: right; +} + +#outputSample +{ + width: 100%; + table-layout: fixed; +} + +#outputSample thead th +{ + color: #dddddd; + background-color: #999999; + padding: 4px; + white-space: nowrap; +} + +#outputSample tbody th +{ + vertical-align: top; + text-align: left; +} + +#outputSample pre +{ + margin: 0; + padding: 0; +} + +.description +{ + border: 1px dotted #B7B7B7; + margin-bottom: 10px; + padding: 10px 10px 0; + overflow: hidden; +} + +label +{ + display: block; + margin-bottom: 6px; +} + +/** + * CKEditor editables are automatically set with the "cke_editable" class + * plus cke_editable_(inline|themed) depending on the editor type. + */ + +/* Style a bit the inline editables. */ +.cke_editable.cke_editable_inline +{ + cursor: pointer; +} + +/* Once an editable element gets focused, the "cke_focus" class is + added to it, so we can style it differently. */ +.cke_editable.cke_editable_inline.cke_focus +{ + box-shadow: inset 0px 0px 20px 3px #ddd, inset 0 0 1px #000; + outline: none; + background: #eee; + cursor: text; +} + +/* Avoid pre-formatted overflows inline editable. */ +.cke_editable_inline pre +{ + white-space: pre-wrap; + word-wrap: break-word; +} + +/** + * Samples index styles. + */ + +.twoColumns, +.twoColumnsLeft, +.twoColumnsRight +{ + overflow: hidden; +} + +.twoColumnsLeft, +.twoColumnsRight +{ + width: 45%; +} + +.twoColumnsLeft +{ + float: left; +} + +.twoColumnsRight +{ + float: right; +} + +dl.samples +{ + padding: 0 0 0 40px; +} +dl.samples > dt +{ + display: list-item; + list-style-type: disc; + list-style-position: outside; + margin: 0 0 3px; +} +dl.samples > dd +{ + margin: 0 0 3px; +} +.warning +{ + color: #ff0000; + background-color: #FFCCBA; + border: 2px dotted #ff0000; + padding: 15px 10px; + margin: 10px 0; +} + +.warning.deprecated { + font-size: 1.3em; +} + +/* Used on inline samples */ + +blockquote +{ + font-style: italic; + font-family: Georgia, Times, "Times New Roman", serif; + padding: 2px 0; + border-style: solid; + border-color: #ccc; + border-width: 0; +} + +.cke_contents_ltr blockquote +{ + padding-left: 20px; + padding-right: 8px; + border-left-width: 5px; +} + +.cke_contents_rtl blockquote +{ + padding-left: 8px; + padding-right: 20px; + border-right-width: 5px; +} + +img.right { + border: 1px solid #ccc; + float: right; + margin-left: 15px; + padding: 5px; +} + +img.left { + border: 1px solid #ccc; + float: left; + margin-right: 15px; + padding: 5px; +} + +.marker +{ + background-color: Yellow; +} diff --git a/nstock/static/plugin_ckeditor/samples/old/sample.js b/nstock/static/plugin_ckeditor/samples/old/sample.js new file mode 100644 index 0000000..ebc077f --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/sample.js @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or http://ckeditor.com/license + */ + +// Tool scripts for the sample pages. +// This file can be ignored and is not required to make use of CKEditor. + +( function() { + CKEDITOR.on( 'instanceReady', function( ev ) { + // Check for sample compliance. + var editor = ev.editor, + meta = CKEDITOR.document.$.getElementsByName( 'ckeditor-sample-required-plugins' ), + requires = meta.length ? CKEDITOR.dom.element.get( meta[ 0 ] ).getAttribute( 'content' ).split( ',' ) : [], + missing = [], + i; + + if ( requires.length ) { + for ( i = 0; i < requires.length; i++ ) { + if ( !editor.plugins[ requires[ i ] ] ) + missing.push( '' + requires[ i ] + '' ); + } + + if ( missing.length ) { + var warn = CKEDITOR.dom.element.createFromHtml( + '
' + + 'To fully experience this demo, the ' + missing.join( ', ' ) + ' plugin' + ( missing.length > 1 ? 's are' : ' is' ) + ' required.' + + '
' + ); + warn.insertBefore( editor.container ); + } + } + + // Set icons. + var doc = new CKEDITOR.dom.document( document ), + icons = doc.find( '.button_icon' ); + + for ( i = 0; i < icons.count(); i++ ) { + var icon = icons.getItem( i ), + name = icon.getAttribute( 'data-icon' ), + style = CKEDITOR.skin.getIconStyle( name, ( CKEDITOR.lang.dir == 'rtl' ) ); + + icon.addClass( 'cke_button_icon' ); + icon.addClass( 'cke_button__' + name + '_icon' ); + icon.setAttribute( 'style', style ); + icon.setStyle( 'float', 'none' ); + + } + } ); +} )(); diff --git a/nstock/static/plugin_ckeditor/samples/old/sample_posteddata.php b/nstock/static/plugin_ckeditor/samples/old/sample_posteddata.php new file mode 100644 index 0000000..1146c91 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/sample_posteddata.php @@ -0,0 +1,16 @@ +
+
+-------------------------------------------------------------------------------------------
+  CKEditor - Posted Data
+
+  We are sorry, but your Web server does not support the PHP language used in this script.
+
+  Please note that CKEditor can be used with any other server-side language than just PHP.
+  To save the content created with CKEditor you need to read the POST data on the server
+  side and write it to a file or the database.
+
+  Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+  For licensing, see LICENSE.md or http://ckeditor.com/license
+-------------------------------------------------------------------------------------------
+
+
*/ include "assets/posteddata.php"; ?> diff --git a/nstock/static/plugin_ckeditor/samples/old/tabindex.html b/nstock/static/plugin_ckeditor/samples/old/tabindex.html new file mode 100644 index 0000000..22ff5be --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/tabindex.html @@ -0,0 +1,78 @@ + + + + + + TAB Key-Based Navigation — CKEditor Sample + + + + + + +

+ CKEditor Samples » TAB Key-Based Navigation +

+
+ This sample is not maintained anymore. Check out its brand new version in CKEditor SDK. +
+
+

+ This sample shows how tab key navigation among editor instances is + affected by the tabIndex attribute from + the original page element. Use TAB key to move between the editors. +

+
+

+ +

+
+

+ +

+

+ +

+ + + diff --git a/nstock/static/plugin_ckeditor/samples/old/toolbar/toolbar.html b/nstock/static/plugin_ckeditor/samples/old/toolbar/toolbar.html new file mode 100644 index 0000000..2b8df46 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/toolbar/toolbar.html @@ -0,0 +1,235 @@ + + + + + + Toolbar Configuration — CKEditor Sample + + + + + + + +

+ CKEditor Samples » Toolbar Configuration +

+
+ This sample is not maintained anymore. Check out the brand new CKEditor Toolbar Configurator. +
+
+

+ This sample page demonstrates editor with loaded full toolbar (all registered buttons) and, if + current editor's configuration modifies default settings, also editor with modified toolbar. +

+ +

Since CKEditor 4 there are two ways to configure toolbar buttons.

+ +

By config.toolbar

+ +

+ You can explicitly define which buttons are displayed in which groups and in which order. + This is the more precise setting, but less flexible. If newly added plugin adds its + own button you'll have to add it manually to your config.toolbar setting as well. +

+ +

To add a CKEditor instance with custom toolbar setting, insert the following JavaScript call to your code:

+ +
+CKEDITOR.replace( 'textarea_id', {
+	toolbar: [
+		{ name: 'document', items: [ 'Source', '-', 'NewPage', 'Preview', '-', 'Templates' ] },	// Defines toolbar group with name (used to create voice label) and items in 3 subgroups.
+		[ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ],			// Defines toolbar group without name.
+		'/',																					// Line break - next group will be placed in new line.
+		{ name: 'basicstyles', items: [ 'Bold', 'Italic' ] }
+	]
+});
+ +

By config.toolbarGroups

+ +

+ You can define which groups of buttons (like e.g. basicstyles, clipboard + and forms) are displayed and in which order. Registered buttons are associated + with toolbar groups by toolbar property in their definition. + This setting's advantage is that you don't have to modify toolbar configuration + when adding/removing plugins which register their own buttons. +

+ +

To add a CKEditor instance with custom toolbar groups setting, insert the following JavaScript call to your code:

+ +
+CKEDITOR.replace( 'textarea_id', {
+	toolbarGroups: [
+		{ name: 'document',	   groups: [ 'mode', 'document' ] },			// Displays document group with its two subgroups.
+ 		{ name: 'clipboard',   groups: [ 'clipboard', 'undo' ] },			// Group's name will be used to create voice label.
+ 		'/',																// Line break - next group will be placed in new line.
+ 		{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
+ 		{ name: 'links' }
+	]
+
+	// NOTE: Remember to leave 'toolbar' property with the default value (null).
+});
+
+ + + +
+

Full toolbar configuration

+

Below you can see editor with full toolbar, generated automatically by the editor.

+

+ Note: To create editor instance with full toolbar you don't have to set anything. + Just leave toolbar and toolbarGroups with the default, null values. +

+ +

+	
+ + + + + + diff --git a/nstock/static/plugin_ckeditor/samples/old/uicolor.html b/nstock/static/plugin_ckeditor/samples/old/uicolor.html new file mode 100644 index 0000000..8acc91f --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/uicolor.html @@ -0,0 +1,72 @@ + + + + + + UI Color Picker — CKEditor Sample + + + + +

+ CKEditor Samples » UI Color +

+
+ This sample is not maintained anymore. Check out its brand new version in CKEditor SDK. +
+
+

+ This sample shows how to automatically replace <textarea> elements + with a CKEditor instance with an option to change the color of its user interface.
+ Note:The UI skin color feature depends on the CKEditor skin + compatibility. The Moono and Kama skins are examples of skins that work with it. +

+
+
+

+ This editor instance has a UI color value defined in configuration to change the skin color, + To specify the color of the user interface, set the uiColor property: +

+
+CKEDITOR.replace( 'textarea_id', {
+	uiColor: '#14B8C4'
+});
+

+ Note that textarea_id in the code above is the id attribute of + the <textarea> element to be replaced. +

+

+ + +

+

+ +

+
+ + + diff --git a/nstock/static/plugin_ckeditor/samples/old/uilanguages.html b/nstock/static/plugin_ckeditor/samples/old/uilanguages.html new file mode 100644 index 0000000..b1bb694 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/uilanguages.html @@ -0,0 +1,122 @@ + + + + + + User Interface Globalization — CKEditor Sample + + + + + +

+ CKEditor Samples » User Interface Languages +

+
+ This sample is not maintained anymore. Check out its brand new version in CKEditor SDK. +
+
+

+ This sample shows how to automatically replace <textarea> elements + with a CKEditor instance with an option to change the language of its user interface. +

+

+ It pulls the language list from CKEditor _languages.js file that contains the list of supported languages and creates + a drop-down list that lets the user change the UI language. +

+

+ By default, CKEditor automatically localizes the editor to the language of the user. + The UI language can be controlled with two configuration options: + language and + + defaultLanguage. The defaultLanguage setting specifies the + default CKEditor language to be used when a localization suitable for user's settings is not available. +

+

+ To specify the user interface language that will be used no matter what language is + specified in user's browser or operating system, set the language property: +

+
+CKEDITOR.replace( 'textarea_id', {
+	// Load the German interface.
+	language: 'de'
+});
+

+ Note that textarea_id in the code above is the id attribute of + the <textarea> element to be replaced. +

+
+
+

+ Available languages ( languages!):
+ +
+ + (You may see strange characters if your system does not support the selected language) + +

+

+ + +

+
+ + + diff --git a/nstock/static/plugin_ckeditor/samples/old/wysiwygarea/fullpage.html b/nstock/static/plugin_ckeditor/samples/old/wysiwygarea/fullpage.html new file mode 100644 index 0000000..8d58389 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/wysiwygarea/fullpage.html @@ -0,0 +1,80 @@ + + + + + + Full Page Editing — CKEditor Sample + + + + + + + + + +

+ CKEditor Samples » Full Page Editing +

+
+ This sample is not maintained anymore. Check out its brand new version in CKEditor SDK. +
+
+

+ This sample shows how to configure CKEditor to edit entire HTML pages, from the + <html> tag to the </html> tag. +

+

+ The CKEditor instance below is inserted with a JavaScript call using the following code: +

+
+CKEDITOR.replace( 'textarea_id', {
+	fullPage: true,
+	allowedContent: true
+});
+
+

+ Note that textarea_id in the code above is the id attribute of + the <textarea> element to be replaced. +

+

+ The allowedContent in the code above is set to true to disable content filtering. + Setting this option is not obligatory, but in full page mode there is a strong chance that one may want be able to freely enter any HTML content in source mode without any limitations. +

+
+
+ + + +

+ +

+
+ + + diff --git a/nstock/static/plugin_ckeditor/samples/old/xhtmlstyle.html b/nstock/static/plugin_ckeditor/samples/old/xhtmlstyle.html new file mode 100644 index 0000000..0732848 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/old/xhtmlstyle.html @@ -0,0 +1,234 @@ + + + + + + XHTML Compliant Output — CKEditor Sample + + + + + + +

+ CKEditor Samples » Producing XHTML Compliant Output +

+
+ This sample is not maintained anymore. Check out its brand new version in CKEditor SDK. +
+
+

+ This sample shows how to configure CKEditor to output valid + XHTML 1.1 code. + Deprecated elements (<font>, <u>) or attributes + (size, face) will be replaced with XHTML compliant code. +

+

+ To add a CKEditor instance outputting valid XHTML code, load the editor using a standard + JavaScript call and define CKEditor features to use the XHTML compliant elements and styles. +

+

+ A snippet of the configuration code can be seen below; check the source of this page for + full definition: +

+
+CKEDITOR.replace( 'textarea_id', {
+	contentsCss: 'assets/outputxhtml.css',
+
+	coreStyles_bold: {
+		element: 'span',
+		attributes: { 'class': 'Bold' }
+	},
+	coreStyles_italic: {
+		element: 'span',
+		attributes: { 'class': 'Italic' }
+	},
+
+	...
+});
+
+
+

+ + + +

+

+ +

+
+ + + diff --git a/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/css/fontello.css b/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/css/fontello.css new file mode 100644 index 0000000..d983707 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/css/fontello.css @@ -0,0 +1,55 @@ +@font-face { + font-family: 'fontello'; + src: url('../font/fontello.eot?89024372'); + src: url('../font/fontello.eot?89024372#iefix') format('embedded-opentype'), + url('../font/fontello.woff?89024372') format('woff'), + url('../font/fontello.ttf?89024372') format('truetype'), + url('../font/fontello.svg?89024372#fontello') format('svg'); + font-weight: normal; + font-style: normal; +} +/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */ +/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */ +/* +@media screen and (-webkit-min-device-pixel-ratio:0) { + @font-face { + font-family: 'fontello'; + src: url('../font/fontello.svg?89024372#fontello') format('svg'); + } +} +*/ + + [class^="icon-"]:before, [class*=" icon-"]:before { + font-family: "fontello"; + font-style: normal; + font-weight: normal; + speak: none; + + display: inline-block; + text-decoration: inherit; + width: 1em; + margin-right: .2em; + text-align: center; + /* opacity: .8; */ + + /* For safety - reset parent styles, that can break glyph codes*/ + font-variant: normal; + text-transform: none; + + /* fix buttons height, for twitter bootstrap */ + line-height: 1em; + + /* Animation center compensation - margins should be symmetric */ + /* remove if not needed */ + margin-left: .2em; + + /* you can be more comfortable with increased icons size */ + /* font-size: 120%; */ + + /* Uncomment for 3D effect */ + /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ +} + +.icon-trash:before { content: '\e802'; } /* '' */ +.icon-down-big:before { content: '\e800'; } /* '' */ +.icon-up-big:before { content: '\e801'; } /* '' */ diff --git a/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/LICENSE.txt b/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/LICENSE.txt new file mode 100644 index 0000000..4a73f6c --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/LICENSE.txt @@ -0,0 +1,10 @@ +Font license info + + +## Font Awesome + + Copyright (C) 2012 by Dave Gandy + + Author: Dave Gandy + License: SIL () + Homepage: http://fortawesome.github.com/Font-Awesome/ diff --git a/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/config.json b/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/config.json new file mode 100644 index 0000000..94809d7 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/config.json @@ -0,0 +1,28 @@ +{ + "name": "", + "css_prefix_text": "icon-", + "css_use_suffix": false, + "hinting": true, + "units_per_em": 1000, + "ascent": 850, + "glyphs": [ + { + "uid": "f48ae54adfb27d8ada53d0fd9e34ee10", + "css": "trash-empty", + "code": 59392, + "src": "fontawesome" + }, + { + "uid": "1c4068ed75209e21af36017df8871802", + "css": "down-big", + "code": 59393, + "src": "fontawesome" + }, + { + "uid": "95376bf082bfec6ce06ea1cda7bd7ead", + "css": "up-big", + "code": 59394, + "src": "fontawesome" + } + ] +} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/fontello.eot b/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/fontello.eot new file mode 100644 index 0000000000000000000000000000000000000000..2732fad4b99afccc74c27aa672ccd40f913b80ca GIT binary patch literal 4988 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 Kt8V<(q5l8`HZgPn literal 0 HcmV?d00001 diff --git a/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/fontello.svg b/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/fontello.svg new file mode 100644 index 0000000..33d14ac --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/fontello.svg @@ -0,0 +1,14 @@ + + + +Copyright (C) 2014 by original authors @ fontello.com + + + + + + + + + + \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/fontello.ttf b/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/fontello.ttf new file mode 100644 index 0000000000000000000000000000000000000000..fbcbf06af5fe25519880166886f3af289acfd960 GIT binary patch literal 4820 zcmd^CTWlNG5uLlsm#CLzk+c)a@}*alWO7N#vLq{(?8tmbah%k$*OY% z_ATvKu-vOj@mD$}GC06gp=A4p<(R2=va9=8AAKd9Q?2l^dUxRbiZBS%{`5+bDwY>*~s3H8xt zNYnh32@V|zxZ2|);1!+|J)(Q?Q87GlT(k`ipE*4c3bvhLEu`NG?tVXX7N217B; zZhv%84Dsxr_B5EGosjA4`I*lz-r4;%8^s0wehJ>4*V;b)xGCWG2ei@!w-D|bMEvyQ zWG0o=+U-o94t9vnz|(#{gnWAOZk>GX?6a+7|E5MAcO20NnNO-U`I~Rnx&u3c3y06P z{a}uBM}WV#r{6g^;SR&ap7b9%Z<}MCpnD<>%yC`l^V)5ok)#Bz!FH|T4TpJ{{<80L z$eF?Od^F_P(ExPL!8+_22fKiuaIl*i>8gW0us`cyKgH2koCSf=PH*x}=4ya;gMQ** zL5D=EgEeXq#~rN0o^Y@W_?&~?6cSH5*aLgf!G4+*TMlldZt;io`o`_e<;A74>`kAP z1O2B4<=kz#4%70QwIZ#X<)!t_Ejcb1*4N6Vm6i2maecLpr%Q`BSFFvtT9>n>&8_A2 zHF+x8UpGyb)=HaJxirt-x1L`dD3=%H!shy_oN)Zgjm`BNrD8d`R4#9v?dz-0$E|)X_J;wswFC8lX_u22{}OhbczOn=D?6()>zBfM2l8nvFIjdEZHMl(8uvEKwE>g z1jY(*l8X4QK46~)V-fRL;AQiH(fhs3g1t#w$dbKFI!TCSfiRm8zdXKQrE&%E<*; zsaT*)862vt z+um$esVV(buG-X;M);KS$McHPN{gnd4gB%rqeKWr(4$kisz7D16{!m9im(l_h=FN! z9IlP?6fJ6x=CO=PBtKa|{SHcoUxRi7OHV60zaxaO%iV%p+}W!+QcXrm7U1_6&CLS$ zX)0AIRGZy#wHgnfz~Wm$Y>6k-A+su2wwYCpp_!EqBrWTXILYKtUQ&w--sPf zsNVg0ijeAwDG}_q%Xjj#%l-UN%#=fRHgS`bUh8k1l6pLb6#BV+Wn|79Bh{D)A}bSX zKn8VI0S#o0Bviso9vMrh+S zU;t72O~gj;;h#-Wo@~5SNg7g)Rp9H?!LUr$d?*)R6xp~`1wKdPS8{J_QkUVkwQl|4 ze2P!D4>ttjA)+yX#!jP4af&EjyQZ{sVct-B+M37V)zVfNxRA$50L?;RT!+SlH4--9 zX9C$n*uLPR<_ZyTAwWS*;>wLZb@N=zvp|X3-tood7d9gK1CQ9f0bY+p40pG)9%Bs4 zJZ+nm4<|&*2?KSDqX`mf&|W?=)12zi)m&1J;hN^W93z~4rhHLo7cqoJ%NC7V#cMa3 z;ZzklCDf1;F)+x>+-iiHJhCuRqK zNCgA!NoC@IjDLy!0`373XjchvQl{#INONtnsGgj_HD0eq1{VWPOd7?@nma^e022U$ z!KAq(Y|CQ+w&fyo&SB_r<}kR#90pG?hryG~c?95V%wceuISi(l!{7>YMggXo!(fIv z46ZVV!BfmR4=~Fd2480mgB)`h|4`kalJ zx?&@yu9|V>D=EEe>K0$$3EaGw-lgA9*g(a<1ypGw3sD`2PZ{_@4oucg5a!mFtzN8-MH2e*ji^AMF4D literal 0 HcmV?d00001 diff --git a/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/fontello.woff b/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/font/fontello.woff new file mode 100644 index 0000000000000000000000000000000000000000..e1d56472f88b35b037149608094afc4bbcf97b50 GIT binary patch literal 2904 zcmY*bc{r5a8-8EQOm-oAc3G0_yAoq$ER)?>YK*a^u}p($QzBc!h>|6VlHJ&{lqiN| z%aSF#WGNzFi12%-@B8QXT-SY_=f1D|InN*GT<1JtXe1H<0Vvp<0Z#hLGx#s3=l>sQ zyOU}F03slj4oAb8vm>4ak03~kg}5HHqWXA+UV4U-B%r(%()b{V!psj+y@PxRkTwDU zOuqqug%Zz7*7xza4AsI0A$j71taaKCOI3R)GL5BLW=s;ZJ zFE&`^13U;`kmd~a4TJi2cV!EU1_fRwK_z{V=OhGU*^^NtK}0X8mJOnSBONKZ83*Jn zPb_}bGpo6|v$@5-tvV(mA{TC~ehRCC$K$YA9M;RbnU$g6%}!ACyvi#qj&mocjk~R@ zdzy>So9R6WEUU3;)Azt)y>DTKU`QBu5cpHD&MD0p6F?|{p8?KX(8 zP%$221f@mZ#lit^5LN*I^jafEBs;Qe{6PD*3cy{>I780Lb{GvEaO6ufzz6Z@;h#L= z93Iy>_pLKZK~Tj{u`N{csOX_mrla}nq%Ya+r@r|o8aFzM|E^xWVJK5gDy>y|(A#9@ z>NBFZfE1NhydfOxKbV{Hkg>4D@BwPe+-*4IWKtSCEZDu42W_7DB3lM^apLN3_FZpC|0Id}3ba2oZ!x;lpF*vvG5Bar{2q;Iowe1FOhN(z|mv2b4#GL zW)?%C&@Z#L(S=@+=e=8Mk%5C+%vHum>iXA$RaXM!iYtTibKq)$p`mlxF(w60F*iT% z2w2W^nI+BQ!cQ6RoVyqD=|RAX+@wNy4~ZHI_}FbJ{LSmt;CN>g_&Pqq-U0 z`x{m0VaPJJn719yx@RqOT-3)V@7LL^ZqMP6(s7@27B!6m`fBASX;P~{*x1U{7ot2K z^Rqczc>H^kS>pf}>+{EGQsa)r?gIr>bztUG%SPXL))gN6XYN{Ud@Jz^&;5EcaM7Db z?YjCOtECJ#?21mVCueTDe|dg`tKM(QEMSZ)Inz;6n{c$=@1%rwDKcQpAx|%q zNf_oQV0+|DpGM`5$GBtWFQZQh8rS`>Kb3JEJIe^O?3$WR@wS^Gvutpp-_wFdDS^yc zOG`R<5Qe&T^AN~Bt{FMt^RNeKa_7$4)OSiBqESOImM92>*$*T47CFaWc~7WCDmWAs>?WY8<)1fgFn;-o zRRS;V;lmo=gmsS$puhM}lLB>oCm0RwuWOuV*&?RP zl+-cGw4EY)ySzg(_PylUj(U!@bkW;#U%0PZakgk9%dGMH58$J~PS4X!qeAGt9n--h z%dAFr4V*V4O!49_h-C`p8}G86n9{FnchBy%NZH=hAbJ|_#lbE1Mj=9t9rU3+d?c+< z&iQyFk#nEv;d1GD`pXOg;K2dFMb5fI=?&yL!`D6)#vl3+%ssAd!Rx_ty1`$dU)WiK z;u66_jf;yTtL7g&=8(DgI!rhCpWoydUp zv>qd;GHU93_*N~CLfDW{%w!18* zjZ|F1B(PiZMT3z+$modrryp=GDX%#!&QQOJGUd%26v zGg!h{b2m-roYdhocL&=0E6-ToBn%0Ayl~wC@nx8@;@5mHP`euW(pSyf^RC_T@9GKm zeyb(m7b)2$h7rS@BQe&bK9(sBKQlK7>&13qX0wAksZ+tXw%u_Jjnv{{&c(C(y*iEDkOA)FBb({PRfl*Nh-4OzMhPaJDL>bo_~y<<^yjv?u@Rc878 z#MD10UTPJ#{gBiB?7iJ{NguPn8lAoO%2L4O;6`MP=2 zvPDA8zBJnU(dCdwyjg6U*Rx>#mo?XyiGg~fo^6_~aZ2xa<+AnxhI}6sbmV{kU@R7x z#aWeClEX90*~hz1-jZTpa1SR$^~JCX3GN5t1H8Y&h`NI5Mo)oLST^K;HUECce{M(2 z9Nhfs4SRBk6$=7!UCfD$ivYm*1OYN$vsY$y_WS7iOLBnMh*&(v31}`M9h&R?S-!uDxe~I&L z^j+IqI0y$OE<{=Uy$85kfHLg+tveABlsL*G${lIhHwI{J1@-LGY5+lfz$eS^qoM); zJ^}Djz@iT5uyv+_U?Qge5HyB*N>qT-hzdsOph_lr7E@b9B`X75kqQG5R2eYV#<{{M h)|m=pL{N{>SsfEVryv3YMICr>r-JDom6<*r{|}rP@vZ;> literal 0 HcmV?d00001 diff --git a/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/index.html b/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/index.html new file mode 100644 index 0000000..cf3d043 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/index.html @@ -0,0 +1,446 @@ + + + + + + + + Toolbar Configurator + + + + + + + + + + + + +
+
+

+ CKEditor Logo +

+ +
+
+ +
+
+
+
+
+

+ Toolbar Configurator + Help +

+ +
+
+ Select configurator type + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ +
+
+
+

What Am I Doing Here?

+ +
+
+
+

Arrange toolbar groups, toggle button visibility according to your needs and get your toolbar configuration.

+

You can replace the content of the config.js file with the generated configuration. If you already set some configuration options you will need to merge both configurations.

+
+
+

Read more about different ways of setting configuration and do not forget about clearing browser cache.

+

Arranging toolbar groups is the recommended way of configuring the toolbar, but if you need more freedom you can use the advanced configurator.

+
+
+ +
+ +

+ +

+
+
+
+
+ +
+

+ CKEditor – The text editor for the Internet – http://ckeditor.com +

+

+ Copyright © 2003-2016, CKSource – Frederico Knabben. All rights reserved. +

+
+ + + + + + + + + + + + + + diff --git a/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/js/abstracttoolbarmodifier.js b/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/js/abstracttoolbarmodifier.js new file mode 100644 index 0000000..65f0b87 --- /dev/null +++ b/nstock/static/plugin_ckeditor/samples/toolbarconfigurator/js/abstracttoolbarmodifier.js @@ -0,0 +1,13 @@ +"function"!=typeof Object.create&&function(){var a=function(){};Object.create=function(b){if(1.cke_dialog_ui_labeled_label,.cke_dialog_ui_hbox_first>.cke_dialog_ui_html,.cke_dialog_ui_hbox_last>.cke_dialog_ui_labeled_label,.cke_dialog_ui_hbox_last>.cke_dialog_ui_html{line-height:30px}.cke_ltr .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_ui_hbox_child{padding-right:10px}.cke_rtl .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_ui_hbox_child{padding-left:10px}.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-right:5px}.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-left:5px;padding-right:0}.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_textarea,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_file{border:1px solid}.cke_dialog_ui_text{margin-bottom:7px}.cke_dialog_ui_select{height:auto!important;margin-bottom:7px}textarea.cke_dialog_ui_input_textarea{overflow:auto;resize:none}a.cke_dialog_ui_button{display:inline-block;*display:inline;*zoom:1;padding:3px 0;margin:0;text-align:center;color:#333;vertical-align:middle;cursor:pointer;border:1px solid #ddd;border-radius:4px;background:#fff}a.cke_dialog_ui_button:hover,a.cke_dialog_ui_button:focus,a.cke_dialog_ui_button:active{border-color:#aaa;background-color:#eee;text-decoration:none}.cke_dialog_page_contents a.cke_dialog_ui_button{height:22px;line-height:22px;background-color:#f4f4f4}.cke_dialog_page_contents a.cke_dialog_ui_button:hover,.cke_dialog_page_contents a.cke_dialog_ui_button:focus,.cke_dialog_page_contents a.cke_dialog_ui_button:active{background-color:#eee}span.cke_dialog_ui_button{padding:0 12px}.cke_hc a.cke_dialog_ui_button:hover,.cke_hc a.cke_dialog_ui_button:focus,.cke_hc a.cke_dialog_ui_button:active{border:3px solid;padding-top:1px;padding-bottom:1px}.cke_hc a.cke_dialog_ui_button:hover span,.cke_hc a.cke_dialog_ui_button:focus span,.cke_hc a.cke_dialog_ui_button:active span{padding-left:10px;padding-right:10px}.cke_dialog_footer_buttons a.cke_dialog_ui_button span{color:inherit;font-size:12px;line-height:20px}a.cke_dialog_ui_button_ok{color:#fff;border-color:#2274c9;background:#3f8edf}a.cke_dialog_ui_button_ok:hover,a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:active{border-color:#1e68b4;background:#2981db}a.cke_dialog_ui_button_cancel{background-color:#fff}a.cke_dialog_ui_button_cancel:focus{outline:0}span.cke_dialog_ui_button{cursor:pointer}.cke_dialog_footer_buttons{display:inline-table;margin:10px;width:auto;position:relative;vertical-align:middle}div.cke_dialog_ui_input_select{display:table}select.cke_dialog_ui_input_select{height:30px;line-height:30px;background-color:#fff;padding:4px 10px;border:1px solid #ddd;outline:0;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.cke_dialog_ui_input_file{width:100%;height:30px}.cke_hc .cke_dialog_ui_labeled_content input:focus,.cke_hc .cke_dialog_ui_labeled_content select:focus,.cke_hc .cke_dialog_ui_labeled_content textarea:focus{outline:1px dotted}.cke_dialog .cke_dark_background{background-color:#eee}.cke_dialog .cke_light_background{background-color:#eee}.cke_dialog .cke_centered{text-align:center}.cke_dialog a.cke_btn_reset{float:right;background:url(images/refresh.png) top left no-repeat;width:16px;height:16px;border:1px none;font-size:1px}.cke_dialog a.cke_btn_locked,.cke_dialog a.cke_btn_unlocked{float:left;width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.cke_dialog a.cke_btn_locked{background-image:url(images/lock.png)}.cke_dialog a.cke_btn_locked .cke_icon{display:none}.cke_dialog a.cke_btn_unlocked{background-image:url(images/lock-open.png)}.cke_dialog .cke_btn_over{border:outset 1px;cursor:pointer}.cke_hidpi .cke_dialog a.cke_btn_reset{background-size:16px;background-image:url(images/hidpi/refresh.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked,.cke_hidpi .cke_dialog a.cke_btn_locked{background-size:16px}.cke_hidpi .cke_dialog a.cke_btn_locked{background-image:url(images/hidpi/lock.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-image:url(images/hidpi/lock-open.png)}.cke_rtl .cke_dialog a.cke_btn_reset{float:left}.cke_rtl .cke_dialog a.cke_btn_locked,.cke_rtl .cke_dialog a.cke_btn_unlocked{float:right}.cke_dialog .ImagePreviewBox,.cke_dialog .FlashPreviewBox{border:1px solid #aaa;border-radius:4px;padding:6px 10px;margin-top:5px;background-color:white}.cke_dialog .ImagePreviewBox{overflow:scroll;height:205px;width:300px}.cke_dialog .ImagePreviewBox table td{white-space:normal}.cke_dialog .FlashPreviewBox{white-space:normal;overflow:auto;height:160px;width:390px}.cke_dialog .ImagePreviewLoader{position:absolute;white-space:normal;overflow:hidden;height:160px;width:230px;margin:2px;padding:2px;opacity:.9;filter:alpha(opacity=90);background-color:#e4e4e4}.cke_dialog .cke_pastetext{width:346px;height:170px}.cke_dialog .cke_pastetext textarea{width:340px;height:170px;resize:none}.cke_dialog iframe.cke_pasteframe{width:346px;height:130px;background-color:white;border:1px solid #aeb3b9;border-radius:4px}.cke_dialog .cke_hand{cursor:pointer}.cke_disabled{color:#a0a0a0}.cke_dialog_body .cke_label{display:none}.cke_dialog_body label{display:inline-block;margin-bottom:3px;cursor:default}.cke_dialog_body label.cke_required{font-weight:bold}.cke_dialog_ui_html{line-height:150%}a.cke_smile{overflow:hidden;display:block;text-align:center;padding:.3em 0}a.cke_smile img{vertical-align:middle}a.cke_specialchar{cursor:inherit;display:block;height:1.25em;padding:.2em .3em;text-align:center}a.cke_smile,a.cke_specialchar{background-color:#eee;border:1px solid transparent;vertical-align:top}a.cke_smile:hover,a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:hover,a.cke_specialchar:focus,a.cke_specialchar:active{background:#fff;outline:0}a.cke_smile:hover,a.cke_specialchar:hover{border-color:#aaa}a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:focus,a.cke_specialchar:active{border-color:#428bca}.cke_dialog_contents a.colorChooser{display:block;margin-top:6px;margin-left:10px;width:80px}.cke_rtl .cke_dialog_contents a.colorChooser{margin-right:10px}.cke_dialog_ui_checkbox{display:inline-block;margin-bottom:5px}.cke_dialog_ui_checkbox_input:focus,.cke_dialog_ui_radio_input:focus,.cke_btn_over{outline:1px dotted #696969}.cke_iframe_shim{display:block;position:absolute;top:0;left:0;z-index:-1;filter:alpha(opacity=0);width:100%;height:100%} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_ie.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_ie.css new file mode 100644 index 0000000..f945588 --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_ie.css @@ -0,0 +1 @@ +input.cke_dialog_ui_input_text,input.cke_dialog_ui_input_password,textarea.cke_dialog_ui_input_textarea{background-color:#fff;outline:0;width:100%;*width:95%;height:30px;padding:4px 10px;border:1px solid #ddd;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}input.cke_dialog_ui_input_text:focus,input.cke_dialog_ui_input_password:focus,textarea.cke_dialog_ui_input_textarea:focus{border-color:#66afe9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.cke_dialog{visibility:visible}.cke_dialog_body{z-index:1;background:#eee;border:1px solid #ddd;border-radius:4px}.cke_browser_gecko19 .cke_dialog_body{position:relative}.cke_dialog strong{font-weight:bold}.cke_dialog_title{font-weight:bold;font-size:13px;cursor:move;position:relative;color:#333;border-bottom:1px solid #ddd;padding:10px 12px;background:#eee}.cke_dialog_contents{background-color:#fff;overflow:auto;padding:15px 10px 5px 10px;margin-top:35px;border-top:1px solid #ddd;border-radius:0 0 4px 4px}.cke_dialog_contents_body{overflow:auto;padding:17px 10px 5px 10px;margin-top:22px}.cke_dialog_footer{text-align:right;position:relative;border-radius:0 0 4px 4px;border-top:1px solid #ddd;background:#eee}.cke_rtl .cke_dialog_footer{text-align:left}.cke_hc .cke_dialog_footer{outline:0;border-top:1px solid #fff}.cke_dialog .cke_resizer{margin-top:28px}.cke_dialog .cke_resizer_rtl{margin-left:5px}.cke_dialog .cke_resizer_ltr{margin-right:5px}.cke_dialog_tabs{height:24px;display:inline-block;margin:10px 0 0;position:absolute;z-index:2;left:10px}.cke_rtl .cke_dialog_tabs{right:10px}a.cke_dialog_tab{height:16px;padding:4px 8px;margin-right:3px;display:inline-block;cursor:pointer;line-height:16px;outline:0;color:#555;border:1px solid #ddd;border-radius:3px 3px 0 0;background:#f3f3f3}.cke_rtl a.cke_dialog_tab{margin-right:0;margin-left:3px}a.cke_dialog_tab:hover{background:#ddd;text-decoration:none}a.cke_dialog_tab_selected{background:#fff;color:#333;border-bottom-color:#fff;cursor:default;filter:none}a.cke_dialog_tab_selected:hover{background:#fff}.cke_hc a.cke_dialog_tab:hover,.cke_hc a.cke_dialog_tab_selected{border:3px solid;padding:2px 6px}a.cke_dialog_tab_disabled{color:#bababa;cursor:default}.cke_dialog_tabs .cke_dialog_ui_input_select{top:-7px!important}.cke_single_page .cke_dialog_tabs{display:none}.cke_single_page .cke_dialog_contents{padding-top:5px;margin-top:0;border-top:0}.cke_dialog_close_button{background-image:url(images/close.png);background-repeat:no-repeat;background-position:0 0;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:9px;z-index:5}.cke_hidpi .cke_dialog_close_button{background-image:url(images/hidpi/close.png);background-size:16px}.cke_dialog_close_button span{display:none}.cke_hc .cke_dialog_close_button span{display:inline;cursor:pointer;font-weight:bold;position:relative;top:3px}.cke_ltr .cke_dialog_close_button{right:5px}.cke_rtl .cke_dialog_close_button{left:6px}div.cke_disabled .cke_dialog_ui_labeled_content div *{background-color:#ddd;cursor:default}.cke_dialog_ui_vbox table,.cke_dialog_ui_hbox table{margin:auto}.cke_dialog_ui_vbox{margin-top:5px}.cke_dialog_ui_vbox_child{padding:5px 0}.cke_dialog_ui_hbox{width:100%}.cke_dialog_ui_hbox_first,.cke_dialog_ui_hbox_child,.cke_dialog_ui_hbox_last{vertical-align:top}.cke_dialog_ui_hbox_first>.cke_dialog_ui_labeled_label,.cke_dialog_ui_hbox_first>.cke_dialog_ui_html,.cke_dialog_ui_hbox_last>.cke_dialog_ui_labeled_label,.cke_dialog_ui_hbox_last>.cke_dialog_ui_html{line-height:30px}.cke_ltr .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_ui_hbox_child{padding-right:10px}.cke_rtl .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_ui_hbox_child{padding-left:10px}.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-right:5px}.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-left:5px;padding-right:0}.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_textarea,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_file{border:1px solid}.cke_dialog_ui_text{margin-bottom:7px}.cke_dialog_ui_select{height:auto!important;margin-bottom:7px}textarea.cke_dialog_ui_input_textarea{overflow:auto;resize:none}a.cke_dialog_ui_button{display:inline-block;*display:inline;*zoom:1;padding:3px 0;margin:0;text-align:center;color:#333;vertical-align:middle;cursor:pointer;border:1px solid #ddd;border-radius:4px;background:#fff}a.cke_dialog_ui_button:hover,a.cke_dialog_ui_button:focus,a.cke_dialog_ui_button:active{border-color:#aaa;background-color:#eee;text-decoration:none}.cke_dialog_page_contents a.cke_dialog_ui_button{height:22px;line-height:22px;background-color:#f4f4f4}.cke_dialog_page_contents a.cke_dialog_ui_button:hover,.cke_dialog_page_contents a.cke_dialog_ui_button:focus,.cke_dialog_page_contents a.cke_dialog_ui_button:active{background-color:#eee}span.cke_dialog_ui_button{padding:0 12px}.cke_hc a.cke_dialog_ui_button:hover,.cke_hc a.cke_dialog_ui_button:focus,.cke_hc a.cke_dialog_ui_button:active{border:3px solid;padding-top:1px;padding-bottom:1px}.cke_hc a.cke_dialog_ui_button:hover span,.cke_hc a.cke_dialog_ui_button:focus span,.cke_hc a.cke_dialog_ui_button:active span{padding-left:10px;padding-right:10px}.cke_dialog_footer_buttons a.cke_dialog_ui_button span{color:inherit;font-size:12px;line-height:20px}a.cke_dialog_ui_button_ok{color:#fff;border-color:#2274c9;background:#3f8edf}a.cke_dialog_ui_button_ok:hover,a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:active{border-color:#1e68b4;background:#2981db}a.cke_dialog_ui_button_cancel{background-color:#fff}a.cke_dialog_ui_button_cancel:focus{outline:0}span.cke_dialog_ui_button{cursor:pointer}.cke_dialog_footer_buttons{display:inline-table;margin:10px;width:auto;position:relative;vertical-align:middle}div.cke_dialog_ui_input_select{display:table}select.cke_dialog_ui_input_select{height:30px;line-height:30px;background-color:#fff;padding:4px 10px;border:1px solid #ddd;outline:0;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.cke_dialog_ui_input_file{width:100%;height:30px}.cke_hc .cke_dialog_ui_labeled_content input:focus,.cke_hc .cke_dialog_ui_labeled_content select:focus,.cke_hc .cke_dialog_ui_labeled_content textarea:focus{outline:1px dotted}.cke_dialog .cke_dark_background{background-color:#eee}.cke_dialog .cke_light_background{background-color:#eee}.cke_dialog .cke_centered{text-align:center}.cke_dialog a.cke_btn_reset{float:right;background:url(images/refresh.png) top left no-repeat;width:16px;height:16px;border:1px none;font-size:1px}.cke_dialog a.cke_btn_locked,.cke_dialog a.cke_btn_unlocked{float:left;width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.cke_dialog a.cke_btn_locked{background-image:url(images/lock.png)}.cke_dialog a.cke_btn_locked .cke_icon{display:none}.cke_dialog a.cke_btn_unlocked{background-image:url(images/lock-open.png)}.cke_dialog .cke_btn_over{border:outset 1px;cursor:pointer}.cke_hidpi .cke_dialog a.cke_btn_reset{background-size:16px;background-image:url(images/hidpi/refresh.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked,.cke_hidpi .cke_dialog a.cke_btn_locked{background-size:16px}.cke_hidpi .cke_dialog a.cke_btn_locked{background-image:url(images/hidpi/lock.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-image:url(images/hidpi/lock-open.png)}.cke_rtl .cke_dialog a.cke_btn_reset{float:left}.cke_rtl .cke_dialog a.cke_btn_locked,.cke_rtl .cke_dialog a.cke_btn_unlocked{float:right}.cke_dialog .ImagePreviewBox,.cke_dialog .FlashPreviewBox{border:1px solid #aaa;border-radius:4px;padding:6px 10px;margin-top:5px;background-color:white}.cke_dialog .ImagePreviewBox{overflow:scroll;height:205px;width:300px}.cke_dialog .ImagePreviewBox table td{white-space:normal}.cke_dialog .FlashPreviewBox{white-space:normal;overflow:auto;height:160px;width:390px}.cke_dialog .ImagePreviewLoader{position:absolute;white-space:normal;overflow:hidden;height:160px;width:230px;margin:2px;padding:2px;opacity:.9;filter:alpha(opacity=90);background-color:#e4e4e4}.cke_dialog .cke_pastetext{width:346px;height:170px}.cke_dialog .cke_pastetext textarea{width:340px;height:170px;resize:none}.cke_dialog iframe.cke_pasteframe{width:346px;height:130px;background-color:white;border:1px solid #aeb3b9;border-radius:4px}.cke_dialog .cke_hand{cursor:pointer}.cke_disabled{color:#a0a0a0}.cke_dialog_body .cke_label{display:none}.cke_dialog_body label{display:inline-block;margin-bottom:3px;cursor:default}.cke_dialog_body label.cke_required{font-weight:bold}.cke_dialog_ui_html{line-height:150%}a.cke_smile{overflow:hidden;display:block;text-align:center;padding:.3em 0}a.cke_smile img{vertical-align:middle}a.cke_specialchar{cursor:inherit;display:block;height:1.25em;padding:.2em .3em;text-align:center}a.cke_smile,a.cke_specialchar{background-color:#eee;border:1px solid transparent;vertical-align:top}a.cke_smile:hover,a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:hover,a.cke_specialchar:focus,a.cke_specialchar:active{background:#fff;outline:0}a.cke_smile:hover,a.cke_specialchar:hover{border-color:#aaa}a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:focus,a.cke_specialchar:active{border-color:#428bca}.cke_dialog_contents a.colorChooser{display:block;margin-top:6px;margin-left:10px;width:80px}.cke_rtl .cke_dialog_contents a.colorChooser{margin-right:10px}.cke_dialog_ui_checkbox{display:inline-block;margin-bottom:5px}.cke_dialog_ui_checkbox_input:focus,.cke_dialog_ui_radio_input:focus,.cke_btn_over{outline:1px dotted #696969}.cke_iframe_shim{display:block;position:absolute;top:0;left:0;z-index:-1;filter:alpha(opacity=0);width:100%;height:100%}.cke_rtl input.cke_dialog_ui_input_text,.cke_rtl input.cke_dialog_ui_input_password{padding-right:2px}.cke_rtl div.cke_dialog_ui_input_text,.cke_rtl div.cke_dialog_ui_input_password{padding-left:2px}.cke_rtl div.cke_dialog_ui_input_text{padding-right:1px}.cke_rtl .cke_dialog_ui_vbox_child,.cke_rtl .cke_dialog_ui_hbox_child,.cke_rtl .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_ui_hbox_last{padding-right:2px!important}.cke_hc .cke_dialog_title,.cke_hc .cke_dialog_footer,.cke_hc a.cke_dialog_tab,.cke_hc a.cke_dialog_ui_button,.cke_hc a.cke_dialog_ui_button:hover,.cke_hc a.cke_dialog_ui_button_ok,.cke_hc a.cke_dialog_ui_button_ok:hover{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_textarea,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_file{border:0} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_ie7.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_ie7.css new file mode 100644 index 0000000..a63ae99 --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_ie7.css @@ -0,0 +1 @@ +input.cke_dialog_ui_input_text,input.cke_dialog_ui_input_password,textarea.cke_dialog_ui_input_textarea{background-color:#fff;outline:0;width:100%;*width:95%;height:30px;padding:4px 10px;border:1px solid #ddd;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}input.cke_dialog_ui_input_text:focus,input.cke_dialog_ui_input_password:focus,textarea.cke_dialog_ui_input_textarea:focus{border-color:#66afe9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.cke_dialog{visibility:visible}.cke_dialog_body{z-index:1;background:#eee;border:1px solid #ddd;border-radius:4px}.cke_browser_gecko19 .cke_dialog_body{position:relative}.cke_dialog strong{font-weight:bold}.cke_dialog_title{font-weight:bold;font-size:13px;cursor:move;position:relative;color:#333;border-bottom:1px solid #ddd;padding:10px 12px;background:#eee}.cke_dialog_contents{background-color:#fff;overflow:auto;padding:15px 10px 5px 10px;margin-top:35px;border-top:1px solid #ddd;border-radius:0 0 4px 4px}.cke_dialog_contents_body{overflow:auto;padding:17px 10px 5px 10px;margin-top:22px}.cke_dialog_footer{text-align:right;position:relative;border-radius:0 0 4px 4px;border-top:1px solid #ddd;background:#eee}.cke_rtl .cke_dialog_footer{text-align:left}.cke_hc .cke_dialog_footer{outline:0;border-top:1px solid #fff}.cke_dialog .cke_resizer{margin-top:28px}.cke_dialog .cke_resizer_rtl{margin-left:5px}.cke_dialog .cke_resizer_ltr{margin-right:5px}.cke_dialog_tabs{height:24px;display:inline-block;margin:10px 0 0;position:absolute;z-index:2;left:10px}.cke_rtl .cke_dialog_tabs{right:10px}a.cke_dialog_tab{height:16px;padding:4px 8px;margin-right:3px;display:inline-block;cursor:pointer;line-height:16px;outline:0;color:#555;border:1px solid #ddd;border-radius:3px 3px 0 0;background:#f3f3f3}.cke_rtl a.cke_dialog_tab{margin-right:0;margin-left:3px}a.cke_dialog_tab:hover{background:#ddd;text-decoration:none}a.cke_dialog_tab_selected{background:#fff;color:#333;border-bottom-color:#fff;cursor:default;filter:none}a.cke_dialog_tab_selected:hover{background:#fff}.cke_hc a.cke_dialog_tab:hover,.cke_hc a.cke_dialog_tab_selected{border:3px solid;padding:2px 6px}a.cke_dialog_tab_disabled{color:#bababa;cursor:default}.cke_dialog_tabs .cke_dialog_ui_input_select{top:-7px!important}.cke_single_page .cke_dialog_tabs{display:none}.cke_single_page .cke_dialog_contents{padding-top:5px;margin-top:0;border-top:0}.cke_dialog_close_button{background-image:url(images/close.png);background-repeat:no-repeat;background-position:0 0;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:9px;z-index:5}.cke_hidpi .cke_dialog_close_button{background-image:url(images/hidpi/close.png);background-size:16px}.cke_dialog_close_button span{display:none}.cke_hc .cke_dialog_close_button span{display:inline;cursor:pointer;font-weight:bold;position:relative;top:3px}.cke_ltr .cke_dialog_close_button{right:5px}.cke_rtl .cke_dialog_close_button{left:6px}div.cke_disabled .cke_dialog_ui_labeled_content div *{background-color:#ddd;cursor:default}.cke_dialog_ui_vbox table,.cke_dialog_ui_hbox table{margin:auto}.cke_dialog_ui_vbox{margin-top:5px}.cke_dialog_ui_vbox_child{padding:5px 0}.cke_dialog_ui_hbox{width:100%}.cke_dialog_ui_hbox_first,.cke_dialog_ui_hbox_child,.cke_dialog_ui_hbox_last{vertical-align:top}.cke_dialog_ui_hbox_first>.cke_dialog_ui_labeled_label,.cke_dialog_ui_hbox_first>.cke_dialog_ui_html,.cke_dialog_ui_hbox_last>.cke_dialog_ui_labeled_label,.cke_dialog_ui_hbox_last>.cke_dialog_ui_html{line-height:30px}.cke_ltr .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_ui_hbox_child{padding-right:10px}.cke_rtl .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_ui_hbox_child{padding-left:10px}.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-right:5px}.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-left:5px;padding-right:0}.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_textarea,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_file{border:1px solid}.cke_dialog_ui_text{margin-bottom:7px}.cke_dialog_ui_select{height:auto!important;margin-bottom:7px}textarea.cke_dialog_ui_input_textarea{overflow:auto;resize:none}a.cke_dialog_ui_button{display:inline-block;*display:inline;*zoom:1;padding:3px 0;margin:0;text-align:center;color:#333;vertical-align:middle;cursor:pointer;border:1px solid #ddd;border-radius:4px;background:#fff}a.cke_dialog_ui_button:hover,a.cke_dialog_ui_button:focus,a.cke_dialog_ui_button:active{border-color:#aaa;background-color:#eee;text-decoration:none}.cke_dialog_page_contents a.cke_dialog_ui_button{height:22px;line-height:22px;background-color:#f4f4f4}.cke_dialog_page_contents a.cke_dialog_ui_button:hover,.cke_dialog_page_contents a.cke_dialog_ui_button:focus,.cke_dialog_page_contents a.cke_dialog_ui_button:active{background-color:#eee}span.cke_dialog_ui_button{padding:0 12px}.cke_hc a.cke_dialog_ui_button:hover,.cke_hc a.cke_dialog_ui_button:focus,.cke_hc a.cke_dialog_ui_button:active{border:3px solid;padding-top:1px;padding-bottom:1px}.cke_hc a.cke_dialog_ui_button:hover span,.cke_hc a.cke_dialog_ui_button:focus span,.cke_hc a.cke_dialog_ui_button:active span{padding-left:10px;padding-right:10px}.cke_dialog_footer_buttons a.cke_dialog_ui_button span{color:inherit;font-size:12px;line-height:20px}a.cke_dialog_ui_button_ok{color:#fff;border-color:#2274c9;background:#3f8edf}a.cke_dialog_ui_button_ok:hover,a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:active{border-color:#1e68b4;background:#2981db}a.cke_dialog_ui_button_cancel{background-color:#fff}a.cke_dialog_ui_button_cancel:focus{outline:0}span.cke_dialog_ui_button{cursor:pointer}.cke_dialog_footer_buttons{display:inline-table;margin:10px;width:auto;position:relative;vertical-align:middle}div.cke_dialog_ui_input_select{display:table}select.cke_dialog_ui_input_select{height:30px;line-height:30px;background-color:#fff;padding:4px 10px;border:1px solid #ddd;outline:0;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.cke_dialog_ui_input_file{width:100%;height:30px}.cke_hc .cke_dialog_ui_labeled_content input:focus,.cke_hc .cke_dialog_ui_labeled_content select:focus,.cke_hc .cke_dialog_ui_labeled_content textarea:focus{outline:1px dotted}.cke_dialog .cke_dark_background{background-color:#eee}.cke_dialog .cke_light_background{background-color:#eee}.cke_dialog .cke_centered{text-align:center}.cke_dialog a.cke_btn_reset{float:right;background:url(images/refresh.png) top left no-repeat;width:16px;height:16px;border:1px none;font-size:1px}.cke_dialog a.cke_btn_locked,.cke_dialog a.cke_btn_unlocked{float:left;width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.cke_dialog a.cke_btn_locked{background-image:url(images/lock.png)}.cke_dialog a.cke_btn_locked .cke_icon{display:none}.cke_dialog a.cke_btn_unlocked{background-image:url(images/lock-open.png)}.cke_dialog .cke_btn_over{border:outset 1px;cursor:pointer}.cke_hidpi .cke_dialog a.cke_btn_reset{background-size:16px;background-image:url(images/hidpi/refresh.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked,.cke_hidpi .cke_dialog a.cke_btn_locked{background-size:16px}.cke_hidpi .cke_dialog a.cke_btn_locked{background-image:url(images/hidpi/lock.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-image:url(images/hidpi/lock-open.png)}.cke_rtl .cke_dialog a.cke_btn_reset{float:left}.cke_rtl .cke_dialog a.cke_btn_locked,.cke_rtl .cke_dialog a.cke_btn_unlocked{float:right}.cke_dialog .ImagePreviewBox,.cke_dialog .FlashPreviewBox{border:1px solid #aaa;border-radius:4px;padding:6px 10px;margin-top:5px;background-color:white}.cke_dialog .ImagePreviewBox{overflow:scroll;height:205px;width:300px}.cke_dialog .ImagePreviewBox table td{white-space:normal}.cke_dialog .FlashPreviewBox{white-space:normal;overflow:auto;height:160px;width:390px}.cke_dialog .ImagePreviewLoader{position:absolute;white-space:normal;overflow:hidden;height:160px;width:230px;margin:2px;padding:2px;opacity:.9;filter:alpha(opacity=90);background-color:#e4e4e4}.cke_dialog .cke_pastetext{width:346px;height:170px}.cke_dialog .cke_pastetext textarea{width:340px;height:170px;resize:none}.cke_dialog iframe.cke_pasteframe{width:346px;height:130px;background-color:white;border:1px solid #aeb3b9;border-radius:4px}.cke_dialog .cke_hand{cursor:pointer}.cke_disabled{color:#a0a0a0}.cke_dialog_body .cke_label{display:none}.cke_dialog_body label{display:inline-block;margin-bottom:3px;cursor:default}.cke_dialog_body label.cke_required{font-weight:bold}.cke_dialog_ui_html{line-height:150%}a.cke_smile{overflow:hidden;display:block;text-align:center;padding:.3em 0}a.cke_smile img{vertical-align:middle}a.cke_specialchar{cursor:inherit;display:block;height:1.25em;padding:.2em .3em;text-align:center}a.cke_smile,a.cke_specialchar{background-color:#eee;border:1px solid transparent;vertical-align:top}a.cke_smile:hover,a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:hover,a.cke_specialchar:focus,a.cke_specialchar:active{background:#fff;outline:0}a.cke_smile:hover,a.cke_specialchar:hover{border-color:#aaa}a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:focus,a.cke_specialchar:active{border-color:#428bca}.cke_dialog_contents a.colorChooser{display:block;margin-top:6px;margin-left:10px;width:80px}.cke_rtl .cke_dialog_contents a.colorChooser{margin-right:10px}.cke_dialog_ui_checkbox{display:inline-block;margin-bottom:5px}.cke_dialog_ui_checkbox_input:focus,.cke_dialog_ui_radio_input:focus,.cke_btn_over{outline:1px dotted #696969}.cke_iframe_shim{display:block;position:absolute;top:0;left:0;z-index:-1;filter:alpha(opacity=0);width:100%;height:100%}.cke_dialog_title{zoom:1}.cke_dialog_footer{border-top:1px solid #bfbfbf}.cke_dialog_footer_buttons{position:static}.cke_dialog_footer_buttons a.cke_dialog_ui_button{vertical-align:top}.cke_dialog .cke_resizer_ltr{padding-left:4px}.cke_dialog .cke_resizer_rtl{padding-right:4px}.cke_dialog_ui_input_text,.cke_dialog_ui_input_password,.cke_dialog_ui_input_textarea,.cke_dialog_ui_input_select{padding:0!important}.cke_dialog_ui_checkbox_input,.cke_dialog_ui_ratio_input,.cke_btn_reset,.cke_btn_locked,.cke_btn_unlocked{border:1px solid transparent!important} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_ie8.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_ie8.css new file mode 100644 index 0000000..fa2e81a --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_ie8.css @@ -0,0 +1 @@ +input.cke_dialog_ui_input_text,input.cke_dialog_ui_input_password,textarea.cke_dialog_ui_input_textarea{background-color:#fff;outline:0;width:100%;*width:95%;height:30px;padding:4px 10px;border:1px solid #ddd;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}input.cke_dialog_ui_input_text:focus,input.cke_dialog_ui_input_password:focus,textarea.cke_dialog_ui_input_textarea:focus{border-color:#66afe9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.cke_dialog{visibility:visible}.cke_dialog_body{z-index:1;background:#eee;border:1px solid #ddd;border-radius:4px}.cke_browser_gecko19 .cke_dialog_body{position:relative}.cke_dialog strong{font-weight:bold}.cke_dialog_title{font-weight:bold;font-size:13px;cursor:move;position:relative;color:#333;border-bottom:1px solid #ddd;padding:10px 12px;background:#eee}.cke_dialog_contents{background-color:#fff;overflow:auto;padding:15px 10px 5px 10px;margin-top:35px;border-top:1px solid #ddd;border-radius:0 0 4px 4px}.cke_dialog_contents_body{overflow:auto;padding:17px 10px 5px 10px;margin-top:22px}.cke_dialog_footer{text-align:right;position:relative;border-radius:0 0 4px 4px;border-top:1px solid #ddd;background:#eee}.cke_rtl .cke_dialog_footer{text-align:left}.cke_hc .cke_dialog_footer{outline:0;border-top:1px solid #fff}.cke_dialog .cke_resizer{margin-top:28px}.cke_dialog .cke_resizer_rtl{margin-left:5px}.cke_dialog .cke_resizer_ltr{margin-right:5px}.cke_dialog_tabs{height:24px;display:inline-block;margin:10px 0 0;position:absolute;z-index:2;left:10px}.cke_rtl .cke_dialog_tabs{right:10px}a.cke_dialog_tab{height:16px;padding:4px 8px;margin-right:3px;display:inline-block;cursor:pointer;line-height:16px;outline:0;color:#555;border:1px solid #ddd;border-radius:3px 3px 0 0;background:#f3f3f3}.cke_rtl a.cke_dialog_tab{margin-right:0;margin-left:3px}a.cke_dialog_tab:hover{background:#ddd;text-decoration:none}a.cke_dialog_tab_selected{background:#fff;color:#333;border-bottom-color:#fff;cursor:default;filter:none}a.cke_dialog_tab_selected:hover{background:#fff}.cke_hc a.cke_dialog_tab:hover,.cke_hc a.cke_dialog_tab_selected{border:3px solid;padding:2px 6px}a.cke_dialog_tab_disabled{color:#bababa;cursor:default}.cke_dialog_tabs .cke_dialog_ui_input_select{top:-7px!important}.cke_single_page .cke_dialog_tabs{display:none}.cke_single_page .cke_dialog_contents{padding-top:5px;margin-top:0;border-top:0}.cke_dialog_close_button{background-image:url(images/close.png);background-repeat:no-repeat;background-position:0 0;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:9px;z-index:5}.cke_hidpi .cke_dialog_close_button{background-image:url(images/hidpi/close.png);background-size:16px}.cke_dialog_close_button span{display:none}.cke_hc .cke_dialog_close_button span{display:inline;cursor:pointer;font-weight:bold;position:relative;top:3px}.cke_ltr .cke_dialog_close_button{right:5px}.cke_rtl .cke_dialog_close_button{left:6px}div.cke_disabled .cke_dialog_ui_labeled_content div *{background-color:#ddd;cursor:default}.cke_dialog_ui_vbox table,.cke_dialog_ui_hbox table{margin:auto}.cke_dialog_ui_vbox{margin-top:5px}.cke_dialog_ui_vbox_child{padding:5px 0}.cke_dialog_ui_hbox{width:100%}.cke_dialog_ui_hbox_first,.cke_dialog_ui_hbox_child,.cke_dialog_ui_hbox_last{vertical-align:top}.cke_dialog_ui_hbox_first>.cke_dialog_ui_labeled_label,.cke_dialog_ui_hbox_first>.cke_dialog_ui_html,.cke_dialog_ui_hbox_last>.cke_dialog_ui_labeled_label,.cke_dialog_ui_hbox_last>.cke_dialog_ui_html{line-height:30px}.cke_ltr .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_ui_hbox_child{padding-right:10px}.cke_rtl .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_ui_hbox_child{padding-left:10px}.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-right:5px}.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-left:5px;padding-right:0}.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_textarea,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_file{border:1px solid}.cke_dialog_ui_text{margin-bottom:7px}.cke_dialog_ui_select{height:auto!important;margin-bottom:7px}textarea.cke_dialog_ui_input_textarea{overflow:auto;resize:none}a.cke_dialog_ui_button{display:inline-block;*display:inline;*zoom:1;padding:3px 0;margin:0;text-align:center;color:#333;vertical-align:middle;cursor:pointer;border:1px solid #ddd;border-radius:4px;background:#fff}a.cke_dialog_ui_button:hover,a.cke_dialog_ui_button:focus,a.cke_dialog_ui_button:active{border-color:#aaa;background-color:#eee;text-decoration:none}.cke_dialog_page_contents a.cke_dialog_ui_button{height:22px;line-height:22px;background-color:#f4f4f4}.cke_dialog_page_contents a.cke_dialog_ui_button:hover,.cke_dialog_page_contents a.cke_dialog_ui_button:focus,.cke_dialog_page_contents a.cke_dialog_ui_button:active{background-color:#eee}span.cke_dialog_ui_button{padding:0 12px}.cke_hc a.cke_dialog_ui_button:hover,.cke_hc a.cke_dialog_ui_button:focus,.cke_hc a.cke_dialog_ui_button:active{border:3px solid;padding-top:1px;padding-bottom:1px}.cke_hc a.cke_dialog_ui_button:hover span,.cke_hc a.cke_dialog_ui_button:focus span,.cke_hc a.cke_dialog_ui_button:active span{padding-left:10px;padding-right:10px}.cke_dialog_footer_buttons a.cke_dialog_ui_button span{color:inherit;font-size:12px;line-height:20px}a.cke_dialog_ui_button_ok{color:#fff;border-color:#2274c9;background:#3f8edf}a.cke_dialog_ui_button_ok:hover,a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:active{border-color:#1e68b4;background:#2981db}a.cke_dialog_ui_button_cancel{background-color:#fff}a.cke_dialog_ui_button_cancel:focus{outline:0}span.cke_dialog_ui_button{cursor:pointer}.cke_dialog_footer_buttons{display:inline-table;margin:10px;width:auto;position:relative;vertical-align:middle}div.cke_dialog_ui_input_select{display:table}select.cke_dialog_ui_input_select{height:30px;line-height:30px;background-color:#fff;padding:4px 10px;border:1px solid #ddd;outline:0;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.cke_dialog_ui_input_file{width:100%;height:30px}.cke_hc .cke_dialog_ui_labeled_content input:focus,.cke_hc .cke_dialog_ui_labeled_content select:focus,.cke_hc .cke_dialog_ui_labeled_content textarea:focus{outline:1px dotted}.cke_dialog .cke_dark_background{background-color:#eee}.cke_dialog .cke_light_background{background-color:#eee}.cke_dialog .cke_centered{text-align:center}.cke_dialog a.cke_btn_reset{float:right;background:url(images/refresh.png) top left no-repeat;width:16px;height:16px;border:1px none;font-size:1px}.cke_dialog a.cke_btn_locked,.cke_dialog a.cke_btn_unlocked{float:left;width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.cke_dialog a.cke_btn_locked{background-image:url(images/lock.png)}.cke_dialog a.cke_btn_locked .cke_icon{display:none}.cke_dialog a.cke_btn_unlocked{background-image:url(images/lock-open.png)}.cke_dialog .cke_btn_over{border:outset 1px;cursor:pointer}.cke_hidpi .cke_dialog a.cke_btn_reset{background-size:16px;background-image:url(images/hidpi/refresh.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked,.cke_hidpi .cke_dialog a.cke_btn_locked{background-size:16px}.cke_hidpi .cke_dialog a.cke_btn_locked{background-image:url(images/hidpi/lock.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-image:url(images/hidpi/lock-open.png)}.cke_rtl .cke_dialog a.cke_btn_reset{float:left}.cke_rtl .cke_dialog a.cke_btn_locked,.cke_rtl .cke_dialog a.cke_btn_unlocked{float:right}.cke_dialog .ImagePreviewBox,.cke_dialog .FlashPreviewBox{border:1px solid #aaa;border-radius:4px;padding:6px 10px;margin-top:5px;background-color:white}.cke_dialog .ImagePreviewBox{overflow:scroll;height:205px;width:300px}.cke_dialog .ImagePreviewBox table td{white-space:normal}.cke_dialog .FlashPreviewBox{white-space:normal;overflow:auto;height:160px;width:390px}.cke_dialog .ImagePreviewLoader{position:absolute;white-space:normal;overflow:hidden;height:160px;width:230px;margin:2px;padding:2px;opacity:.9;filter:alpha(opacity=90);background-color:#e4e4e4}.cke_dialog .cke_pastetext{width:346px;height:170px}.cke_dialog .cke_pastetext textarea{width:340px;height:170px;resize:none}.cke_dialog iframe.cke_pasteframe{width:346px;height:130px;background-color:white;border:1px solid #aeb3b9;border-radius:4px}.cke_dialog .cke_hand{cursor:pointer}.cke_disabled{color:#a0a0a0}.cke_dialog_body .cke_label{display:none}.cke_dialog_body label{display:inline-block;margin-bottom:3px;cursor:default}.cke_dialog_body label.cke_required{font-weight:bold}.cke_dialog_ui_html{line-height:150%}a.cke_smile{overflow:hidden;display:block;text-align:center;padding:.3em 0}a.cke_smile img{vertical-align:middle}a.cke_specialchar{cursor:inherit;display:block;height:1.25em;padding:.2em .3em;text-align:center}a.cke_smile,a.cke_specialchar{background-color:#eee;border:1px solid transparent;vertical-align:top}a.cke_smile:hover,a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:hover,a.cke_specialchar:focus,a.cke_specialchar:active{background:#fff;outline:0}a.cke_smile:hover,a.cke_specialchar:hover{border-color:#aaa}a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:focus,a.cke_specialchar:active{border-color:#428bca}.cke_dialog_contents a.colorChooser{display:block;margin-top:6px;margin-left:10px;width:80px}.cke_rtl .cke_dialog_contents a.colorChooser{margin-right:10px}.cke_dialog_ui_checkbox{display:inline-block;margin-bottom:5px}.cke_dialog_ui_checkbox_input:focus,.cke_dialog_ui_radio_input:focus,.cke_btn_over{outline:1px dotted #696969}.cke_iframe_shim{display:block;position:absolute;top:0;left:0;z-index:-1;filter:alpha(opacity=0);width:100%;height:100%}a.cke_dialog_ui_button_ok:focus span,a.cke_dialog_ui_button_ok:active span,a.cke_dialog_ui_button_cancel:focus span,a.cke_dialog_ui_button_cancel:active span{display:block} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_iequirks.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_iequirks.css new file mode 100644 index 0000000..480263a --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_iequirks.css @@ -0,0 +1 @@ +input.cke_dialog_ui_input_text,input.cke_dialog_ui_input_password,textarea.cke_dialog_ui_input_textarea{background-color:#fff;outline:0;width:100%;*width:95%;height:30px;padding:4px 10px;border:1px solid #ddd;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}input.cke_dialog_ui_input_text:focus,input.cke_dialog_ui_input_password:focus,textarea.cke_dialog_ui_input_textarea:focus{border-color:#66afe9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.cke_dialog{visibility:visible}.cke_dialog_body{z-index:1;background:#eee;border:1px solid #ddd;border-radius:4px}.cke_browser_gecko19 .cke_dialog_body{position:relative}.cke_dialog strong{font-weight:bold}.cke_dialog_title{font-weight:bold;font-size:13px;cursor:move;position:relative;color:#333;border-bottom:1px solid #ddd;padding:10px 12px;background:#eee}.cke_dialog_contents{background-color:#fff;overflow:auto;padding:15px 10px 5px 10px;margin-top:35px;border-top:1px solid #ddd;border-radius:0 0 4px 4px}.cke_dialog_contents_body{overflow:auto;padding:17px 10px 5px 10px;margin-top:22px}.cke_dialog_footer{text-align:right;position:relative;border-radius:0 0 4px 4px;border-top:1px solid #ddd;background:#eee}.cke_rtl .cke_dialog_footer{text-align:left}.cke_hc .cke_dialog_footer{outline:0;border-top:1px solid #fff}.cke_dialog .cke_resizer{margin-top:28px}.cke_dialog .cke_resizer_rtl{margin-left:5px}.cke_dialog .cke_resizer_ltr{margin-right:5px}.cke_dialog_tabs{height:24px;display:inline-block;margin:10px 0 0;position:absolute;z-index:2;left:10px}.cke_rtl .cke_dialog_tabs{right:10px}a.cke_dialog_tab{height:16px;padding:4px 8px;margin-right:3px;display:inline-block;cursor:pointer;line-height:16px;outline:0;color:#555;border:1px solid #ddd;border-radius:3px 3px 0 0;background:#f3f3f3}.cke_rtl a.cke_dialog_tab{margin-right:0;margin-left:3px}a.cke_dialog_tab:hover{background:#ddd;text-decoration:none}a.cke_dialog_tab_selected{background:#fff;color:#333;border-bottom-color:#fff;cursor:default;filter:none}a.cke_dialog_tab_selected:hover{background:#fff}.cke_hc a.cke_dialog_tab:hover,.cke_hc a.cke_dialog_tab_selected{border:3px solid;padding:2px 6px}a.cke_dialog_tab_disabled{color:#bababa;cursor:default}.cke_dialog_tabs .cke_dialog_ui_input_select{top:-7px!important}.cke_single_page .cke_dialog_tabs{display:none}.cke_single_page .cke_dialog_contents{padding-top:5px;margin-top:0;border-top:0}.cke_dialog_close_button{background-image:url(images/close.png);background-repeat:no-repeat;background-position:0 0;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:9px;z-index:5}.cke_hidpi .cke_dialog_close_button{background-image:url(images/hidpi/close.png);background-size:16px}.cke_dialog_close_button span{display:none}.cke_hc .cke_dialog_close_button span{display:inline;cursor:pointer;font-weight:bold;position:relative;top:3px}.cke_ltr .cke_dialog_close_button{right:5px}.cke_rtl .cke_dialog_close_button{left:6px}div.cke_disabled .cke_dialog_ui_labeled_content div *{background-color:#ddd;cursor:default}.cke_dialog_ui_vbox table,.cke_dialog_ui_hbox table{margin:auto}.cke_dialog_ui_vbox{margin-top:5px}.cke_dialog_ui_vbox_child{padding:5px 0}.cke_dialog_ui_hbox{width:100%}.cke_dialog_ui_hbox_first,.cke_dialog_ui_hbox_child,.cke_dialog_ui_hbox_last{vertical-align:top}.cke_dialog_ui_hbox_first>.cke_dialog_ui_labeled_label,.cke_dialog_ui_hbox_first>.cke_dialog_ui_html,.cke_dialog_ui_hbox_last>.cke_dialog_ui_labeled_label,.cke_dialog_ui_hbox_last>.cke_dialog_ui_html{line-height:30px}.cke_ltr .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_ui_hbox_child{padding-right:10px}.cke_rtl .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_ui_hbox_child{padding-left:10px}.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-right:5px}.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-left:5px;padding-right:0}.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_textarea,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_file{border:1px solid}.cke_dialog_ui_text{margin-bottom:7px}.cke_dialog_ui_select{height:auto!important;margin-bottom:7px}textarea.cke_dialog_ui_input_textarea{overflow:auto;resize:none}a.cke_dialog_ui_button{display:inline-block;*display:inline;*zoom:1;padding:3px 0;margin:0;text-align:center;color:#333;vertical-align:middle;cursor:pointer;border:1px solid #ddd;border-radius:4px;background:#fff}a.cke_dialog_ui_button:hover,a.cke_dialog_ui_button:focus,a.cke_dialog_ui_button:active{border-color:#aaa;background-color:#eee;text-decoration:none}.cke_dialog_page_contents a.cke_dialog_ui_button{height:22px;line-height:22px;background-color:#f4f4f4}.cke_dialog_page_contents a.cke_dialog_ui_button:hover,.cke_dialog_page_contents a.cke_dialog_ui_button:focus,.cke_dialog_page_contents a.cke_dialog_ui_button:active{background-color:#eee}span.cke_dialog_ui_button{padding:0 12px}.cke_hc a.cke_dialog_ui_button:hover,.cke_hc a.cke_dialog_ui_button:focus,.cke_hc a.cke_dialog_ui_button:active{border:3px solid;padding-top:1px;padding-bottom:1px}.cke_hc a.cke_dialog_ui_button:hover span,.cke_hc a.cke_dialog_ui_button:focus span,.cke_hc a.cke_dialog_ui_button:active span{padding-left:10px;padding-right:10px}.cke_dialog_footer_buttons a.cke_dialog_ui_button span{color:inherit;font-size:12px;line-height:20px}a.cke_dialog_ui_button_ok{color:#fff;border-color:#2274c9;background:#3f8edf}a.cke_dialog_ui_button_ok:hover,a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:active{border-color:#1e68b4;background:#2981db}a.cke_dialog_ui_button_cancel{background-color:#fff}a.cke_dialog_ui_button_cancel:focus{outline:0}span.cke_dialog_ui_button{cursor:pointer}.cke_dialog_footer_buttons{display:inline-table;margin:10px;width:auto;position:relative;vertical-align:middle}div.cke_dialog_ui_input_select{display:table}select.cke_dialog_ui_input_select{height:30px;line-height:30px;background-color:#fff;padding:4px 10px;border:1px solid #ddd;outline:0;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.cke_dialog_ui_input_file{width:100%;height:30px}.cke_hc .cke_dialog_ui_labeled_content input:focus,.cke_hc .cke_dialog_ui_labeled_content select:focus,.cke_hc .cke_dialog_ui_labeled_content textarea:focus{outline:1px dotted}.cke_dialog .cke_dark_background{background-color:#eee}.cke_dialog .cke_light_background{background-color:#eee}.cke_dialog .cke_centered{text-align:center}.cke_dialog a.cke_btn_reset{float:right;background:url(images/refresh.png) top left no-repeat;width:16px;height:16px;border:1px none;font-size:1px}.cke_dialog a.cke_btn_locked,.cke_dialog a.cke_btn_unlocked{float:left;width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.cke_dialog a.cke_btn_locked{background-image:url(images/lock.png)}.cke_dialog a.cke_btn_locked .cke_icon{display:none}.cke_dialog a.cke_btn_unlocked{background-image:url(images/lock-open.png)}.cke_dialog .cke_btn_over{border:outset 1px;cursor:pointer}.cke_hidpi .cke_dialog a.cke_btn_reset{background-size:16px;background-image:url(images/hidpi/refresh.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked,.cke_hidpi .cke_dialog a.cke_btn_locked{background-size:16px}.cke_hidpi .cke_dialog a.cke_btn_locked{background-image:url(images/hidpi/lock.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-image:url(images/hidpi/lock-open.png)}.cke_rtl .cke_dialog a.cke_btn_reset{float:left}.cke_rtl .cke_dialog a.cke_btn_locked,.cke_rtl .cke_dialog a.cke_btn_unlocked{float:right}.cke_dialog .ImagePreviewBox,.cke_dialog .FlashPreviewBox{border:1px solid #aaa;border-radius:4px;padding:6px 10px;margin-top:5px;background-color:white}.cke_dialog .ImagePreviewBox{overflow:scroll;height:205px;width:300px}.cke_dialog .ImagePreviewBox table td{white-space:normal}.cke_dialog .FlashPreviewBox{white-space:normal;overflow:auto;height:160px;width:390px}.cke_dialog .ImagePreviewLoader{position:absolute;white-space:normal;overflow:hidden;height:160px;width:230px;margin:2px;padding:2px;opacity:.9;filter:alpha(opacity=90);background-color:#e4e4e4}.cke_dialog .cke_pastetext{width:346px;height:170px}.cke_dialog .cke_pastetext textarea{width:340px;height:170px;resize:none}.cke_dialog iframe.cke_pasteframe{width:346px;height:130px;background-color:white;border:1px solid #aeb3b9;border-radius:4px}.cke_dialog .cke_hand{cursor:pointer}.cke_disabled{color:#a0a0a0}.cke_dialog_body .cke_label{display:none}.cke_dialog_body label{display:inline-block;margin-bottom:3px;cursor:default}.cke_dialog_body label.cke_required{font-weight:bold}.cke_dialog_ui_html{line-height:150%}a.cke_smile{overflow:hidden;display:block;text-align:center;padding:.3em 0}a.cke_smile img{vertical-align:middle}a.cke_specialchar{cursor:inherit;display:block;height:1.25em;padding:.2em .3em;text-align:center}a.cke_smile,a.cke_specialchar{background-color:#eee;border:1px solid transparent;vertical-align:top}a.cke_smile:hover,a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:hover,a.cke_specialchar:focus,a.cke_specialchar:active{background:#fff;outline:0}a.cke_smile:hover,a.cke_specialchar:hover{border-color:#aaa}a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:focus,a.cke_specialchar:active{border-color:#428bca}.cke_dialog_contents a.colorChooser{display:block;margin-top:6px;margin-left:10px;width:80px}.cke_rtl .cke_dialog_contents a.colorChooser{margin-right:10px}.cke_dialog_ui_checkbox{display:inline-block;margin-bottom:5px}.cke_dialog_ui_checkbox_input:focus,.cke_dialog_ui_radio_input:focus,.cke_btn_over{outline:1px dotted #696969}.cke_iframe_shim{display:block;position:absolute;top:0;left:0;z-index:-1;filter:alpha(opacity=0);width:100%;height:100%}.cke_dialog_footer{filter:""} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_opera.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_opera.css new file mode 100644 index 0000000..21fc692 --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/dialog_opera.css @@ -0,0 +1 @@ +input.cke_dialog_ui_input_text,input.cke_dialog_ui_input_password,textarea.cke_dialog_ui_input_textarea{background-color:#fff;outline:0;width:100%;*width:95%;height:30px;padding:4px 10px;border:1px solid #ddd;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}input.cke_dialog_ui_input_text:focus,input.cke_dialog_ui_input_password:focus,textarea.cke_dialog_ui_input_textarea:focus{border-color:#66afe9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.cke_dialog{visibility:visible}.cke_dialog_body{z-index:1;background:#eee;border:1px solid #ddd;border-radius:4px}.cke_browser_gecko19 .cke_dialog_body{position:relative}.cke_dialog strong{font-weight:bold}.cke_dialog_title{font-weight:bold;font-size:13px;cursor:move;position:relative;color:#333;border-bottom:1px solid #ddd;padding:10px 12px;background:#eee}.cke_dialog_contents{background-color:#fff;overflow:auto;padding:15px 10px 5px 10px;margin-top:35px;border-top:1px solid #ddd;border-radius:0 0 4px 4px}.cke_dialog_contents_body{overflow:auto;padding:17px 10px 5px 10px;margin-top:22px}.cke_dialog_footer{text-align:right;position:relative;border-radius:0 0 4px 4px;border-top:1px solid #ddd;background:#eee}.cke_rtl .cke_dialog_footer{text-align:left}.cke_hc .cke_dialog_footer{outline:0;border-top:1px solid #fff}.cke_dialog .cke_resizer{margin-top:28px}.cke_dialog .cke_resizer_rtl{margin-left:5px}.cke_dialog .cke_resizer_ltr{margin-right:5px}.cke_dialog_tabs{height:24px;display:inline-block;margin:10px 0 0;position:absolute;z-index:2;left:10px}.cke_rtl .cke_dialog_tabs{right:10px}a.cke_dialog_tab{height:16px;padding:4px 8px;margin-right:3px;display:inline-block;cursor:pointer;line-height:16px;outline:0;color:#555;border:1px solid #ddd;border-radius:3px 3px 0 0;background:#f3f3f3}.cke_rtl a.cke_dialog_tab{margin-right:0;margin-left:3px}a.cke_dialog_tab:hover{background:#ddd;text-decoration:none}a.cke_dialog_tab_selected{background:#fff;color:#333;border-bottom-color:#fff;cursor:default;filter:none}a.cke_dialog_tab_selected:hover{background:#fff}.cke_hc a.cke_dialog_tab:hover,.cke_hc a.cke_dialog_tab_selected{border:3px solid;padding:2px 6px}a.cke_dialog_tab_disabled{color:#bababa;cursor:default}.cke_dialog_tabs .cke_dialog_ui_input_select{top:-7px!important}.cke_single_page .cke_dialog_tabs{display:none}.cke_single_page .cke_dialog_contents{padding-top:5px;margin-top:0;border-top:0}.cke_dialog_close_button{background-image:url(images/close.png);background-repeat:no-repeat;background-position:0 0;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:9px;z-index:5}.cke_hidpi .cke_dialog_close_button{background-image:url(images/hidpi/close.png);background-size:16px}.cke_dialog_close_button span{display:none}.cke_hc .cke_dialog_close_button span{display:inline;cursor:pointer;font-weight:bold;position:relative;top:3px}.cke_ltr .cke_dialog_close_button{right:5px}.cke_rtl .cke_dialog_close_button{left:6px}div.cke_disabled .cke_dialog_ui_labeled_content div *{background-color:#ddd;cursor:default}.cke_dialog_ui_vbox table,.cke_dialog_ui_hbox table{margin:auto}.cke_dialog_ui_vbox{margin-top:5px}.cke_dialog_ui_vbox_child{padding:5px 0}.cke_dialog_ui_hbox{width:100%}.cke_dialog_ui_hbox_first,.cke_dialog_ui_hbox_child,.cke_dialog_ui_hbox_last{vertical-align:top}.cke_dialog_ui_hbox_first>.cke_dialog_ui_labeled_label,.cke_dialog_ui_hbox_first>.cke_dialog_ui_html,.cke_dialog_ui_hbox_last>.cke_dialog_ui_labeled_label,.cke_dialog_ui_hbox_last>.cke_dialog_ui_html{line-height:30px}.cke_ltr .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_ui_hbox_child{padding-right:10px}.cke_rtl .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_ui_hbox_child{padding-left:10px}.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-right:5px}.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-left:5px;padding-right:0}.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_textarea,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_file{border:1px solid}.cke_dialog_ui_text{margin-bottom:7px}.cke_dialog_ui_select{height:auto!important;margin-bottom:7px}textarea.cke_dialog_ui_input_textarea{overflow:auto;resize:none}a.cke_dialog_ui_button{display:inline-block;*display:inline;*zoom:1;padding:3px 0;margin:0;text-align:center;color:#333;vertical-align:middle;cursor:pointer;border:1px solid #ddd;border-radius:4px;background:#fff}a.cke_dialog_ui_button:hover,a.cke_dialog_ui_button:focus,a.cke_dialog_ui_button:active{border-color:#aaa;background-color:#eee;text-decoration:none}.cke_dialog_page_contents a.cke_dialog_ui_button{height:22px;line-height:22px;background-color:#f4f4f4}.cke_dialog_page_contents a.cke_dialog_ui_button:hover,.cke_dialog_page_contents a.cke_dialog_ui_button:focus,.cke_dialog_page_contents a.cke_dialog_ui_button:active{background-color:#eee}span.cke_dialog_ui_button{padding:0 12px}.cke_hc a.cke_dialog_ui_button:hover,.cke_hc a.cke_dialog_ui_button:focus,.cke_hc a.cke_dialog_ui_button:active{border:3px solid;padding-top:1px;padding-bottom:1px}.cke_hc a.cke_dialog_ui_button:hover span,.cke_hc a.cke_dialog_ui_button:focus span,.cke_hc a.cke_dialog_ui_button:active span{padding-left:10px;padding-right:10px}.cke_dialog_footer_buttons a.cke_dialog_ui_button span{color:inherit;font-size:12px;line-height:20px}a.cke_dialog_ui_button_ok{color:#fff;border-color:#2274c9;background:#3f8edf}a.cke_dialog_ui_button_ok:hover,a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:active{border-color:#1e68b4;background:#2981db}a.cke_dialog_ui_button_cancel{background-color:#fff}a.cke_dialog_ui_button_cancel:focus{outline:0}span.cke_dialog_ui_button{cursor:pointer}.cke_dialog_footer_buttons{display:inline-table;margin:10px;width:auto;position:relative;vertical-align:middle}div.cke_dialog_ui_input_select{display:table}select.cke_dialog_ui_input_select{height:30px;line-height:30px;background-color:#fff;padding:4px 10px;border:1px solid #ddd;outline:0;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.cke_dialog_ui_input_file{width:100%;height:30px}.cke_hc .cke_dialog_ui_labeled_content input:focus,.cke_hc .cke_dialog_ui_labeled_content select:focus,.cke_hc .cke_dialog_ui_labeled_content textarea:focus{outline:1px dotted}.cke_dialog .cke_dark_background{background-color:#eee}.cke_dialog .cke_light_background{background-color:#eee}.cke_dialog .cke_centered{text-align:center}.cke_dialog a.cke_btn_reset{float:right;background:url(images/refresh.png) top left no-repeat;width:16px;height:16px;border:1px none;font-size:1px}.cke_dialog a.cke_btn_locked,.cke_dialog a.cke_btn_unlocked{float:left;width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.cke_dialog a.cke_btn_locked{background-image:url(images/lock.png)}.cke_dialog a.cke_btn_locked .cke_icon{display:none}.cke_dialog a.cke_btn_unlocked{background-image:url(images/lock-open.png)}.cke_dialog .cke_btn_over{border:outset 1px;cursor:pointer}.cke_hidpi .cke_dialog a.cke_btn_reset{background-size:16px;background-image:url(images/hidpi/refresh.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked,.cke_hidpi .cke_dialog a.cke_btn_locked{background-size:16px}.cke_hidpi .cke_dialog a.cke_btn_locked{background-image:url(images/hidpi/lock.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-image:url(images/hidpi/lock-open.png)}.cke_rtl .cke_dialog a.cke_btn_reset{float:left}.cke_rtl .cke_dialog a.cke_btn_locked,.cke_rtl .cke_dialog a.cke_btn_unlocked{float:right}.cke_dialog .ImagePreviewBox,.cke_dialog .FlashPreviewBox{border:1px solid #aaa;border-radius:4px;padding:6px 10px;margin-top:5px;background-color:white}.cke_dialog .ImagePreviewBox{overflow:scroll;height:205px;width:300px}.cke_dialog .ImagePreviewBox table td{white-space:normal}.cke_dialog .FlashPreviewBox{white-space:normal;overflow:auto;height:160px;width:390px}.cke_dialog .ImagePreviewLoader{position:absolute;white-space:normal;overflow:hidden;height:160px;width:230px;margin:2px;padding:2px;opacity:.9;filter:alpha(opacity=90);background-color:#e4e4e4}.cke_dialog .cke_pastetext{width:346px;height:170px}.cke_dialog .cke_pastetext textarea{width:340px;height:170px;resize:none}.cke_dialog iframe.cke_pasteframe{width:346px;height:130px;background-color:white;border:1px solid #aeb3b9;border-radius:4px}.cke_dialog .cke_hand{cursor:pointer}.cke_disabled{color:#a0a0a0}.cke_dialog_body .cke_label{display:none}.cke_dialog_body label{display:inline-block;margin-bottom:3px;cursor:default}.cke_dialog_body label.cke_required{font-weight:bold}.cke_dialog_ui_html{line-height:150%}a.cke_smile{overflow:hidden;display:block;text-align:center;padding:.3em 0}a.cke_smile img{vertical-align:middle}a.cke_specialchar{cursor:inherit;display:block;height:1.25em;padding:.2em .3em;text-align:center}a.cke_smile,a.cke_specialchar{background-color:#eee;border:1px solid transparent;vertical-align:top}a.cke_smile:hover,a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:hover,a.cke_specialchar:focus,a.cke_specialchar:active{background:#fff;outline:0}a.cke_smile:hover,a.cke_specialchar:hover{border-color:#aaa}a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:focus,a.cke_specialchar:active{border-color:#428bca}.cke_dialog_contents a.colorChooser{display:block;margin-top:6px;margin-left:10px;width:80px}.cke_rtl .cke_dialog_contents a.colorChooser{margin-right:10px}.cke_dialog_ui_checkbox{display:inline-block;margin-bottom:5px}.cke_dialog_ui_checkbox_input:focus,.cke_dialog_ui_radio_input:focus,.cke_btn_over{outline:1px dotted #696969}.cke_iframe_shim{display:block;position:absolute;top:0;left:0;z-index:-1;filter:alpha(opacity=0);width:100%;height:100%}.cke_dialog_footer{display:block;height:38px}.cke_ltr .cke_dialog_footer>*{float:right}.cke_rtl .cke_dialog_footer>*{float:left} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor.css new file mode 100644 index 0000000..8ba7c92 --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor.css @@ -0,0 +1 @@ +.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none}.cke_reset_all,.cke_reset_all *{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#333;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;margin-top:10px;border:1px solid #ddd}.cke_reset_all fieldset legend{padding:0 5px}.cke_reset_all select{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.cke_chrome{display:block;border:1px solid #ddd;border-radius:4px;padding:0 3px;background:#eee}.cke_inner{display:block;-webkit-touch-callout:none;background:transparent;padding:0}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_float .cke_top{border:1px solid #ddd}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top,.cke_bottom{padding:3px 0 0;background:#eee}.cke_top{white-space:normal}.cke_contents{background-color:#fff;border:1px solid #ddd;border-radius:4px}.cke_bottom{position:relative}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #555 transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #aaa;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;margin-top:5px;background-color:#fff;border:1px solid #aaa;border-radius:4px}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:178px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_list{list-style-type:none;margin:3px;padding:0;white-space:nowrap}.cke_panel_listItem{margin:0;padding-bottom:1px}.cke_panel_listItem a{padding:3px 4px;display:block;border:1px solid #fff;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis;border-radius:2px}.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{background-color:#e1edf7}* html .cke_panel_listItem a{width:100%;color:#000}*:first-child+html .cke_panel_listItem a{color:#000}.cke_panel_listItem.cke_selected a{background-color:#92bce0;outline:0}.cke_hc .cke_panel_listItem a{border-style:none}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:1px 2px}.cke_panel_grouptitle{font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:6px 6px;color:#474747;border-bottom:1px solid #aaa;background:#eee}.cke_panel_grouptitle:first-child{border-radius:4px 4px 0 0}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_colorblock{padding:3px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}span.cke_colorbox{width:10px;height:10px;border:1px solid #aaa;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorbox{border:1px solid #fff;padding:2px;float:left;width:12px;height:12px;border-radius:2px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{border:1px solid #ddd;background-color:#eee}a.cke_colorauto,a.cke_colormore{border:1px solid #fff;padding:2px;display:block;cursor:pointer}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{border:1px solid #ddd;background-color:#eee}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{float:left;margin:0 6px 3px 0;padding:2px;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_hc .cke_toolgroup{border:0;margin-right:10px;margin-bottom:10px}.cke_rtl .cke_toolgroup *:first-child{border-radius:0 4px 4px 0}.cke_rtl .cke_toolgroup *:last-child{border-radius:4px 0 0 4px}.cke_rtl .cke_toolgroup{float:right;margin-left:6px;margin-right:0}a.cke_button{display:inline-block;height:18px;padding:2px 4px;outline:0;cursor:default;float:left;border:0;border-radius:2px}.cke_rtl .cke_button{float:right}.cke_hc .cke_button{border:1px solid black;padding:3px 5px;margin:-2px 4px 0 -2px}.cke_button_on{background:#92bce0}.cke_hc .cke_button_on{border-width:3px;padding:1px 3px}.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border-width:3px;padding:1px 3px}.cke_button_disabled .cke_button_icon{opacity:.3}.cke_hc .cke_button_disabled{opacity:.5}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{background:#e1edf7}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:18px;vertical-align:middle;float:left;cursor:default;color:#555}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px -2px 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#ddd;margin:4px 2px 0;height:16px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{width:0;border-left:1px solid;margin:1px 5px 0 0}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #a6a6a6;border-bottom-color:#979797;border-radius:4px;background:#e4e4e4}.cke_toolbox_collapser:hover{background:#ccc}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#474747}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:3px solid #474747;border-top:3px solid transparent}.cke_rtl .cke_toolbox_collapser{float:left}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0;margin-right:2px}.cke_menubutton{display:block}.cke_button_icon{opacity:.8}.cke_menuitem span{cursor:default}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#d3d3d3;display:block}.cke_hc .cke_menubutton{padding:2px}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#d7d8d7;opacity:.70;filter:alpha(opacity=70);padding:4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#d0d2d0}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_on{border:1px solid #dedede;background-color:#f2f2f2}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#eff0ef}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d3d3d3;height:1px;filter:alpha(opacity=70);opacity:.70}.cke_menuarrow{background-image:url(images/arrow.png);background-position:0 10px;background-repeat:no-repeat;padding:0 5px}.cke_menuarrow span{display:none}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:-2px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_button{display:inline-block;float:left;margin:0 6px 5px 0;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus{outline:0}.cke_combo_off a.cke_combo_button:active{border-color:#333}.cke_combo_on a.cke_combo_button{border-color:#333}.cke_rtl .cke_combo_button{float:right;margin-left:5px;margin-right:0}.cke_hc a.cke_combo_button{padding:3px}.cke_hc .cke_combo_on a.cke_combo_button{border-width:3px;padding:1px}.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border-width:3px;padding:1px}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#474747;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 7px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #333}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}.cke_path_item,.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#4c4c4c;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#bfbfbf;color:#333;border-radius:2px}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combo__fontsize .cke_combo_text{width:30px}.cke_combopanel__fontsize{width:120px}.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_gecko.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_gecko.css new file mode 100644 index 0000000..b3e000d --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_gecko.css @@ -0,0 +1 @@ +.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none}.cke_reset_all,.cke_reset_all *{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#333;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;margin-top:10px;border:1px solid #ddd}.cke_reset_all fieldset legend{padding:0 5px}.cke_reset_all select{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.cke_chrome{display:block;border:1px solid #ddd;border-radius:4px;padding:0 3px;background:#eee}.cke_inner{display:block;-webkit-touch-callout:none;background:transparent;padding:0}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_float .cke_top{border:1px solid #ddd}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top,.cke_bottom{padding:3px 0 0;background:#eee}.cke_top{white-space:normal}.cke_contents{background-color:#fff;border:1px solid #ddd;border-radius:4px}.cke_bottom{position:relative}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #555 transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #aaa;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;margin-top:5px;background-color:#fff;border:1px solid #aaa;border-radius:4px}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:178px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_list{list-style-type:none;margin:3px;padding:0;white-space:nowrap}.cke_panel_listItem{margin:0;padding-bottom:1px}.cke_panel_listItem a{padding:3px 4px;display:block;border:1px solid #fff;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis;border-radius:2px}.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{background-color:#e1edf7}* html .cke_panel_listItem a{width:100%;color:#000}*:first-child+html .cke_panel_listItem a{color:#000}.cke_panel_listItem.cke_selected a{background-color:#92bce0;outline:0}.cke_hc .cke_panel_listItem a{border-style:none}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:1px 2px}.cke_panel_grouptitle{font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:6px 6px;color:#474747;border-bottom:1px solid #aaa;background:#eee}.cke_panel_grouptitle:first-child{border-radius:4px 4px 0 0}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_colorblock{padding:3px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}span.cke_colorbox{width:10px;height:10px;border:1px solid #aaa;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorbox{border:1px solid #fff;padding:2px;float:left;width:12px;height:12px;border-radius:2px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{border:1px solid #ddd;background-color:#eee}a.cke_colorauto,a.cke_colormore{border:1px solid #fff;padding:2px;display:block;cursor:pointer}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{border:1px solid #ddd;background-color:#eee}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{float:left;margin:0 6px 3px 0;padding:2px;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_hc .cke_toolgroup{border:0;margin-right:10px;margin-bottom:10px}.cke_rtl .cke_toolgroup *:first-child{border-radius:0 4px 4px 0}.cke_rtl .cke_toolgroup *:last-child{border-radius:4px 0 0 4px}.cke_rtl .cke_toolgroup{float:right;margin-left:6px;margin-right:0}a.cke_button{display:inline-block;height:18px;padding:2px 4px;outline:0;cursor:default;float:left;border:0;border-radius:2px}.cke_rtl .cke_button{float:right}.cke_hc .cke_button{border:1px solid black;padding:3px 5px;margin:-2px 4px 0 -2px}.cke_button_on{background:#92bce0}.cke_hc .cke_button_on{border-width:3px;padding:1px 3px}.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border-width:3px;padding:1px 3px}.cke_button_disabled .cke_button_icon{opacity:.3}.cke_hc .cke_button_disabled{opacity:.5}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{background:#e1edf7}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:18px;vertical-align:middle;float:left;cursor:default;color:#555}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px -2px 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#ddd;margin:4px 2px 0;height:16px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{width:0;border-left:1px solid;margin:1px 5px 0 0}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #a6a6a6;border-bottom-color:#979797;border-radius:4px;background:#e4e4e4}.cke_toolbox_collapser:hover{background:#ccc}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#474747}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:3px solid #474747;border-top:3px solid transparent}.cke_rtl .cke_toolbox_collapser{float:left}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0;margin-right:2px}.cke_menubutton{display:block}.cke_button_icon{opacity:.8}.cke_menuitem span{cursor:default}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#d3d3d3;display:block}.cke_hc .cke_menubutton{padding:2px}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#d7d8d7;opacity:.70;filter:alpha(opacity=70);padding:4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#d0d2d0}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_on{border:1px solid #dedede;background-color:#f2f2f2}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#eff0ef}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d3d3d3;height:1px;filter:alpha(opacity=70);opacity:.70}.cke_menuarrow{background-image:url(images/arrow.png);background-position:0 10px;background-repeat:no-repeat;padding:0 5px}.cke_menuarrow span{display:none}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:-2px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_button{display:inline-block;float:left;margin:0 6px 5px 0;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus{outline:0}.cke_combo_off a.cke_combo_button:active{border-color:#333}.cke_combo_on a.cke_combo_button{border-color:#333}.cke_rtl .cke_combo_button{float:right;margin-left:5px;margin-right:0}.cke_hc a.cke_combo_button{padding:3px}.cke_hc .cke_combo_on a.cke_combo_button{border-width:3px;padding:1px}.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border-width:3px;padding:1px}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#474747;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 7px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #333}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}.cke_path_item,.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#4c4c4c;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#bfbfbf;color:#333;border-radius:2px}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combo__fontsize .cke_combo_text{width:30px}.cke_combopanel__fontsize{width:120px}.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}.cke_bottom{padding-bottom:3px}.cke_combo_text{margin-bottom:-1px;margin-top:1px} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_ie.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_ie.css new file mode 100644 index 0000000..f66f9b5 --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_ie.css @@ -0,0 +1 @@ +.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none}.cke_reset_all,.cke_reset_all *{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#333;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;margin-top:10px;border:1px solid #ddd}.cke_reset_all fieldset legend{padding:0 5px}.cke_reset_all select{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.cke_chrome{display:block;border:1px solid #ddd;border-radius:4px;padding:0 3px;background:#eee}.cke_inner{display:block;-webkit-touch-callout:none;background:transparent;padding:0}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_float .cke_top{border:1px solid #ddd}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top,.cke_bottom{padding:3px 0 0;background:#eee}.cke_top{white-space:normal}.cke_contents{background-color:#fff;border:1px solid #ddd;border-radius:4px}.cke_bottom{position:relative}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #555 transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #aaa;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;margin-top:5px;background-color:#fff;border:1px solid #aaa;border-radius:4px}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:178px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_list{list-style-type:none;margin:3px;padding:0;white-space:nowrap}.cke_panel_listItem{margin:0;padding-bottom:1px}.cke_panel_listItem a{padding:3px 4px;display:block;border:1px solid #fff;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis;border-radius:2px}.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{background-color:#e1edf7}* html .cke_panel_listItem a{width:100%;color:#000}*:first-child+html .cke_panel_listItem a{color:#000}.cke_panel_listItem.cke_selected a{background-color:#92bce0;outline:0}.cke_hc .cke_panel_listItem a{border-style:none}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:1px 2px}.cke_panel_grouptitle{font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:6px 6px;color:#474747;border-bottom:1px solid #aaa;background:#eee}.cke_panel_grouptitle:first-child{border-radius:4px 4px 0 0}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_colorblock{padding:3px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}span.cke_colorbox{width:10px;height:10px;border:1px solid #aaa;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorbox{border:1px solid #fff;padding:2px;float:left;width:12px;height:12px;border-radius:2px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{border:1px solid #ddd;background-color:#eee}a.cke_colorauto,a.cke_colormore{border:1px solid #fff;padding:2px;display:block;cursor:pointer}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{border:1px solid #ddd;background-color:#eee}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{float:left;margin:0 6px 3px 0;padding:2px;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_hc .cke_toolgroup{border:0;margin-right:10px;margin-bottom:10px}.cke_rtl .cke_toolgroup *:first-child{border-radius:0 4px 4px 0}.cke_rtl .cke_toolgroup *:last-child{border-radius:4px 0 0 4px}.cke_rtl .cke_toolgroup{float:right;margin-left:6px;margin-right:0}a.cke_button{display:inline-block;height:18px;padding:2px 4px;outline:0;cursor:default;float:left;border:0;border-radius:2px}.cke_rtl .cke_button{float:right}.cke_hc .cke_button{border:1px solid black;padding:3px 5px;margin:-2px 4px 0 -2px}.cke_button_on{background:#92bce0}.cke_hc .cke_button_on{border-width:3px;padding:1px 3px}.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border-width:3px;padding:1px 3px}.cke_button_disabled .cke_button_icon{opacity:.3}.cke_hc .cke_button_disabled{opacity:.5}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{background:#e1edf7}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:18px;vertical-align:middle;float:left;cursor:default;color:#555}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px -2px 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#ddd;margin:4px 2px 0;height:16px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{width:0;border-left:1px solid;margin:1px 5px 0 0}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #a6a6a6;border-bottom-color:#979797;border-radius:4px;background:#e4e4e4}.cke_toolbox_collapser:hover{background:#ccc}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#474747}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:3px solid #474747;border-top:3px solid transparent}.cke_rtl .cke_toolbox_collapser{float:left}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0;margin-right:2px}.cke_menubutton{display:block}.cke_button_icon{opacity:.8}.cke_menuitem span{cursor:default}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#d3d3d3;display:block}.cke_hc .cke_menubutton{padding:2px}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#d7d8d7;opacity:.70;filter:alpha(opacity=70);padding:4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#d0d2d0}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_on{border:1px solid #dedede;background-color:#f2f2f2}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#eff0ef}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d3d3d3;height:1px;filter:alpha(opacity=70);opacity:.70}.cke_menuarrow{background-image:url(images/arrow.png);background-position:0 10px;background-repeat:no-repeat;padding:0 5px}.cke_menuarrow span{display:none}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:-2px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_button{display:inline-block;float:left;margin:0 6px 5px 0;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus{outline:0}.cke_combo_off a.cke_combo_button:active{border-color:#333}.cke_combo_on a.cke_combo_button{border-color:#333}.cke_rtl .cke_combo_button{float:right;margin-left:5px;margin-right:0}.cke_hc a.cke_combo_button{padding:3px}.cke_hc .cke_combo_on a.cke_combo_button{border-width:3px;padding:1px}.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border-width:3px;padding:1px}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#474747;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 7px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #333}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}.cke_path_item,.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#4c4c4c;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#bfbfbf;color:#333;border-radius:2px}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combo__fontsize .cke_combo_text{width:30px}.cke_combopanel__fontsize{width:120px}.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}a.cke_button_disabled,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{filter:alpha(opacity=30)}.cke_button_disabled .cke_button_icon{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#00ffffff,endColorstr=#00ffffff)}.cke_button_off:hover,.cke_button_off:focus,.cke_button_off:active{filter:alpha(opacity=100)}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{filter:alpha(opacity=30)}.cke_toolbox_collapser{border:1px solid #a6a6a6}.cke_toolbox_collapser .cke_arrow{margin-top:1px}.cke_hc .cke_top,.cke_hc .cke_bottom,.cke_hc .cke_combo_button,.cke_hc a.cke_combo_button:hover,.cke_hc a.cke_combo_button:focus,.cke_hc .cke_toolgroup,.cke_hc .cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc .cke_toolbox_collapser,.cke_hc .cke_toolbox_collapser:hover,.cke_hc .cke_panel_grouptitle{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_ie7.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_ie7.css new file mode 100644 index 0000000..8e1f3f5 --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_ie7.css @@ -0,0 +1 @@ +.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none}.cke_reset_all,.cke_reset_all *{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#333;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;margin-top:10px;border:1px solid #ddd}.cke_reset_all fieldset legend{padding:0 5px}.cke_reset_all select{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.cke_chrome{display:block;border:1px solid #ddd;border-radius:4px;padding:0 3px;background:#eee}.cke_inner{display:block;-webkit-touch-callout:none;background:transparent;padding:0}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_float .cke_top{border:1px solid #ddd}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top,.cke_bottom{padding:3px 0 0;background:#eee}.cke_top{white-space:normal}.cke_contents{background-color:#fff;border:1px solid #ddd;border-radius:4px}.cke_bottom{position:relative}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #555 transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #aaa;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;margin-top:5px;background-color:#fff;border:1px solid #aaa;border-radius:4px}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:178px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_list{list-style-type:none;margin:3px;padding:0;white-space:nowrap}.cke_panel_listItem{margin:0;padding-bottom:1px}.cke_panel_listItem a{padding:3px 4px;display:block;border:1px solid #fff;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis;border-radius:2px}.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{background-color:#e1edf7}* html .cke_panel_listItem a{width:100%;color:#000}*:first-child+html .cke_panel_listItem a{color:#000}.cke_panel_listItem.cke_selected a{background-color:#92bce0;outline:0}.cke_hc .cke_panel_listItem a{border-style:none}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:1px 2px}.cke_panel_grouptitle{font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:6px 6px;color:#474747;border-bottom:1px solid #aaa;background:#eee}.cke_panel_grouptitle:first-child{border-radius:4px 4px 0 0}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_colorblock{padding:3px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}span.cke_colorbox{width:10px;height:10px;border:1px solid #aaa;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorbox{border:1px solid #fff;padding:2px;float:left;width:12px;height:12px;border-radius:2px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{border:1px solid #ddd;background-color:#eee}a.cke_colorauto,a.cke_colormore{border:1px solid #fff;padding:2px;display:block;cursor:pointer}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{border:1px solid #ddd;background-color:#eee}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{float:left;margin:0 6px 3px 0;padding:2px;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_hc .cke_toolgroup{border:0;margin-right:10px;margin-bottom:10px}.cke_rtl .cke_toolgroup *:first-child{border-radius:0 4px 4px 0}.cke_rtl .cke_toolgroup *:last-child{border-radius:4px 0 0 4px}.cke_rtl .cke_toolgroup{float:right;margin-left:6px;margin-right:0}a.cke_button{display:inline-block;height:18px;padding:2px 4px;outline:0;cursor:default;float:left;border:0;border-radius:2px}.cke_rtl .cke_button{float:right}.cke_hc .cke_button{border:1px solid black;padding:3px 5px;margin:-2px 4px 0 -2px}.cke_button_on{background:#92bce0}.cke_hc .cke_button_on{border-width:3px;padding:1px 3px}.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border-width:3px;padding:1px 3px}.cke_button_disabled .cke_button_icon{opacity:.3}.cke_hc .cke_button_disabled{opacity:.5}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{background:#e1edf7}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:18px;vertical-align:middle;float:left;cursor:default;color:#555}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px -2px 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#ddd;margin:4px 2px 0;height:16px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{width:0;border-left:1px solid;margin:1px 5px 0 0}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #a6a6a6;border-bottom-color:#979797;border-radius:4px;background:#e4e4e4}.cke_toolbox_collapser:hover{background:#ccc}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#474747}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:3px solid #474747;border-top:3px solid transparent}.cke_rtl .cke_toolbox_collapser{float:left}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0;margin-right:2px}.cke_menubutton{display:block}.cke_button_icon{opacity:.8}.cke_menuitem span{cursor:default}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#d3d3d3;display:block}.cke_hc .cke_menubutton{padding:2px}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#d7d8d7;opacity:.70;filter:alpha(opacity=70);padding:4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#d0d2d0}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_on{border:1px solid #dedede;background-color:#f2f2f2}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#eff0ef}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d3d3d3;height:1px;filter:alpha(opacity=70);opacity:.70}.cke_menuarrow{background-image:url(images/arrow.png);background-position:0 10px;background-repeat:no-repeat;padding:0 5px}.cke_menuarrow span{display:none}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:-2px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_button{display:inline-block;float:left;margin:0 6px 5px 0;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus{outline:0}.cke_combo_off a.cke_combo_button:active{border-color:#333}.cke_combo_on a.cke_combo_button{border-color:#333}.cke_rtl .cke_combo_button{float:right;margin-left:5px;margin-right:0}.cke_hc a.cke_combo_button{padding:3px}.cke_hc .cke_combo_on a.cke_combo_button{border-width:3px;padding:1px}.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border-width:3px;padding:1px}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#474747;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 7px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #333}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}.cke_path_item,.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#4c4c4c;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#bfbfbf;color:#333;border-radius:2px}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combo__fontsize .cke_combo_text{width:30px}.cke_combopanel__fontsize{width:120px}.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}.cke_rtl .cke_toolgroup,.cke_rtl .cke_toolbar_separator,.cke_rtl .cke_button,.cke_rtl .cke_button *,.cke_rtl .cke_combo,.cke_rtl .cke_combo *,.cke_rtl .cke_path_item,.cke_rtl .cke_path_item *,.cke_rtl .cke_path_empty{float:none}.cke_rtl .cke_toolgroup,.cke_rtl .cke_toolbar_separator,.cke_rtl .cke_combo_button,.cke_rtl .cke_combo_button *,.cke_rtl .cke_button,.cke_rtl .cke_button_icon{display:inline-block;vertical-align:top}.cke_toolbox{display:inline-block;padding-bottom:5px;height:100%}.cke_rtl .cke_toolbox{padding-bottom:0}.cke_toolbar{margin-bottom:5px}.cke_rtl .cke_toolbar{margin-bottom:0}.cke_toolgroup{height:26px}.cke_toolgroup,.cke_combo{position:relative}a.cke_button{float:none;vertical-align:top}.cke_toolbar_separator{display:inline-block;float:none;vertical-align:top;background-color:#c0c0c0}.cke_toolbox_collapser .cke_arrow{margin-top:0}.cke_toolbox_collapser .cke_arrow{border-width:4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{border-width:3px}.cke_rtl .cke_button_arrow{padding-top:8px;margin-right:2px}.cke_rtl .cke_combo_inlinelabel{display:table-cell;vertical-align:middle}.cke_menubutton{display:block;height:24px}.cke_menubutton_inner{display:block;position:relative}.cke_menubutton_icon{height:16px;width:16px}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:inline-block}.cke_menubutton_label{width:auto;vertical-align:top;line-height:24px;height:24px;margin:0 10px 0 0}.cke_menuarrow{width:5px;height:6px;padding:0;position:absolute;right:8px;top:10px;background-position:0 0}.cke_rtl .cke_menubutton_icon{position:absolute;right:0;top:0}.cke_rtl .cke_menubutton_label{float:right;clear:both;margin:0 24px 0 10px}.cke_hc .cke_rtl .cke_menubutton_label{margin-right:0}.cke_rtl .cke_menuarrow{left:8px;right:auto;background-position:0 -24px}.cke_hc .cke_menuarrow{top:5px;padding:0 5px}.cke_rtl input.cke_dialog_ui_input_text,.cke_rtl input.cke_dialog_ui_input_password{position:relative}.cke_wysiwyg_div{padding-top:0!important;padding-bottom:0!important} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_ie8.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_ie8.css new file mode 100644 index 0000000..7a10f0f --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_ie8.css @@ -0,0 +1 @@ +.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none}.cke_reset_all,.cke_reset_all *{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#333;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;margin-top:10px;border:1px solid #ddd}.cke_reset_all fieldset legend{padding:0 5px}.cke_reset_all select{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.cke_chrome{display:block;border:1px solid #ddd;border-radius:4px;padding:0 3px;background:#eee}.cke_inner{display:block;-webkit-touch-callout:none;background:transparent;padding:0}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_float .cke_top{border:1px solid #ddd}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top,.cke_bottom{padding:3px 0 0;background:#eee}.cke_top{white-space:normal}.cke_contents{background-color:#fff;border:1px solid #ddd;border-radius:4px}.cke_bottom{position:relative}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #555 transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #aaa;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;margin-top:5px;background-color:#fff;border:1px solid #aaa;border-radius:4px}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:178px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_list{list-style-type:none;margin:3px;padding:0;white-space:nowrap}.cke_panel_listItem{margin:0;padding-bottom:1px}.cke_panel_listItem a{padding:3px 4px;display:block;border:1px solid #fff;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis;border-radius:2px}.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{background-color:#e1edf7}* html .cke_panel_listItem a{width:100%;color:#000}*:first-child+html .cke_panel_listItem a{color:#000}.cke_panel_listItem.cke_selected a{background-color:#92bce0;outline:0}.cke_hc .cke_panel_listItem a{border-style:none}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:1px 2px}.cke_panel_grouptitle{font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:6px 6px;color:#474747;border-bottom:1px solid #aaa;background:#eee}.cke_panel_grouptitle:first-child{border-radius:4px 4px 0 0}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_colorblock{padding:3px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}span.cke_colorbox{width:10px;height:10px;border:1px solid #aaa;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorbox{border:1px solid #fff;padding:2px;float:left;width:12px;height:12px;border-radius:2px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{border:1px solid #ddd;background-color:#eee}a.cke_colorauto,a.cke_colormore{border:1px solid #fff;padding:2px;display:block;cursor:pointer}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{border:1px solid #ddd;background-color:#eee}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{float:left;margin:0 6px 3px 0;padding:2px;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_hc .cke_toolgroup{border:0;margin-right:10px;margin-bottom:10px}.cke_rtl .cke_toolgroup *:first-child{border-radius:0 4px 4px 0}.cke_rtl .cke_toolgroup *:last-child{border-radius:4px 0 0 4px}.cke_rtl .cke_toolgroup{float:right;margin-left:6px;margin-right:0}a.cke_button{display:inline-block;height:18px;padding:2px 4px;outline:0;cursor:default;float:left;border:0;border-radius:2px}.cke_rtl .cke_button{float:right}.cke_hc .cke_button{border:1px solid black;padding:3px 5px;margin:-2px 4px 0 -2px}.cke_button_on{background:#92bce0}.cke_hc .cke_button_on{border-width:3px;padding:1px 3px}.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border-width:3px;padding:1px 3px}.cke_button_disabled .cke_button_icon{opacity:.3}.cke_hc .cke_button_disabled{opacity:.5}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{background:#e1edf7}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:18px;vertical-align:middle;float:left;cursor:default;color:#555}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px -2px 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#ddd;margin:4px 2px 0;height:16px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{width:0;border-left:1px solid;margin:1px 5px 0 0}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #a6a6a6;border-bottom-color:#979797;border-radius:4px;background:#e4e4e4}.cke_toolbox_collapser:hover{background:#ccc}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#474747}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:3px solid #474747;border-top:3px solid transparent}.cke_rtl .cke_toolbox_collapser{float:left}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0;margin-right:2px}.cke_menubutton{display:block}.cke_button_icon{opacity:.8}.cke_menuitem span{cursor:default}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#d3d3d3;display:block}.cke_hc .cke_menubutton{padding:2px}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#d7d8d7;opacity:.70;filter:alpha(opacity=70);padding:4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#d0d2d0}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_on{border:1px solid #dedede;background-color:#f2f2f2}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#eff0ef}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d3d3d3;height:1px;filter:alpha(opacity=70);opacity:.70}.cke_menuarrow{background-image:url(images/arrow.png);background-position:0 10px;background-repeat:no-repeat;padding:0 5px}.cke_menuarrow span{display:none}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:-2px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_button{display:inline-block;float:left;margin:0 6px 5px 0;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus{outline:0}.cke_combo_off a.cke_combo_button:active{border-color:#333}.cke_combo_on a.cke_combo_button{border-color:#333}.cke_rtl .cke_combo_button{float:right;margin-left:5px;margin-right:0}.cke_hc a.cke_combo_button{padding:3px}.cke_hc .cke_combo_on a.cke_combo_button{border-width:3px;padding:1px}.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border-width:3px;padding:1px}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#474747;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 7px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #333}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}.cke_path_item,.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#4c4c4c;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#bfbfbf;color:#333;border-radius:2px}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combo__fontsize .cke_combo_text{width:30px}.cke_combopanel__fontsize{width:120px}.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}.cke_toolbox_collapser .cke_arrow{border-width:4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{border-width:3px}.cke_toolbox_collapser .cke_arrow{margin-top:0} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_iequirks.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_iequirks.css new file mode 100644 index 0000000..65e3dc7 --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/.temp/css/editor_iequirks.css @@ -0,0 +1 @@ +.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none}.cke_reset_all,.cke_reset_all *{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#333;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;margin-top:10px;border:1px solid #ddd}.cke_reset_all fieldset legend{padding:0 5px}.cke_reset_all select{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.cke_chrome{display:block;border:1px solid #ddd;border-radius:4px;padding:0 3px;background:#eee}.cke_inner{display:block;-webkit-touch-callout:none;background:transparent;padding:0}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_float .cke_top{border:1px solid #ddd}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top,.cke_bottom{padding:3px 0 0;background:#eee}.cke_top{white-space:normal}.cke_contents{background-color:#fff;border:1px solid #ddd;border-radius:4px}.cke_bottom{position:relative}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #555 transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #aaa;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;margin-top:5px;background-color:#fff;border:1px solid #aaa;border-radius:4px}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:178px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_list{list-style-type:none;margin:3px;padding:0;white-space:nowrap}.cke_panel_listItem{margin:0;padding-bottom:1px}.cke_panel_listItem a{padding:3px 4px;display:block;border:1px solid #fff;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis;border-radius:2px}.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{background-color:#e1edf7}* html .cke_panel_listItem a{width:100%;color:#000}*:first-child+html .cke_panel_listItem a{color:#000}.cke_panel_listItem.cke_selected a{background-color:#92bce0;outline:0}.cke_hc .cke_panel_listItem a{border-style:none}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:1px 2px}.cke_panel_grouptitle{font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:6px 6px;color:#474747;border-bottom:1px solid #aaa;background:#eee}.cke_panel_grouptitle:first-child{border-radius:4px 4px 0 0}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_colorblock{padding:3px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}span.cke_colorbox{width:10px;height:10px;border:1px solid #aaa;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorbox{border:1px solid #fff;padding:2px;float:left;width:12px;height:12px;border-radius:2px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{border:1px solid #ddd;background-color:#eee}a.cke_colorauto,a.cke_colormore{border:1px solid #fff;padding:2px;display:block;cursor:pointer}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{border:1px solid #ddd;background-color:#eee}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{float:left;margin:0 6px 3px 0;padding:2px;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_hc .cke_toolgroup{border:0;margin-right:10px;margin-bottom:10px}.cke_rtl .cke_toolgroup *:first-child{border-radius:0 4px 4px 0}.cke_rtl .cke_toolgroup *:last-child{border-radius:4px 0 0 4px}.cke_rtl .cke_toolgroup{float:right;margin-left:6px;margin-right:0}a.cke_button{display:inline-block;height:18px;padding:2px 4px;outline:0;cursor:default;float:left;border:0;border-radius:2px}.cke_rtl .cke_button{float:right}.cke_hc .cke_button{border:1px solid black;padding:3px 5px;margin:-2px 4px 0 -2px}.cke_button_on{background:#92bce0}.cke_hc .cke_button_on{border-width:3px;padding:1px 3px}.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border-width:3px;padding:1px 3px}.cke_button_disabled .cke_button_icon{opacity:.3}.cke_hc .cke_button_disabled{opacity:.5}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{background:#e1edf7}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:18px;vertical-align:middle;float:left;cursor:default;color:#555}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px -2px 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#ddd;margin:4px 2px 0;height:16px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{width:0;border-left:1px solid;margin:1px 5px 0 0}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #a6a6a6;border-bottom-color:#979797;border-radius:4px;background:#e4e4e4}.cke_toolbox_collapser:hover{background:#ccc}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#474747}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:3px solid #474747;border-top:3px solid transparent}.cke_rtl .cke_toolbox_collapser{float:left}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0;margin-right:2px}.cke_menubutton{display:block}.cke_button_icon{opacity:.8}.cke_menuitem span{cursor:default}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#d3d3d3;display:block}.cke_hc .cke_menubutton{padding:2px}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#d7d8d7;opacity:.70;filter:alpha(opacity=70);padding:4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#d0d2d0}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_on{border:1px solid #dedede;background-color:#f2f2f2}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#eff0ef}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d3d3d3;height:1px;filter:alpha(opacity=70);opacity:.70}.cke_menuarrow{background-image:url(images/arrow.png);background-position:0 10px;background-repeat:no-repeat;padding:0 5px}.cke_menuarrow span{display:none}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:-2px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_button{display:inline-block;float:left;margin:0 6px 5px 0;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus{outline:0}.cke_combo_off a.cke_combo_button:active{border-color:#333}.cke_combo_on a.cke_combo_button{border-color:#333}.cke_rtl .cke_combo_button{float:right;margin-left:5px;margin-right:0}.cke_hc a.cke_combo_button{padding:3px}.cke_hc .cke_combo_on a.cke_combo_button{border-width:3px;padding:1px}.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border-width:3px;padding:1px}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#474747;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 7px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #333}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}.cke_path_item,.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#4c4c4c;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#bfbfbf;color:#333;border-radius:2px}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combo__fontsize .cke_combo_text{width:30px}.cke_combopanel__fontsize{width:120px}.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}.cke_top,.cke_contents,.cke_bottom{width:100%}.cke_button_arrow{font-size:0}.cke_rtl .cke_toolgroup,.cke_rtl .cke_toolbar_separator,.cke_rtl .cke_button,.cke_rtl .cke_button *,.cke_rtl .cke_combo,.cke_rtl .cke_combo *,.cke_rtl .cke_path_item,.cke_rtl .cke_path_item *,.cke_rtl .cke_path_empty{float:none}.cke_rtl .cke_toolgroup,.cke_rtl .cke_toolbar_separator,.cke_rtl .cke_combo_button,.cke_rtl .cke_combo_button *,.cke_rtl .cke_button,.cke_rtl .cke_button_icon{display:inline-block;vertical-align:top}.cke_rtl .cke_button_icon{float:none}.cke_resizer{width:10px}.cke_source{white-space:normal}.cke_bottom{position:static}.cke_colorbox{font-size:0} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/dialog.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/dialog.css new file mode 100644 index 0000000..1ca45fd --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/dialog.css @@ -0,0 +1 @@ +input.cke_dialog_ui_input_password,input.cke_dialog_ui_input_text,textarea.cke_dialog_ui_input_textarea{background-color:#fff;outline:0;width:100%;*width:95%;height:30px;padding:4px 10px;border:1px solid #ddd;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}input.cke_dialog_ui_input_password:focus,input.cke_dialog_ui_input_text:focus,textarea.cke_dialog_ui_input_textarea:focus{border-color:#66afe9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.cke_dialog{visibility:visible}.cke_dialog_body{z-index:1;background:#eee;border:1px solid #ddd;border-radius:4px}.cke_browser_gecko19 .cke_dialog_body{position:relative}.cke_dialog strong{font-weight:700}.cke_dialog_title{font-weight:700;font-size:13px;cursor:move;position:relative;color:#333;border-bottom:1px solid #ddd;padding:10px 12px;background:#eee}.cke_dialog_contents{background-color:#fff;overflow:auto;padding:15px 10px 5px;margin-top:35px;border-top:1px solid #ddd;border-radius:0 0 4px 4px}.cke_dialog_contents_body{overflow:auto;padding:17px 10px 5px;margin-top:22px}.cke_dialog_footer{text-align:right;position:relative;border-radius:0 0 4px 4px;border-top:1px solid #ddd;background:#eee}.cke_rtl .cke_dialog_footer{text-align:left}.cke_hc .cke_dialog_footer{outline:0;border-top:1px solid #fff}.cke_dialog .cke_resizer{margin-top:28px}.cke_dialog .cke_resizer_rtl{margin-left:5px}.cke_dialog .cke_resizer_ltr{margin-right:5px}.cke_dialog_tabs{height:24px;display:inline-block;margin:10px 0 0;position:absolute;z-index:2;left:10px}.cke_rtl .cke_dialog_tabs{right:10px}a.cke_dialog_tab{height:16px;padding:4px 8px;margin-right:3px;display:inline-block;cursor:pointer;line-height:16px;outline:0;color:#555;border:1px solid #ddd;border-radius:3px 3px 0 0;background:#f3f3f3}.cke_rtl a.cke_dialog_tab{margin-right:0;margin-left:3px}a.cke_dialog_tab:hover{background:#ddd;text-decoration:none}a.cke_dialog_tab_selected{background:#fff;color:#333;border-bottom-color:#fff;cursor:default;filter:none}a.cke_dialog_tab_selected:hover{background:#fff}.cke_hc a.cke_dialog_tab:hover,.cke_hc a.cke_dialog_tab_selected{border:3px solid;padding:2px 6px}a.cke_dialog_tab_disabled{color:#bababa;cursor:default}.cke_dialog_tabs .cke_dialog_ui_input_select{top:-7px!important}.cke_single_page .cke_dialog_tabs{display:none}.cke_single_page .cke_dialog_contents{padding-top:5px;margin-top:0;border-top:0}.cke_dialog_close_button{background-image:url(images/close.png);background-repeat:no-repeat;background-position:0 0;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:9px;z-index:5}.cke_hidpi .cke_dialog_close_button{background-image:url(images/hidpi/close.png);background-size:16px}.cke_dialog_close_button span{display:none}.cke_hc .cke_dialog_close_button span{display:inline;cursor:pointer;font-weight:700;position:relative;top:3px}.cke_ltr .cke_dialog_close_button{right:5px}.cke_rtl .cke_dialog_close_button{left:6px}div.cke_disabled .cke_dialog_ui_labeled_content div *{background-color:#ddd;cursor:default}.cke_dialog_ui_hbox table,.cke_dialog_ui_vbox table{margin:auto}.cke_dialog_ui_vbox{margin-top:5px}.cke_dialog_ui_vbox_child{padding:5px 0}.cke_dialog_ui_hbox{width:100%}.cke_dialog_ui_hbox_child,.cke_dialog_ui_hbox_first,.cke_dialog_ui_hbox_last{vertical-align:top}.cke_dialog_ui_hbox_first>.cke_dialog_ui_html,.cke_dialog_ui_hbox_first>.cke_dialog_ui_labeled_label,.cke_dialog_ui_hbox_last>.cke_dialog_ui_html,.cke_dialog_ui_hbox_last>.cke_dialog_ui_labeled_label{line-height:30px}.cke_ltr .cke_dialog_ui_hbox_child,.cke_ltr .cke_dialog_ui_hbox_first{padding-right:10px}.cke_rtl .cke_dialog_ui_hbox_child,.cke_rtl .cke_dialog_ui_hbox_first{padding-left:10px}.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child,.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first{padding-right:5px}.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child,.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first{padding-left:5px;padding-right:0}.cke_hc div.cke_dialog_ui_input_file,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_textarea{border:1px solid}.cke_dialog_ui_text{margin-bottom:7px}.cke_dialog_ui_select{height:auto!important;margin-bottom:7px}textarea.cke_dialog_ui_input_textarea{overflow:auto;resize:none}a.cke_dialog_ui_button{display:inline-block;*display:inline;*zoom:1;padding:3px 0;margin:0;text-align:center;color:#333;vertical-align:middle;cursor:pointer;border:1px solid #ddd;border-radius:4px;background:#fff}a.cke_dialog_ui_button:active,a.cke_dialog_ui_button:focus,a.cke_dialog_ui_button:hover{border-color:#aaa;background-color:#eee;text-decoration:none}.cke_dialog_page_contents a.cke_dialog_ui_button{height:22px;line-height:22px;background-color:#f4f4f4}.cke_dialog_page_contents a.cke_dialog_ui_button:active,.cke_dialog_page_contents a.cke_dialog_ui_button:focus,.cke_dialog_page_contents a.cke_dialog_ui_button:hover{background-color:#eee}span.cke_dialog_ui_button{padding:0 12px}.cke_hc a.cke_dialog_ui_button:active,.cke_hc a.cke_dialog_ui_button:focus,.cke_hc a.cke_dialog_ui_button:hover{border:3px solid;padding-top:1px;padding-bottom:1px}.cke_hc a.cke_dialog_ui_button:active span,.cke_hc a.cke_dialog_ui_button:focus span,.cke_hc a.cke_dialog_ui_button:hover span{padding-left:10px;padding-right:10px}.cke_dialog_footer_buttons a.cke_dialog_ui_button span{color:inherit;font-size:12px;line-height:20px}a.cke_dialog_ui_button_ok{color:#fff;border-color:#2274c9;background:#3f8edf}a.cke_dialog_ui_button_ok:active,a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:hover{border-color:#1e68b4;background:#2981db}a.cke_dialog_ui_button_cancel{background-color:#fff}a.cke_dialog_ui_button_cancel:focus{outline:0}span.cke_dialog_ui_button{cursor:pointer}.cke_dialog_footer_buttons{display:inline-table;margin:10px;width:auto;position:relative;vertical-align:middle}div.cke_dialog_ui_input_select{display:table}select.cke_dialog_ui_input_select{height:30px;line-height:30px;background-color:#fff;padding:4px 10px;border:1px solid #ddd;outline:0;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.cke_dialog_ui_input_file{width:100%;height:30px}.cke_hc .cke_dialog_ui_labeled_content input:focus,.cke_hc .cke_dialog_ui_labeled_content select:focus,.cke_hc .cke_dialog_ui_labeled_content textarea:focus{outline:1px dotted}.cke_dialog .cke_dark_background,.cke_dialog .cke_light_background{background-color:#eee}.cke_dialog .cke_centered{text-align:center}.cke_dialog a.cke_btn_reset{float:right;background:url(images/refresh.png) top left no-repeat;width:16px;height:16px;border:1px none;font-size:1px}.cke_dialog a.cke_btn_locked,.cke_dialog a.cke_btn_unlocked{float:left;width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.cke_dialog a.cke_btn_locked{background-image:url(images/lock.png)}.cke_dialog a.cke_btn_locked .cke_icon{display:none}.cke_dialog a.cke_btn_unlocked{background-image:url(images/lock-open.png)}.cke_dialog .cke_btn_over{border:outset 1px;cursor:pointer}.cke_hidpi .cke_dialog a.cke_btn_reset{background-size:16px;background-image:url(images/hidpi/refresh.png)}.cke_hidpi .cke_dialog a.cke_btn_locked,.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-size:16px}.cke_hidpi .cke_dialog a.cke_btn_locked{background-image:url(images/hidpi/lock.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-image:url(images/hidpi/lock-open.png)}.cke_rtl .cke_dialog a.cke_btn_reset{float:left}.cke_rtl .cke_dialog a.cke_btn_locked,.cke_rtl .cke_dialog a.cke_btn_unlocked{float:right}.cke_dialog .FlashPreviewBox,.cke_dialog .ImagePreviewBox{border:1px solid #aaa;border-radius:4px;padding:6px 10px;margin-top:5px;background-color:#fff}.cke_dialog .ImagePreviewBox{overflow:scroll;height:205px;width:300px}.cke_dialog .ImagePreviewBox table td{white-space:normal}.cke_dialog .FlashPreviewBox{white-space:normal;overflow:auto;height:160px;width:390px}.cke_dialog .ImagePreviewLoader{position:absolute;white-space:normal;overflow:hidden;height:160px;width:230px;margin:2px;padding:2px;opacity:.9;filter:alpha(opacity=90);background-color:#e4e4e4}.cke_dialog .cke_pastetext{width:346px;height:170px}.cke_dialog .cke_pastetext textarea{width:340px;height:170px;resize:none}.cke_dialog iframe.cke_pasteframe{width:346px;height:130px;background-color:#fff;border:1px solid #aeb3b9;border-radius:4px}.cke_dialog .cke_hand{cursor:pointer}.cke_disabled{color:#a0a0a0}.cke_dialog_body .cke_label{display:none}.cke_dialog_body label{display:inline-block;margin-bottom:3px;cursor:default}.cke_dialog_body label.cke_required{font-weight:700}.cke_dialog_ui_html{line-height:150%}a.cke_smile{overflow:hidden;display:block;text-align:center;padding:.3em 0}a.cke_smile img{vertical-align:middle}a.cke_specialchar{cursor:inherit;display:block;height:1.25em;padding:.2em .3em;text-align:center}a.cke_smile,a.cke_specialchar{background-color:#eee;border:1px solid transparent;vertical-align:top}a.cke_smile:active,a.cke_smile:focus,a.cke_smile:hover,a.cke_specialchar:active,a.cke_specialchar:focus,a.cke_specialchar:hover{background:#fff;outline:0}a.cke_smile:hover,a.cke_specialchar:hover{border-color:#aaa}a.cke_smile:active,a.cke_smile:focus,a.cke_specialchar:active,a.cke_specialchar:focus{border-color:#428bca}.cke_dialog_contents a.colorChooser{display:block;margin-top:6px;margin-left:10px;width:80px}.cke_rtl .cke_dialog_contents a.colorChooser{margin-right:10px}.cke_dialog_ui_checkbox{display:inline-block;margin-bottom:5px}.cke_btn_over,.cke_dialog_ui_checkbox_input:focus,.cke_dialog_ui_radio_input:focus{outline:1px dotted #696969}.cke_iframe_shim{display:block;position:absolute;top:0;left:0;z-index:-1;filter:alpha(opacity=0);width:100%;height:100%} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_ie.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_ie.css new file mode 100644 index 0000000..49c228b --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_ie.css @@ -0,0 +1 @@ +input.cke_dialog_ui_input_password,input.cke_dialog_ui_input_text,textarea.cke_dialog_ui_input_textarea{background-color:#fff;outline:0;width:100%;*width:95%;height:30px;padding:4px 10px;border:1px solid #ddd;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}input.cke_dialog_ui_input_password:focus,input.cke_dialog_ui_input_text:focus,textarea.cke_dialog_ui_input_textarea:focus{border-color:#66afe9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.cke_dialog{visibility:visible}.cke_dialog_body{z-index:1;background:#eee;border:1px solid #ddd;border-radius:4px}.cke_browser_gecko19 .cke_dialog_body{position:relative}.cke_dialog strong{font-weight:700}.cke_dialog_title{font-weight:700;font-size:13px;cursor:move;position:relative;color:#333;border-bottom:1px solid #ddd;padding:10px 12px;background:#eee}.cke_dialog_contents{background-color:#fff;overflow:auto;padding:15px 10px 5px;margin-top:35px;border-top:1px solid #ddd;border-radius:0 0 4px 4px}.cke_dialog_contents_body{overflow:auto;padding:17px 10px 5px;margin-top:22px}.cke_dialog_footer{text-align:right;position:relative;border-radius:0 0 4px 4px;border-top:1px solid #ddd;background:#eee}.cke_rtl .cke_dialog_footer{text-align:left}.cke_hc .cke_dialog_footer{outline:0;border-top:1px solid #fff}.cke_dialog .cke_resizer{margin-top:28px}.cke_dialog .cke_resizer_rtl{margin-left:5px}.cke_dialog .cke_resizer_ltr{margin-right:5px}.cke_dialog_tabs{height:24px;display:inline-block;margin:10px 0 0;position:absolute;z-index:2;left:10px}.cke_rtl .cke_dialog_tabs{right:10px}a.cke_dialog_tab{height:16px;padding:4px 8px;margin-right:3px;display:inline-block;cursor:pointer;line-height:16px;outline:0;color:#555;border:1px solid #ddd;border-radius:3px 3px 0 0;background:#f3f3f3}.cke_rtl a.cke_dialog_tab{margin-right:0;margin-left:3px}a.cke_dialog_tab:hover{background:#ddd;text-decoration:none}a.cke_dialog_tab_selected{background:#fff;color:#333;border-bottom-color:#fff;cursor:default;filter:none}a.cke_dialog_tab_selected:hover{background:#fff}.cke_hc a.cke_dialog_tab:hover,.cke_hc a.cke_dialog_tab_selected{border:3px solid;padding:2px 6px}a.cke_dialog_tab_disabled{color:#bababa;cursor:default}.cke_dialog_tabs .cke_dialog_ui_input_select{top:-7px!important}.cke_single_page .cke_dialog_tabs{display:none}.cke_single_page .cke_dialog_contents{padding-top:5px;margin-top:0;border-top:0}.cke_dialog_close_button{background-image:url(images/close.png);background-repeat:no-repeat;background-position:0 0;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:9px;z-index:5}.cke_hidpi .cke_dialog_close_button{background-image:url(images/hidpi/close.png);background-size:16px}.cke_dialog_close_button span{display:none}.cke_hc .cke_dialog_close_button span{display:inline;cursor:pointer;font-weight:700;position:relative;top:3px}.cke_ltr .cke_dialog_close_button{right:5px}.cke_rtl .cke_dialog_close_button{left:6px}div.cke_disabled .cke_dialog_ui_labeled_content div *{background-color:#ddd;cursor:default}.cke_dialog_ui_hbox table,.cke_dialog_ui_vbox table{margin:auto}.cke_dialog_ui_vbox{margin-top:5px}.cke_dialog_ui_vbox_child{padding:5px 0}.cke_dialog_ui_hbox{width:100%}.cke_dialog_ui_hbox_child,.cke_dialog_ui_hbox_first,.cke_dialog_ui_hbox_last{vertical-align:top}.cke_dialog_ui_hbox_first>.cke_dialog_ui_html,.cke_dialog_ui_hbox_first>.cke_dialog_ui_labeled_label,.cke_dialog_ui_hbox_last>.cke_dialog_ui_html,.cke_dialog_ui_hbox_last>.cke_dialog_ui_labeled_label{line-height:30px}.cke_ltr .cke_dialog_ui_hbox_child,.cke_ltr .cke_dialog_ui_hbox_first{padding-right:10px}.cke_rtl .cke_dialog_ui_hbox_child,.cke_rtl .cke_dialog_ui_hbox_first{padding-left:10px}.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child,.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first{padding-right:5px}.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child,.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first{padding-left:5px;padding-right:0}.cke_dialog_ui_text{margin-bottom:7px}.cke_dialog_ui_select{height:auto!important;margin-bottom:7px}textarea.cke_dialog_ui_input_textarea{overflow:auto;resize:none}a.cke_dialog_ui_button{display:inline-block;*display:inline;*zoom:1;padding:3px 0;margin:0;text-align:center;color:#333;vertical-align:middle;cursor:pointer;border:1px solid #ddd;border-radius:4px;background:#fff}a.cke_dialog_ui_button:active,a.cke_dialog_ui_button:focus,a.cke_dialog_ui_button:hover{border-color:#aaa;background-color:#eee;text-decoration:none}.cke_dialog_page_contents a.cke_dialog_ui_button{height:22px;line-height:22px;background-color:#f4f4f4}.cke_dialog_page_contents a.cke_dialog_ui_button:active,.cke_dialog_page_contents a.cke_dialog_ui_button:focus,.cke_dialog_page_contents a.cke_dialog_ui_button:hover{background-color:#eee}span.cke_dialog_ui_button{padding:0 12px}.cke_hc a.cke_dialog_ui_button:active,.cke_hc a.cke_dialog_ui_button:focus,.cke_hc a.cke_dialog_ui_button:hover{border:3px solid;padding-top:1px;padding-bottom:1px}.cke_hc a.cke_dialog_ui_button:active span,.cke_hc a.cke_dialog_ui_button:focus span,.cke_hc a.cke_dialog_ui_button:hover span{padding-left:10px;padding-right:10px}.cke_dialog_footer_buttons a.cke_dialog_ui_button span{color:inherit;font-size:12px;line-height:20px}a.cke_dialog_ui_button_ok{color:#fff;border-color:#2274c9;background:#3f8edf}a.cke_dialog_ui_button_ok:active,a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:hover{border-color:#1e68b4;background:#2981db}a.cke_dialog_ui_button_cancel{background-color:#fff}a.cke_dialog_ui_button_cancel:focus{outline:0}span.cke_dialog_ui_button{cursor:pointer}.cke_dialog_footer_buttons{display:inline-table;margin:10px;width:auto;position:relative;vertical-align:middle}div.cke_dialog_ui_input_select{display:table}select.cke_dialog_ui_input_select{height:30px;line-height:30px;background-color:#fff;padding:4px 10px;border:1px solid #ddd;outline:0;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.cke_dialog_ui_input_file{width:100%;height:30px}.cke_hc .cke_dialog_ui_labeled_content input:focus,.cke_hc .cke_dialog_ui_labeled_content select:focus,.cke_hc .cke_dialog_ui_labeled_content textarea:focus{outline:1px dotted}.cke_dialog .cke_dark_background,.cke_dialog .cke_light_background{background-color:#eee}.cke_dialog .cke_centered{text-align:center}.cke_dialog a.cke_btn_reset{float:right;background:url(images/refresh.png) top left no-repeat;width:16px;height:16px;border:1px none;font-size:1px}.cke_dialog a.cke_btn_locked,.cke_dialog a.cke_btn_unlocked{float:left;width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.cke_dialog a.cke_btn_locked{background-image:url(images/lock.png)}.cke_dialog a.cke_btn_locked .cke_icon{display:none}.cke_dialog a.cke_btn_unlocked{background-image:url(images/lock-open.png)}.cke_dialog .cke_btn_over{border:outset 1px;cursor:pointer}.cke_hidpi .cke_dialog a.cke_btn_reset{background-size:16px;background-image:url(images/hidpi/refresh.png)}.cke_hidpi .cke_dialog a.cke_btn_locked,.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-size:16px}.cke_hidpi .cke_dialog a.cke_btn_locked{background-image:url(images/hidpi/lock.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-image:url(images/hidpi/lock-open.png)}.cke_rtl .cke_dialog a.cke_btn_reset{float:left}.cke_rtl .cke_dialog a.cke_btn_locked,.cke_rtl .cke_dialog a.cke_btn_unlocked{float:right}.cke_dialog .FlashPreviewBox,.cke_dialog .ImagePreviewBox{border:1px solid #aaa;border-radius:4px;padding:6px 10px;margin-top:5px;background-color:#fff}.cke_dialog .ImagePreviewBox{overflow:scroll;height:205px;width:300px}.cke_dialog .ImagePreviewBox table td{white-space:normal}.cke_dialog .FlashPreviewBox{white-space:normal;overflow:auto;height:160px;width:390px}.cke_dialog .ImagePreviewLoader{position:absolute;white-space:normal;overflow:hidden;height:160px;width:230px;margin:2px;padding:2px;opacity:.9;filter:alpha(opacity=90);background-color:#e4e4e4}.cke_dialog .cke_pastetext{width:346px;height:170px}.cke_dialog .cke_pastetext textarea{width:340px;height:170px;resize:none}.cke_dialog iframe.cke_pasteframe{width:346px;height:130px;background-color:#fff;border:1px solid #aeb3b9;border-radius:4px}.cke_dialog .cke_hand{cursor:pointer}.cke_disabled{color:#a0a0a0}.cke_dialog_body .cke_label{display:none}.cke_dialog_body label{display:inline-block;margin-bottom:3px;cursor:default}.cke_dialog_body label.cke_required{font-weight:700}.cke_dialog_ui_html{line-height:150%}a.cke_smile{overflow:hidden;display:block;text-align:center;padding:.3em 0}a.cke_smile img{vertical-align:middle}a.cke_specialchar{cursor:inherit;display:block;height:1.25em;padding:.2em .3em;text-align:center}a.cke_smile,a.cke_specialchar{background-color:#eee;border:1px solid transparent;vertical-align:top}a.cke_smile:active,a.cke_smile:focus,a.cke_smile:hover,a.cke_specialchar:active,a.cke_specialchar:focus,a.cke_specialchar:hover{background:#fff;outline:0}a.cke_smile:hover,a.cke_specialchar:hover{border-color:#aaa}a.cke_smile:active,a.cke_smile:focus,a.cke_specialchar:active,a.cke_specialchar:focus{border-color:#428bca}.cke_dialog_contents a.colorChooser{display:block;margin-top:6px;margin-left:10px;width:80px}.cke_rtl .cke_dialog_contents a.colorChooser{margin-right:10px}.cke_dialog_ui_checkbox{display:inline-block;margin-bottom:5px}.cke_btn_over,.cke_dialog_ui_checkbox_input:focus,.cke_dialog_ui_radio_input:focus{outline:1px dotted #696969}.cke_iframe_shim{display:block;position:absolute;top:0;left:0;z-index:-1;filter:alpha(opacity=0);width:100%;height:100%}.cke_rtl input.cke_dialog_ui_input_password,.cke_rtl input.cke_dialog_ui_input_text{padding-right:2px}.cke_rtl div.cke_dialog_ui_input_password,.cke_rtl div.cke_dialog_ui_input_text{padding-left:2px}.cke_rtl div.cke_dialog_ui_input_text{padding-right:1px}.cke_rtl .cke_dialog_ui_hbox_child,.cke_rtl .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_ui_hbox_last,.cke_rtl .cke_dialog_ui_vbox_child{padding-right:2px!important}.cke_hc .cke_dialog_footer,.cke_hc .cke_dialog_title,.cke_hc a.cke_dialog_tab,.cke_hc a.cke_dialog_ui_button,.cke_hc a.cke_dialog_ui_button:hover,.cke_hc a.cke_dialog_ui_button_ok,.cke_hc a.cke_dialog_ui_button_ok:hover{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.cke_hc div.cke_dialog_ui_input_file,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_textarea{border:0} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_ie7.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_ie7.css new file mode 100644 index 0000000..d3e7e7e --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_ie7.css @@ -0,0 +1 @@ +input.cke_dialog_ui_input_password,input.cke_dialog_ui_input_text,textarea.cke_dialog_ui_input_textarea{background-color:#fff;outline:0;width:100%;*width:95%;height:30px;padding:4px 10px;border:1px solid #ddd;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}input.cke_dialog_ui_input_password:focus,input.cke_dialog_ui_input_text:focus,textarea.cke_dialog_ui_input_textarea:focus{border-color:#66afe9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.cke_dialog{visibility:visible}.cke_dialog_body{z-index:1;background:#eee;border:1px solid #ddd;border-radius:4px}.cke_browser_gecko19 .cke_dialog_body{position:relative}.cke_dialog strong{font-weight:700}.cke_dialog_title{font-weight:700;font-size:13px;cursor:move;position:relative;color:#333;border-bottom:1px solid #ddd;padding:10px 12px;background:#eee}.cke_dialog_contents{background-color:#fff;overflow:auto;padding:15px 10px 5px;margin-top:35px;border-top:1px solid #ddd;border-radius:0 0 4px 4px}.cke_dialog_contents_body{overflow:auto;padding:17px 10px 5px;margin-top:22px}.cke_dialog_footer{text-align:right;position:relative;border-radius:0 0 4px 4px;background:#eee}.cke_rtl .cke_dialog_footer{text-align:left}.cke_hc .cke_dialog_footer{outline:0;border-top:1px solid #fff}.cke_dialog .cke_resizer{margin-top:28px}.cke_dialog .cke_resizer_rtl{margin-left:5px}.cke_dialog .cke_resizer_ltr{margin-right:5px}.cke_dialog_tabs{height:24px;display:inline-block;margin:10px 0 0;position:absolute;z-index:2;left:10px}.cke_rtl .cke_dialog_tabs{right:10px}a.cke_dialog_tab{height:16px;padding:4px 8px;margin-right:3px;display:inline-block;cursor:pointer;line-height:16px;outline:0;color:#555;border:1px solid #ddd;border-radius:3px 3px 0 0;background:#f3f3f3}.cke_rtl a.cke_dialog_tab{margin-right:0;margin-left:3px}a.cke_dialog_tab:hover{background:#ddd;text-decoration:none}a.cke_dialog_tab_selected{background:#fff;color:#333;border-bottom-color:#fff;cursor:default;filter:none}a.cke_dialog_tab_selected:hover{background:#fff}.cke_hc a.cke_dialog_tab:hover,.cke_hc a.cke_dialog_tab_selected{border:3px solid;padding:2px 6px}a.cke_dialog_tab_disabled{color:#bababa;cursor:default}.cke_dialog_tabs .cke_dialog_ui_input_select{top:-7px!important}.cke_single_page .cke_dialog_tabs{display:none}.cke_single_page .cke_dialog_contents{padding-top:5px;margin-top:0;border-top:0}.cke_dialog_close_button{background-image:url(images/close.png);background-repeat:no-repeat;background-position:0 0;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:9px;z-index:5}.cke_hidpi .cke_dialog_close_button{background-image:url(images/hidpi/close.png);background-size:16px}.cke_dialog_close_button span{display:none}.cke_hc .cke_dialog_close_button span{display:inline;cursor:pointer;font-weight:700;position:relative;top:3px}.cke_ltr .cke_dialog_close_button{right:5px}.cke_rtl .cke_dialog_close_button{left:6px}div.cke_disabled .cke_dialog_ui_labeled_content div *{background-color:#ddd;cursor:default}.cke_dialog_ui_hbox table,.cke_dialog_ui_vbox table{margin:auto}.cke_dialog_ui_vbox{margin-top:5px}.cke_dialog_ui_vbox_child{padding:5px 0}.cke_dialog_ui_hbox{width:100%}.cke_dialog_ui_hbox_child,.cke_dialog_ui_hbox_first,.cke_dialog_ui_hbox_last{vertical-align:top}.cke_dialog_ui_hbox_first>.cke_dialog_ui_html,.cke_dialog_ui_hbox_first>.cke_dialog_ui_labeled_label,.cke_dialog_ui_hbox_last>.cke_dialog_ui_html,.cke_dialog_ui_hbox_last>.cke_dialog_ui_labeled_label{line-height:30px}.cke_ltr .cke_dialog_ui_hbox_child,.cke_ltr .cke_dialog_ui_hbox_first{padding-right:10px}.cke_rtl .cke_dialog_ui_hbox_child,.cke_rtl .cke_dialog_ui_hbox_first{padding-left:10px}.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child,.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first{padding-right:5px}.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child,.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first{padding-left:5px;padding-right:0}.cke_hc div.cke_dialog_ui_input_file,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_textarea{border:1px solid}.cke_dialog_ui_text{margin-bottom:7px}.cke_dialog_ui_select{height:auto!important;margin-bottom:7px}textarea.cke_dialog_ui_input_textarea{overflow:auto;resize:none}a.cke_dialog_ui_button{display:inline-block;*display:inline;*zoom:1;padding:3px 0;margin:0;text-align:center;color:#333;vertical-align:middle;cursor:pointer;border:1px solid #ddd;border-radius:4px;background:#fff}a.cke_dialog_ui_button:active,a.cke_dialog_ui_button:focus,a.cke_dialog_ui_button:hover{border-color:#aaa;background-color:#eee;text-decoration:none}.cke_dialog_page_contents a.cke_dialog_ui_button{height:22px;line-height:22px;background-color:#f4f4f4}.cke_dialog_page_contents a.cke_dialog_ui_button:active,.cke_dialog_page_contents a.cke_dialog_ui_button:focus,.cke_dialog_page_contents a.cke_dialog_ui_button:hover{background-color:#eee}span.cke_dialog_ui_button{padding:0 12px}.cke_hc a.cke_dialog_ui_button:active,.cke_hc a.cke_dialog_ui_button:focus,.cke_hc a.cke_dialog_ui_button:hover{border:3px solid;padding-top:1px;padding-bottom:1px}.cke_hc a.cke_dialog_ui_button:active span,.cke_hc a.cke_dialog_ui_button:focus span,.cke_hc a.cke_dialog_ui_button:hover span{padding-left:10px;padding-right:10px}.cke_dialog_footer_buttons a.cke_dialog_ui_button span{color:inherit;font-size:12px;line-height:20px}a.cke_dialog_ui_button_ok{color:#fff;border-color:#2274c9;background:#3f8edf}a.cke_dialog_ui_button_ok:active,a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:hover{border-color:#1e68b4;background:#2981db}a.cke_dialog_ui_button_cancel{background-color:#fff}a.cke_dialog_ui_button_cancel:focus{outline:0}span.cke_dialog_ui_button{cursor:pointer}.cke_dialog_footer_buttons{display:inline-table;margin:10px;width:auto;vertical-align:middle}div.cke_dialog_ui_input_select{display:table}select.cke_dialog_ui_input_select{height:30px;line-height:30px;background-color:#fff;padding:4px 10px;border:1px solid #ddd;outline:0;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.cke_dialog_ui_input_file{width:100%;height:30px}.cke_hc .cke_dialog_ui_labeled_content input:focus,.cke_hc .cke_dialog_ui_labeled_content select:focus,.cke_hc .cke_dialog_ui_labeled_content textarea:focus{outline:1px dotted}.cke_dialog .cke_dark_background,.cke_dialog .cke_light_background{background-color:#eee}.cke_dialog .cke_centered{text-align:center}.cke_dialog a.cke_btn_reset{float:right;background:url(images/refresh.png) top left no-repeat;width:16px;height:16px;border:1px none;font-size:1px}.cke_dialog a.cke_btn_locked,.cke_dialog a.cke_btn_unlocked{float:left;width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.cke_dialog a.cke_btn_locked{background-image:url(images/lock.png)}.cke_dialog a.cke_btn_locked .cke_icon{display:none}.cke_dialog a.cke_btn_unlocked{background-image:url(images/lock-open.png)}.cke_dialog .cke_btn_over{border:outset 1px;cursor:pointer}.cke_hidpi .cke_dialog a.cke_btn_reset{background-size:16px;background-image:url(images/hidpi/refresh.png)}.cke_hidpi .cke_dialog a.cke_btn_locked,.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-size:16px}.cke_hidpi .cke_dialog a.cke_btn_locked{background-image:url(images/hidpi/lock.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-image:url(images/hidpi/lock-open.png)}.cke_rtl .cke_dialog a.cke_btn_reset{float:left}.cke_rtl .cke_dialog a.cke_btn_locked,.cke_rtl .cke_dialog a.cke_btn_unlocked{float:right}.cke_dialog .FlashPreviewBox,.cke_dialog .ImagePreviewBox{border:1px solid #aaa;border-radius:4px;padding:6px 10px;margin-top:5px;background-color:#fff}.cke_dialog .ImagePreviewBox{overflow:scroll;height:205px;width:300px}.cke_dialog .ImagePreviewBox table td{white-space:normal}.cke_dialog .FlashPreviewBox{white-space:normal;overflow:auto;height:160px;width:390px}.cke_dialog .ImagePreviewLoader{position:absolute;white-space:normal;overflow:hidden;height:160px;width:230px;margin:2px;padding:2px;opacity:.9;filter:alpha(opacity=90);background-color:#e4e4e4}.cke_dialog .cke_pastetext{width:346px;height:170px}.cke_dialog .cke_pastetext textarea{width:340px;height:170px;resize:none}.cke_dialog iframe.cke_pasteframe{width:346px;height:130px;background-color:#fff;border:1px solid #aeb3b9;border-radius:4px}.cke_dialog .cke_hand{cursor:pointer}.cke_disabled{color:#a0a0a0}.cke_dialog_body .cke_label{display:none}.cke_dialog_body label{display:inline-block;margin-bottom:3px;cursor:default}.cke_dialog_body label.cke_required{font-weight:700}.cke_dialog_ui_html{line-height:150%}a.cke_smile{overflow:hidden;display:block;text-align:center;padding:.3em 0}a.cke_smile img{vertical-align:middle}a.cke_specialchar{cursor:inherit;display:block;height:1.25em;padding:.2em .3em;text-align:center}a.cke_smile,a.cke_specialchar{background-color:#eee;border:1px solid transparent;vertical-align:top}a.cke_smile:active,a.cke_smile:focus,a.cke_smile:hover,a.cke_specialchar:active,a.cke_specialchar:focus,a.cke_specialchar:hover{background:#fff;outline:0}a.cke_smile:hover,a.cke_specialchar:hover{border-color:#aaa}a.cke_smile:active,a.cke_smile:focus,a.cke_specialchar:active,a.cke_specialchar:focus{border-color:#428bca}.cke_dialog_contents a.colorChooser{display:block;margin-top:6px;margin-left:10px;width:80px}.cke_rtl .cke_dialog_contents a.colorChooser{margin-right:10px}.cke_dialog_ui_checkbox{display:inline-block;margin-bottom:5px}.cke_btn_over,.cke_dialog_ui_checkbox_input:focus,.cke_dialog_ui_radio_input:focus{outline:1px dotted #696969}.cke_iframe_shim{display:block;position:absolute;top:0;left:0;z-index:-1;filter:alpha(opacity=0);width:100%;height:100%}.cke_dialog_title{zoom:1}.cke_dialog_footer{border-top:1px solid #bfbfbf}.cke_dialog_footer_buttons{position:static}.cke_dialog_footer_buttons a.cke_dialog_ui_button{vertical-align:top}.cke_dialog .cke_resizer_ltr{padding-left:4px}.cke_dialog .cke_resizer_rtl{padding-right:4px}.cke_dialog_ui_input_password,.cke_dialog_ui_input_select,.cke_dialog_ui_input_text,.cke_dialog_ui_input_textarea{padding:0!important}.cke_btn_locked,.cke_btn_reset,.cke_btn_unlocked,.cke_dialog_ui_checkbox_input,.cke_dialog_ui_ratio_input{border:1px solid transparent!important} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_ie8.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_ie8.css new file mode 100644 index 0000000..9a71a5f --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_ie8.css @@ -0,0 +1 @@ +input.cke_dialog_ui_input_password,input.cke_dialog_ui_input_text,textarea.cke_dialog_ui_input_textarea{background-color:#fff;outline:0;width:100%;*width:95%;height:30px;padding:4px 10px;border:1px solid #ddd;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}input.cke_dialog_ui_input_password:focus,input.cke_dialog_ui_input_text:focus,textarea.cke_dialog_ui_input_textarea:focus{border-color:#66afe9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.cke_dialog{visibility:visible}.cke_dialog_body{z-index:1;background:#eee;border:1px solid #ddd;border-radius:4px}.cke_browser_gecko19 .cke_dialog_body{position:relative}.cke_dialog strong{font-weight:700}.cke_dialog_title{font-weight:700;font-size:13px;cursor:move;position:relative;color:#333;border-bottom:1px solid #ddd;padding:10px 12px;background:#eee}.cke_dialog_contents{background-color:#fff;overflow:auto;padding:15px 10px 5px;margin-top:35px;border-top:1px solid #ddd;border-radius:0 0 4px 4px}.cke_dialog_contents_body{overflow:auto;padding:17px 10px 5px;margin-top:22px}.cke_dialog_footer{text-align:right;position:relative;border-radius:0 0 4px 4px;border-top:1px solid #ddd;background:#eee}.cke_rtl .cke_dialog_footer{text-align:left}.cke_hc .cke_dialog_footer{outline:0;border-top:1px solid #fff}.cke_dialog .cke_resizer{margin-top:28px}.cke_dialog .cke_resizer_rtl{margin-left:5px}.cke_dialog .cke_resizer_ltr{margin-right:5px}.cke_dialog_tabs{height:24px;display:inline-block;margin:10px 0 0;position:absolute;z-index:2;left:10px}.cke_rtl .cke_dialog_tabs{right:10px}a.cke_dialog_tab{height:16px;padding:4px 8px;margin-right:3px;display:inline-block;cursor:pointer;line-height:16px;outline:0;color:#555;border:1px solid #ddd;border-radius:3px 3px 0 0;background:#f3f3f3}.cke_rtl a.cke_dialog_tab{margin-right:0;margin-left:3px}a.cke_dialog_tab:hover{background:#ddd;text-decoration:none}a.cke_dialog_tab_selected{background:#fff;color:#333;border-bottom-color:#fff;cursor:default;filter:none}a.cke_dialog_tab_selected:hover{background:#fff}.cke_hc a.cke_dialog_tab:hover,.cke_hc a.cke_dialog_tab_selected{border:3px solid;padding:2px 6px}a.cke_dialog_tab_disabled{color:#bababa;cursor:default}.cke_dialog_tabs .cke_dialog_ui_input_select{top:-7px!important}.cke_single_page .cke_dialog_tabs{display:none}.cke_single_page .cke_dialog_contents{padding-top:5px;margin-top:0;border-top:0}.cke_dialog_close_button{background-image:url(images/close.png);background-repeat:no-repeat;background-position:0 0;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:9px;z-index:5}.cke_hidpi .cke_dialog_close_button{background-image:url(images/hidpi/close.png);background-size:16px}.cke_dialog_close_button span{display:none}.cke_hc .cke_dialog_close_button span{display:inline;cursor:pointer;font-weight:700;position:relative;top:3px}.cke_ltr .cke_dialog_close_button{right:5px}.cke_rtl .cke_dialog_close_button{left:6px}div.cke_disabled .cke_dialog_ui_labeled_content div *{background-color:#ddd;cursor:default}.cke_dialog_ui_hbox table,.cke_dialog_ui_vbox table{margin:auto}.cke_dialog_ui_vbox{margin-top:5px}.cke_dialog_ui_vbox_child{padding:5px 0}.cke_dialog_ui_hbox{width:100%}.cke_dialog_ui_hbox_child,.cke_dialog_ui_hbox_first,.cke_dialog_ui_hbox_last{vertical-align:top}.cke_dialog_ui_hbox_first>.cke_dialog_ui_html,.cke_dialog_ui_hbox_first>.cke_dialog_ui_labeled_label,.cke_dialog_ui_hbox_last>.cke_dialog_ui_html,.cke_dialog_ui_hbox_last>.cke_dialog_ui_labeled_label{line-height:30px}.cke_ltr .cke_dialog_ui_hbox_child,.cke_ltr .cke_dialog_ui_hbox_first{padding-right:10px}.cke_rtl .cke_dialog_ui_hbox_child,.cke_rtl .cke_dialog_ui_hbox_first{padding-left:10px}.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child,.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first{padding-right:5px}.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child,.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first{padding-left:5px;padding-right:0}.cke_hc div.cke_dialog_ui_input_file,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_textarea{border:1px solid}.cke_dialog_ui_text{margin-bottom:7px}.cke_dialog_ui_select{height:auto!important;margin-bottom:7px}textarea.cke_dialog_ui_input_textarea{overflow:auto;resize:none}a.cke_dialog_ui_button{display:inline-block;*display:inline;*zoom:1;padding:3px 0;margin:0;text-align:center;color:#333;vertical-align:middle;cursor:pointer;border:1px solid #ddd;border-radius:4px;background:#fff}a.cke_dialog_ui_button:active,a.cke_dialog_ui_button:focus,a.cke_dialog_ui_button:hover{border-color:#aaa;background-color:#eee;text-decoration:none}.cke_dialog_page_contents a.cke_dialog_ui_button{height:22px;line-height:22px;background-color:#f4f4f4}.cke_dialog_page_contents a.cke_dialog_ui_button:active,.cke_dialog_page_contents a.cke_dialog_ui_button:focus,.cke_dialog_page_contents a.cke_dialog_ui_button:hover{background-color:#eee}span.cke_dialog_ui_button{padding:0 12px}.cke_hc a.cke_dialog_ui_button:active,.cke_hc a.cke_dialog_ui_button:focus,.cke_hc a.cke_dialog_ui_button:hover{border:3px solid;padding-top:1px;padding-bottom:1px}.cke_hc a.cke_dialog_ui_button:active span,.cke_hc a.cke_dialog_ui_button:focus span,.cke_hc a.cke_dialog_ui_button:hover span{padding-left:10px;padding-right:10px}.cke_dialog_footer_buttons a.cke_dialog_ui_button span{color:inherit;font-size:12px;line-height:20px}a.cke_dialog_ui_button_ok{color:#fff;border-color:#2274c9;background:#3f8edf}a.cke_dialog_ui_button_ok:active,a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:hover{border-color:#1e68b4;background:#2981db}a.cke_dialog_ui_button_cancel{background-color:#fff}a.cke_dialog_ui_button_cancel:focus{outline:0}span.cke_dialog_ui_button{cursor:pointer}.cke_dialog_footer_buttons{display:inline-table;margin:10px;width:auto;position:relative;vertical-align:middle}div.cke_dialog_ui_input_select{display:table}select.cke_dialog_ui_input_select{height:30px;line-height:30px;background-color:#fff;padding:4px 10px;border:1px solid #ddd;outline:0;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.cke_dialog_ui_input_file{width:100%;height:30px}.cke_hc .cke_dialog_ui_labeled_content input:focus,.cke_hc .cke_dialog_ui_labeled_content select:focus,.cke_hc .cke_dialog_ui_labeled_content textarea:focus{outline:1px dotted}.cke_dialog .cke_dark_background,.cke_dialog .cke_light_background{background-color:#eee}.cke_dialog .cke_centered{text-align:center}.cke_dialog a.cke_btn_reset{float:right;background:url(images/refresh.png) top left no-repeat;width:16px;height:16px;border:1px none;font-size:1px}.cke_dialog a.cke_btn_locked,.cke_dialog a.cke_btn_unlocked{float:left;width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.cke_dialog a.cke_btn_locked{background-image:url(images/lock.png)}.cke_dialog a.cke_btn_locked .cke_icon{display:none}.cke_dialog a.cke_btn_unlocked{background-image:url(images/lock-open.png)}.cke_dialog .cke_btn_over{border:outset 1px;cursor:pointer}.cke_hidpi .cke_dialog a.cke_btn_reset{background-size:16px;background-image:url(images/hidpi/refresh.png)}.cke_hidpi .cke_dialog a.cke_btn_locked,.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-size:16px}.cke_hidpi .cke_dialog a.cke_btn_locked{background-image:url(images/hidpi/lock.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-image:url(images/hidpi/lock-open.png)}.cke_rtl .cke_dialog a.cke_btn_reset{float:left}.cke_rtl .cke_dialog a.cke_btn_locked,.cke_rtl .cke_dialog a.cke_btn_unlocked{float:right}.cke_dialog .FlashPreviewBox,.cke_dialog .ImagePreviewBox{border:1px solid #aaa;border-radius:4px;padding:6px 10px;margin-top:5px;background-color:#fff}.cke_dialog .ImagePreviewBox{overflow:scroll;height:205px;width:300px}.cke_dialog .ImagePreviewBox table td{white-space:normal}.cke_dialog .FlashPreviewBox{white-space:normal;overflow:auto;height:160px;width:390px}.cke_dialog .ImagePreviewLoader{position:absolute;white-space:normal;overflow:hidden;height:160px;width:230px;margin:2px;padding:2px;opacity:.9;filter:alpha(opacity=90);background-color:#e4e4e4}.cke_dialog .cke_pastetext{width:346px;height:170px}.cke_dialog .cke_pastetext textarea{width:340px;height:170px;resize:none}.cke_dialog iframe.cke_pasteframe{width:346px;height:130px;background-color:#fff;border:1px solid #aeb3b9;border-radius:4px}.cke_dialog .cke_hand{cursor:pointer}.cke_disabled{color:#a0a0a0}.cke_dialog_body .cke_label{display:none}.cke_dialog_body label{display:inline-block;margin-bottom:3px;cursor:default}.cke_dialog_body label.cke_required{font-weight:700}.cke_dialog_ui_html{line-height:150%}a.cke_smile{overflow:hidden;display:block;text-align:center;padding:.3em 0}a.cke_smile img{vertical-align:middle}a.cke_specialchar{cursor:inherit;display:block;height:1.25em;padding:.2em .3em;text-align:center}a.cke_smile,a.cke_specialchar{background-color:#eee;border:1px solid transparent;vertical-align:top}a.cke_smile:active,a.cke_smile:focus,a.cke_smile:hover,a.cke_specialchar:active,a.cke_specialchar:focus,a.cke_specialchar:hover{background:#fff;outline:0}a.cke_smile:hover,a.cke_specialchar:hover{border-color:#aaa}a.cke_smile:active,a.cke_smile:focus,a.cke_specialchar:active,a.cke_specialchar:focus{border-color:#428bca}.cke_dialog_contents a.colorChooser{display:block;margin-top:6px;margin-left:10px;width:80px}.cke_rtl .cke_dialog_contents a.colorChooser{margin-right:10px}.cke_dialog_ui_checkbox{display:inline-block;margin-bottom:5px}.cke_btn_over,.cke_dialog_ui_checkbox_input:focus,.cke_dialog_ui_radio_input:focus{outline:1px dotted #696969}.cke_iframe_shim{display:block;position:absolute;top:0;left:0;z-index:-1;filter:alpha(opacity=0);width:100%;height:100%}a.cke_dialog_ui_button_cancel:active span,a.cke_dialog_ui_button_cancel:focus span,a.cke_dialog_ui_button_ok:active span,a.cke_dialog_ui_button_ok:focus span{display:block} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_iequirks.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_iequirks.css new file mode 100644 index 0000000..8467352 --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_iequirks.css @@ -0,0 +1 @@ +input.cke_dialog_ui_input_password,input.cke_dialog_ui_input_text,textarea.cke_dialog_ui_input_textarea{background-color:#fff;outline:0;width:100%;*width:95%;height:30px;padding:4px 10px;border:1px solid #ddd;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}input.cke_dialog_ui_input_password:focus,input.cke_dialog_ui_input_text:focus,textarea.cke_dialog_ui_input_textarea:focus{border-color:#66afe9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.cke_dialog{visibility:visible}.cke_dialog_body{z-index:1;background:#eee;border:1px solid #ddd;border-radius:4px}.cke_browser_gecko19 .cke_dialog_body{position:relative}.cke_dialog strong{font-weight:700}.cke_dialog_title{font-weight:700;font-size:13px;cursor:move;position:relative;color:#333;border-bottom:1px solid #ddd;padding:10px 12px;background:#eee}.cke_dialog_contents{background-color:#fff;overflow:auto;padding:15px 10px 5px;margin-top:35px;border-top:1px solid #ddd;border-radius:0 0 4px 4px}.cke_dialog_contents_body{overflow:auto;padding:17px 10px 5px;margin-top:22px}.cke_dialog_footer{text-align:right;position:relative;border-radius:0 0 4px 4px;border-top:1px solid #ddd}.cke_rtl .cke_dialog_footer{text-align:left}.cke_hc .cke_dialog_footer{outline:0;border-top:1px solid #fff}.cke_dialog .cke_resizer{margin-top:28px}.cke_dialog .cke_resizer_rtl{margin-left:5px}.cke_dialog .cke_resizer_ltr{margin-right:5px}.cke_dialog_tabs{height:24px;display:inline-block;margin:10px 0 0;position:absolute;z-index:2;left:10px}.cke_rtl .cke_dialog_tabs{right:10px}a.cke_dialog_tab{height:16px;padding:4px 8px;margin-right:3px;display:inline-block;cursor:pointer;line-height:16px;outline:0;color:#555;border:1px solid #ddd;border-radius:3px 3px 0 0;background:#f3f3f3}.cke_rtl a.cke_dialog_tab{margin-right:0;margin-left:3px}a.cke_dialog_tab:hover{background:#ddd;text-decoration:none}a.cke_dialog_tab_selected{background:#fff;color:#333;border-bottom-color:#fff;cursor:default;filter:none}a.cke_dialog_tab_selected:hover{background:#fff}.cke_hc a.cke_dialog_tab:hover,.cke_hc a.cke_dialog_tab_selected{border:3px solid;padding:2px 6px}a.cke_dialog_tab_disabled{color:#bababa;cursor:default}.cke_dialog_tabs .cke_dialog_ui_input_select{top:-7px!important}.cke_single_page .cke_dialog_tabs{display:none}.cke_single_page .cke_dialog_contents{padding-top:5px;margin-top:0;border-top:0}.cke_dialog_close_button{background-image:url(images/close.png);background-repeat:no-repeat;background-position:0 0;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:9px;z-index:5}.cke_hidpi .cke_dialog_close_button{background-image:url(images/hidpi/close.png);background-size:16px}.cke_dialog_close_button span{display:none}.cke_hc .cke_dialog_close_button span{display:inline;cursor:pointer;font-weight:700;position:relative;top:3px}.cke_ltr .cke_dialog_close_button{right:5px}.cke_rtl .cke_dialog_close_button{left:6px}div.cke_disabled .cke_dialog_ui_labeled_content div *{background-color:#ddd;cursor:default}.cke_dialog_ui_hbox table,.cke_dialog_ui_vbox table{margin:auto}.cke_dialog_ui_vbox{margin-top:5px}.cke_dialog_ui_vbox_child{padding:5px 0}.cke_dialog_ui_hbox{width:100%}.cke_dialog_ui_hbox_child,.cke_dialog_ui_hbox_first,.cke_dialog_ui_hbox_last{vertical-align:top}.cke_dialog_ui_hbox_first>.cke_dialog_ui_html,.cke_dialog_ui_hbox_first>.cke_dialog_ui_labeled_label,.cke_dialog_ui_hbox_last>.cke_dialog_ui_html,.cke_dialog_ui_hbox_last>.cke_dialog_ui_labeled_label{line-height:30px}.cke_ltr .cke_dialog_ui_hbox_child,.cke_ltr .cke_dialog_ui_hbox_first{padding-right:10px}.cke_rtl .cke_dialog_ui_hbox_child,.cke_rtl .cke_dialog_ui_hbox_first{padding-left:10px}.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child,.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first{padding-right:5px}.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child,.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first{padding-left:5px;padding-right:0}.cke_hc div.cke_dialog_ui_input_file,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_textarea{border:1px solid}.cke_dialog_ui_text{margin-bottom:7px}.cke_dialog_ui_select{height:auto!important;margin-bottom:7px}textarea.cke_dialog_ui_input_textarea{overflow:auto;resize:none}a.cke_dialog_ui_button{display:inline-block;*display:inline;*zoom:1;padding:3px 0;margin:0;text-align:center;color:#333;vertical-align:middle;cursor:pointer;border:1px solid #ddd;border-radius:4px;background:#fff}a.cke_dialog_ui_button:active,a.cke_dialog_ui_button:focus,a.cke_dialog_ui_button:hover{border-color:#aaa;background-color:#eee;text-decoration:none}.cke_dialog_page_contents a.cke_dialog_ui_button{height:22px;line-height:22px;background-color:#f4f4f4}.cke_dialog_page_contents a.cke_dialog_ui_button:active,.cke_dialog_page_contents a.cke_dialog_ui_button:focus,.cke_dialog_page_contents a.cke_dialog_ui_button:hover{background-color:#eee}span.cke_dialog_ui_button{padding:0 12px}.cke_hc a.cke_dialog_ui_button:active,.cke_hc a.cke_dialog_ui_button:focus,.cke_hc a.cke_dialog_ui_button:hover{border:3px solid;padding-top:1px;padding-bottom:1px}.cke_hc a.cke_dialog_ui_button:active span,.cke_hc a.cke_dialog_ui_button:focus span,.cke_hc a.cke_dialog_ui_button:hover span{padding-left:10px;padding-right:10px}.cke_dialog_footer_buttons a.cke_dialog_ui_button span{color:inherit;font-size:12px;line-height:20px}a.cke_dialog_ui_button_ok{color:#fff;border-color:#2274c9;background:#3f8edf}a.cke_dialog_ui_button_ok:active,a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:hover{border-color:#1e68b4;background:#2981db}a.cke_dialog_ui_button_cancel{background-color:#fff}a.cke_dialog_ui_button_cancel:focus{outline:0}span.cke_dialog_ui_button{cursor:pointer}.cke_dialog_footer_buttons{display:inline-table;margin:10px;width:auto;position:relative;vertical-align:middle}div.cke_dialog_ui_input_select{display:table}select.cke_dialog_ui_input_select{height:30px;line-height:30px;background-color:#fff;padding:4px 10px;border:1px solid #ddd;outline:0;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.cke_dialog_ui_input_file{width:100%;height:30px}.cke_hc .cke_dialog_ui_labeled_content input:focus,.cke_hc .cke_dialog_ui_labeled_content select:focus,.cke_hc .cke_dialog_ui_labeled_content textarea:focus{outline:1px dotted}.cke_dialog .cke_dark_background,.cke_dialog .cke_light_background{background-color:#eee}.cke_dialog .cke_centered{text-align:center}.cke_dialog a.cke_btn_reset{float:right;background:url(images/refresh.png) top left no-repeat;width:16px;height:16px;border:1px none;font-size:1px}.cke_dialog a.cke_btn_locked,.cke_dialog a.cke_btn_unlocked{float:left;width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.cke_dialog a.cke_btn_locked{background-image:url(images/lock.png)}.cke_dialog a.cke_btn_locked .cke_icon{display:none}.cke_dialog a.cke_btn_unlocked{background-image:url(images/lock-open.png)}.cke_dialog .cke_btn_over{border:outset 1px;cursor:pointer}.cke_hidpi .cke_dialog a.cke_btn_reset{background-size:16px;background-image:url(images/hidpi/refresh.png)}.cke_hidpi .cke_dialog a.cke_btn_locked,.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-size:16px}.cke_hidpi .cke_dialog a.cke_btn_locked{background-image:url(images/hidpi/lock.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-image:url(images/hidpi/lock-open.png)}.cke_rtl .cke_dialog a.cke_btn_reset{float:left}.cke_rtl .cke_dialog a.cke_btn_locked,.cke_rtl .cke_dialog a.cke_btn_unlocked{float:right}.cke_dialog .FlashPreviewBox,.cke_dialog .ImagePreviewBox{border:1px solid #aaa;border-radius:4px;padding:6px 10px;margin-top:5px;background-color:#fff}.cke_dialog .ImagePreviewBox{overflow:scroll;height:205px;width:300px}.cke_dialog .ImagePreviewBox table td{white-space:normal}.cke_dialog .FlashPreviewBox{white-space:normal;overflow:auto;height:160px;width:390px}.cke_dialog .ImagePreviewLoader{position:absolute;white-space:normal;overflow:hidden;height:160px;width:230px;margin:2px;padding:2px;opacity:.9;filter:alpha(opacity=90);background-color:#e4e4e4}.cke_dialog .cke_pastetext{width:346px;height:170px}.cke_dialog .cke_pastetext textarea{width:340px;height:170px;resize:none}.cke_dialog iframe.cke_pasteframe{width:346px;height:130px;background-color:#fff;border:1px solid #aeb3b9;border-radius:4px}.cke_dialog .cke_hand{cursor:pointer}.cke_disabled{color:#a0a0a0}.cke_dialog_body .cke_label{display:none}.cke_dialog_body label{display:inline-block;margin-bottom:3px;cursor:default}.cke_dialog_body label.cke_required{font-weight:700}.cke_dialog_ui_html{line-height:150%}a.cke_smile{overflow:hidden;display:block;text-align:center;padding:.3em 0}a.cke_smile img{vertical-align:middle}a.cke_specialchar{cursor:inherit;display:block;height:1.25em;padding:.2em .3em;text-align:center}a.cke_smile,a.cke_specialchar{background-color:#eee;border:1px solid transparent;vertical-align:top}a.cke_smile:active,a.cke_smile:focus,a.cke_smile:hover,a.cke_specialchar:active,a.cke_specialchar:focus,a.cke_specialchar:hover{background:#fff;outline:0}a.cke_smile:hover,a.cke_specialchar:hover{border-color:#aaa}a.cke_smile:active,a.cke_smile:focus,a.cke_specialchar:active,a.cke_specialchar:focus{border-color:#428bca}.cke_dialog_contents a.colorChooser{display:block;margin-top:6px;margin-left:10px;width:80px}.cke_rtl .cke_dialog_contents a.colorChooser{margin-right:10px}.cke_dialog_ui_checkbox{display:inline-block;margin-bottom:5px}.cke_btn_over,.cke_dialog_ui_checkbox_input:focus,.cke_dialog_ui_radio_input:focus{outline:1px dotted #696969}.cke_iframe_shim{display:block;position:absolute;top:0;left:0;z-index:-1;filter:alpha(opacity=0);width:100%;height:100%}.cke_dialog_footer{filter:""} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_opera.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_opera.css new file mode 100644 index 0000000..24e0470 --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/dialog_opera.css @@ -0,0 +1 @@ +input.cke_dialog_ui_input_password,input.cke_dialog_ui_input_text,textarea.cke_dialog_ui_input_textarea{background-color:#fff;outline:0;width:100%;*width:95%;height:30px;padding:4px 10px;border:1px solid #ddd;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}input.cke_dialog_ui_input_password:focus,input.cke_dialog_ui_input_text:focus,textarea.cke_dialog_ui_input_textarea:focus{border-color:#66afe9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.cke_dialog{visibility:visible}.cke_dialog_body{z-index:1;background:#eee;border:1px solid #ddd;border-radius:4px}.cke_browser_gecko19 .cke_dialog_body{position:relative}.cke_dialog strong{font-weight:700}.cke_dialog_title{font-weight:700;font-size:13px;cursor:move;position:relative;color:#333;border-bottom:1px solid #ddd;padding:10px 12px;background:#eee}.cke_dialog_contents{background-color:#fff;overflow:auto;padding:15px 10px 5px;margin-top:35px;border-top:1px solid #ddd;border-radius:0 0 4px 4px}.cke_dialog_contents_body{overflow:auto;padding:17px 10px 5px;margin-top:22px}.cke_dialog_footer{text-align:right;position:relative;border-radius:0 0 4px 4px;border-top:1px solid #ddd;background:#eee}.cke_rtl .cke_dialog_footer{text-align:left}.cke_hc .cke_dialog_footer{outline:0;border-top:1px solid #fff}.cke_dialog .cke_resizer{margin-top:28px}.cke_dialog .cke_resizer_rtl{margin-left:5px}.cke_dialog .cke_resizer_ltr{margin-right:5px}.cke_dialog_tabs{height:24px;display:inline-block;margin:10px 0 0;position:absolute;z-index:2;left:10px}.cke_rtl .cke_dialog_tabs{right:10px}a.cke_dialog_tab{height:16px;padding:4px 8px;margin-right:3px;display:inline-block;cursor:pointer;line-height:16px;outline:0;color:#555;border:1px solid #ddd;border-radius:3px 3px 0 0;background:#f3f3f3}.cke_rtl a.cke_dialog_tab{margin-right:0;margin-left:3px}a.cke_dialog_tab:hover{background:#ddd;text-decoration:none}a.cke_dialog_tab_selected{background:#fff;color:#333;border-bottom-color:#fff;cursor:default;filter:none}a.cke_dialog_tab_selected:hover{background:#fff}.cke_hc a.cke_dialog_tab:hover,.cke_hc a.cke_dialog_tab_selected{border:3px solid;padding:2px 6px}a.cke_dialog_tab_disabled{color:#bababa;cursor:default}.cke_dialog_tabs .cke_dialog_ui_input_select{top:-7px!important}.cke_single_page .cke_dialog_tabs{display:none}.cke_single_page .cke_dialog_contents{padding-top:5px;margin-top:0;border-top:0}.cke_dialog_close_button{background-image:url(images/close.png);background-repeat:no-repeat;background-position:0 0;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:9px;z-index:5}.cke_hidpi .cke_dialog_close_button{background-image:url(images/hidpi/close.png);background-size:16px}.cke_dialog_close_button span{display:none}.cke_hc .cke_dialog_close_button span{display:inline;cursor:pointer;font-weight:700;position:relative;top:3px}.cke_ltr .cke_dialog_close_button{right:5px}.cke_rtl .cke_dialog_close_button{left:6px}div.cke_disabled .cke_dialog_ui_labeled_content div *{background-color:#ddd;cursor:default}.cke_dialog_ui_hbox table,.cke_dialog_ui_vbox table{margin:auto}.cke_dialog_ui_vbox{margin-top:5px}.cke_dialog_ui_vbox_child{padding:5px 0}.cke_dialog_ui_hbox{width:100%}.cke_dialog_ui_hbox_child,.cke_dialog_ui_hbox_first,.cke_dialog_ui_hbox_last{vertical-align:top}.cke_dialog_ui_hbox_first>.cke_dialog_ui_html,.cke_dialog_ui_hbox_first>.cke_dialog_ui_labeled_label,.cke_dialog_ui_hbox_last>.cke_dialog_ui_html,.cke_dialog_ui_hbox_last>.cke_dialog_ui_labeled_label{line-height:30px}.cke_ltr .cke_dialog_ui_hbox_child,.cke_ltr .cke_dialog_ui_hbox_first{padding-right:10px}.cke_rtl .cke_dialog_ui_hbox_child,.cke_rtl .cke_dialog_ui_hbox_first{padding-left:10px}.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child,.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first{padding-right:5px}.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child,.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first{padding-left:5px;padding-right:0}.cke_hc div.cke_dialog_ui_input_file,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_textarea{border:1px solid}.cke_dialog_ui_text{margin-bottom:7px}.cke_dialog_ui_select{height:auto!important;margin-bottom:7px}textarea.cke_dialog_ui_input_textarea{overflow:auto;resize:none}a.cke_dialog_ui_button{display:inline-block;*display:inline;*zoom:1;padding:3px 0;margin:0;text-align:center;color:#333;vertical-align:middle;cursor:pointer;border:1px solid #ddd;border-radius:4px;background:#fff}a.cke_dialog_ui_button:active,a.cke_dialog_ui_button:focus,a.cke_dialog_ui_button:hover{border-color:#aaa;background-color:#eee;text-decoration:none}.cke_dialog_page_contents a.cke_dialog_ui_button{height:22px;line-height:22px;background-color:#f4f4f4}.cke_dialog_page_contents a.cke_dialog_ui_button:active,.cke_dialog_page_contents a.cke_dialog_ui_button:focus,.cke_dialog_page_contents a.cke_dialog_ui_button:hover{background-color:#eee}span.cke_dialog_ui_button{padding:0 12px}.cke_hc a.cke_dialog_ui_button:active,.cke_hc a.cke_dialog_ui_button:focus,.cke_hc a.cke_dialog_ui_button:hover{border:3px solid;padding-top:1px;padding-bottom:1px}.cke_hc a.cke_dialog_ui_button:active span,.cke_hc a.cke_dialog_ui_button:focus span,.cke_hc a.cke_dialog_ui_button:hover span{padding-left:10px;padding-right:10px}.cke_dialog_footer_buttons a.cke_dialog_ui_button span{color:inherit;font-size:12px;line-height:20px}a.cke_dialog_ui_button_ok{color:#fff;border-color:#2274c9;background:#3f8edf}a.cke_dialog_ui_button_ok:active,a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:hover{border-color:#1e68b4;background:#2981db}a.cke_dialog_ui_button_cancel{background-color:#fff}a.cke_dialog_ui_button_cancel:focus{outline:0}span.cke_dialog_ui_button{cursor:pointer}.cke_dialog_footer_buttons{display:inline-table;margin:10px;width:auto;position:relative;vertical-align:middle}div.cke_dialog_ui_input_select{display:table}select.cke_dialog_ui_input_select{height:30px;line-height:30px;background-color:#fff;padding:4px 10px;border:1px solid #ddd;outline:0;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.cke_dialog_ui_input_file{width:100%;height:30px}.cke_hc .cke_dialog_ui_labeled_content input:focus,.cke_hc .cke_dialog_ui_labeled_content select:focus,.cke_hc .cke_dialog_ui_labeled_content textarea:focus{outline:1px dotted}.cke_dialog .cke_dark_background,.cke_dialog .cke_light_background{background-color:#eee}.cke_dialog .cke_centered{text-align:center}.cke_dialog a.cke_btn_reset{float:right;background:url(images/refresh.png) top left no-repeat;width:16px;height:16px;border:1px none;font-size:1px}.cke_dialog a.cke_btn_locked,.cke_dialog a.cke_btn_unlocked{float:left;width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.cke_dialog a.cke_btn_locked{background-image:url(images/lock.png)}.cke_dialog a.cke_btn_locked .cke_icon{display:none}.cke_dialog a.cke_btn_unlocked{background-image:url(images/lock-open.png)}.cke_dialog .cke_btn_over{border:outset 1px;cursor:pointer}.cke_hidpi .cke_dialog a.cke_btn_reset{background-size:16px;background-image:url(images/hidpi/refresh.png)}.cke_hidpi .cke_dialog a.cke_btn_locked,.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-size:16px}.cke_hidpi .cke_dialog a.cke_btn_locked{background-image:url(images/hidpi/lock.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-image:url(images/hidpi/lock-open.png)}.cke_rtl .cke_dialog a.cke_btn_reset{float:left}.cke_rtl .cke_dialog a.cke_btn_locked,.cke_rtl .cke_dialog a.cke_btn_unlocked{float:right}.cke_dialog .FlashPreviewBox,.cke_dialog .ImagePreviewBox{border:1px solid #aaa;border-radius:4px;padding:6px 10px;margin-top:5px;background-color:#fff}.cke_dialog .ImagePreviewBox{overflow:scroll;height:205px;width:300px}.cke_dialog .ImagePreviewBox table td{white-space:normal}.cke_dialog .FlashPreviewBox{white-space:normal;overflow:auto;height:160px;width:390px}.cke_dialog .ImagePreviewLoader{position:absolute;white-space:normal;overflow:hidden;height:160px;width:230px;margin:2px;padding:2px;opacity:.9;filter:alpha(opacity=90);background-color:#e4e4e4}.cke_dialog .cke_pastetext{width:346px;height:170px}.cke_dialog .cke_pastetext textarea{width:340px;height:170px;resize:none}.cke_dialog iframe.cke_pasteframe{width:346px;height:130px;background-color:#fff;border:1px solid #aeb3b9;border-radius:4px}.cke_dialog .cke_hand{cursor:pointer}.cke_disabled{color:#a0a0a0}.cke_dialog_body .cke_label{display:none}.cke_dialog_body label{display:inline-block;margin-bottom:3px;cursor:default}.cke_dialog_body label.cke_required{font-weight:700}.cke_dialog_ui_html{line-height:150%}a.cke_smile{overflow:hidden;display:block;text-align:center;padding:.3em 0}a.cke_smile img{vertical-align:middle}a.cke_specialchar{cursor:inherit;display:block;height:1.25em;padding:.2em .3em;text-align:center}a.cke_smile,a.cke_specialchar{background-color:#eee;border:1px solid transparent;vertical-align:top}a.cke_smile:active,a.cke_smile:focus,a.cke_smile:hover,a.cke_specialchar:active,a.cke_specialchar:focus,a.cke_specialchar:hover{background:#fff;outline:0}a.cke_smile:hover,a.cke_specialchar:hover{border-color:#aaa}a.cke_smile:active,a.cke_smile:focus,a.cke_specialchar:active,a.cke_specialchar:focus{border-color:#428bca}.cke_dialog_contents a.colorChooser{display:block;margin-top:6px;margin-left:10px;width:80px}.cke_rtl .cke_dialog_contents a.colorChooser{margin-right:10px}.cke_dialog_ui_checkbox{display:inline-block;margin-bottom:5px}.cke_btn_over,.cke_dialog_ui_checkbox_input:focus,.cke_dialog_ui_radio_input:focus{outline:1px dotted #696969}.cke_iframe_shim{display:block;position:absolute;top:0;left:0;z-index:-1;filter:alpha(opacity=0);width:100%;height:100%}.cke_dialog_footer{display:block;height:38px}.cke_ltr .cke_dialog_footer>*{float:right}.cke_rtl .cke_dialog_footer>*{float:left} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/editor.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/editor.css new file mode 100644 index 0000000..6ff8453 --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/editor.css @@ -0,0 +1 @@ +.cke_reset{margin:0;padding:0;border:0;background:0;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none}.cke_reset_all,.cke_reset_all *{margin:0;padding:0;border:0;background:0;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#333;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre}.cke_reset_all input[type=password],.cke_reset_all input[type=text],.cke_reset_all textarea{cursor:text}.cke_reset_all input[type=password][disabled],.cke_reset_all input[type=text][disabled],.cke_reset_all textarea[disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;margin-top:10px;border:1px solid #ddd}.cke_reset_all fieldset legend{padding:0 5px}.cke_reset_all select{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.cke_chrome{display:block;border:1px solid #ddd;border-radius:4px;padding:0 3px;background:#eee}.cke_inner{display:block;-webkit-touch-callout:none;background:0;padding:0}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_float .cke_top{border:1px solid #ddd}.cke_bottom,.cke_contents,.cke_top{display:block;overflow:hidden}.cke_bottom,.cke_top{padding:3px 0 0;background:#eee}.cke_top{white-space:normal}.cke_contents{background-color:#fff;border:1px solid #ddd;border-radius:4px}.cke_bottom{position:relative}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #555 transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #aaa;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;margin-top:5px;background-color:#fff;border:1px solid #aaa;border-radius:4px}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:178px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_list{list-style-type:none;margin:3px;padding:0;white-space:nowrap}.cke_panel_listItem{margin:0;padding-bottom:1px}.cke_panel_listItem a{padding:3px 4px;display:block;border:1px solid #fff;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis;border-radius:2px}.cke_panel_listItem a:active,.cke_panel_listItem a:focus,.cke_panel_listItem a:hover{background-color:#e1edf7}* html .cke_panel_listItem a{width:100%;color:#000}:first-child+html .cke_panel_listItem a{color:#000}.cke_panel_listItem.cke_selected a{background-color:#92bce0;outline:0}.cke_hc .cke_panel_listItem a{border-style:none}.cke_hc .cke_panel_listItem a:active,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:hover{border:2px solid;padding:1px 2px}.cke_panel_grouptitle{font-size:11px;font-weight:700;white-space:nowrap;margin:0;padding:6px;color:#474747;border-bottom:1px solid #aaa;background:#eee}.cke_panel_grouptitle:first-child{border-radius:4px 4px 0 0}.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem p,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_colorblock{padding:3px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}span.cke_colorbox{width:10px;height:10px;border:1px solid #aaa;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorbox{border:1px solid #fff;padding:2px;float:left;width:12px;height:12px;border-radius:2px}.cke_rtl a.cke_colorbox{float:right}a:active.cke_colorbox,a:focus.cke_colorbox,a:hover.cke_colorbox{border:1px solid #ddd;background-color:#eee}a.cke_colorauto,a.cke_colormore{border:1px solid #fff;padding:2px;display:block;cursor:pointer}a:active.cke_colorauto,a:active.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:hover.cke_colorauto,a:hover.cke_colormore{border:1px solid #ddd;background-color:#eee}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{float:left;margin:0 6px 3px 0;padding:2px;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_hc .cke_toolgroup{border:0;margin-right:10px;margin-bottom:10px}.cke_rtl .cke_toolgroup :first-child{border-radius:0 4px 4px 0}.cke_rtl .cke_toolgroup :last-child{border-radius:4px 0 0 4px}.cke_rtl .cke_toolgroup{float:right;margin-left:6px;margin-right:0}a.cke_button{display:inline-block;height:18px;padding:2px 4px;outline:0;cursor:default;float:left;border:0;border-radius:2px}.cke_rtl .cke_button{float:right}.cke_hc .cke_button{border:1px solid #000;padding:3px 5px;margin:-2px 4px 0 -2px}.cke_button_on{background:#92bce0}.cke_hc .cke_button_on,.cke_hc a.cke_button_disabled:active,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_off:active,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:hover{border-width:3px;padding:1px 3px}.cke_button_disabled .cke_button_icon{opacity:.3}.cke_hc .cke_button_disabled{opacity:.5}a.cke_button_disabled:active,a.cke_button_disabled:focus,a.cke_button_disabled:hover,a.cke_button_off:active,a.cke_button_off:focus,a.cke_button_off:hover{background:#e1edf7}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:18px;vertical-align:middle;float:left;cursor:default;color:#555}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px -2px 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#ddd;margin:4px 2px 0;height:16px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{width:0;border-left:1px solid;margin:1px 5px 0 0}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #a6a6a6;border-bottom-color:#979797;border-radius:4px;background:#e4e4e4}.cke_toolbox_collapser:hover{background:#ccc}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#474747}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:3px solid #474747;border-top:3px solid transparent}.cke_rtl .cke_toolbox_collapser{float:left}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0;margin-right:2px}.cke_menubutton{display:block}.cke_button_icon{opacity:.8}.cke_menuitem span{cursor:default}.cke_menubutton:active,.cke_menubutton:focus,.cke_menubutton:hover{display:block}.cke_hc .cke_menubutton{padding:2px}.cke_hc .cke_menubutton:active,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:hover{border:2px solid;padding:0}.cke_menubutton_inner{display:table-row}.cke_menuarrow,.cke_menubutton_icon,.cke_menubutton_label{display:table-cell}.cke_menubutton_icon{background-color:#d7d8d7;opacity:.7;filter:alpha(opacity=70);padding:4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:active .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:hover .cke_menubutton_icon{background-color:#d0d2d0}.cke_menubutton_disabled:active .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:hover .cke_menubutton_icon{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_on{border:1px solid #dedede;background-color:#f2f2f2}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px}.cke_menubutton:active,.cke_menubutton:focus,.cke_menubutton:hover{background-color:#eff0ef}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d3d3d3;height:1px;filter:alpha(opacity=70);opacity:.7}.cke_menuarrow{background-image:url(images/arrow.png);background-position:0 10px;background-repeat:no-repeat;padding:0 5px}.cke_menuarrow span{display:none}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:-2px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_button{display:inline-block;float:left;margin:0 6px 5px 0;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_combo_off a.cke_combo_button:focus,.cke_combo_off a.cke_combo_button:hover{outline:0}.cke_combo_off a.cke_combo_button:active,.cke_combo_on a.cke_combo_button{border-color:#333}.cke_rtl .cke_combo_button{float:right;margin-left:5px;margin-right:0}.cke_hc a.cke_combo_button{padding:3px}.cke_hc .cke_combo_off a.cke_combo_button:active,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_on a.cke_combo_button{border-width:3px;padding:1px}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#474747;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 7px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #333}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}.cke_path_empty,.cke_path_item{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#4c4c4c;font-weight:700;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_empty,.cke_rtl .cke_path_item{float:right}a.cke_path_item:active,a.cke_path_item:focus,a.cke_path_item:hover{background-color:#bfbfbf;color:#333;border-radius:2px}.cke_hc a.cke_path_item:active,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:hover{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combo__fontsize .cke_combo_text{width:30px}.cke_combopanel__fontsize{width:120px}.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre}.cke_wysiwyg_div,.cke_wysiwyg_frame{background-color:#fff}.cke_chrome{visibility:inherit}.cke_voice_label,legend.cke_voice_label{display:none}.cke_button__about_icon{background:url(icons.png) no-repeat 0 -0px!important}.cke_rtl .cke_button__anchor_icon,.cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon{background:url(icons.png) no-repeat 0 -24px!important}.cke_ltr .cke_button__anchor_icon{background:url(icons.png) no-repeat 0 -48px!important}.cke_button__bgcolor_icon{background:url(icons.png) no-repeat 0 -72px!important}.cke_button__bidiltr_icon{background:url(icons.png) no-repeat 0 -96px!important}.cke_button__bidirtl_icon{background:url(icons.png) no-repeat 0 -120px!important}.cke_button__blockquote_icon{background:url(icons.png) no-repeat 0 -144px!important}.cke_button__bold_icon{background:url(icons.png) no-repeat 0 -168px!important}.cke_rtl .cke_button__bulletedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons.png) no-repeat 0 -192px!important}.cke_ltr .cke_button__bulletedlist_icon{background:url(icons.png) no-repeat 0 -216px!important}.cke_button__button_icon{background:url(icons.png) no-repeat 0 -240px!important}.cke_button__checkbox_icon{background:url(icons.png) no-repeat 0 -264px!important}.cke_rtl .cke_button__copy_icon,.cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons.png) no-repeat 0 -288px!important}.cke_ltr .cke_button__copy_icon{background:url(icons.png) no-repeat 0 -312px!important}.cke_button__creatediv_icon{background:url(icons.png) no-repeat 0 -336px!important}.cke_rtl .cke_button__cut_icon,.cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons.png) no-repeat 0 -360px!important}.cke_ltr .cke_button__cut_icon{background:url(icons.png) no-repeat 0 -384px!important}.cke_button__find_icon{background:url(icons.png) no-repeat 0 -408px!important}.cke_button__flash_icon{background:url(icons.png) no-repeat 0 -432px!important}.cke_button__form_icon{background:url(icons.png) no-repeat 0 -456px!important}.cke_rtl .cke_button__hiddenfield_icon,.cke_mixed_dir_content .cke_rtl .cke_button__hiddenfield_icon{background:url(icons.png) no-repeat 0 -480px!important}.cke_ltr .cke_button__hiddenfield_icon{background:url(icons.png) no-repeat 0 -504px!important}.cke_button__horizontalrule_icon{background:url(icons.png) no-repeat 0 -528px!important}.cke_button__iframe_icon{background:url(icons.png) no-repeat 0 -552px!important}.cke_button__image_icon{background:url(icons.png) no-repeat 0 -576px!important}.cke_button__imagebutton_icon{background:url(icons.png) no-repeat 0 -600px!important}.cke_rtl .cke_button__indent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons.png) no-repeat 0 -624px!important}.cke_ltr .cke_button__indent_icon{background:url(icons.png) no-repeat 0 -648px!important}.cke_button__italic_icon{background:url(icons.png) no-repeat 0 -672px!important}.cke_button__justifyblock_icon{background:url(icons.png) no-repeat 0 -696px!important}.cke_button__justifycenter_icon{background:url(icons.png) no-repeat 0 -720px!important}.cke_button__justifyleft_icon{background:url(icons.png) no-repeat 0 -744px!important}.cke_button__justifyright_icon{background:url(icons.png) no-repeat 0 -768px!important}.cke_button__link_icon{background:url(icons.png) no-repeat 0 -792px!important}.cke_button__maximize_icon{background:url(icons.png) no-repeat 0 -816px!important}.cke_rtl .cke_button__newpage_icon,.cke_mixed_dir_content .cke_rtl .cke_button__newpage_icon{background:url(icons.png) no-repeat 0 -840px!important}.cke_ltr .cke_button__newpage_icon{background:url(icons.png) no-repeat 0 -864px!important}.cke_rtl .cke_button__numberedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons.png) no-repeat 0 -888px!important}.cke_ltr .cke_button__numberedlist_icon{background:url(icons.png) no-repeat 0 -912px!important}.cke_rtl .cke_button__outdent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons.png) no-repeat 0 -936px!important}.cke_ltr .cke_button__outdent_icon{background:url(icons.png) no-repeat 0 -960px!important}.cke_rtl .cke_button__pagebreak_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pagebreak_icon{background:url(icons.png) no-repeat 0 -984px!important}.cke_ltr .cke_button__pagebreak_icon{background:url(icons.png) no-repeat 0 -1008px!important}.cke_rtl .cke_button__paste_icon,.cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons.png) no-repeat 0 -1032px!important}.cke_ltr .cke_button__paste_icon{background:url(icons.png) no-repeat 0 -1056px!important}.cke_rtl .cke_button__pastefromword_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons.png) no-repeat 0 -1080px!important}.cke_ltr .cke_button__pastefromword_icon{background:url(icons.png) no-repeat 0 -1104px!important}.cke_rtl .cke_button__pastetext_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons.png) no-repeat 0 -1128px!important}.cke_ltr .cke_button__pastetext_icon{background:url(icons.png) no-repeat 0 -1152px!important}.cke_rtl .cke_button__preview_icon,.cke_mixed_dir_content .cke_rtl .cke_button__preview_icon{background:url(icons.png) no-repeat 0 -1176px!important}.cke_ltr .cke_button__preview_icon{background:url(icons.png) no-repeat 0 -1200px!important}.cke_button__print_icon{background:url(icons.png) no-repeat 0 -1224px!important}.cke_button__radio_icon{background:url(icons.png) no-repeat 0 -1248px!important}.cke_rtl .cke_button__redo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons.png) no-repeat 0 -1272px!important}.cke_ltr .cke_button__redo_icon{background:url(icons.png) no-repeat 0 -1296px!important}.cke_button__removeformat_icon{background:url(icons.png) no-repeat 0 -1320px!important}.cke_button__replace_icon{background:url(icons.png) no-repeat 0 -1344px!important}.cke_button__save_icon{background:url(icons.png) no-repeat 0 -1368px!important}.cke_button__scayt_icon{background:url(icons.png) no-repeat 0 -1392px!important}.cke_rtl .cke_button__select_icon,.cke_mixed_dir_content .cke_rtl .cke_button__select_icon{background:url(icons.png) no-repeat 0 -1416px!important}.cke_ltr .cke_button__select_icon{background:url(icons.png) no-repeat 0 -1440px!important}.cke_button__selectall_icon{background:url(icons.png) no-repeat 0 -1464px!important}.cke_rtl .cke_button__showblocks_icon,.cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons.png) no-repeat 0 -1488px!important}.cke_ltr .cke_button__showblocks_icon{background:url(icons.png) no-repeat 0 -1512px!important}.cke_button__smiley_icon{background:url(icons.png) no-repeat 0 -1536px!important}.cke_rtl .cke_button__source_icon,.cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons.png) no-repeat 0 -1560px!important}.cke_ltr .cke_button__source_icon{background:url(icons.png) no-repeat 0 -1584px!important}.cke_button__specialchar_icon{background:url(icons.png) no-repeat 0 -1608px!important}.cke_button__spellchecker_icon{background:url(icons.png) no-repeat 0 -1632px!important}.cke_button__strike_icon{background:url(icons.png) no-repeat 0 -1656px!important}.cke_button__subscript_icon{background:url(icons.png) no-repeat 0 -1680px!important}.cke_button__superscript_icon{background:url(icons.png) no-repeat 0 -1704px!important}.cke_button__table_icon{background:url(icons.png) no-repeat 0 -1728px!important}.cke_rtl .cke_button__templates_icon,.cke_mixed_dir_content .cke_rtl .cke_button__templates_icon{background:url(icons.png) no-repeat 0 -1752px!important}.cke_ltr .cke_button__templates_icon{background:url(icons.png) no-repeat 0 -1776px!important}.cke_rtl .cke_button__textarea_icon,.cke_mixed_dir_content .cke_rtl .cke_button__textarea_icon{background:url(icons.png) no-repeat 0 -1800px!important}.cke_ltr .cke_button__textarea_icon{background:url(icons.png) no-repeat 0 -1824px!important}.cke_button__textcolor_icon{background:url(icons.png) no-repeat 0 -1848px!important}.cke_rtl .cke_button__textfield_icon,.cke_mixed_dir_content .cke_rtl .cke_button__textfield_icon{background:url(icons.png) no-repeat 0 -1872px!important}.cke_ltr .cke_button__textfield_icon{background:url(icons.png) no-repeat 0 -1896px!important}.cke_button__underline_icon{background:url(icons.png) no-repeat 0 -1920px!important}.cke_rtl .cke_button__undo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons.png) no-repeat 0 -1944px!important}.cke_ltr .cke_button__undo_icon{background:url(icons.png) no-repeat 0 -1968px!important}.cke_button__unlink_icon{background:url(icons.png) no-repeat 0 -1992px!important}.cke_hidpi .cke_button__about_icon{background:url(icons_hidpi.png) no-repeat 0 -0px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__anchor_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon{background:url(icons_hidpi.png) no-repeat 0 -24px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__anchor_icon,.cke_ltr.cke_hidpi .cke_button__anchor_icon{background:url(icons_hidpi.png) no-repeat 0 -48px!important;background-size:16px!important}.cke_hidpi .cke_button__bgcolor_icon{background:url(icons_hidpi.png) no-repeat 0 -72px!important;background-size:16px!important}.cke_hidpi .cke_button__bidiltr_icon{background:url(icons_hidpi.png) no-repeat 0 -96px!important;background-size:16px!important}.cke_hidpi .cke_button__bidirtl_icon{background:url(icons_hidpi.png) no-repeat 0 -120px!important;background-size:16px!important}.cke_hidpi .cke_button__blockquote_icon{background:url(icons_hidpi.png) no-repeat 0 -144px!important;background-size:16px!important}.cke_hidpi .cke_button__bold_icon{background:url(icons_hidpi.png) no-repeat 0 -168px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons_hidpi.png) no-repeat 0 -192px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon{background:url(icons_hidpi.png) no-repeat 0 -216px!important;background-size:16px!important}.cke_hidpi .cke_button__button_icon{background:url(icons_hidpi.png) no-repeat 0 -240px!important;background-size:16px!important}.cke_hidpi .cke_button__checkbox_icon{background:url(icons_hidpi.png) no-repeat 0 -264px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__copy_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons_hidpi.png) no-repeat 0 -288px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon{background:url(icons_hidpi.png) no-repeat 0 -312px!important;background-size:16px!important}.cke_hidpi .cke_button__creatediv_icon{background:url(icons_hidpi.png) no-repeat 0 -336px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__cut_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons_hidpi.png) no-repeat 0 -360px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon{background:url(icons_hidpi.png) no-repeat 0 -384px!important;background-size:16px!important}.cke_hidpi .cke_button__find_icon{background:url(icons_hidpi.png) no-repeat 0 -408px!important;background-size:16px!important}.cke_hidpi .cke_button__flash_icon{background:url(icons_hidpi.png) no-repeat 0 -432px!important;background-size:16px!important}.cke_hidpi .cke_button__form_icon{background:url(icons_hidpi.png) no-repeat 0 -456px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__hiddenfield_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__hiddenfield_icon{background:url(icons_hidpi.png) no-repeat 0 -480px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__hiddenfield_icon,.cke_ltr.cke_hidpi .cke_button__hiddenfield_icon{background:url(icons_hidpi.png) no-repeat 0 -504px!important;background-size:16px!important}.cke_hidpi .cke_button__horizontalrule_icon{background:url(icons_hidpi.png) no-repeat 0 -528px!important;background-size:16px!important}.cke_hidpi .cke_button__iframe_icon{background:url(icons_hidpi.png) no-repeat 0 -552px!important;background-size:16px!important}.cke_hidpi .cke_button__image_icon{background:url(icons_hidpi.png) no-repeat 0 -576px!important;background-size:16px!important}.cke_hidpi .cke_button__imagebutton_icon{background:url(icons_hidpi.png) no-repeat 0 -600px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__indent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons_hidpi.png) no-repeat 0 -624px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon{background:url(icons_hidpi.png) no-repeat 0 -648px!important;background-size:16px!important}.cke_hidpi .cke_button__italic_icon{background:url(icons_hidpi.png) no-repeat 0 -672px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyblock_icon{background:url(icons_hidpi.png) no-repeat 0 -696px!important;background-size:16px!important}.cke_hidpi .cke_button__justifycenter_icon{background:url(icons_hidpi.png) no-repeat 0 -720px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyleft_icon{background:url(icons_hidpi.png) no-repeat 0 -744px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyright_icon{background:url(icons_hidpi.png) no-repeat 0 -768px!important;background-size:16px!important}.cke_hidpi .cke_button__link_icon{background:url(icons_hidpi.png) no-repeat 0 -792px!important;background-size:16px!important}.cke_hidpi .cke_button__maximize_icon{background:url(icons_hidpi.png) no-repeat 0 -816px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__newpage_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__newpage_icon{background:url(icons_hidpi.png) no-repeat 0 -840px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__newpage_icon,.cke_ltr.cke_hidpi .cke_button__newpage_icon{background:url(icons_hidpi.png) no-repeat 0 -864px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons_hidpi.png) no-repeat 0 -888px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon{background:url(icons_hidpi.png) no-repeat 0 -912px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__outdent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons_hidpi.png) no-repeat 0 -936px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon{background:url(icons_hidpi.png) no-repeat 0 -960px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pagebreak_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pagebreak_icon{background:url(icons_hidpi.png) no-repeat 0 -984px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pagebreak_icon,.cke_ltr.cke_hidpi .cke_button__pagebreak_icon{background:url(icons_hidpi.png) no-repeat 0 -1008px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__paste_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons_hidpi.png) no-repeat 0 -1032px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon{background:url(icons_hidpi.png) no-repeat 0 -1056px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons_hidpi.png) no-repeat 0 -1080px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon{background:url(icons_hidpi.png) no-repeat 0 -1104px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastetext_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons_hidpi.png) no-repeat 0 -1128px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon{background:url(icons_hidpi.png) no-repeat 0 -1152px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__preview_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__preview_icon{background:url(icons_hidpi.png) no-repeat 0 -1176px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__preview_icon,.cke_ltr.cke_hidpi .cke_button__preview_icon{background:url(icons_hidpi.png) no-repeat 0 -1200px!important;background-size:16px!important}.cke_hidpi .cke_button__print_icon{background:url(icons_hidpi.png) no-repeat 0 -1224px!important;background-size:16px!important}.cke_hidpi .cke_button__radio_icon{background:url(icons_hidpi.png) no-repeat 0 -1248px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__redo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons_hidpi.png) no-repeat 0 -1272px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon{background:url(icons_hidpi.png) no-repeat 0 -1296px!important;background-size:16px!important}.cke_hidpi .cke_button__removeformat_icon{background:url(icons_hidpi.png) no-repeat 0 -1320px!important;background-size:16px!important}.cke_hidpi .cke_button__replace_icon{background:url(icons_hidpi.png) no-repeat 0 -1344px!important;background-size:16px!important}.cke_hidpi .cke_button__save_icon{background:url(icons_hidpi.png) no-repeat 0 -1368px!important;background-size:16px!important}.cke_hidpi .cke_button__scayt_icon{background:url(icons_hidpi.png) no-repeat 0 -1392px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__select_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__select_icon{background:url(icons_hidpi.png) no-repeat 0 -1416px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__select_icon,.cke_ltr.cke_hidpi .cke_button__select_icon{background:url(icons_hidpi.png) no-repeat 0 -1440px!important;background-size:16px!important}.cke_hidpi .cke_button__selectall_icon{background:url(icons_hidpi.png) no-repeat 0 -1464px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__showblocks_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons_hidpi.png) no-repeat 0 -1488px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__showblocks_icon,.cke_ltr.cke_hidpi .cke_button__showblocks_icon{background:url(icons_hidpi.png) no-repeat 0 -1512px!important;background-size:16px!important}.cke_hidpi .cke_button__smiley_icon{background:url(icons_hidpi.png) no-repeat 0 -1536px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__source_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons_hidpi.png) no-repeat 0 -1560px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon{background:url(icons_hidpi.png) no-repeat 0 -1584px!important;background-size:16px!important}.cke_hidpi .cke_button__specialchar_icon{background:url(icons_hidpi.png) no-repeat 0 -1608px!important;background-size:16px!important}.cke_hidpi .cke_button__spellchecker_icon{background:url(icons_hidpi.png) no-repeat 0 -1632px!important;background-size:16px!important}.cke_hidpi .cke_button__strike_icon{background:url(icons_hidpi.png) no-repeat 0 -1656px!important;background-size:16px!important}.cke_hidpi .cke_button__subscript_icon{background:url(icons_hidpi.png) no-repeat 0 -1680px!important;background-size:16px!important}.cke_hidpi .cke_button__superscript_icon{background:url(icons_hidpi.png) no-repeat 0 -1704px!important;background-size:16px!important}.cke_hidpi .cke_button__table_icon{background:url(icons_hidpi.png) no-repeat 0 -1728px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__templates_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__templates_icon{background:url(icons_hidpi.png) no-repeat 0 -1752px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__templates_icon,.cke_ltr.cke_hidpi .cke_button__templates_icon{background:url(icons_hidpi.png) no-repeat 0 -1776px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__textarea_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__textarea_icon{background:url(icons_hidpi.png) no-repeat 0 -1800px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__textarea_icon,.cke_ltr.cke_hidpi .cke_button__textarea_icon{background:url(icons_hidpi.png) no-repeat 0 -1824px!important;background-size:16px!important}.cke_hidpi .cke_button__textcolor_icon{background:url(icons_hidpi.png) no-repeat 0 -1848px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__textfield_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__textfield_icon{background:url(icons_hidpi.png) no-repeat 0 -1872px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__textfield_icon,.cke_ltr.cke_hidpi .cke_button__textfield_icon{background:url(icons_hidpi.png) no-repeat 0 -1896px!important;background-size:16px!important}.cke_hidpi .cke_button__underline_icon{background:url(icons_hidpi.png) no-repeat 0 -1920px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__undo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons_hidpi.png) no-repeat 0 -1944px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon{background:url(icons_hidpi.png) no-repeat 0 -1968px!important;background-size:16px!important}.cke_hidpi .cke_button__unlink_icon{background:url(icons_hidpi.png) no-repeat 0 -1992px!important;background-size:16px!important}.cke_button__about_icon {background: url(icons.png?t=3876e73) no-repeat 0 -0px !important;}.cke_button__bold_icon {background: url(icons.png?t=3876e73) no-repeat 0 -24px !important;}.cke_button__italic_icon {background: url(icons.png?t=3876e73) no-repeat 0 -48px !important;}.cke_button__strike_icon {background: url(icons.png?t=3876e73) no-repeat 0 -72px !important;}.cke_button__subscript_icon {background: url(icons.png?t=3876e73) no-repeat 0 -96px !important;}.cke_button__superscript_icon {background: url(icons.png?t=3876e73) no-repeat 0 -120px !important;}.cke_button__underline_icon {background: url(icons.png?t=3876e73) no-repeat 0 -144px !important;}.cke_button__bidiltr_icon {background: url(icons.png?t=3876e73) no-repeat 0 -168px !important;}.cke_button__bidirtl_icon {background: url(icons.png?t=3876e73) no-repeat 0 -192px !important;}.cke_button__blockquote_icon {background: url(icons.png?t=3876e73) no-repeat 0 -216px !important;}.cke_rtl .cke_button__copy_icon, .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons.png?t=3876e73) no-repeat 0 -240px !important;}.cke_ltr .cke_button__copy_icon {background: url(icons.png?t=3876e73) no-repeat 0 -264px !important;}.cke_rtl .cke_button__cut_icon, .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons.png?t=3876e73) no-repeat 0 -288px !important;}.cke_ltr .cke_button__cut_icon {background: url(icons.png?t=3876e73) no-repeat 0 -312px !important;}.cke_rtl .cke_button__paste_icon, .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons.png?t=3876e73) no-repeat 0 -336px !important;}.cke_ltr .cke_button__paste_icon {background: url(icons.png?t=3876e73) no-repeat 0 -360px !important;}.cke_button__bgcolor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -384px !important;}.cke_button__textcolor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -408px !important;}.cke_rtl .cke_button__templates_icon, .cke_mixed_dir_content .cke_rtl .cke_button__templates_icon {background: url(icons.png?t=3876e73) no-repeat 0 -432px !important;}.cke_ltr .cke_button__templates_icon {background: url(icons.png?t=3876e73) no-repeat 0 -456px !important;}.cke_button__creatediv_icon {background: url(icons.png?t=3876e73) no-repeat 0 -480px !important;}.cke_rtl .cke_button__find_icon, .cke_mixed_dir_content .cke_rtl .cke_button__find_icon {background: url(icons.png?t=3876e73) no-repeat 0 -504px !important;}.cke_ltr .cke_button__find_icon {background: url(icons.png?t=3876e73) no-repeat 0 -528px !important;}.cke_button__replace_icon {background: url(icons.png?t=3876e73) no-repeat 0 -552px !important;}.cke_button__flash_icon {background: url(icons.png?t=3876e73) no-repeat 0 -576px !important;}.cke_button__button_icon {background: url(icons.png?t=3876e73) no-repeat 0 -600px !important;}.cke_button__checkbox_icon {background: url(icons.png?t=3876e73) no-repeat 0 -624px !important;}.cke_button__form_icon {background: url(icons.png?t=3876e73) no-repeat 0 -648px !important;}.cke_button__hiddenfield_icon {background: url(icons.png?t=3876e73) no-repeat 0 -672px !important;}.cke_button__imagebutton_icon {background: url(icons.png?t=3876e73) no-repeat 0 -696px !important;}.cke_button__radio_icon {background: url(icons.png?t=3876e73) no-repeat 0 -720px !important;}.cke_rtl .cke_button__select_icon, .cke_mixed_dir_content .cke_rtl .cke_button__select_icon {background: url(icons.png?t=3876e73) no-repeat 0 -744px !important;}.cke_ltr .cke_button__select_icon {background: url(icons.png?t=3876e73) no-repeat 0 -768px !important;}.cke_rtl .cke_button__textarea_icon, .cke_mixed_dir_content .cke_rtl .cke_button__textarea_icon {background: url(icons.png?t=3876e73) no-repeat 0 -792px !important;}.cke_ltr .cke_button__textarea_icon {background: url(icons.png?t=3876e73) no-repeat 0 -816px !important;}.cke_rtl .cke_button__textfield_icon, .cke_mixed_dir_content .cke_rtl .cke_button__textfield_icon {background: url(icons.png?t=3876e73) no-repeat 0 -840px !important;}.cke_ltr .cke_button__textfield_icon {background: url(icons.png?t=3876e73) no-repeat 0 -864px !important;}.cke_button__horizontalrule_icon {background: url(icons.png?t=3876e73) no-repeat 0 -888px !important;}.cke_button__iframe_icon {background: url(icons.png?t=3876e73) no-repeat 0 -912px !important;}.cke_button__image_icon {background: url(icons.png?t=3876e73) no-repeat 0 -936px !important;}.cke_rtl .cke_button__indent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -960px !important;}.cke_ltr .cke_button__indent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -984px !important;}.cke_rtl .cke_button__outdent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1008px !important;}.cke_ltr .cke_button__outdent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1032px !important;}.cke_button__smiley_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1056px !important;}.cke_button__justifyblock_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1080px !important;}.cke_button__justifycenter_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1104px !important;}.cke_button__justifyleft_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1128px !important;}.cke_button__justifyright_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1152px !important;}.cke_button__language_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1176px !important;}.cke_rtl .cke_button__anchor_icon, .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1200px !important;}.cke_ltr .cke_button__anchor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1224px !important;}.cke_button__link_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1248px !important;}.cke_button__unlink_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1272px !important;}.cke_rtl .cke_button__bulletedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1296px !important;}.cke_ltr .cke_button__bulletedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1320px !important;}.cke_rtl .cke_button__numberedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1344px !important;}.cke_ltr .cke_button__numberedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1368px !important;}.cke_button__maximize_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1392px !important;}.cke_rtl .cke_button__newpage_icon, .cke_mixed_dir_content .cke_rtl .cke_button__newpage_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1416px !important;}.cke_ltr .cke_button__newpage_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1440px !important;}.cke_rtl .cke_button__pagebreak_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pagebreak_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1464px !important;}.cke_ltr .cke_button__pagebreak_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1488px !important;}.cke_rtl .cke_button__pastetext_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1512px !important;}.cke_ltr .cke_button__pastetext_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1536px !important;}.cke_rtl .cke_button__pastefromword_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1560px !important;}.cke_ltr .cke_button__pastefromword_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1584px !important;}.cke_rtl .cke_button__preview_icon, .cke_mixed_dir_content .cke_rtl .cke_button__preview_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1608px !important;}.cke_ltr .cke_button__preview_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1632px !important;}.cke_button__print_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1656px !important;}.cke_button__removeformat_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1680px !important;}.cke_button__save_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1704px !important;}.cke_button__selectall_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1728px !important;}.cke_rtl .cke_button__showblocks_icon, .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1752px !important;}.cke_ltr .cke_button__showblocks_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1776px !important;}.cke_rtl .cke_button__source_icon, .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1800px !important;}.cke_ltr .cke_button__source_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1824px !important;}.cke_button__specialchar_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1848px !important;}.cke_button__scayt_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1872px !important;}.cke_button__table_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1896px !important;}.cke_rtl .cke_button__redo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1920px !important;}.cke_ltr .cke_button__redo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1944px !important;}.cke_rtl .cke_button__undo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1968px !important;}.cke_ltr .cke_button__undo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1992px !important;}.cke_button__spellchecker_icon {background: url(icons.png?t=3876e73) no-repeat 0 -2016px !important;}.cke_hidpi .cke_button__about_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -0px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bold_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -24px !important;background-size: 16px !important;}.cke_hidpi .cke_button__italic_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -48px !important;background-size: 16px !important;}.cke_hidpi .cke_button__strike_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -72px !important;background-size: 16px !important;}.cke_hidpi .cke_button__subscript_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -96px !important;background-size: 16px !important;}.cke_hidpi .cke_button__superscript_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -120px !important;background-size: 16px !important;}.cke_hidpi .cke_button__underline_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -144px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bidiltr_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -168px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bidirtl_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -192px !important;background-size: 16px !important;}.cke_hidpi .cke_button__blockquote_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -216px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__copy_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -240px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -264px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__cut_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -288px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -312px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__paste_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -336px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -360px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bgcolor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -384px !important;background-size: 16px !important;}.cke_hidpi .cke_button__textcolor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -408px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__templates_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__templates_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -432px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__templates_icon,.cke_ltr.cke_hidpi .cke_button__templates_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -456px !important;background-size: 16px !important;}.cke_hidpi .cke_button__creatediv_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -480px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__find_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__find_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -504px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__find_icon,.cke_ltr.cke_hidpi .cke_button__find_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -528px !important;background-size: 16px !important;}.cke_hidpi .cke_button__replace_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -552px !important;background-size: 16px !important;}.cke_hidpi .cke_button__flash_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -576px !important;background-size: 16px !important;}.cke_hidpi .cke_button__button_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -600px !important;background-size: 16px !important;}.cke_hidpi .cke_button__checkbox_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -624px !important;background-size: 16px !important;}.cke_hidpi .cke_button__form_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -648px !important;background-size: 16px !important;}.cke_hidpi .cke_button__hiddenfield_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -672px !important;background-size: 16px !important;}.cke_hidpi .cke_button__imagebutton_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -696px !important;background-size: 16px !important;}.cke_hidpi .cke_button__radio_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -720px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__select_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__select_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -744px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__select_icon,.cke_ltr.cke_hidpi .cke_button__select_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -768px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__textarea_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__textarea_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -792px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__textarea_icon,.cke_ltr.cke_hidpi .cke_button__textarea_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -816px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__textfield_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__textfield_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -840px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__textfield_icon,.cke_ltr.cke_hidpi .cke_button__textfield_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -864px !important;background-size: 16px !important;}.cke_hidpi .cke_button__horizontalrule_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -888px !important;background-size: 16px !important;}.cke_hidpi .cke_button__iframe_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -912px !important;background-size: 16px !important;}.cke_hidpi .cke_button__image_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -936px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__indent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -960px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -984px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__outdent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1008px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1032px !important;background-size: 16px !important;}.cke_hidpi .cke_button__smiley_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1056px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyblock_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1080px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifycenter_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1104px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyleft_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1128px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyright_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1152px !important;background-size: 16px !important;}.cke_hidpi .cke_button__language_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1176px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__anchor_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1200px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__anchor_icon,.cke_ltr.cke_hidpi .cke_button__anchor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1224px !important;background-size: 16px !important;}.cke_hidpi .cke_button__link_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1248px !important;background-size: 16px !important;}.cke_hidpi .cke_button__unlink_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1272px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1296px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1320px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1344px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1368px !important;background-size: 16px !important;}.cke_hidpi .cke_button__maximize_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1392px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__newpage_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__newpage_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1416px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__newpage_icon,.cke_ltr.cke_hidpi .cke_button__newpage_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1440px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pagebreak_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pagebreak_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1464px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pagebreak_icon,.cke_ltr.cke_hidpi .cke_button__pagebreak_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1488px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastetext_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1512px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1536px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1560px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1584px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__preview_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__preview_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1608px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__preview_icon,.cke_ltr.cke_hidpi .cke_button__preview_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1632px !important;background-size: 16px !important;}.cke_hidpi .cke_button__print_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1656px !important;background-size: 16px !important;}.cke_hidpi .cke_button__removeformat_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1680px !important;background-size: 16px !important;}.cke_hidpi .cke_button__save_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1704px !important;background-size: 16px !important;}.cke_hidpi .cke_button__selectall_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1728px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__showblocks_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1752px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__showblocks_icon,.cke_ltr.cke_hidpi .cke_button__showblocks_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1776px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__source_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1800px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1824px !important;background-size: 16px !important;}.cke_hidpi .cke_button__specialchar_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1848px !important;background-size: 16px !important;}.cke_hidpi .cke_button__scayt_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1872px !important;background-size: 16px !important;}.cke_hidpi .cke_button__table_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1896px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__redo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1920px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1944px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__undo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1968px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1992px !important;background-size: 16px !important;}.cke_hidpi .cke_button__spellchecker_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -2016px !important;background-size: 16px !important;} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/editor_gecko.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/editor_gecko.css new file mode 100644 index 0000000..a0d3b30 --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/editor_gecko.css @@ -0,0 +1 @@ +.cke_reset{margin:0;padding:0;border:0;background:0;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none}.cke_reset_all,.cke_reset_all *{margin:0;padding:0;border:0;background:0;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#333;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre}.cke_reset_all input[type=password],.cke_reset_all input[type=text],.cke_reset_all textarea{cursor:text}.cke_reset_all input[type=password][disabled],.cke_reset_all input[type=text][disabled],.cke_reset_all textarea[disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;margin-top:10px;border:1px solid #ddd}.cke_reset_all fieldset legend{padding:0 5px}.cke_reset_all select{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.cke_chrome{display:block;border:1px solid #ddd;border-radius:4px;padding:0 3px;background:#eee}.cke_inner{display:block;-webkit-touch-callout:none;background:0;padding:0}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_float .cke_top{border:1px solid #ddd}.cke_bottom,.cke_contents,.cke_top{display:block;overflow:hidden}.cke_bottom,.cke_top{padding:3px 0 0;background:#eee}.cke_top{white-space:normal}.cke_contents{background-color:#fff;border:1px solid #ddd;border-radius:4px}.cke_bottom{position:relative}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #555 transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #aaa;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;margin-top:5px;background-color:#fff;border:1px solid #aaa;border-radius:4px}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:178px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_list{list-style-type:none;margin:3px;padding:0;white-space:nowrap}.cke_panel_listItem{margin:0;padding-bottom:1px}.cke_panel_listItem a{padding:3px 4px;display:block;border:1px solid #fff;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis;border-radius:2px}.cke_panel_listItem a:active,.cke_panel_listItem a:focus,.cke_panel_listItem a:hover{background-color:#e1edf7}* html .cke_panel_listItem a{width:100%;color:#000}:first-child+html .cke_panel_listItem a{color:#000}.cke_panel_listItem.cke_selected a{background-color:#92bce0;outline:0}.cke_hc .cke_panel_listItem a{border-style:none}.cke_hc .cke_panel_listItem a:active,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:hover{border:2px solid;padding:1px 2px}.cke_panel_grouptitle{font-size:11px;font-weight:700;white-space:nowrap;margin:0;padding:6px;color:#474747;border-bottom:1px solid #aaa;background:#eee}.cke_panel_grouptitle:first-child{border-radius:4px 4px 0 0}.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem p,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_colorblock{padding:3px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}span.cke_colorbox{width:10px;height:10px;border:1px solid #aaa;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorbox{border:1px solid #fff;padding:2px;float:left;width:12px;height:12px;border-radius:2px}.cke_rtl a.cke_colorbox{float:right}a:active.cke_colorbox,a:focus.cke_colorbox,a:hover.cke_colorbox{border:1px solid #ddd;background-color:#eee}a.cke_colorauto,a.cke_colormore{border:1px solid #fff;padding:2px;display:block;cursor:pointer}a:active.cke_colorauto,a:active.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:hover.cke_colorauto,a:hover.cke_colormore{border:1px solid #ddd;background-color:#eee}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{float:left;margin:0 6px 3px 0;padding:2px;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_hc .cke_toolgroup{border:0;margin-right:10px;margin-bottom:10px}.cke_rtl .cke_toolgroup :first-child{border-radius:0 4px 4px 0}.cke_rtl .cke_toolgroup :last-child{border-radius:4px 0 0 4px}.cke_rtl .cke_toolgroup{float:right;margin-left:6px;margin-right:0}a.cke_button{display:inline-block;height:18px;padding:2px 4px;outline:0;cursor:default;float:left;border:0;border-radius:2px}.cke_rtl .cke_button{float:right}.cke_hc .cke_button{border:1px solid #000;padding:3px 5px;margin:-2px 4px 0 -2px}.cke_button_on{background:#92bce0}.cke_hc .cke_button_on,.cke_hc a.cke_button_disabled:active,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_off:active,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:hover{border-width:3px;padding:1px 3px}.cke_button_disabled .cke_button_icon{opacity:.3}.cke_hc .cke_button_disabled{opacity:.5}a.cke_button_disabled:active,a.cke_button_disabled:focus,a.cke_button_disabled:hover,a.cke_button_off:active,a.cke_button_off:focus,a.cke_button_off:hover{background:#e1edf7}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:18px;vertical-align:middle;float:left;cursor:default;color:#555}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px -2px 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#ddd;margin:4px 2px 0;height:16px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{width:0;border-left:1px solid;margin:1px 5px 0 0}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #a6a6a6;border-bottom-color:#979797;border-radius:4px;background:#e4e4e4}.cke_toolbox_collapser:hover{background:#ccc}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#474747}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:3px solid #474747;border-top:3px solid transparent}.cke_rtl .cke_toolbox_collapser{float:left}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0;margin-right:2px}.cke_menubutton{display:block}.cke_button_icon{opacity:.8}.cke_menuitem span{cursor:default}.cke_menubutton:active,.cke_menubutton:focus,.cke_menubutton:hover{display:block}.cke_hc .cke_menubutton{padding:2px}.cke_hc .cke_menubutton:active,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:hover{border:2px solid;padding:0}.cke_menubutton_inner{display:table-row}.cke_menuarrow,.cke_menubutton_icon,.cke_menubutton_label{display:table-cell}.cke_menubutton_icon{background-color:#d7d8d7;opacity:.7;filter:alpha(opacity=70);padding:4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:active .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:hover .cke_menubutton_icon{background-color:#d0d2d0}.cke_menubutton_disabled:active .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:hover .cke_menubutton_icon{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_on{border:1px solid #dedede;background-color:#f2f2f2}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px}.cke_menubutton:active,.cke_menubutton:focus,.cke_menubutton:hover{background-color:#eff0ef}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d3d3d3;height:1px;filter:alpha(opacity=70);opacity:.7}.cke_menuarrow{background-image:url(images/arrow.png);background-position:0 10px;background-repeat:no-repeat;padding:0 5px}.cke_menuarrow span{display:none}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:-2px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_button{display:inline-block;float:left;margin:0 6px 5px 0;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_combo_off a.cke_combo_button:focus,.cke_combo_off a.cke_combo_button:hover{outline:0}.cke_combo_off a.cke_combo_button:active,.cke_combo_on a.cke_combo_button{border-color:#333}.cke_rtl .cke_combo_button{float:right;margin-left:5px;margin-right:0}.cke_hc a.cke_combo_button{padding:3px}.cke_hc .cke_combo_off a.cke_combo_button:active,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_on a.cke_combo_button{border-width:3px;padding:1px}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#474747;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 7px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #333}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}.cke_path_empty,.cke_path_item{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#4c4c4c;font-weight:700;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_empty,.cke_rtl .cke_path_item{float:right}a.cke_path_item:active,a.cke_path_item:focus,a.cke_path_item:hover{background-color:#bfbfbf;color:#333;border-radius:2px}.cke_hc a.cke_path_item:active,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:hover{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combo__fontsize .cke_combo_text{width:30px}.cke_combopanel__fontsize{width:120px}.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre}.cke_wysiwyg_div,.cke_wysiwyg_frame{background-color:#fff}.cke_chrome{visibility:inherit}.cke_voice_label,legend.cke_voice_label{display:none}.cke_bottom{padding-bottom:3px}.cke_combo_text{margin-bottom:-1px;margin-top:1px}.cke_button__about_icon {background: url(icons.png?t=3876e73) no-repeat 0 -0px !important;}.cke_button__bold_icon {background: url(icons.png?t=3876e73) no-repeat 0 -24px !important;}.cke_button__italic_icon {background: url(icons.png?t=3876e73) no-repeat 0 -48px !important;}.cke_button__strike_icon {background: url(icons.png?t=3876e73) no-repeat 0 -72px !important;}.cke_button__subscript_icon {background: url(icons.png?t=3876e73) no-repeat 0 -96px !important;}.cke_button__superscript_icon {background: url(icons.png?t=3876e73) no-repeat 0 -120px !important;}.cke_button__underline_icon {background: url(icons.png?t=3876e73) no-repeat 0 -144px !important;}.cke_button__bidiltr_icon {background: url(icons.png?t=3876e73) no-repeat 0 -168px !important;}.cke_button__bidirtl_icon {background: url(icons.png?t=3876e73) no-repeat 0 -192px !important;}.cke_button__blockquote_icon {background: url(icons.png?t=3876e73) no-repeat 0 -216px !important;}.cke_rtl .cke_button__copy_icon, .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons.png?t=3876e73) no-repeat 0 -240px !important;}.cke_ltr .cke_button__copy_icon {background: url(icons.png?t=3876e73) no-repeat 0 -264px !important;}.cke_rtl .cke_button__cut_icon, .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons.png?t=3876e73) no-repeat 0 -288px !important;}.cke_ltr .cke_button__cut_icon {background: url(icons.png?t=3876e73) no-repeat 0 -312px !important;}.cke_rtl .cke_button__paste_icon, .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons.png?t=3876e73) no-repeat 0 -336px !important;}.cke_ltr .cke_button__paste_icon {background: url(icons.png?t=3876e73) no-repeat 0 -360px !important;}.cke_button__bgcolor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -384px !important;}.cke_button__textcolor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -408px !important;}.cke_rtl .cke_button__templates_icon, .cke_mixed_dir_content .cke_rtl .cke_button__templates_icon {background: url(icons.png?t=3876e73) no-repeat 0 -432px !important;}.cke_ltr .cke_button__templates_icon {background: url(icons.png?t=3876e73) no-repeat 0 -456px !important;}.cke_button__creatediv_icon {background: url(icons.png?t=3876e73) no-repeat 0 -480px !important;}.cke_rtl .cke_button__find_icon, .cke_mixed_dir_content .cke_rtl .cke_button__find_icon {background: url(icons.png?t=3876e73) no-repeat 0 -504px !important;}.cke_ltr .cke_button__find_icon {background: url(icons.png?t=3876e73) no-repeat 0 -528px !important;}.cke_button__replace_icon {background: url(icons.png?t=3876e73) no-repeat 0 -552px !important;}.cke_button__flash_icon {background: url(icons.png?t=3876e73) no-repeat 0 -576px !important;}.cke_button__button_icon {background: url(icons.png?t=3876e73) no-repeat 0 -600px !important;}.cke_button__checkbox_icon {background: url(icons.png?t=3876e73) no-repeat 0 -624px !important;}.cke_button__form_icon {background: url(icons.png?t=3876e73) no-repeat 0 -648px !important;}.cke_button__hiddenfield_icon {background: url(icons.png?t=3876e73) no-repeat 0 -672px !important;}.cke_button__imagebutton_icon {background: url(icons.png?t=3876e73) no-repeat 0 -696px !important;}.cke_button__radio_icon {background: url(icons.png?t=3876e73) no-repeat 0 -720px !important;}.cke_rtl .cke_button__select_icon, .cke_mixed_dir_content .cke_rtl .cke_button__select_icon {background: url(icons.png?t=3876e73) no-repeat 0 -744px !important;}.cke_ltr .cke_button__select_icon {background: url(icons.png?t=3876e73) no-repeat 0 -768px !important;}.cke_rtl .cke_button__textarea_icon, .cke_mixed_dir_content .cke_rtl .cke_button__textarea_icon {background: url(icons.png?t=3876e73) no-repeat 0 -792px !important;}.cke_ltr .cke_button__textarea_icon {background: url(icons.png?t=3876e73) no-repeat 0 -816px !important;}.cke_rtl .cke_button__textfield_icon, .cke_mixed_dir_content .cke_rtl .cke_button__textfield_icon {background: url(icons.png?t=3876e73) no-repeat 0 -840px !important;}.cke_ltr .cke_button__textfield_icon {background: url(icons.png?t=3876e73) no-repeat 0 -864px !important;}.cke_button__horizontalrule_icon {background: url(icons.png?t=3876e73) no-repeat 0 -888px !important;}.cke_button__iframe_icon {background: url(icons.png?t=3876e73) no-repeat 0 -912px !important;}.cke_button__image_icon {background: url(icons.png?t=3876e73) no-repeat 0 -936px !important;}.cke_rtl .cke_button__indent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -960px !important;}.cke_ltr .cke_button__indent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -984px !important;}.cke_rtl .cke_button__outdent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1008px !important;}.cke_ltr .cke_button__outdent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1032px !important;}.cke_button__smiley_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1056px !important;}.cke_button__justifyblock_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1080px !important;}.cke_button__justifycenter_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1104px !important;}.cke_button__justifyleft_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1128px !important;}.cke_button__justifyright_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1152px !important;}.cke_button__language_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1176px !important;}.cke_rtl .cke_button__anchor_icon, .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1200px !important;}.cke_ltr .cke_button__anchor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1224px !important;}.cke_button__link_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1248px !important;}.cke_button__unlink_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1272px !important;}.cke_rtl .cke_button__bulletedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1296px !important;}.cke_ltr .cke_button__bulletedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1320px !important;}.cke_rtl .cke_button__numberedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1344px !important;}.cke_ltr .cke_button__numberedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1368px !important;}.cke_button__maximize_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1392px !important;}.cke_rtl .cke_button__newpage_icon, .cke_mixed_dir_content .cke_rtl .cke_button__newpage_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1416px !important;}.cke_ltr .cke_button__newpage_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1440px !important;}.cke_rtl .cke_button__pagebreak_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pagebreak_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1464px !important;}.cke_ltr .cke_button__pagebreak_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1488px !important;}.cke_rtl .cke_button__pastetext_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1512px !important;}.cke_ltr .cke_button__pastetext_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1536px !important;}.cke_rtl .cke_button__pastefromword_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1560px !important;}.cke_ltr .cke_button__pastefromword_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1584px !important;}.cke_rtl .cke_button__preview_icon, .cke_mixed_dir_content .cke_rtl .cke_button__preview_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1608px !important;}.cke_ltr .cke_button__preview_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1632px !important;}.cke_button__print_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1656px !important;}.cke_button__removeformat_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1680px !important;}.cke_button__save_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1704px !important;}.cke_button__selectall_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1728px !important;}.cke_rtl .cke_button__showblocks_icon, .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1752px !important;}.cke_ltr .cke_button__showblocks_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1776px !important;}.cke_rtl .cke_button__source_icon, .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1800px !important;}.cke_ltr .cke_button__source_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1824px !important;}.cke_button__specialchar_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1848px !important;}.cke_button__scayt_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1872px !important;}.cke_button__table_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1896px !important;}.cke_rtl .cke_button__redo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1920px !important;}.cke_ltr .cke_button__redo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1944px !important;}.cke_rtl .cke_button__undo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1968px !important;}.cke_ltr .cke_button__undo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1992px !important;}.cke_button__spellchecker_icon {background: url(icons.png?t=3876e73) no-repeat 0 -2016px !important;}.cke_hidpi .cke_button__about_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -0px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bold_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -24px !important;background-size: 16px !important;}.cke_hidpi .cke_button__italic_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -48px !important;background-size: 16px !important;}.cke_hidpi .cke_button__strike_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -72px !important;background-size: 16px !important;}.cke_hidpi .cke_button__subscript_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -96px !important;background-size: 16px !important;}.cke_hidpi .cke_button__superscript_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -120px !important;background-size: 16px !important;}.cke_hidpi .cke_button__underline_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -144px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bidiltr_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -168px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bidirtl_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -192px !important;background-size: 16px !important;}.cke_hidpi .cke_button__blockquote_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -216px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__copy_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -240px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -264px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__cut_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -288px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -312px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__paste_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -336px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -360px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bgcolor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -384px !important;background-size: 16px !important;}.cke_hidpi .cke_button__textcolor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -408px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__templates_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__templates_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -432px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__templates_icon,.cke_ltr.cke_hidpi .cke_button__templates_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -456px !important;background-size: 16px !important;}.cke_hidpi .cke_button__creatediv_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -480px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__find_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__find_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -504px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__find_icon,.cke_ltr.cke_hidpi .cke_button__find_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -528px !important;background-size: 16px !important;}.cke_hidpi .cke_button__replace_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -552px !important;background-size: 16px !important;}.cke_hidpi .cke_button__flash_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -576px !important;background-size: 16px !important;}.cke_hidpi .cke_button__button_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -600px !important;background-size: 16px !important;}.cke_hidpi .cke_button__checkbox_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -624px !important;background-size: 16px !important;}.cke_hidpi .cke_button__form_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -648px !important;background-size: 16px !important;}.cke_hidpi .cke_button__hiddenfield_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -672px !important;background-size: 16px !important;}.cke_hidpi .cke_button__imagebutton_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -696px !important;background-size: 16px !important;}.cke_hidpi .cke_button__radio_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -720px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__select_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__select_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -744px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__select_icon,.cke_ltr.cke_hidpi .cke_button__select_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -768px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__textarea_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__textarea_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -792px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__textarea_icon,.cke_ltr.cke_hidpi .cke_button__textarea_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -816px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__textfield_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__textfield_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -840px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__textfield_icon,.cke_ltr.cke_hidpi .cke_button__textfield_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -864px !important;background-size: 16px !important;}.cke_hidpi .cke_button__horizontalrule_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -888px !important;background-size: 16px !important;}.cke_hidpi .cke_button__iframe_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -912px !important;background-size: 16px !important;}.cke_hidpi .cke_button__image_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -936px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__indent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -960px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -984px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__outdent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1008px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1032px !important;background-size: 16px !important;}.cke_hidpi .cke_button__smiley_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1056px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyblock_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1080px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifycenter_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1104px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyleft_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1128px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyright_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1152px !important;background-size: 16px !important;}.cke_hidpi .cke_button__language_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1176px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__anchor_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1200px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__anchor_icon,.cke_ltr.cke_hidpi .cke_button__anchor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1224px !important;background-size: 16px !important;}.cke_hidpi .cke_button__link_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1248px !important;background-size: 16px !important;}.cke_hidpi .cke_button__unlink_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1272px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1296px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1320px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1344px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1368px !important;background-size: 16px !important;}.cke_hidpi .cke_button__maximize_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1392px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__newpage_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__newpage_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1416px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__newpage_icon,.cke_ltr.cke_hidpi .cke_button__newpage_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1440px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pagebreak_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pagebreak_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1464px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pagebreak_icon,.cke_ltr.cke_hidpi .cke_button__pagebreak_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1488px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastetext_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1512px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1536px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1560px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1584px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__preview_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__preview_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1608px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__preview_icon,.cke_ltr.cke_hidpi .cke_button__preview_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1632px !important;background-size: 16px !important;}.cke_hidpi .cke_button__print_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1656px !important;background-size: 16px !important;}.cke_hidpi .cke_button__removeformat_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1680px !important;background-size: 16px !important;}.cke_hidpi .cke_button__save_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1704px !important;background-size: 16px !important;}.cke_hidpi .cke_button__selectall_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1728px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__showblocks_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1752px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__showblocks_icon,.cke_ltr.cke_hidpi .cke_button__showblocks_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1776px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__source_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1800px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1824px !important;background-size: 16px !important;}.cke_hidpi .cke_button__specialchar_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1848px !important;background-size: 16px !important;}.cke_hidpi .cke_button__scayt_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1872px !important;background-size: 16px !important;}.cke_hidpi .cke_button__table_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1896px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__redo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1920px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1944px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__undo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1968px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1992px !important;background-size: 16px !important;}.cke_hidpi .cke_button__spellchecker_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -2016px !important;background-size: 16px !important;} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/editor_ie.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/editor_ie.css new file mode 100644 index 0000000..57ab0c5 --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/editor_ie.css @@ -0,0 +1 @@ +.cke_reset{margin:0;padding:0;border:0;background:0;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none}.cke_reset_all,.cke_reset_all *{margin:0;padding:0;border:0;background:0;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#333;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre}.cke_reset_all input[type=password],.cke_reset_all input[type=text],.cke_reset_all textarea{cursor:text}.cke_reset_all input[type=password][disabled],.cke_reset_all input[type=text][disabled],.cke_reset_all textarea[disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;margin-top:10px;border:1px solid #ddd}.cke_reset_all fieldset legend{padding:0 5px}.cke_reset_all select{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.cke_chrome{display:block;border:1px solid #ddd;border-radius:4px;padding:0 3px;background:#eee}.cke_inner{display:block;-webkit-touch-callout:none;background:0;padding:0}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_float .cke_top{border:1px solid #ddd}.cke_bottom,.cke_contents,.cke_top{display:block;overflow:hidden}.cke_bottom,.cke_top{padding:3px 0 0;background:#eee}.cke_top{white-space:normal}.cke_contents{background-color:#fff;border:1px solid #ddd;border-radius:4px}.cke_bottom{position:relative}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #555 transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #aaa;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;margin-top:5px;background-color:#fff;border:1px solid #aaa;border-radius:4px}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:178px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_list{list-style-type:none;margin:3px;padding:0;white-space:nowrap}.cke_panel_listItem{margin:0;padding-bottom:1px}.cke_panel_listItem a{padding:3px 4px;display:block;border:1px solid #fff;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis;border-radius:2px}.cke_panel_listItem a:active,.cke_panel_listItem a:focus,.cke_panel_listItem a:hover{background-color:#e1edf7}* html .cke_panel_listItem a{width:100%;color:#000}:first-child+html .cke_panel_listItem a{color:#000}.cke_panel_listItem.cke_selected a{background-color:#92bce0;outline:0}.cke_hc .cke_panel_listItem a{border-style:none}.cke_hc .cke_panel_listItem a:active,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:hover{border:2px solid;padding:1px 2px}.cke_panel_grouptitle{font-size:11px;font-weight:700;white-space:nowrap;margin:0;padding:6px;color:#474747;border-bottom:1px solid #aaa;background:#eee}.cke_panel_grouptitle:first-child{border-radius:4px 4px 0 0}.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem p,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_colorblock{padding:3px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}span.cke_colorbox{width:10px;height:10px;border:1px solid #aaa;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorbox{border:1px solid #fff;padding:2px;float:left;width:12px;height:12px;border-radius:2px}.cke_rtl a.cke_colorbox{float:right}a:active.cke_colorbox,a:focus.cke_colorbox,a:hover.cke_colorbox{border:1px solid #ddd;background-color:#eee}a.cke_colorauto,a.cke_colormore{border:1px solid #fff;padding:2px;display:block;cursor:pointer}a:active.cke_colorauto,a:active.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:hover.cke_colorauto,a:hover.cke_colormore{border:1px solid #ddd;background-color:#eee}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{float:left;margin:0 6px 3px 0;padding:2px;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_hc .cke_toolgroup{border:0;margin-right:10px;margin-bottom:10px}.cke_rtl .cke_toolgroup :first-child{border-radius:0 4px 4px 0}.cke_rtl .cke_toolgroup :last-child{border-radius:4px 0 0 4px}.cke_rtl .cke_toolgroup{float:right;margin-left:6px;margin-right:0}a.cke_button{display:inline-block;height:18px;padding:2px 4px;outline:0;cursor:default;float:left;border:0;border-radius:2px}.cke_rtl .cke_button{float:right}.cke_hc .cke_button{border:1px solid #000;padding:3px 5px;margin:-2px 4px 0 -2px}.cke_button_on{background:#92bce0}.cke_hc .cke_button_on,.cke_hc a.cke_button_disabled:active,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_off:active,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:hover{border-width:3px;padding:1px 3px}.cke_button_disabled .cke_button_icon{opacity:.3}.cke_hc .cke_button_disabled{opacity:.5}a.cke_button_disabled:active,a.cke_button_disabled:focus,a.cke_button_disabled:hover,a.cke_button_off:active,a.cke_button_off:focus,a.cke_button_off:hover{background:#e1edf7}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:18px;vertical-align:middle;float:left;cursor:default;color:#555}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px -2px 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#ddd;margin:4px 2px 0;height:16px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{width:0;border-left:1px solid;margin:1px 5px 0 0}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border-radius:4px;background:#e4e4e4}.cke_toolbox_collapser:hover{background:#ccc}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#474747}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:3px solid #474747;border-top:3px solid transparent}.cke_rtl .cke_toolbox_collapser{float:left}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0;margin-right:2px}.cke_menubutton{display:block}.cke_button_icon{opacity:.8}.cke_menuitem span{cursor:default}.cke_menubutton:active,.cke_menubutton:focus,.cke_menubutton:hover{display:block}.cke_hc .cke_menubutton{padding:2px}.cke_hc .cke_menubutton:active,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:hover{border:2px solid;padding:0}.cke_menubutton_inner{display:table-row}.cke_menuarrow,.cke_menubutton_icon,.cke_menubutton_label{display:table-cell}.cke_menubutton_icon{background-color:#d7d8d7;opacity:.7;filter:alpha(opacity=70);padding:4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:active .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:hover .cke_menubutton_icon{background-color:#d0d2d0}.cke_menubutton_disabled:active .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:hover .cke_menubutton_icon{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_on{border:1px solid #dedede;background-color:#f2f2f2}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px}.cke_menubutton:active,.cke_menubutton:focus,.cke_menubutton:hover{background-color:#eff0ef}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d3d3d3;height:1px;filter:alpha(opacity=70);opacity:.7}.cke_menuarrow{background-image:url(images/arrow.png);background-position:0 10px;background-repeat:no-repeat;padding:0 5px}.cke_menuarrow span{display:none}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:-2px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_button{display:inline-block;float:left;margin:0 6px 5px 0;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_combo_off a.cke_combo_button:focus,.cke_combo_off a.cke_combo_button:hover{outline:0}.cke_combo_off a.cke_combo_button:active,.cke_combo_on a.cke_combo_button{border-color:#333}.cke_rtl .cke_combo_button{float:right;margin-left:5px;margin-right:0}.cke_hc a.cke_combo_button{padding:3px}.cke_hc .cke_combo_off a.cke_combo_button:active,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_on a.cke_combo_button{border-width:3px;padding:1px}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#474747;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 7px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #333}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}.cke_path_empty,.cke_path_item{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#4c4c4c;font-weight:700;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_empty,.cke_rtl .cke_path_item{float:right}a.cke_path_item:active,a.cke_path_item:focus,a.cke_path_item:hover{background-color:#bfbfbf;color:#333;border-radius:2px}.cke_hc a.cke_path_item:active,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:hover{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combo__fontsize .cke_combo_text{width:30px}.cke_combopanel__fontsize{width:120px}.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre}.cke_wysiwyg_div,.cke_wysiwyg_frame{background-color:#fff}.cke_chrome{visibility:inherit}.cke_voice_label,legend.cke_voice_label{display:none}a.cke_button_disabled,a.cke_button_disabled:active,a.cke_button_disabled:focus,a.cke_button_disabled:hover{filter:alpha(opacity=30)}.cke_button_disabled .cke_button_icon{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#00ffffff,endColorstr=#00ffffff)}.cke_button_off:active,.cke_button_off:focus,.cke_button_off:hover{filter:alpha(opacity=100)}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{filter:alpha(opacity=30)}.cke_toolbox_collapser{border:1px solid #a6a6a6}.cke_toolbox_collapser .cke_arrow{margin-top:1px}.cke_hc .cke_bottom,.cke_hc .cke_button_on,.cke_hc .cke_combo_button,.cke_hc .cke_panel_grouptitle,.cke_hc .cke_toolbox_collapser,.cke_hc .cke_toolbox_collapser:hover,.cke_hc .cke_toolgroup,.cke_hc .cke_top,.cke_hc a.cke_button_off:active,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_combo_button:focus,.cke_hc a.cke_combo_button:hover{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.cke_button__about_icon {background: url(icons.png?t=3876e73) no-repeat 0 -0px !important;}.cke_button__bold_icon {background: url(icons.png?t=3876e73) no-repeat 0 -24px !important;}.cke_button__italic_icon {background: url(icons.png?t=3876e73) no-repeat 0 -48px !important;}.cke_button__strike_icon {background: url(icons.png?t=3876e73) no-repeat 0 -72px !important;}.cke_button__subscript_icon {background: url(icons.png?t=3876e73) no-repeat 0 -96px !important;}.cke_button__superscript_icon {background: url(icons.png?t=3876e73) no-repeat 0 -120px !important;}.cke_button__underline_icon {background: url(icons.png?t=3876e73) no-repeat 0 -144px !important;}.cke_button__bidiltr_icon {background: url(icons.png?t=3876e73) no-repeat 0 -168px !important;}.cke_button__bidirtl_icon {background: url(icons.png?t=3876e73) no-repeat 0 -192px !important;}.cke_button__blockquote_icon {background: url(icons.png?t=3876e73) no-repeat 0 -216px !important;}.cke_rtl .cke_button__copy_icon, .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons.png?t=3876e73) no-repeat 0 -240px !important;}.cke_ltr .cke_button__copy_icon {background: url(icons.png?t=3876e73) no-repeat 0 -264px !important;}.cke_rtl .cke_button__cut_icon, .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons.png?t=3876e73) no-repeat 0 -288px !important;}.cke_ltr .cke_button__cut_icon {background: url(icons.png?t=3876e73) no-repeat 0 -312px !important;}.cke_rtl .cke_button__paste_icon, .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons.png?t=3876e73) no-repeat 0 -336px !important;}.cke_ltr .cke_button__paste_icon {background: url(icons.png?t=3876e73) no-repeat 0 -360px !important;}.cke_button__bgcolor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -384px !important;}.cke_button__textcolor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -408px !important;}.cke_rtl .cke_button__templates_icon, .cke_mixed_dir_content .cke_rtl .cke_button__templates_icon {background: url(icons.png?t=3876e73) no-repeat 0 -432px !important;}.cke_ltr .cke_button__templates_icon {background: url(icons.png?t=3876e73) no-repeat 0 -456px !important;}.cke_button__creatediv_icon {background: url(icons.png?t=3876e73) no-repeat 0 -480px !important;}.cke_rtl .cke_button__find_icon, .cke_mixed_dir_content .cke_rtl .cke_button__find_icon {background: url(icons.png?t=3876e73) no-repeat 0 -504px !important;}.cke_ltr .cke_button__find_icon {background: url(icons.png?t=3876e73) no-repeat 0 -528px !important;}.cke_button__replace_icon {background: url(icons.png?t=3876e73) no-repeat 0 -552px !important;}.cke_button__flash_icon {background: url(icons.png?t=3876e73) no-repeat 0 -576px !important;}.cke_button__button_icon {background: url(icons.png?t=3876e73) no-repeat 0 -600px !important;}.cke_button__checkbox_icon {background: url(icons.png?t=3876e73) no-repeat 0 -624px !important;}.cke_button__form_icon {background: url(icons.png?t=3876e73) no-repeat 0 -648px !important;}.cke_button__hiddenfield_icon {background: url(icons.png?t=3876e73) no-repeat 0 -672px !important;}.cke_button__imagebutton_icon {background: url(icons.png?t=3876e73) no-repeat 0 -696px !important;}.cke_button__radio_icon {background: url(icons.png?t=3876e73) no-repeat 0 -720px !important;}.cke_rtl .cke_button__select_icon, .cke_mixed_dir_content .cke_rtl .cke_button__select_icon {background: url(icons.png?t=3876e73) no-repeat 0 -744px !important;}.cke_ltr .cke_button__select_icon {background: url(icons.png?t=3876e73) no-repeat 0 -768px !important;}.cke_rtl .cke_button__textarea_icon, .cke_mixed_dir_content .cke_rtl .cke_button__textarea_icon {background: url(icons.png?t=3876e73) no-repeat 0 -792px !important;}.cke_ltr .cke_button__textarea_icon {background: url(icons.png?t=3876e73) no-repeat 0 -816px !important;}.cke_rtl .cke_button__textfield_icon, .cke_mixed_dir_content .cke_rtl .cke_button__textfield_icon {background: url(icons.png?t=3876e73) no-repeat 0 -840px !important;}.cke_ltr .cke_button__textfield_icon {background: url(icons.png?t=3876e73) no-repeat 0 -864px !important;}.cke_button__horizontalrule_icon {background: url(icons.png?t=3876e73) no-repeat 0 -888px !important;}.cke_button__iframe_icon {background: url(icons.png?t=3876e73) no-repeat 0 -912px !important;}.cke_button__image_icon {background: url(icons.png?t=3876e73) no-repeat 0 -936px !important;}.cke_rtl .cke_button__indent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -960px !important;}.cke_ltr .cke_button__indent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -984px !important;}.cke_rtl .cke_button__outdent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1008px !important;}.cke_ltr .cke_button__outdent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1032px !important;}.cke_button__smiley_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1056px !important;}.cke_button__justifyblock_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1080px !important;}.cke_button__justifycenter_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1104px !important;}.cke_button__justifyleft_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1128px !important;}.cke_button__justifyright_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1152px !important;}.cke_button__language_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1176px !important;}.cke_rtl .cke_button__anchor_icon, .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1200px !important;}.cke_ltr .cke_button__anchor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1224px !important;}.cke_button__link_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1248px !important;}.cke_button__unlink_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1272px !important;}.cke_rtl .cke_button__bulletedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1296px !important;}.cke_ltr .cke_button__bulletedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1320px !important;}.cke_rtl .cke_button__numberedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1344px !important;}.cke_ltr .cke_button__numberedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1368px !important;}.cke_button__maximize_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1392px !important;}.cke_rtl .cke_button__newpage_icon, .cke_mixed_dir_content .cke_rtl .cke_button__newpage_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1416px !important;}.cke_ltr .cke_button__newpage_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1440px !important;}.cke_rtl .cke_button__pagebreak_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pagebreak_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1464px !important;}.cke_ltr .cke_button__pagebreak_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1488px !important;}.cke_rtl .cke_button__pastetext_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1512px !important;}.cke_ltr .cke_button__pastetext_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1536px !important;}.cke_rtl .cke_button__pastefromword_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1560px !important;}.cke_ltr .cke_button__pastefromword_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1584px !important;}.cke_rtl .cke_button__preview_icon, .cke_mixed_dir_content .cke_rtl .cke_button__preview_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1608px !important;}.cke_ltr .cke_button__preview_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1632px !important;}.cke_button__print_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1656px !important;}.cke_button__removeformat_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1680px !important;}.cke_button__save_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1704px !important;}.cke_button__selectall_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1728px !important;}.cke_rtl .cke_button__showblocks_icon, .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1752px !important;}.cke_ltr .cke_button__showblocks_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1776px !important;}.cke_rtl .cke_button__source_icon, .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1800px !important;}.cke_ltr .cke_button__source_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1824px !important;}.cke_button__specialchar_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1848px !important;}.cke_button__scayt_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1872px !important;}.cke_button__table_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1896px !important;}.cke_rtl .cke_button__redo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1920px !important;}.cke_ltr .cke_button__redo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1944px !important;}.cke_rtl .cke_button__undo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1968px !important;}.cke_ltr .cke_button__undo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1992px !important;}.cke_button__spellchecker_icon {background: url(icons.png?t=3876e73) no-repeat 0 -2016px !important;}.cke_hidpi .cke_button__about_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -0px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bold_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -24px !important;background-size: 16px !important;}.cke_hidpi .cke_button__italic_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -48px !important;background-size: 16px !important;}.cke_hidpi .cke_button__strike_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -72px !important;background-size: 16px !important;}.cke_hidpi .cke_button__subscript_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -96px !important;background-size: 16px !important;}.cke_hidpi .cke_button__superscript_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -120px !important;background-size: 16px !important;}.cke_hidpi .cke_button__underline_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -144px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bidiltr_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -168px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bidirtl_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -192px !important;background-size: 16px !important;}.cke_hidpi .cke_button__blockquote_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -216px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__copy_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -240px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -264px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__cut_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -288px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -312px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__paste_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -336px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -360px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bgcolor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -384px !important;background-size: 16px !important;}.cke_hidpi .cke_button__textcolor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -408px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__templates_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__templates_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -432px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__templates_icon,.cke_ltr.cke_hidpi .cke_button__templates_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -456px !important;background-size: 16px !important;}.cke_hidpi .cke_button__creatediv_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -480px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__find_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__find_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -504px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__find_icon,.cke_ltr.cke_hidpi .cke_button__find_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -528px !important;background-size: 16px !important;}.cke_hidpi .cke_button__replace_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -552px !important;background-size: 16px !important;}.cke_hidpi .cke_button__flash_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -576px !important;background-size: 16px !important;}.cke_hidpi .cke_button__button_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -600px !important;background-size: 16px !important;}.cke_hidpi .cke_button__checkbox_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -624px !important;background-size: 16px !important;}.cke_hidpi .cke_button__form_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -648px !important;background-size: 16px !important;}.cke_hidpi .cke_button__hiddenfield_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -672px !important;background-size: 16px !important;}.cke_hidpi .cke_button__imagebutton_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -696px !important;background-size: 16px !important;}.cke_hidpi .cke_button__radio_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -720px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__select_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__select_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -744px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__select_icon,.cke_ltr.cke_hidpi .cke_button__select_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -768px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__textarea_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__textarea_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -792px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__textarea_icon,.cke_ltr.cke_hidpi .cke_button__textarea_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -816px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__textfield_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__textfield_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -840px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__textfield_icon,.cke_ltr.cke_hidpi .cke_button__textfield_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -864px !important;background-size: 16px !important;}.cke_hidpi .cke_button__horizontalrule_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -888px !important;background-size: 16px !important;}.cke_hidpi .cke_button__iframe_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -912px !important;background-size: 16px !important;}.cke_hidpi .cke_button__image_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -936px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__indent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -960px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -984px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__outdent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1008px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1032px !important;background-size: 16px !important;}.cke_hidpi .cke_button__smiley_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1056px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyblock_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1080px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifycenter_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1104px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyleft_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1128px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyright_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1152px !important;background-size: 16px !important;}.cke_hidpi .cke_button__language_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1176px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__anchor_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1200px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__anchor_icon,.cke_ltr.cke_hidpi .cke_button__anchor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1224px !important;background-size: 16px !important;}.cke_hidpi .cke_button__link_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1248px !important;background-size: 16px !important;}.cke_hidpi .cke_button__unlink_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1272px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1296px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1320px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1344px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1368px !important;background-size: 16px !important;}.cke_hidpi .cke_button__maximize_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1392px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__newpage_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__newpage_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1416px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__newpage_icon,.cke_ltr.cke_hidpi .cke_button__newpage_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1440px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pagebreak_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pagebreak_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1464px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pagebreak_icon,.cke_ltr.cke_hidpi .cke_button__pagebreak_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1488px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastetext_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1512px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1536px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1560px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1584px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__preview_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__preview_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1608px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__preview_icon,.cke_ltr.cke_hidpi .cke_button__preview_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1632px !important;background-size: 16px !important;}.cke_hidpi .cke_button__print_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1656px !important;background-size: 16px !important;}.cke_hidpi .cke_button__removeformat_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1680px !important;background-size: 16px !important;}.cke_hidpi .cke_button__save_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1704px !important;background-size: 16px !important;}.cke_hidpi .cke_button__selectall_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1728px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__showblocks_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1752px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__showblocks_icon,.cke_ltr.cke_hidpi .cke_button__showblocks_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1776px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__source_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1800px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1824px !important;background-size: 16px !important;}.cke_hidpi .cke_button__specialchar_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1848px !important;background-size: 16px !important;}.cke_hidpi .cke_button__scayt_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1872px !important;background-size: 16px !important;}.cke_hidpi .cke_button__table_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1896px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__redo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1920px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1944px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__undo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1968px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1992px !important;background-size: 16px !important;}.cke_hidpi .cke_button__spellchecker_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -2016px !important;background-size: 16px !important;} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/editor_ie7.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/editor_ie7.css new file mode 100644 index 0000000..7e4ad18 --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/editor_ie7.css @@ -0,0 +1 @@ +.cke_reset{margin:0;padding:0;border:0;background:0;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none}.cke_reset_all,.cke_reset_all *{margin:0;padding:0;border:0;background:0;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#333;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre}.cke_reset_all input[type=password],.cke_reset_all input[type=text],.cke_reset_all textarea{cursor:text}.cke_reset_all input[type=password][disabled],.cke_reset_all input[type=text][disabled],.cke_reset_all textarea[disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;margin-top:10px;border:1px solid #ddd}.cke_reset_all fieldset legend{padding:0 5px}.cke_reset_all select{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.cke_chrome{display:block;border:1px solid #ddd;border-radius:4px;padding:0 3px;background:#eee}.cke_inner{display:block;-webkit-touch-callout:none;background:0;padding:0}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_float .cke_top{border:1px solid #ddd}.cke_bottom,.cke_contents,.cke_top{display:block;overflow:hidden}.cke_bottom,.cke_top{padding:3px 0 0;background:#eee}.cke_top{white-space:normal}.cke_contents{background-color:#fff;border:1px solid #ddd;border-radius:4px}.cke_bottom{position:relative}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #555 transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #aaa;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;margin-top:5px;background-color:#fff;border:1px solid #aaa;border-radius:4px}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:178px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_list{list-style-type:none;margin:3px;padding:0;white-space:nowrap}.cke_panel_listItem{margin:0;padding-bottom:1px}.cke_panel_listItem a{padding:3px 4px;display:block;border:1px solid #fff;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis;border-radius:2px}.cke_panel_listItem a:active,.cke_panel_listItem a:focus,.cke_panel_listItem a:hover{background-color:#e1edf7}* html .cke_panel_listItem a{width:100%;color:#000}:first-child+html .cke_panel_listItem a{color:#000}.cke_panel_listItem.cke_selected a{background-color:#92bce0;outline:0}.cke_hc .cke_panel_listItem a{border-style:none}.cke_hc .cke_panel_listItem a:active,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:hover{border:2px solid;padding:1px 2px}.cke_panel_grouptitle{font-size:11px;font-weight:700;white-space:nowrap;margin:0;padding:6px;color:#474747;border-bottom:1px solid #aaa;background:#eee}.cke_panel_grouptitle:first-child{border-radius:4px 4px 0 0}.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem p,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_colorblock{padding:3px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}span.cke_colorbox{width:10px;height:10px;border:1px solid #aaa;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorbox{border:1px solid #fff;padding:2px;float:left;width:12px;height:12px;border-radius:2px}.cke_rtl a.cke_colorbox{float:right}a:active.cke_colorbox,a:focus.cke_colorbox,a:hover.cke_colorbox{border:1px solid #ddd;background-color:#eee}a.cke_colorauto,a.cke_colormore{border:1px solid #fff;padding:2px;display:block;cursor:pointer}a:active.cke_colorauto,a:active.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:hover.cke_colorauto,a:hover.cke_colormore{border:1px solid #ddd;background-color:#eee}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{float:left;margin:0 6px 3px 0;padding:2px;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_hc .cke_toolgroup{border:0;margin-right:10px;margin-bottom:10px}.cke_rtl .cke_toolgroup :first-child{border-radius:0 4px 4px 0}.cke_rtl .cke_toolgroup :last-child{border-radius:4px 0 0 4px}.cke_rtl .cke_toolgroup{margin-left:6px;margin-right:0}a.cke_button{display:inline-block;height:18px;padding:2px 4px;outline:0;cursor:default;border:0;border-radius:2px}.cke_hc .cke_button{border:1px solid #000;padding:3px 5px;margin:-2px 4px 0 -2px}.cke_button_on{background:#92bce0}.cke_hc .cke_button_on,.cke_hc a.cke_button_disabled:active,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_off:active,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:hover{border-width:3px;padding:1px 3px}.cke_button_disabled .cke_button_icon{opacity:.3}.cke_hc .cke_button_disabled{opacity:.5}a.cke_button_disabled:active,a.cke_button_disabled:focus,a.cke_button_disabled:hover,a.cke_button_off:active,a.cke_button_off:focus,a.cke_button_off:hover{background:#e1edf7}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:18px;vertical-align:middle;float:left;cursor:default;color:#555}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_rtl .cke_button_arrow{margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px -2px 0 3px;width:auto;border:0}.cke_toolbar_separator{margin:4px 2px 0;height:16px;width:1px}.cke_hc .cke_toolbar_separator{width:0;border-left:1px solid;margin:1px 5px 0 0}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #a6a6a6;border-bottom-color:#979797;border-radius:4px;background:#e4e4e4}.cke_toolbox_collapser:hover{background:#ccc}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#474747}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:3px solid #474747;border-top:3px solid transparent}.cke_rtl .cke_toolbox_collapser{float:left}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0;margin-right:2px}.cke_button_icon{opacity:.8}.cke_menuitem span{cursor:default}.cke_menubutton:active,.cke_menubutton:focus,.cke_menubutton:hover{display:block}.cke_hc .cke_menubutton{padding:2px}.cke_hc .cke_menubutton:active,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:hover{border:2px solid;padding:0}.cke_menubutton_icon{background-color:#d7d8d7;opacity:.7;filter:alpha(opacity=70);padding:4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:active .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:hover .cke_menubutton_icon{background-color:#d0d2d0}.cke_menubutton_disabled:active .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:hover .cke_menubutton_icon{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_label{padding:0 5px;background-color:transparent}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_on{border:1px solid #dedede;background-color:#f2f2f2}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px}.cke_menubutton:active,.cke_menubutton:focus,.cke_menubutton:hover{background-color:#eff0ef}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d3d3d3;height:1px;filter:alpha(opacity=70);opacity:.7}.cke_menuarrow{background-image:url(images/arrow.png);background-repeat:no-repeat}.cke_menuarrow span{display:none}.cke_rtl .cke_menuarrow{background-repeat:no-repeat}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left}.cke_hc .cke_combo{margin-top:-2px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_button{display:inline-block;float:left;margin:0 6px 5px 0;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_combo_off a.cke_combo_button:focus,.cke_combo_off a.cke_combo_button:hover{outline:0}.cke_combo_off a.cke_combo_button:active,.cke_combo_on a.cke_combo_button{border-color:#333}.cke_rtl .cke_combo_button{float:right;margin-left:5px;margin-right:0}.cke_hc a.cke_combo_button{padding:3px}.cke_hc .cke_combo_off a.cke_combo_button:active,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_on a.cke_combo_button{border-width:3px;padding:1px}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#474747;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 7px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #333}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}.cke_path_empty,.cke_path_item{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#4c4c4c;font-weight:700;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_empty,.cke_rtl .cke_path_item{float:right}a.cke_path_item:active,a.cke_path_item:focus,a.cke_path_item:hover{background-color:#bfbfbf;color:#333;border-radius:2px}.cke_hc a.cke_path_item:active,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:hover{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combo__fontsize .cke_combo_text{width:30px}.cke_combopanel__fontsize{width:120px}.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre}.cke_wysiwyg_div,.cke_wysiwyg_frame{background-color:#fff}.cke_chrome{visibility:inherit}.cke_voice_label,legend.cke_voice_label{display:none}.cke_rtl .cke_button,.cke_rtl .cke_button *,.cke_rtl .cke_combo,.cke_rtl .cke_combo *,.cke_rtl .cke_path_empty,.cke_rtl .cke_path_item,.cke_rtl .cke_path_item *,.cke_rtl .cke_toolbar_separator,.cke_rtl .cke_toolgroup{float:none}.cke_rtl .cke_button,.cke_rtl .cke_button_icon,.cke_rtl .cke_combo_button,.cke_rtl .cke_combo_button *,.cke_rtl .cke_toolbar_separator,.cke_rtl .cke_toolgroup{display:inline-block;vertical-align:top}.cke_toolbox{display:inline-block;padding-bottom:5px;height:100%}.cke_rtl .cke_toolbox{padding-bottom:0}.cke_toolbar{margin-bottom:5px}.cke_rtl .cke_toolbar{margin-bottom:0}.cke_toolgroup{height:26px}.cke_combo,.cke_toolgroup{position:relative}a.cke_button{float:none;vertical-align:top}.cke_toolbar_separator{display:inline-block;float:none;vertical-align:top;background-color:silver}.cke_toolbox_collapser .cke_arrow{margin-top:0;border-width:4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{border-width:3px}.cke_rtl .cke_button_arrow{padding-top:8px;margin-right:2px}.cke_rtl .cke_combo_inlinelabel{display:table-cell;vertical-align:middle}.cke_menubutton{display:block;height:24px}.cke_menubutton_inner{display:block;position:relative}.cke_menubutton_icon{height:16px;width:16px}.cke_menuarrow,.cke_menubutton_icon,.cke_menubutton_label{display:inline-block}.cke_menubutton_label{width:auto;vertical-align:top;line-height:24px;height:24px;margin:0 10px 0 0}.cke_menuarrow{width:5px;height:6px;padding:0;position:absolute;right:8px;top:10px;background-position:0 0}.cke_rtl .cke_menubutton_icon{position:absolute;right:0;top:0}.cke_rtl .cke_menubutton_label{float:right;clear:both;margin:0 24px 0 10px}.cke_hc .cke_rtl .cke_menubutton_label{margin-right:0}.cke_rtl .cke_menuarrow{left:8px;right:auto;background-position:0 -24px}.cke_hc .cke_menuarrow{top:5px;padding:0 5px}.cke_rtl input.cke_dialog_ui_input_password,.cke_rtl input.cke_dialog_ui_input_text{position:relative}.cke_wysiwyg_div{padding-top:0!important;padding-bottom:0!important}.cke_button__about_icon {background: url(icons.png?t=3876e73) no-repeat 0 -0px !important;}.cke_button__bold_icon {background: url(icons.png?t=3876e73) no-repeat 0 -24px !important;}.cke_button__italic_icon {background: url(icons.png?t=3876e73) no-repeat 0 -48px !important;}.cke_button__strike_icon {background: url(icons.png?t=3876e73) no-repeat 0 -72px !important;}.cke_button__subscript_icon {background: url(icons.png?t=3876e73) no-repeat 0 -96px !important;}.cke_button__superscript_icon {background: url(icons.png?t=3876e73) no-repeat 0 -120px !important;}.cke_button__underline_icon {background: url(icons.png?t=3876e73) no-repeat 0 -144px !important;}.cke_button__bidiltr_icon {background: url(icons.png?t=3876e73) no-repeat 0 -168px !important;}.cke_button__bidirtl_icon {background: url(icons.png?t=3876e73) no-repeat 0 -192px !important;}.cke_button__blockquote_icon {background: url(icons.png?t=3876e73) no-repeat 0 -216px !important;}.cke_rtl .cke_button__copy_icon, .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons.png?t=3876e73) no-repeat 0 -240px !important;}.cke_ltr .cke_button__copy_icon {background: url(icons.png?t=3876e73) no-repeat 0 -264px !important;}.cke_rtl .cke_button__cut_icon, .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons.png?t=3876e73) no-repeat 0 -288px !important;}.cke_ltr .cke_button__cut_icon {background: url(icons.png?t=3876e73) no-repeat 0 -312px !important;}.cke_rtl .cke_button__paste_icon, .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons.png?t=3876e73) no-repeat 0 -336px !important;}.cke_ltr .cke_button__paste_icon {background: url(icons.png?t=3876e73) no-repeat 0 -360px !important;}.cke_button__bgcolor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -384px !important;}.cke_button__textcolor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -408px !important;}.cke_rtl .cke_button__templates_icon, .cke_mixed_dir_content .cke_rtl .cke_button__templates_icon {background: url(icons.png?t=3876e73) no-repeat 0 -432px !important;}.cke_ltr .cke_button__templates_icon {background: url(icons.png?t=3876e73) no-repeat 0 -456px !important;}.cke_button__creatediv_icon {background: url(icons.png?t=3876e73) no-repeat 0 -480px !important;}.cke_rtl .cke_button__find_icon, .cke_mixed_dir_content .cke_rtl .cke_button__find_icon {background: url(icons.png?t=3876e73) no-repeat 0 -504px !important;}.cke_ltr .cke_button__find_icon {background: url(icons.png?t=3876e73) no-repeat 0 -528px !important;}.cke_button__replace_icon {background: url(icons.png?t=3876e73) no-repeat 0 -552px !important;}.cke_button__flash_icon {background: url(icons.png?t=3876e73) no-repeat 0 -576px !important;}.cke_button__button_icon {background: url(icons.png?t=3876e73) no-repeat 0 -600px !important;}.cke_button__checkbox_icon {background: url(icons.png?t=3876e73) no-repeat 0 -624px !important;}.cke_button__form_icon {background: url(icons.png?t=3876e73) no-repeat 0 -648px !important;}.cke_button__hiddenfield_icon {background: url(icons.png?t=3876e73) no-repeat 0 -672px !important;}.cke_button__imagebutton_icon {background: url(icons.png?t=3876e73) no-repeat 0 -696px !important;}.cke_button__radio_icon {background: url(icons.png?t=3876e73) no-repeat 0 -720px !important;}.cke_rtl .cke_button__select_icon, .cke_mixed_dir_content .cke_rtl .cke_button__select_icon {background: url(icons.png?t=3876e73) no-repeat 0 -744px !important;}.cke_ltr .cke_button__select_icon {background: url(icons.png?t=3876e73) no-repeat 0 -768px !important;}.cke_rtl .cke_button__textarea_icon, .cke_mixed_dir_content .cke_rtl .cke_button__textarea_icon {background: url(icons.png?t=3876e73) no-repeat 0 -792px !important;}.cke_ltr .cke_button__textarea_icon {background: url(icons.png?t=3876e73) no-repeat 0 -816px !important;}.cke_rtl .cke_button__textfield_icon, .cke_mixed_dir_content .cke_rtl .cke_button__textfield_icon {background: url(icons.png?t=3876e73) no-repeat 0 -840px !important;}.cke_ltr .cke_button__textfield_icon {background: url(icons.png?t=3876e73) no-repeat 0 -864px !important;}.cke_button__horizontalrule_icon {background: url(icons.png?t=3876e73) no-repeat 0 -888px !important;}.cke_button__iframe_icon {background: url(icons.png?t=3876e73) no-repeat 0 -912px !important;}.cke_button__image_icon {background: url(icons.png?t=3876e73) no-repeat 0 -936px !important;}.cke_rtl .cke_button__indent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -960px !important;}.cke_ltr .cke_button__indent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -984px !important;}.cke_rtl .cke_button__outdent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1008px !important;}.cke_ltr .cke_button__outdent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1032px !important;}.cke_button__smiley_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1056px !important;}.cke_button__justifyblock_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1080px !important;}.cke_button__justifycenter_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1104px !important;}.cke_button__justifyleft_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1128px !important;}.cke_button__justifyright_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1152px !important;}.cke_button__language_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1176px !important;}.cke_rtl .cke_button__anchor_icon, .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1200px !important;}.cke_ltr .cke_button__anchor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1224px !important;}.cke_button__link_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1248px !important;}.cke_button__unlink_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1272px !important;}.cke_rtl .cke_button__bulletedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1296px !important;}.cke_ltr .cke_button__bulletedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1320px !important;}.cke_rtl .cke_button__numberedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1344px !important;}.cke_ltr .cke_button__numberedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1368px !important;}.cke_button__maximize_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1392px !important;}.cke_rtl .cke_button__newpage_icon, .cke_mixed_dir_content .cke_rtl .cke_button__newpage_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1416px !important;}.cke_ltr .cke_button__newpage_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1440px !important;}.cke_rtl .cke_button__pagebreak_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pagebreak_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1464px !important;}.cke_ltr .cke_button__pagebreak_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1488px !important;}.cke_rtl .cke_button__pastetext_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1512px !important;}.cke_ltr .cke_button__pastetext_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1536px !important;}.cke_rtl .cke_button__pastefromword_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1560px !important;}.cke_ltr .cke_button__pastefromword_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1584px !important;}.cke_rtl .cke_button__preview_icon, .cke_mixed_dir_content .cke_rtl .cke_button__preview_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1608px !important;}.cke_ltr .cke_button__preview_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1632px !important;}.cke_button__print_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1656px !important;}.cke_button__removeformat_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1680px !important;}.cke_button__save_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1704px !important;}.cke_button__selectall_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1728px !important;}.cke_rtl .cke_button__showblocks_icon, .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1752px !important;}.cke_ltr .cke_button__showblocks_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1776px !important;}.cke_rtl .cke_button__source_icon, .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1800px !important;}.cke_ltr .cke_button__source_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1824px !important;}.cke_button__specialchar_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1848px !important;}.cke_button__scayt_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1872px !important;}.cke_button__table_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1896px !important;}.cke_rtl .cke_button__redo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1920px !important;}.cke_ltr .cke_button__redo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1944px !important;}.cke_rtl .cke_button__undo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1968px !important;}.cke_ltr .cke_button__undo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1992px !important;}.cke_button__spellchecker_icon {background: url(icons.png?t=3876e73) no-repeat 0 -2016px !important;}.cke_hidpi .cke_button__about_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -0px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bold_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -24px !important;background-size: 16px !important;}.cke_hidpi .cke_button__italic_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -48px !important;background-size: 16px !important;}.cke_hidpi .cke_button__strike_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -72px !important;background-size: 16px !important;}.cke_hidpi .cke_button__subscript_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -96px !important;background-size: 16px !important;}.cke_hidpi .cke_button__superscript_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -120px !important;background-size: 16px !important;}.cke_hidpi .cke_button__underline_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -144px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bidiltr_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -168px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bidirtl_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -192px !important;background-size: 16px !important;}.cke_hidpi .cke_button__blockquote_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -216px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__copy_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -240px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -264px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__cut_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -288px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -312px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__paste_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -336px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -360px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bgcolor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -384px !important;background-size: 16px !important;}.cke_hidpi .cke_button__textcolor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -408px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__templates_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__templates_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -432px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__templates_icon,.cke_ltr.cke_hidpi .cke_button__templates_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -456px !important;background-size: 16px !important;}.cke_hidpi .cke_button__creatediv_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -480px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__find_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__find_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -504px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__find_icon,.cke_ltr.cke_hidpi .cke_button__find_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -528px !important;background-size: 16px !important;}.cke_hidpi .cke_button__replace_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -552px !important;background-size: 16px !important;}.cke_hidpi .cke_button__flash_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -576px !important;background-size: 16px !important;}.cke_hidpi .cke_button__button_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -600px !important;background-size: 16px !important;}.cke_hidpi .cke_button__checkbox_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -624px !important;background-size: 16px !important;}.cke_hidpi .cke_button__form_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -648px !important;background-size: 16px !important;}.cke_hidpi .cke_button__hiddenfield_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -672px !important;background-size: 16px !important;}.cke_hidpi .cke_button__imagebutton_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -696px !important;background-size: 16px !important;}.cke_hidpi .cke_button__radio_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -720px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__select_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__select_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -744px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__select_icon,.cke_ltr.cke_hidpi .cke_button__select_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -768px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__textarea_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__textarea_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -792px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__textarea_icon,.cke_ltr.cke_hidpi .cke_button__textarea_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -816px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__textfield_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__textfield_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -840px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__textfield_icon,.cke_ltr.cke_hidpi .cke_button__textfield_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -864px !important;background-size: 16px !important;}.cke_hidpi .cke_button__horizontalrule_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -888px !important;background-size: 16px !important;}.cke_hidpi .cke_button__iframe_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -912px !important;background-size: 16px !important;}.cke_hidpi .cke_button__image_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -936px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__indent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -960px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -984px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__outdent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1008px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1032px !important;background-size: 16px !important;}.cke_hidpi .cke_button__smiley_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1056px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyblock_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1080px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifycenter_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1104px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyleft_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1128px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyright_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1152px !important;background-size: 16px !important;}.cke_hidpi .cke_button__language_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1176px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__anchor_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1200px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__anchor_icon,.cke_ltr.cke_hidpi .cke_button__anchor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1224px !important;background-size: 16px !important;}.cke_hidpi .cke_button__link_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1248px !important;background-size: 16px !important;}.cke_hidpi .cke_button__unlink_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1272px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1296px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1320px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1344px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1368px !important;background-size: 16px !important;}.cke_hidpi .cke_button__maximize_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1392px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__newpage_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__newpage_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1416px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__newpage_icon,.cke_ltr.cke_hidpi .cke_button__newpage_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1440px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pagebreak_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pagebreak_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1464px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pagebreak_icon,.cke_ltr.cke_hidpi .cke_button__pagebreak_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1488px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastetext_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1512px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1536px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1560px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1584px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__preview_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__preview_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1608px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__preview_icon,.cke_ltr.cke_hidpi .cke_button__preview_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1632px !important;background-size: 16px !important;}.cke_hidpi .cke_button__print_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1656px !important;background-size: 16px !important;}.cke_hidpi .cke_button__removeformat_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1680px !important;background-size: 16px !important;}.cke_hidpi .cke_button__save_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1704px !important;background-size: 16px !important;}.cke_hidpi .cke_button__selectall_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1728px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__showblocks_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1752px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__showblocks_icon,.cke_ltr.cke_hidpi .cke_button__showblocks_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1776px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__source_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1800px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1824px !important;background-size: 16px !important;}.cke_hidpi .cke_button__specialchar_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1848px !important;background-size: 16px !important;}.cke_hidpi .cke_button__scayt_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1872px !important;background-size: 16px !important;}.cke_hidpi .cke_button__table_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1896px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__redo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1920px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1944px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__undo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1968px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1992px !important;background-size: 16px !important;}.cke_hidpi .cke_button__spellchecker_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -2016px !important;background-size: 16px !important;} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/editor_ie8.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/editor_ie8.css new file mode 100644 index 0000000..6d5b65d --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/editor_ie8.css @@ -0,0 +1 @@ +.cke_reset{margin:0;padding:0;border:0;background:0;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none}.cke_reset_all,.cke_reset_all *{margin:0;padding:0;border:0;background:0;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#333;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre}.cke_reset_all input[type=password],.cke_reset_all input[type=text],.cke_reset_all textarea{cursor:text}.cke_reset_all input[type=password][disabled],.cke_reset_all input[type=text][disabled],.cke_reset_all textarea[disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;margin-top:10px;border:1px solid #ddd}.cke_reset_all fieldset legend{padding:0 5px}.cke_reset_all select{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.cke_chrome{display:block;border:1px solid #ddd;border-radius:4px;padding:0 3px;background:#eee}.cke_inner{display:block;-webkit-touch-callout:none;background:0;padding:0}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_float .cke_top{border:1px solid #ddd}.cke_bottom,.cke_contents,.cke_top{display:block;overflow:hidden}.cke_bottom,.cke_top{padding:3px 0 0;background:#eee}.cke_top{white-space:normal}.cke_contents{background-color:#fff;border:1px solid #ddd;border-radius:4px}.cke_bottom{position:relative}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #555 transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #aaa;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;margin-top:5px;background-color:#fff;border:1px solid #aaa;border-radius:4px}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:178px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_list{list-style-type:none;margin:3px;padding:0;white-space:nowrap}.cke_panel_listItem{margin:0;padding-bottom:1px}.cke_panel_listItem a{padding:3px 4px;display:block;border:1px solid #fff;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis;border-radius:2px}.cke_panel_listItem a:active,.cke_panel_listItem a:focus,.cke_panel_listItem a:hover{background-color:#e1edf7}* html .cke_panel_listItem a{width:100%;color:#000}:first-child+html .cke_panel_listItem a{color:#000}.cke_panel_listItem.cke_selected a{background-color:#92bce0;outline:0}.cke_hc .cke_panel_listItem a{border-style:none}.cke_hc .cke_panel_listItem a:active,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:hover{border:2px solid;padding:1px 2px}.cke_panel_grouptitle{font-size:11px;font-weight:700;white-space:nowrap;margin:0;padding:6px;color:#474747;border-bottom:1px solid #aaa;background:#eee}.cke_panel_grouptitle:first-child{border-radius:4px 4px 0 0}.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem p,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_colorblock{padding:3px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}span.cke_colorbox{width:10px;height:10px;border:1px solid #aaa;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorbox{border:1px solid #fff;padding:2px;float:left;width:12px;height:12px;border-radius:2px}.cke_rtl a.cke_colorbox{float:right}a:active.cke_colorbox,a:focus.cke_colorbox,a:hover.cke_colorbox{border:1px solid #ddd;background-color:#eee}a.cke_colorauto,a.cke_colormore{border:1px solid #fff;padding:2px;display:block;cursor:pointer}a:active.cke_colorauto,a:active.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:hover.cke_colorauto,a:hover.cke_colormore{border:1px solid #ddd;background-color:#eee}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{float:left;margin:0 6px 3px 0;padding:2px;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_hc .cke_toolgroup{border:0;margin-right:10px;margin-bottom:10px}.cke_rtl .cke_toolgroup :first-child{border-radius:0 4px 4px 0}.cke_rtl .cke_toolgroup :last-child{border-radius:4px 0 0 4px}.cke_rtl .cke_toolgroup{float:right;margin-left:6px;margin-right:0}a.cke_button{display:inline-block;height:18px;padding:2px 4px;outline:0;cursor:default;float:left;border:0;border-radius:2px}.cke_rtl .cke_button{float:right}.cke_hc .cke_button{border:1px solid #000;padding:3px 5px;margin:-2px 4px 0 -2px}.cke_button_on{background:#92bce0}.cke_hc .cke_button_on,.cke_hc a.cke_button_disabled:active,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_off:active,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:hover{border-width:3px;padding:1px 3px}.cke_button_disabled .cke_button_icon{opacity:.3}.cke_hc .cke_button_disabled{opacity:.5}a.cke_button_disabled:active,a.cke_button_disabled:focus,a.cke_button_disabled:hover,a.cke_button_off:active,a.cke_button_off:focus,a.cke_button_off:hover{background:#e1edf7}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:18px;vertical-align:middle;float:left;cursor:default;color:#555}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px -2px 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#ddd;margin:4px 2px 0;height:16px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{width:0;border-left:1px solid;margin:1px 5px 0 0}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #a6a6a6;border-bottom-color:#979797;border-radius:4px;background:#e4e4e4}.cke_toolbox_collapser:hover{background:#ccc}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#474747}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:3px solid #474747;border-top:3px solid transparent}.cke_rtl .cke_toolbox_collapser{float:left}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0;margin-right:2px}.cke_menubutton{display:block}.cke_button_icon{opacity:.8}.cke_menuitem span{cursor:default}.cke_menubutton:active,.cke_menubutton:focus,.cke_menubutton:hover{display:block}.cke_hc .cke_menubutton{padding:2px}.cke_hc .cke_menubutton:active,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:hover{border:2px solid;padding:0}.cke_menubutton_inner{display:table-row}.cke_menuarrow,.cke_menubutton_icon,.cke_menubutton_label{display:table-cell}.cke_menubutton_icon{background-color:#d7d8d7;opacity:.7;filter:alpha(opacity=70);padding:4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:active .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:hover .cke_menubutton_icon{background-color:#d0d2d0}.cke_menubutton_disabled:active .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:hover .cke_menubutton_icon{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_on{border:1px solid #dedede;background-color:#f2f2f2}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px}.cke_menubutton:active,.cke_menubutton:focus,.cke_menubutton:hover{background-color:#eff0ef}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d3d3d3;height:1px;filter:alpha(opacity=70);opacity:.7}.cke_menuarrow{background-image:url(images/arrow.png);background-position:0 10px;background-repeat:no-repeat;padding:0 5px}.cke_menuarrow span{display:none}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:-2px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_button{display:inline-block;float:left;margin:0 6px 5px 0;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_combo_off a.cke_combo_button:focus,.cke_combo_off a.cke_combo_button:hover{outline:0}.cke_combo_off a.cke_combo_button:active,.cke_combo_on a.cke_combo_button{border-color:#333}.cke_rtl .cke_combo_button{float:right;margin-left:5px;margin-right:0}.cke_hc a.cke_combo_button{padding:3px}.cke_hc .cke_combo_off a.cke_combo_button:active,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_on a.cke_combo_button{border-width:3px;padding:1px}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#474747;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 7px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #333}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}.cke_path_empty,.cke_path_item{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#4c4c4c;font-weight:700;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_empty,.cke_rtl .cke_path_item{float:right}a.cke_path_item:active,a.cke_path_item:focus,a.cke_path_item:hover{background-color:#bfbfbf;color:#333;border-radius:2px}.cke_hc a.cke_path_item:active,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:hover{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combo__fontsize .cke_combo_text{width:30px}.cke_combopanel__fontsize{width:120px}.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre}.cke_wysiwyg_div,.cke_wysiwyg_frame{background-color:#fff}.cke_chrome{visibility:inherit}.cke_voice_label,legend.cke_voice_label{display:none}.cke_toolbox_collapser .cke_arrow{border-width:4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{border-width:3px}.cke_toolbox_collapser .cke_arrow{margin-top:0}.cke_button__about_icon {background: url(icons.png?t=3876e73) no-repeat 0 -0px !important;}.cke_button__bold_icon {background: url(icons.png?t=3876e73) no-repeat 0 -24px !important;}.cke_button__italic_icon {background: url(icons.png?t=3876e73) no-repeat 0 -48px !important;}.cke_button__strike_icon {background: url(icons.png?t=3876e73) no-repeat 0 -72px !important;}.cke_button__subscript_icon {background: url(icons.png?t=3876e73) no-repeat 0 -96px !important;}.cke_button__superscript_icon {background: url(icons.png?t=3876e73) no-repeat 0 -120px !important;}.cke_button__underline_icon {background: url(icons.png?t=3876e73) no-repeat 0 -144px !important;}.cke_button__bidiltr_icon {background: url(icons.png?t=3876e73) no-repeat 0 -168px !important;}.cke_button__bidirtl_icon {background: url(icons.png?t=3876e73) no-repeat 0 -192px !important;}.cke_button__blockquote_icon {background: url(icons.png?t=3876e73) no-repeat 0 -216px !important;}.cke_rtl .cke_button__copy_icon, .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons.png?t=3876e73) no-repeat 0 -240px !important;}.cke_ltr .cke_button__copy_icon {background: url(icons.png?t=3876e73) no-repeat 0 -264px !important;}.cke_rtl .cke_button__cut_icon, .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons.png?t=3876e73) no-repeat 0 -288px !important;}.cke_ltr .cke_button__cut_icon {background: url(icons.png?t=3876e73) no-repeat 0 -312px !important;}.cke_rtl .cke_button__paste_icon, .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons.png?t=3876e73) no-repeat 0 -336px !important;}.cke_ltr .cke_button__paste_icon {background: url(icons.png?t=3876e73) no-repeat 0 -360px !important;}.cke_button__bgcolor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -384px !important;}.cke_button__textcolor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -408px !important;}.cke_rtl .cke_button__templates_icon, .cke_mixed_dir_content .cke_rtl .cke_button__templates_icon {background: url(icons.png?t=3876e73) no-repeat 0 -432px !important;}.cke_ltr .cke_button__templates_icon {background: url(icons.png?t=3876e73) no-repeat 0 -456px !important;}.cke_button__creatediv_icon {background: url(icons.png?t=3876e73) no-repeat 0 -480px !important;}.cke_rtl .cke_button__find_icon, .cke_mixed_dir_content .cke_rtl .cke_button__find_icon {background: url(icons.png?t=3876e73) no-repeat 0 -504px !important;}.cke_ltr .cke_button__find_icon {background: url(icons.png?t=3876e73) no-repeat 0 -528px !important;}.cke_button__replace_icon {background: url(icons.png?t=3876e73) no-repeat 0 -552px !important;}.cke_button__flash_icon {background: url(icons.png?t=3876e73) no-repeat 0 -576px !important;}.cke_button__button_icon {background: url(icons.png?t=3876e73) no-repeat 0 -600px !important;}.cke_button__checkbox_icon {background: url(icons.png?t=3876e73) no-repeat 0 -624px !important;}.cke_button__form_icon {background: url(icons.png?t=3876e73) no-repeat 0 -648px !important;}.cke_button__hiddenfield_icon {background: url(icons.png?t=3876e73) no-repeat 0 -672px !important;}.cke_button__imagebutton_icon {background: url(icons.png?t=3876e73) no-repeat 0 -696px !important;}.cke_button__radio_icon {background: url(icons.png?t=3876e73) no-repeat 0 -720px !important;}.cke_rtl .cke_button__select_icon, .cke_mixed_dir_content .cke_rtl .cke_button__select_icon {background: url(icons.png?t=3876e73) no-repeat 0 -744px !important;}.cke_ltr .cke_button__select_icon {background: url(icons.png?t=3876e73) no-repeat 0 -768px !important;}.cke_rtl .cke_button__textarea_icon, .cke_mixed_dir_content .cke_rtl .cke_button__textarea_icon {background: url(icons.png?t=3876e73) no-repeat 0 -792px !important;}.cke_ltr .cke_button__textarea_icon {background: url(icons.png?t=3876e73) no-repeat 0 -816px !important;}.cke_rtl .cke_button__textfield_icon, .cke_mixed_dir_content .cke_rtl .cke_button__textfield_icon {background: url(icons.png?t=3876e73) no-repeat 0 -840px !important;}.cke_ltr .cke_button__textfield_icon {background: url(icons.png?t=3876e73) no-repeat 0 -864px !important;}.cke_button__horizontalrule_icon {background: url(icons.png?t=3876e73) no-repeat 0 -888px !important;}.cke_button__iframe_icon {background: url(icons.png?t=3876e73) no-repeat 0 -912px !important;}.cke_button__image_icon {background: url(icons.png?t=3876e73) no-repeat 0 -936px !important;}.cke_rtl .cke_button__indent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -960px !important;}.cke_ltr .cke_button__indent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -984px !important;}.cke_rtl .cke_button__outdent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1008px !important;}.cke_ltr .cke_button__outdent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1032px !important;}.cke_button__smiley_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1056px !important;}.cke_button__justifyblock_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1080px !important;}.cke_button__justifycenter_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1104px !important;}.cke_button__justifyleft_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1128px !important;}.cke_button__justifyright_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1152px !important;}.cke_button__language_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1176px !important;}.cke_rtl .cke_button__anchor_icon, .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1200px !important;}.cke_ltr .cke_button__anchor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1224px !important;}.cke_button__link_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1248px !important;}.cke_button__unlink_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1272px !important;}.cke_rtl .cke_button__bulletedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1296px !important;}.cke_ltr .cke_button__bulletedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1320px !important;}.cke_rtl .cke_button__numberedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1344px !important;}.cke_ltr .cke_button__numberedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1368px !important;}.cke_button__maximize_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1392px !important;}.cke_rtl .cke_button__newpage_icon, .cke_mixed_dir_content .cke_rtl .cke_button__newpage_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1416px !important;}.cke_ltr .cke_button__newpage_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1440px !important;}.cke_rtl .cke_button__pagebreak_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pagebreak_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1464px !important;}.cke_ltr .cke_button__pagebreak_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1488px !important;}.cke_rtl .cke_button__pastetext_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1512px !important;}.cke_ltr .cke_button__pastetext_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1536px !important;}.cke_rtl .cke_button__pastefromword_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1560px !important;}.cke_ltr .cke_button__pastefromword_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1584px !important;}.cke_rtl .cke_button__preview_icon, .cke_mixed_dir_content .cke_rtl .cke_button__preview_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1608px !important;}.cke_ltr .cke_button__preview_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1632px !important;}.cke_button__print_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1656px !important;}.cke_button__removeformat_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1680px !important;}.cke_button__save_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1704px !important;}.cke_button__selectall_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1728px !important;}.cke_rtl .cke_button__showblocks_icon, .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1752px !important;}.cke_ltr .cke_button__showblocks_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1776px !important;}.cke_rtl .cke_button__source_icon, .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1800px !important;}.cke_ltr .cke_button__source_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1824px !important;}.cke_button__specialchar_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1848px !important;}.cke_button__scayt_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1872px !important;}.cke_button__table_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1896px !important;}.cke_rtl .cke_button__redo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1920px !important;}.cke_ltr .cke_button__redo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1944px !important;}.cke_rtl .cke_button__undo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1968px !important;}.cke_ltr .cke_button__undo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1992px !important;}.cke_button__spellchecker_icon {background: url(icons.png?t=3876e73) no-repeat 0 -2016px !important;}.cke_hidpi .cke_button__about_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -0px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bold_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -24px !important;background-size: 16px !important;}.cke_hidpi .cke_button__italic_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -48px !important;background-size: 16px !important;}.cke_hidpi .cke_button__strike_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -72px !important;background-size: 16px !important;}.cke_hidpi .cke_button__subscript_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -96px !important;background-size: 16px !important;}.cke_hidpi .cke_button__superscript_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -120px !important;background-size: 16px !important;}.cke_hidpi .cke_button__underline_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -144px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bidiltr_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -168px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bidirtl_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -192px !important;background-size: 16px !important;}.cke_hidpi .cke_button__blockquote_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -216px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__copy_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -240px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -264px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__cut_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -288px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -312px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__paste_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -336px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -360px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bgcolor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -384px !important;background-size: 16px !important;}.cke_hidpi .cke_button__textcolor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -408px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__templates_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__templates_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -432px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__templates_icon,.cke_ltr.cke_hidpi .cke_button__templates_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -456px !important;background-size: 16px !important;}.cke_hidpi .cke_button__creatediv_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -480px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__find_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__find_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -504px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__find_icon,.cke_ltr.cke_hidpi .cke_button__find_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -528px !important;background-size: 16px !important;}.cke_hidpi .cke_button__replace_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -552px !important;background-size: 16px !important;}.cke_hidpi .cke_button__flash_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -576px !important;background-size: 16px !important;}.cke_hidpi .cke_button__button_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -600px !important;background-size: 16px !important;}.cke_hidpi .cke_button__checkbox_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -624px !important;background-size: 16px !important;}.cke_hidpi .cke_button__form_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -648px !important;background-size: 16px !important;}.cke_hidpi .cke_button__hiddenfield_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -672px !important;background-size: 16px !important;}.cke_hidpi .cke_button__imagebutton_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -696px !important;background-size: 16px !important;}.cke_hidpi .cke_button__radio_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -720px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__select_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__select_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -744px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__select_icon,.cke_ltr.cke_hidpi .cke_button__select_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -768px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__textarea_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__textarea_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -792px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__textarea_icon,.cke_ltr.cke_hidpi .cke_button__textarea_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -816px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__textfield_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__textfield_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -840px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__textfield_icon,.cke_ltr.cke_hidpi .cke_button__textfield_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -864px !important;background-size: 16px !important;}.cke_hidpi .cke_button__horizontalrule_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -888px !important;background-size: 16px !important;}.cke_hidpi .cke_button__iframe_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -912px !important;background-size: 16px !important;}.cke_hidpi .cke_button__image_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -936px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__indent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -960px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -984px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__outdent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1008px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1032px !important;background-size: 16px !important;}.cke_hidpi .cke_button__smiley_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1056px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyblock_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1080px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifycenter_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1104px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyleft_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1128px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyright_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1152px !important;background-size: 16px !important;}.cke_hidpi .cke_button__language_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1176px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__anchor_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1200px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__anchor_icon,.cke_ltr.cke_hidpi .cke_button__anchor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1224px !important;background-size: 16px !important;}.cke_hidpi .cke_button__link_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1248px !important;background-size: 16px !important;}.cke_hidpi .cke_button__unlink_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1272px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1296px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1320px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1344px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1368px !important;background-size: 16px !important;}.cke_hidpi .cke_button__maximize_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1392px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__newpage_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__newpage_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1416px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__newpage_icon,.cke_ltr.cke_hidpi .cke_button__newpage_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1440px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pagebreak_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pagebreak_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1464px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pagebreak_icon,.cke_ltr.cke_hidpi .cke_button__pagebreak_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1488px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastetext_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1512px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1536px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1560px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1584px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__preview_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__preview_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1608px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__preview_icon,.cke_ltr.cke_hidpi .cke_button__preview_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1632px !important;background-size: 16px !important;}.cke_hidpi .cke_button__print_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1656px !important;background-size: 16px !important;}.cke_hidpi .cke_button__removeformat_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1680px !important;background-size: 16px !important;}.cke_hidpi .cke_button__save_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1704px !important;background-size: 16px !important;}.cke_hidpi .cke_button__selectall_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1728px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__showblocks_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1752px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__showblocks_icon,.cke_ltr.cke_hidpi .cke_button__showblocks_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1776px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__source_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1800px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1824px !important;background-size: 16px !important;}.cke_hidpi .cke_button__specialchar_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1848px !important;background-size: 16px !important;}.cke_hidpi .cke_button__scayt_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1872px !important;background-size: 16px !important;}.cke_hidpi .cke_button__table_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1896px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__redo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1920px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1944px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__undo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1968px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1992px !important;background-size: 16px !important;}.cke_hidpi .cke_button__spellchecker_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -2016px !important;background-size: 16px !important;} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/editor_iequirks.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/editor_iequirks.css new file mode 100644 index 0000000..7f842be --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/editor_iequirks.css @@ -0,0 +1 @@ +.cke_reset{margin:0;padding:0;border:0;background:0;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none}.cke_reset_all,.cke_reset_all *{margin:0;padding:0;border:0;background:0;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#333;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre}.cke_reset_all input[type=password],.cke_reset_all input[type=text],.cke_reset_all textarea{cursor:text}.cke_reset_all input[type=password][disabled],.cke_reset_all input[type=text][disabled],.cke_reset_all textarea[disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;margin-top:10px;border:1px solid #ddd}.cke_reset_all fieldset legend{padding:0 5px}.cke_reset_all select{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.cke_chrome{display:block;border:1px solid #ddd;border-radius:4px;padding:0 3px;background:#eee}.cke_inner{display:block;-webkit-touch-callout:none;background:0;padding:0}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_float .cke_top{border:1px solid #ddd}.cke_bottom,.cke_contents,.cke_top{display:block;overflow:hidden}.cke_bottom,.cke_top{padding:3px 0 0;background:#eee}.cke_top{white-space:normal}.cke_contents{background-color:#fff;border:1px solid #ddd;border-radius:4px}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #555 transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #aaa;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;margin-top:5px;background-color:#fff;border:1px solid #aaa;border-radius:4px}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:178px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_list{list-style-type:none;margin:3px;padding:0;white-space:nowrap}.cke_panel_listItem{margin:0;padding-bottom:1px}.cke_panel_listItem a{padding:3px 4px;display:block;border:1px solid #fff;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis;border-radius:2px}.cke_panel_listItem a:active,.cke_panel_listItem a:focus,.cke_panel_listItem a:hover{background-color:#e1edf7}* html .cke_panel_listItem a{width:100%;color:#000}:first-child+html .cke_panel_listItem a{color:#000}.cke_panel_listItem.cke_selected a{background-color:#92bce0;outline:0}.cke_hc .cke_panel_listItem a{border-style:none}.cke_hc .cke_panel_listItem a:active,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:hover{border:2px solid;padding:1px 2px}.cke_panel_grouptitle{font-size:11px;font-weight:700;white-space:nowrap;margin:0;padding:6px;color:#474747;border-bottom:1px solid #aaa;background:#eee}.cke_panel_grouptitle:first-child{border-radius:4px 4px 0 0}.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem p,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_colorblock{padding:3px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}span.cke_colorbox{width:10px;height:10px;border:1px solid #aaa;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorbox{border:1px solid #fff;padding:2px;float:left;width:12px;height:12px;border-radius:2px}.cke_rtl a.cke_colorbox{float:right}a:active.cke_colorbox,a:focus.cke_colorbox,a:hover.cke_colorbox{border:1px solid #ddd;background-color:#eee}a.cke_colorauto,a.cke_colormore{border:1px solid #fff;padding:2px;display:block;cursor:pointer}a:active.cke_colorauto,a:active.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:hover.cke_colorauto,a:hover.cke_colormore{border:1px solid #ddd;background-color:#eee}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{float:left;margin:0 6px 3px 0;padding:2px;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_hc .cke_toolgroup{border:0;margin-right:10px;margin-bottom:10px}.cke_rtl .cke_toolgroup :first-child{border-radius:0 4px 4px 0}.cke_rtl .cke_toolgroup :last-child{border-radius:4px 0 0 4px}.cke_rtl .cke_toolgroup{margin-left:6px;margin-right:0}a.cke_button{display:inline-block;height:18px;padding:2px 4px;outline:0;cursor:default;float:left;border:0;border-radius:2px}.cke_hc .cke_button{border:1px solid #000;padding:3px 5px;margin:-2px 4px 0 -2px}.cke_button_on{background:#92bce0}.cke_hc .cke_button_on,.cke_hc a.cke_button_disabled:active,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_off:active,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:hover{border-width:3px;padding:1px 3px}.cke_button_disabled .cke_button_icon{opacity:.3}.cke_hc .cke_button_disabled{opacity:.5}a.cke_button_disabled:active,a.cke_button_disabled:focus,a.cke_button_disabled:hover,a.cke_button_off:active,a.cke_button_off:focus,a.cke_button_off:hover{background:#e1edf7}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:18px;vertical-align:middle;float:left;cursor:default;color:#555}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px -2px 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#ddd;margin:4px 2px 0;height:16px;width:1px}.cke_hc .cke_toolbar_separator{width:0;border-left:1px solid;margin:1px 5px 0 0}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #a6a6a6;border-bottom-color:#979797;border-radius:4px;background:#e4e4e4}.cke_toolbox_collapser:hover{background:#ccc}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#474747}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:3px solid #474747;border-top:3px solid transparent}.cke_rtl .cke_toolbox_collapser{float:left}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0;margin-right:2px}.cke_menubutton{display:block}.cke_button_icon{opacity:.8}.cke_menuitem span{cursor:default}.cke_menubutton:active,.cke_menubutton:focus,.cke_menubutton:hover{display:block}.cke_hc .cke_menubutton{padding:2px}.cke_hc .cke_menubutton:active,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:hover{border:2px solid;padding:0}.cke_menubutton_inner{display:table-row}.cke_menuarrow,.cke_menubutton_icon,.cke_menubutton_label{display:table-cell}.cke_menubutton_icon{background-color:#d7d8d7;opacity:.7;filter:alpha(opacity=70);padding:4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:active .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:hover .cke_menubutton_icon{background-color:#d0d2d0}.cke_menubutton_disabled:active .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:hover .cke_menubutton_icon{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_on{border:1px solid #dedede;background-color:#f2f2f2}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px}.cke_menubutton:active,.cke_menubutton:focus,.cke_menubutton:hover{background-color:#eff0ef}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d3d3d3;height:1px;filter:alpha(opacity=70);opacity:.7}.cke_menuarrow{background-image:url(images/arrow.png);background-position:0 10px;background-repeat:no-repeat;padding:0 5px}.cke_menuarrow span{display:none}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left}.cke_hc .cke_combo{margin-top:-2px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_button{display:inline-block;float:left;margin:0 6px 5px 0;border:1px solid #ddd;border-radius:4px;background:#fff}.cke_combo_off a.cke_combo_button:focus,.cke_combo_off a.cke_combo_button:hover{outline:0}.cke_combo_off a.cke_combo_button:active,.cke_combo_on a.cke_combo_button{border-color:#333}.cke_rtl .cke_combo_button{float:right;margin-left:5px;margin-right:0}.cke_hc a.cke_combo_button{padding:3px}.cke_hc .cke_combo_off a.cke_combo_button:active,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_on a.cke_combo_button{border-width:3px;padding:1px}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#474747;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 7px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #333}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}.cke_path_empty,.cke_path_item{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#4c4c4c;font-weight:700;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_empty,.cke_rtl .cke_path_item{float:right}a.cke_path_item:active,a.cke_path_item:focus,a.cke_path_item:hover{background-color:#bfbfbf;color:#333;border-radius:2px}.cke_hc a.cke_path_item:active,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:hover{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combo__fontsize .cke_combo_text{width:30px}.cke_combopanel__fontsize{width:120px}.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff}.cke_wysiwyg_div,.cke_wysiwyg_frame{background-color:#fff}.cke_chrome{visibility:inherit}.cke_voice_label,legend.cke_voice_label{display:none}.cke_bottom,.cke_contents,.cke_top{width:100%}.cke_button_arrow{font-size:0}.cke_rtl .cke_button,.cke_rtl .cke_button *,.cke_rtl .cke_combo,.cke_rtl .cke_combo *,.cke_rtl .cke_path_empty,.cke_rtl .cke_path_item,.cke_rtl .cke_path_item *,.cke_rtl .cke_toolbar_separator,.cke_rtl .cke_toolgroup{float:none}.cke_rtl .cke_button,.cke_rtl .cke_button_icon,.cke_rtl .cke_combo_button,.cke_rtl .cke_combo_button *,.cke_rtl .cke_toolbar_separator,.cke_rtl .cke_toolgroup{display:inline-block;vertical-align:top}.cke_rtl .cke_button_icon{float:none}.cke_resizer{width:10px}.cke_source{white-space:normal}.cke_bottom{position:static}.cke_colorbox{font-size:0}.cke_button__about_icon {background: url(icons.png?t=3876e73) no-repeat 0 -0px !important;}.cke_button__bold_icon {background: url(icons.png?t=3876e73) no-repeat 0 -24px !important;}.cke_button__italic_icon {background: url(icons.png?t=3876e73) no-repeat 0 -48px !important;}.cke_button__strike_icon {background: url(icons.png?t=3876e73) no-repeat 0 -72px !important;}.cke_button__subscript_icon {background: url(icons.png?t=3876e73) no-repeat 0 -96px !important;}.cke_button__superscript_icon {background: url(icons.png?t=3876e73) no-repeat 0 -120px !important;}.cke_button__underline_icon {background: url(icons.png?t=3876e73) no-repeat 0 -144px !important;}.cke_button__bidiltr_icon {background: url(icons.png?t=3876e73) no-repeat 0 -168px !important;}.cke_button__bidirtl_icon {background: url(icons.png?t=3876e73) no-repeat 0 -192px !important;}.cke_button__blockquote_icon {background: url(icons.png?t=3876e73) no-repeat 0 -216px !important;}.cke_rtl .cke_button__copy_icon, .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons.png?t=3876e73) no-repeat 0 -240px !important;}.cke_ltr .cke_button__copy_icon {background: url(icons.png?t=3876e73) no-repeat 0 -264px !important;}.cke_rtl .cke_button__cut_icon, .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons.png?t=3876e73) no-repeat 0 -288px !important;}.cke_ltr .cke_button__cut_icon {background: url(icons.png?t=3876e73) no-repeat 0 -312px !important;}.cke_rtl .cke_button__paste_icon, .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons.png?t=3876e73) no-repeat 0 -336px !important;}.cke_ltr .cke_button__paste_icon {background: url(icons.png?t=3876e73) no-repeat 0 -360px !important;}.cke_button__bgcolor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -384px !important;}.cke_button__textcolor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -408px !important;}.cke_rtl .cke_button__templates_icon, .cke_mixed_dir_content .cke_rtl .cke_button__templates_icon {background: url(icons.png?t=3876e73) no-repeat 0 -432px !important;}.cke_ltr .cke_button__templates_icon {background: url(icons.png?t=3876e73) no-repeat 0 -456px !important;}.cke_button__creatediv_icon {background: url(icons.png?t=3876e73) no-repeat 0 -480px !important;}.cke_rtl .cke_button__find_icon, .cke_mixed_dir_content .cke_rtl .cke_button__find_icon {background: url(icons.png?t=3876e73) no-repeat 0 -504px !important;}.cke_ltr .cke_button__find_icon {background: url(icons.png?t=3876e73) no-repeat 0 -528px !important;}.cke_button__replace_icon {background: url(icons.png?t=3876e73) no-repeat 0 -552px !important;}.cke_button__flash_icon {background: url(icons.png?t=3876e73) no-repeat 0 -576px !important;}.cke_button__button_icon {background: url(icons.png?t=3876e73) no-repeat 0 -600px !important;}.cke_button__checkbox_icon {background: url(icons.png?t=3876e73) no-repeat 0 -624px !important;}.cke_button__form_icon {background: url(icons.png?t=3876e73) no-repeat 0 -648px !important;}.cke_button__hiddenfield_icon {background: url(icons.png?t=3876e73) no-repeat 0 -672px !important;}.cke_button__imagebutton_icon {background: url(icons.png?t=3876e73) no-repeat 0 -696px !important;}.cke_button__radio_icon {background: url(icons.png?t=3876e73) no-repeat 0 -720px !important;}.cke_rtl .cke_button__select_icon, .cke_mixed_dir_content .cke_rtl .cke_button__select_icon {background: url(icons.png?t=3876e73) no-repeat 0 -744px !important;}.cke_ltr .cke_button__select_icon {background: url(icons.png?t=3876e73) no-repeat 0 -768px !important;}.cke_rtl .cke_button__textarea_icon, .cke_mixed_dir_content .cke_rtl .cke_button__textarea_icon {background: url(icons.png?t=3876e73) no-repeat 0 -792px !important;}.cke_ltr .cke_button__textarea_icon {background: url(icons.png?t=3876e73) no-repeat 0 -816px !important;}.cke_rtl .cke_button__textfield_icon, .cke_mixed_dir_content .cke_rtl .cke_button__textfield_icon {background: url(icons.png?t=3876e73) no-repeat 0 -840px !important;}.cke_ltr .cke_button__textfield_icon {background: url(icons.png?t=3876e73) no-repeat 0 -864px !important;}.cke_button__horizontalrule_icon {background: url(icons.png?t=3876e73) no-repeat 0 -888px !important;}.cke_button__iframe_icon {background: url(icons.png?t=3876e73) no-repeat 0 -912px !important;}.cke_button__image_icon {background: url(icons.png?t=3876e73) no-repeat 0 -936px !important;}.cke_rtl .cke_button__indent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -960px !important;}.cke_ltr .cke_button__indent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -984px !important;}.cke_rtl .cke_button__outdent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1008px !important;}.cke_ltr .cke_button__outdent_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1032px !important;}.cke_button__smiley_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1056px !important;}.cke_button__justifyblock_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1080px !important;}.cke_button__justifycenter_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1104px !important;}.cke_button__justifyleft_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1128px !important;}.cke_button__justifyright_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1152px !important;}.cke_button__language_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1176px !important;}.cke_rtl .cke_button__anchor_icon, .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1200px !important;}.cke_ltr .cke_button__anchor_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1224px !important;}.cke_button__link_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1248px !important;}.cke_button__unlink_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1272px !important;}.cke_rtl .cke_button__bulletedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1296px !important;}.cke_ltr .cke_button__bulletedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1320px !important;}.cke_rtl .cke_button__numberedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1344px !important;}.cke_ltr .cke_button__numberedlist_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1368px !important;}.cke_button__maximize_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1392px !important;}.cke_rtl .cke_button__newpage_icon, .cke_mixed_dir_content .cke_rtl .cke_button__newpage_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1416px !important;}.cke_ltr .cke_button__newpage_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1440px !important;}.cke_rtl .cke_button__pagebreak_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pagebreak_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1464px !important;}.cke_ltr .cke_button__pagebreak_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1488px !important;}.cke_rtl .cke_button__pastetext_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1512px !important;}.cke_ltr .cke_button__pastetext_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1536px !important;}.cke_rtl .cke_button__pastefromword_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1560px !important;}.cke_ltr .cke_button__pastefromword_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1584px !important;}.cke_rtl .cke_button__preview_icon, .cke_mixed_dir_content .cke_rtl .cke_button__preview_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1608px !important;}.cke_ltr .cke_button__preview_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1632px !important;}.cke_button__print_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1656px !important;}.cke_button__removeformat_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1680px !important;}.cke_button__save_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1704px !important;}.cke_button__selectall_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1728px !important;}.cke_rtl .cke_button__showblocks_icon, .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1752px !important;}.cke_ltr .cke_button__showblocks_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1776px !important;}.cke_rtl .cke_button__source_icon, .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1800px !important;}.cke_ltr .cke_button__source_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1824px !important;}.cke_button__specialchar_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1848px !important;}.cke_button__scayt_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1872px !important;}.cke_button__table_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1896px !important;}.cke_rtl .cke_button__redo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1920px !important;}.cke_ltr .cke_button__redo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1944px !important;}.cke_rtl .cke_button__undo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1968px !important;}.cke_ltr .cke_button__undo_icon {background: url(icons.png?t=3876e73) no-repeat 0 -1992px !important;}.cke_button__spellchecker_icon {background: url(icons.png?t=3876e73) no-repeat 0 -2016px !important;}.cke_hidpi .cke_button__about_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -0px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bold_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -24px !important;background-size: 16px !important;}.cke_hidpi .cke_button__italic_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -48px !important;background-size: 16px !important;}.cke_hidpi .cke_button__strike_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -72px !important;background-size: 16px !important;}.cke_hidpi .cke_button__subscript_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -96px !important;background-size: 16px !important;}.cke_hidpi .cke_button__superscript_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -120px !important;background-size: 16px !important;}.cke_hidpi .cke_button__underline_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -144px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bidiltr_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -168px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bidirtl_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -192px !important;background-size: 16px !important;}.cke_hidpi .cke_button__blockquote_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -216px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__copy_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -240px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -264px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__cut_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -288px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -312px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__paste_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -336px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -360px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bgcolor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -384px !important;background-size: 16px !important;}.cke_hidpi .cke_button__textcolor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -408px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__templates_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__templates_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -432px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__templates_icon,.cke_ltr.cke_hidpi .cke_button__templates_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -456px !important;background-size: 16px !important;}.cke_hidpi .cke_button__creatediv_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -480px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__find_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__find_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -504px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__find_icon,.cke_ltr.cke_hidpi .cke_button__find_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -528px !important;background-size: 16px !important;}.cke_hidpi .cke_button__replace_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -552px !important;background-size: 16px !important;}.cke_hidpi .cke_button__flash_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -576px !important;background-size: 16px !important;}.cke_hidpi .cke_button__button_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -600px !important;background-size: 16px !important;}.cke_hidpi .cke_button__checkbox_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -624px !important;background-size: 16px !important;}.cke_hidpi .cke_button__form_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -648px !important;background-size: 16px !important;}.cke_hidpi .cke_button__hiddenfield_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -672px !important;background-size: 16px !important;}.cke_hidpi .cke_button__imagebutton_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -696px !important;background-size: 16px !important;}.cke_hidpi .cke_button__radio_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -720px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__select_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__select_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -744px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__select_icon,.cke_ltr.cke_hidpi .cke_button__select_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -768px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__textarea_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__textarea_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -792px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__textarea_icon,.cke_ltr.cke_hidpi .cke_button__textarea_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -816px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__textfield_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__textfield_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -840px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__textfield_icon,.cke_ltr.cke_hidpi .cke_button__textfield_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -864px !important;background-size: 16px !important;}.cke_hidpi .cke_button__horizontalrule_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -888px !important;background-size: 16px !important;}.cke_hidpi .cke_button__iframe_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -912px !important;background-size: 16px !important;}.cke_hidpi .cke_button__image_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -936px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__indent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -960px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -984px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__outdent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1008px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1032px !important;background-size: 16px !important;}.cke_hidpi .cke_button__smiley_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1056px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyblock_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1080px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifycenter_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1104px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyleft_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1128px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyright_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1152px !important;background-size: 16px !important;}.cke_hidpi .cke_button__language_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1176px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__anchor_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1200px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__anchor_icon,.cke_ltr.cke_hidpi .cke_button__anchor_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1224px !important;background-size: 16px !important;}.cke_hidpi .cke_button__link_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1248px !important;background-size: 16px !important;}.cke_hidpi .cke_button__unlink_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1272px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1296px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1320px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1344px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1368px !important;background-size: 16px !important;}.cke_hidpi .cke_button__maximize_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1392px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__newpage_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__newpage_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1416px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__newpage_icon,.cke_ltr.cke_hidpi .cke_button__newpage_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1440px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pagebreak_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pagebreak_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1464px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pagebreak_icon,.cke_ltr.cke_hidpi .cke_button__pagebreak_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1488px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastetext_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1512px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1536px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1560px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1584px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__preview_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__preview_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1608px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__preview_icon,.cke_ltr.cke_hidpi .cke_button__preview_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1632px !important;background-size: 16px !important;}.cke_hidpi .cke_button__print_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1656px !important;background-size: 16px !important;}.cke_hidpi .cke_button__removeformat_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1680px !important;background-size: 16px !important;}.cke_hidpi .cke_button__save_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1704px !important;background-size: 16px !important;}.cke_hidpi .cke_button__selectall_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1728px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__showblocks_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1752px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__showblocks_icon,.cke_ltr.cke_hidpi .cke_button__showblocks_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1776px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__source_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1800px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1824px !important;background-size: 16px !important;}.cke_hidpi .cke_button__specialchar_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1848px !important;background-size: 16px !important;}.cke_hidpi .cke_button__scayt_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1872px !important;background-size: 16px !important;}.cke_hidpi .cke_button__table_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1896px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__redo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1920px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1944px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__undo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1968px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -1992px !important;background-size: 16px !important;}.cke_hidpi .cke_button__spellchecker_icon {background: url(icons_hidpi.png?t=3876e73) no-repeat 0 -2016px !important;background-size: 16px !important;} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/icons.png b/nstock/static/plugin_ckeditor/skins/bootstrapck/icons.png new file mode 100644 index 0000000000000000000000000000000000000000..eaefc17a1077fa849c3d726b14dd3cebf2c7fc0e GIT binary patch literal 20634 zcmXtg1yq#X_w_?}D;>j-(jzGyqcn�@8xgU6KNWA}R0^Qi6b#gfvo0cStu#H%P;G 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 z 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 literal 0 HcmV?d00001 diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/images/arrow.png b/nstock/static/plugin_ckeditor/skins/bootstrapck/images/arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..0d1eb39c6763770690d4cd6faf81503975a25f08 GIT binary patch literal 261 zcmeAS@N?(olHy`uVBq!ia0vp^Y(Ol>0V4T5^Y?)SlDyqr82*Fcg1yTp14TFsJR*x3 z7`TN&n2}-D90{Nxdx@v7EBhTTAs$Q7;?s#GK%q&VE{-7@=ig3J6RR&$neB-Qn+l0CXLLr>mdKI;Vst0B#;z A`2YX_ literal 0 HcmV?d00001 diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/images/close.png b/nstock/static/plugin_ckeditor/skins/bootstrapck/images/close.png new file mode 100644 index 0000000000000000000000000000000000000000..b2acd4fc5c669b2ec35fe085ba614526a6d41aef GIT binary patch literal 415 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf4nJ zaJ>d$#-?uGD4?KdiEBiOb5UwyNoIbYLP%zADua=}k*U6+$=w;LnLq_HAO*qsX(i=} zMX3yqDfvmM3T~N2spa`a*~JRZ!DcV^Z0Z53`{C*07-G?Tb@Ik6Cr1I-^K1u21W&Sa zew3DTtJYrKz@N4+kzHr)k*Et9nTe0@-&n?_BJt^xPr`}r^@hG|({Ao8f0ueAF*r0d zM%X-j<^MwqM7cxfGA1YFq}@Kz>A|Sen0jvK9+QJ2FPOLmU$PgXoj_NL%A~2D0L)nYF#kW5vpQ{w+&FarclU~4ZFXqO#>W{&HRyQ8! zv}phJCPFuhP3aPIpM&}V*#|3D?R8@olw_=aaBbls{=T=NrB_T2a_wM_Yg{<+&zNr?TansnKFi(#4<^TF+`iw`twk7=U4g-b(gQu&X%Q~loCIFan=-W9}o8^Y|XL|*vV*TlVg{B?RXSmmU z!?@vj(fe7?=d_11sIb@+3rdE`9^T2s;ax2#$*`XJ&nn0iGArD92SZBhV(m0hhGab@=K?D!hUEL-)m*Oh z#eP2B(6GbHI_#_{$J)b@?P)dbVG7wVRUJ4ZXi@?ZDjy5FETYR zF*MznWoZBa0338hSaefwW^{L9a%BKPWN%_+AVz6&Wp{6KYjYq&Q#RoIfM5T)b7eVolQB-hna_FLilM=q@P^4Ip9swtZP6eHG)m?D* zFA%}WMd+ZDgIpY%qSlMOgf#8ogOKDq?tL%sdyw;@C}NmUL+w5a0>*4b&+`&Dh)5aO z2UdYa-~)I9u7Ojn^>go@zsBs@7Lx>s$Og~?CKLGHfo-kzg{uJP5s1h-a1}Sd1J-~t zFbk{zx4;B&E+Sj5yiN{?NC|iZrU7k?IS9k>$41}xJ*CtM5YTaAp*xN|9C!offf-wK zfG`XrW6U96PVBi5r^w&}pM_TLpxA(e;034?!%IZMNu{JOPxgo27ies%WvSy$b&%A4U1*jD% zK+y?Y>d@JUhKeKsuLJ01u4^P)dbVG7wVRUJ4ZXi@?ZDjy5FETYR zF*MznWoZBa0338hSaefwW^{L9a%BKPWN%_+AVz6&Wp{6KYjYq&Q#R_~(wsr002ov JPDHLkV1mH6dbVG7wVRUJ4ZXi@?ZDjy5FETYR zF*MznWoZBa0338hSaefwW^{L9a%BKPWN%_+AVz6&Wp{6KYjYq&Q#R@0%RWvxJy=Xs-(K;CEQAm0Jp0xG9S4#6?~@rIECB-H}Fz^o|} z{{T*y*^R_UAZaP^0+{CrI0oDW9s*y1MZhj#v%~i_aL~+NLVgiOWuUbHc_+|lX76)B zN!>tS$hQNiH?!}BNSp#BZ3Ol@md=~m*$B~-HU^wBvnz3qg)&g@zY#4w8Zu99-t;EIXE(qPN%DZg(3KXnZ1dL)$jZM{sbbU1puy2 z_Bbw(nT^KzBo#2%fqg3_xTM3t?p!RB$z1R}Zy-v*umf9MiU6RFU`WZei@6W3c0A<3 zww5TMHZFdifb0eHF$AxZw51qkNp--o5Io>{-bkc?tlf5Cmn9`?!IH`er8;ZfVW5zJ zs}8IN=#VrghP;AcFj*B^8VB0L{!z{7CUC^T@d^;oYi529@eE)eV8BYpzBV&!D5e>m zBq*XKA$$#R2lyoE5kWVcPtXY$6o@qloN+BgPDGMwfO|kigwQzq3~V#Aekk(4z|5Wz zWZ^@J-t*%?8$n|#NDjqM#jAni1jXhmv;l%ot=-H9T`{IK tmWRYt5j3t!f4nJ zaJ>d$#-?uGD4?KdiEBiOb5UwyNoIbYLP%zADua=}k*U6+$=w;LnLq_HAO*qsX(i=} zMX3yqDfvmM3T~N2spa`a*~JRZ!DcV^Z0Z53d+q7s7-G@8^wL^CXGa0n2l<+E?FT1{ z@Njh>Y0{X)KJ&Ep8?KO0R(}Rl4kkql8@ARp>l~7*41J4te$jvHX=c5-`q`T|XO`?* zm)ksd?V^phOM<+Nt(E#dcIfT9aN4qd-Bd@HIS)jg=R9WA4-J*oJ-eVWKW18x-Likt zE+qxs-BX#CP7!ol``FrM>&}%oTc=FwhzPl%H?MF;@w_vlD^_K77%!=RShAtr@Lut` z@Xz}$M1QCf{_T6us@Nc|Y^T=)HulT4%8ibiPuZJ&S$_!@cKuUw+TF2rzwC~A>&(*D oW~UeQcRrorQ<-u0pxO^sDOKAS6_sYaKyNd6y85}Sb4q9e00-oo4gdfE literal 0 HcmV?d00001 diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/images/lock.png b/nstock/static/plugin_ckeditor/skins/bootstrapck/images/lock.png new file mode 100644 index 0000000000000000000000000000000000000000..2f7347a46bf060e5b90cac5d2c39a388b1bce389 GIT binary patch literal 413 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf4nJ zaJ>d$#-?uGD4?KdiEBiOb5UwyNoIbYLP%zADua=}k*U6+$=w;LnLq_HAO*qsX(i=} zMX3yqDfvmM3T~N2spa`a*~JRZ!DcV^Z0Z53`{wE57-G@8^wMfSW=9dW2l-JpiYgK^ zp4ux8D{Y+7^w=@&pm1MG79Ld!#Z+4t5@hP4|vBR+J&$pVs?LD^-8}kKuUER;*8ff!KV)u_D znk}pF)tvjWobB+L`!g@!i#r#c%D=2zZ#rj8(*BLvoIR&E{W(+-+ZfpMkz;XX z%Qu1S7M*<=e$t!QXNMQ`pGpeh000W>0fLJSS^xk56?8>dbVG7wVRUJ4ZXi@?ZDjy5FETYR zF*MznWoZBa0338hSaefwW^{L9a%BKPWN%_+AVz6&Wp{6KYjYq&Q#RRzVO2@ZXi77!-UoqNr#i);2Z@S}2l2EmB!%VI%hQDX2u0$Q=Y53uDOt zAXX9)(%4(42vK|?fhgJ;xfayL{iHNfiF+L2p z;U9S_JdTLVeaFZjSP$X|w&O6iVLBp?;VQmC)yl7`ss)bXJ}zPNZ}QLMOkLLtYZOGp zM!dk$Vp_pF?82swZ3>@;l`z=>Kf(jN$3;BEYh1|8m#y+&2_oV^kqtAMd8Ol9#vIOP z=I1VBw+pAR6W?*Kr);)qnv;ESzl42dUB*&3C^MIel2P2mmcd}~w65#t-2{te-GM#$ z(r3dVTr2xm{Ssyi^9b$?0qfX5;2FJl5D}BOUV@%jy^D|7jT;y%zKOc7Z?nFQx2(4D z1kRQD6 literal 0 HcmV?d00001 diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/readme.md b/nstock/static/plugin_ckeditor/skins/bootstrapck/readme.md new file mode 100644 index 0000000..422e006 --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/readme.md @@ -0,0 +1,35 @@ +BootstrapCK Skin +==================== + +The BootstrapCK-Skin is a skin for [CKEditor4](http://ckeditor.com/) based on [Twitter Bootstrap3](http://getbootstrap.com/) styles. + +[Sass](http://sass-lang.com/) is used to rewrite the editor's styles and [Grunt](http://gruntjs.com/) to be able to watch, convert and minify the sass into css files. These files aren't really needed for the simple use of the skin, but handy if you want to make some adjustments to it. + +For more information about skins, please check the [CKEditor Skin SDK](http://docs.cksource.com/CKEditor_4.x/Skin_SDK) +documentation. + +## Installation + +**Just skin please** + +Add the whole bootstrapck folder to the skin folder.
+In ckeditor.js and config.js change the skin name to "bootstrapck".
+Done! + +**The whole skin - sass - grunt package** + +All the sass files are included in the bootstrapck folder, so first follow the 'just skin please'-steps
+Now add the Gruntfile.js and the package.json to de ckeditor folder. + + npm install + grunt build + +You can start tampering now. + +## Demo + +http://kunstmaan.github.io/BootstrapCK4-Skin/ + +### Previous version + +If you would like to get the Bootstrap2 skin for CKeditor3, [here](https://github.com/Kunstmaan/BootstrapCK-Skin)'s the previous version. diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/sample/bootstrapck-sample.html b/nstock/static/plugin_ckeditor/skins/bootstrapck/sample/bootstrapck-sample.html new file mode 100644 index 0000000..f38770a --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/sample/bootstrapck-sample.html @@ -0,0 +1,127 @@ + + + + + + + Kunstmaan/BootstrapCK4-Skin @ GitHub + + + + + + Fork me on GitHub + +
+ + + +

+ BootstrapCK4-Skin + by Kunstmaan +

+ + +

Demo

+
+

+ +

+
+ + + + +

About

+

The BootstrapCK4-Skin is a skin for CKEditor4 based on Twitter Bootstrap3 styles.

+

Sass is used to rewrite the editor's styles and Grunt to be able to watch, convert and minify the sass into css files. These files aren't really needed for the simple use of the skin, but handy if you want to make some adjustments to it.

+

For more information about skins, please check the CKEditor Skin SDK

+ + +

Installation

+

Just skin please

+ +

Add the whole bootstrapck folder to the skin folder.
+ In ckeditor.js and config.js change the skin name to "bootstrapck".
+ Done!

+ +

The whole skin - sass - grunt package

+ +

All the sass files are included in the bootstrapck folder, so first follow the 'just skin please'-steps
+ Now add the Gruntfile.js and the package.json to de ckeditor folder.

+
npm install 
grunt build
+

You can start tampering now.

+

Or if you'd like to adjust the icons, use the bootstrapck-dev folder instead.

+ + +

Authors

+

Indri Kenens (indri.kenens@kunstmaan.be)

+ +

Contact

+

Kunstmaan (support@kunstmaan.be)

+ + +

Download

+

+ You can download this project in either + zip or + tar formats. +

+

You can also clone the project with Git + by running:

$ git clone git://github.com/Kunstmaan/BootstrapCK4-Skin

+ + +

Previous version

+

If you would like to get the Bootstrap2 skin for CKeditor3, here's the previous version.

+ + + +
+ + + + + + + + + + + + + + + + + + diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/sample/css/bootstrapck-sample.css b/nstock/static/plugin_ckeditor/skins/bootstrapck/sample/css/bootstrapck-sample.css new file mode 100644 index 0000000..c135ef0 --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/sample/css/bootstrapck-sample.css @@ -0,0 +1 @@ +body{margin-top:1.0em;background-color:#fff;font-family:Helvetica,Arial,sans-serif;color:#404040}.container{margin:0 auto;width:900px;padding:0 0 20px}h1{font-size:40px;margin:40px 0 28px;padding:110px 0 9px;border-bottom:1px solid #ccc}h1 a,h1 a:visited,h1 a:focus,h1 a:hover{color:#404040;text-decoration:none}h1 span{font-size:18px;font-weight:normal;color:#bfbfbf}h1 span a,h1 span a:visited,h1 span a:focus,h1 span a:hover{color:#bfbfbf}h1 a{text-decoration:none}h2{font-size:23px;margin:10px 0 8px}h3{font-size:16px;margin:10px 0 8px}p{margin:0 0 30px;font-size:13px;line-height:18px}a,a:visited,a:focus{color:#0069d6;text-decoration:none}a:hover{color:#00438a;text-decoration:underline}.download{float:right}pre{background:#f5f5f5;color:#404040;padding:16px;border:1px solid rgba(0,0,0,0.05);border-radius:4px;box-shadow:0 1px 1px rgba(0,0,0,0.05) inset;margin:-20px 0 10px;line-height:200%}.twitter{margin:-20px 0 40px;color:#666}.twitter iframe{vertical-align:bottom;margin:0 0 0 5px}.footer{text-align:center;padding-top:20px;margin-top:60px;font-size:14px;color:#808080;border-top:1px solid #ccc}.footer a,.footer a:visited,.footer a:focus{color:#333}.footer a:hover{color:#000} \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/sample/js/analytics.js b/nstock/static/plugin_ckeditor/skins/bootstrapck/sample/js/analytics.js new file mode 100644 index 0000000..fd6c93a --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/sample/js/analytics.js @@ -0,0 +1,4 @@ +var _ga=_ga||{},_gaq=_gaq||[];_ga.trackSocial=function(a,c){_ga.trackFacebook(a,c);_ga.trackTwitter(a,c)}; +_ga.trackFacebook=function(a,c){var d=_ga.buildTrackerName_(c);try{FB&&FB.Event&&FB.Event.subscribe&&(FB.Event.subscribe("edge.create",function(b){_gaq.push([d+"_trackSocial","facebook","like",b,a])}),FB.Event.subscribe("edge.remove",function(b){_gaq.push([d+"_trackSocial","facebook","unlike",b,a])}),FB.Event.subscribe("message.send",function(b){_gaq.push([d+"_trackSocial","facebook","send",b,a])}))}catch(e){}};_ga.buildTrackerName_=function(a){return a?a+".":""}; +_ga.trackTwitter=function(a,c){var d=_ga.buildTrackerName_(c);try{twttr&&twttr.events&&twttr.events.bind&&twttr.events.bind("tweet",function(b){if(b){var c;b.target&&"IFRAME"==b.target.nodeName&&(c=_ga.extractParamFromUri_(b.target.src,"url"));_gaq.push([d+"_trackSocial","twitter","tweet",c,a])}})}catch(e){}};_ga.extractParamFromUri_=function(a,c){if(a){var a=a.split("#")[0],d=a.split("?");if(1!=d.length)for(var d=decodeURI(d[1]),c=c+"=",d=d.split("&"),e=0,b;b=d[e];++e)if(0===b.indexOf(c))return unescape(b.split("=")[1])}}; +jQuery&&jQuery("a").click(function(){var a=jQuery(this).attr("href");null!=a&&(a.match(/^http/i)&&!a.match(document.domain)?_gaq.push(["_trackEvent","outgoing","click",a]):a.match(/\.(doc|pdf|xls|ppt|zip|txt|vsd|vxd|js|css|rar|exe|wma|mov|avi|wmv|mp3)$/i)?_gaq.push(["_trackEvent","download","click",a]):a.match(/^mailto:/i)&&_gaq.push(["_trackEvent","mailto","click",a]))}); \ No newline at end of file diff --git a/nstock/static/plugin_ckeditor/skins/bootstrapck/sample/js/jquery-1.11.0.min.js b/nstock/static/plugin_ckeditor/skins/bootstrapck/sample/js/jquery-1.11.0.min.js new file mode 100644 index 0000000..662b227 --- /dev/null +++ b/nstock/static/plugin_ckeditor/skins/bootstrapck/sample/js/jquery-1.11.0.min.js @@ -0,0 +1,189 @@ +!function(o,ea){"object"==typeof module&&"object"==typeof module.exports?module.exports=o.document?ea(o,!0):function(o){if(!o.document)throw Error("jQuery requires a window with a document");return ea(o)}:ea(o)}("undefined"!=typeof window?window:this,function(o,ea){function Ba(a){var b=a.length,d=c.type(a);return"function"===d||c.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===d||0===b||"number"==typeof b&&0e;e++)c.event.add(b,d,h[d][e])}g.data&&(g.data=c.extend({},g.data))}}function hb(a,b){var d=c(b.createElement(a)).appendTo(b.body),e=o.getDefaultComputedStyle?o.getDefaultComputedStyle(d[0]).display:c.css(d[0],"display");return d.detach(),e}function ib(a){var b=l,d=jb[a];return d||(d=hb(a,b),"none"!==d&&d||(fa=(fa||c("