From 2ba476c6ef0d0f4641fc8cafea396cc688261630 Mon Sep 17 00:00:00 2001 From: rembo10 Date: Mon, 31 Mar 2014 16:21:50 -0700 Subject: [PATCH] Updated beets lib ( + mutagen ) and added unidecode --- {lib/beets => beets}/__init__.py | 15 +- beets/autotag/__init__.py | 244 +++ beets/autotag/hooks.py | 545 ++++++ beets/autotag/match.py | 456 +++++ {lib/beets => beets}/autotag/mb.py | 201 ++- beets/config_default.yaml | 102 ++ beets/dbcore/__init__.py | 20 + beets/dbcore/db.py | 727 ++++++++ beets/dbcore/query.py | 494 +++++ beets/dbcore/types.py | 140 ++ {lib/beets => beets}/importer.py | 596 +++--- beets/library.py | 1216 +++++++++++++ beets/mediafile.py | 1672 +++++++++++++++++ {lib/beets => beets}/plugins.py | 181 +- {lib/beets => beets}/ui/__init__.py | 639 ++++--- beets/ui/commands.py | 1404 +++++++++++++++ beets/ui/completion_base.sh | 162 ++ beets/ui/migrate.py | 401 +++++ {lib/beets => beets}/util/__init__.py | 299 ++- beets/util/artresizer.py | 188 ++ {lib/beets => beets}/util/bluelet.py | 73 +- beets/util/confit.py | 900 +++++++++ {lib/beets => beets}/util/enumeration.py | 2 +- {lib/beets => beets}/util/functemplate.py | 5 +- {lib/beets => beets}/util/pipeline.py | 51 +- {lib/beets => beets}/vfs.py | 6 +- headphones/importer.py | 2 +- headphones/librarysync.py | 2 +- headphones/music_encoder.py | 2 +- headphones/postprocessor.py | 6 +- lib/beets/autotag/__init__.py | 191 -- lib/beets/autotag/art.py | 152 -- lib/beets/autotag/hooks.py | 190 -- lib/beets/autotag/match.py | 497 ----- lib/beets/library.py | 1735 ------------------ lib/beets/mediafile.py | 1084 ----------- lib/beets/ui/commands.py | 1198 ------------ lib/munkres.py | 77 +- lib/mutagen/id3.py | 2005 --------------------- lib/mutagen/musepack.py | 118 -- lib/unidecode/__init__.py | 63 + lib/unidecode/x000.py | 258 +++ lib/unidecode/x001.py | 258 +++ lib/unidecode/x002.py | 257 +++ lib/unidecode/x003.py | 257 +++ lib/unidecode/x004.py | 257 +++ lib/unidecode/x005.py | 257 +++ lib/unidecode/x006.py | 257 +++ lib/unidecode/x007.py | 257 +++ lib/unidecode/x009.py | 257 +++ lib/unidecode/x00a.py | 257 +++ lib/unidecode/x00b.py | 257 +++ lib/unidecode/x00c.py | 257 +++ lib/unidecode/x00d.py | 257 +++ lib/unidecode/x00e.py | 257 +++ lib/unidecode/x00f.py | 257 +++ lib/unidecode/x010.py | 257 +++ lib/unidecode/x011.py | 257 +++ lib/unidecode/x012.py | 258 +++ lib/unidecode/x013.py | 257 +++ lib/unidecode/x014.py | 258 +++ lib/unidecode/x015.py | 258 +++ lib/unidecode/x016.py | 257 +++ lib/unidecode/x017.py | 257 +++ lib/unidecode/x018.py | 257 +++ lib/unidecode/x01d.py | 257 +++ lib/unidecode/x01e.py | 257 +++ lib/unidecode/x01f.py | 257 +++ lib/unidecode/x020.py | 257 +++ lib/unidecode/x021.py | 257 +++ lib/unidecode/x022.py | 257 +++ lib/unidecode/x023.py | 257 +++ lib/unidecode/x024.py | 257 +++ lib/unidecode/x025.py | 257 +++ lib/unidecode/x026.py | 257 +++ lib/unidecode/x027.py | 257 +++ lib/unidecode/x028.py | 258 +++ lib/unidecode/x029.py | 257 +++ lib/unidecode/x02a.py | 257 +++ lib/unidecode/x02c.py | 257 +++ lib/unidecode/x02e.py | 257 +++ lib/unidecode/x02f.py | 257 +++ lib/unidecode/x030.py | 257 +++ lib/unidecode/x031.py | 257 +++ lib/unidecode/x032.py | 257 +++ lib/unidecode/x033.py | 257 +++ lib/unidecode/x04d.py | 257 +++ lib/unidecode/x04e.py | 258 +++ lib/unidecode/x04f.py | 258 +++ lib/unidecode/x050.py | 258 +++ lib/unidecode/x051.py | 258 +++ lib/unidecode/x052.py | 258 +++ lib/unidecode/x053.py | 258 +++ lib/unidecode/x054.py | 258 +++ lib/unidecode/x055.py | 258 +++ lib/unidecode/x056.py | 258 +++ lib/unidecode/x057.py | 258 +++ lib/unidecode/x058.py | 258 +++ lib/unidecode/x059.py | 258 +++ lib/unidecode/x05a.py | 258 +++ lib/unidecode/x05b.py | 258 +++ lib/unidecode/x05c.py | 258 +++ lib/unidecode/x05d.py | 258 +++ lib/unidecode/x05e.py | 258 +++ lib/unidecode/x05f.py | 258 +++ lib/unidecode/x060.py | 258 +++ lib/unidecode/x061.py | 258 +++ lib/unidecode/x062.py | 258 +++ lib/unidecode/x063.py | 258 +++ lib/unidecode/x064.py | 258 +++ lib/unidecode/x065.py | 258 +++ lib/unidecode/x066.py | 258 +++ lib/unidecode/x067.py | 258 +++ lib/unidecode/x068.py | 258 +++ lib/unidecode/x069.py | 258 +++ lib/unidecode/x06a.py | 258 +++ lib/unidecode/x06b.py | 258 +++ lib/unidecode/x06c.py | 258 +++ lib/unidecode/x06d.py | 258 +++ lib/unidecode/x06e.py | 258 +++ lib/unidecode/x06f.py | 258 +++ lib/unidecode/x070.py | 258 +++ lib/unidecode/x071.py | 258 +++ lib/unidecode/x072.py | 258 +++ lib/unidecode/x073.py | 258 +++ lib/unidecode/x074.py | 258 +++ lib/unidecode/x075.py | 258 +++ lib/unidecode/x076.py | 258 +++ lib/unidecode/x077.py | 258 +++ lib/unidecode/x078.py | 258 +++ lib/unidecode/x079.py | 258 +++ lib/unidecode/x07a.py | 258 +++ lib/unidecode/x07b.py | 258 +++ lib/unidecode/x07c.py | 258 +++ lib/unidecode/x07d.py | 258 +++ lib/unidecode/x07e.py | 258 +++ lib/unidecode/x07f.py | 258 +++ lib/unidecode/x080.py | 258 +++ lib/unidecode/x081.py | 258 +++ lib/unidecode/x082.py | 258 +++ lib/unidecode/x083.py | 258 +++ lib/unidecode/x084.py | 258 +++ lib/unidecode/x085.py | 258 +++ lib/unidecode/x086.py | 258 +++ lib/unidecode/x087.py | 258 +++ lib/unidecode/x088.py | 258 +++ lib/unidecode/x089.py | 258 +++ lib/unidecode/x08a.py | 258 +++ lib/unidecode/x08b.py | 258 +++ lib/unidecode/x08c.py | 258 +++ lib/unidecode/x08d.py | 258 +++ lib/unidecode/x08e.py | 258 +++ lib/unidecode/x08f.py | 258 +++ lib/unidecode/x090.py | 258 +++ lib/unidecode/x091.py | 258 +++ lib/unidecode/x092.py | 258 +++ lib/unidecode/x093.py | 258 +++ lib/unidecode/x094.py | 258 +++ lib/unidecode/x095.py | 258 +++ lib/unidecode/x096.py | 258 +++ lib/unidecode/x097.py | 258 +++ lib/unidecode/x098.py | 258 +++ lib/unidecode/x099.py | 258 +++ lib/unidecode/x09a.py | 258 +++ lib/unidecode/x09b.py | 258 +++ lib/unidecode/x09c.py | 258 +++ lib/unidecode/x09d.py | 258 +++ lib/unidecode/x09e.py | 258 +++ lib/unidecode/x09f.py | 257 +++ lib/unidecode/x0a0.py | 258 +++ lib/unidecode/x0a1.py | 258 +++ lib/unidecode/x0a2.py | 258 +++ lib/unidecode/x0a3.py | 258 +++ lib/unidecode/x0a4.py | 257 +++ lib/unidecode/x0ac.py | 258 +++ lib/unidecode/x0ad.py | 258 +++ lib/unidecode/x0ae.py | 258 +++ lib/unidecode/x0af.py | 258 +++ lib/unidecode/x0b0.py | 258 +++ lib/unidecode/x0b1.py | 258 +++ lib/unidecode/x0b2.py | 258 +++ lib/unidecode/x0b3.py | 258 +++ lib/unidecode/x0b4.py | 258 +++ lib/unidecode/x0b5.py | 258 +++ lib/unidecode/x0b6.py | 258 +++ lib/unidecode/x0b7.py | 258 +++ lib/unidecode/x0b8.py | 258 +++ lib/unidecode/x0b9.py | 258 +++ lib/unidecode/x0ba.py | 258 +++ lib/unidecode/x0bb.py | 258 +++ lib/unidecode/x0bc.py | 258 +++ lib/unidecode/x0bd.py | 258 +++ lib/unidecode/x0be.py | 258 +++ lib/unidecode/x0bf.py | 258 +++ lib/unidecode/x0c0.py | 258 +++ lib/unidecode/x0c1.py | 258 +++ lib/unidecode/x0c2.py | 258 +++ lib/unidecode/x0c3.py | 258 +++ lib/unidecode/x0c4.py | 258 +++ lib/unidecode/x0c5.py | 258 +++ lib/unidecode/x0c6.py | 258 +++ lib/unidecode/x0c7.py | 258 +++ lib/unidecode/x0c8.py | 258 +++ lib/unidecode/x0c9.py | 258 +++ lib/unidecode/x0ca.py | 258 +++ lib/unidecode/x0cb.py | 258 +++ lib/unidecode/x0cc.py | 258 +++ lib/unidecode/x0cd.py | 258 +++ lib/unidecode/x0ce.py | 258 +++ lib/unidecode/x0cf.py | 258 +++ lib/unidecode/x0d0.py | 258 +++ lib/unidecode/x0d1.py | 258 +++ lib/unidecode/x0d2.py | 258 +++ lib/unidecode/x0d3.py | 258 +++ lib/unidecode/x0d4.py | 258 +++ lib/unidecode/x0d5.py | 258 +++ lib/unidecode/x0d6.py | 258 +++ lib/unidecode/x0d7.py | 257 +++ lib/unidecode/x0f9.py | 258 +++ lib/unidecode/x0fa.py | 257 +++ lib/unidecode/x0fb.py | 258 +++ lib/unidecode/x0fc.py | 258 +++ lib/unidecode/x0fd.py | 257 +++ lib/unidecode/x0fe.py | 258 +++ lib/unidecode/x0ff.py | 258 +++ lib/unidecode/x1d4.py | 258 +++ lib/unidecode/x1d5.py | 258 +++ lib/unidecode/x1d6.py | 258 +++ lib/unidecode/x1d7.py | 258 +++ {lib/mutagen => mutagen}/__init__.py | 136 +- {lib/mutagen => mutagen}/_constants.py | 66 +- mutagen/_id3frames.py | 1842 +++++++++++++++++++ mutagen/_id3specs.py | 465 +++++ mutagen/_id3util.py | 176 ++ {lib/mutagen => mutagen}/_util.py | 79 +- {lib/mutagen => mutagen}/_vorbis.py | 105 +- {lib/mutagen => mutagen}/apev2.py | 150 +- {lib/mutagen => mutagen}/asf.py | 88 +- {lib/mutagen => mutagen}/easyid3.py | 127 +- {lib/mutagen => mutagen}/easymp4.py | 53 +- {lib/mutagen => mutagen}/flac.py | 495 +++-- mutagen/id3.py | 919 ++++++++++ {lib/mutagen => mutagen}/m4a.py | 109 +- {lib/mutagen => mutagen}/monkeysaudio.py | 26 +- {lib/mutagen => mutagen}/mp3.py | 146 +- {lib/mutagen => mutagen}/mp4.py | 350 ++-- mutagen/musepack.py | 257 +++ {lib/mutagen => mutagen}/ogg.py | 125 +- {lib/mutagen => mutagen}/oggflac.py | 42 +- mutagen/oggopus.py | 125 ++ {lib/mutagen => mutagen}/oggspeex.py | 36 +- {lib/mutagen => mutagen}/oggtheora.py | 39 +- {lib/mutagen => mutagen}/oggvorbis.py | 37 +- {lib/mutagen => mutagen}/optimfrog.py | 27 +- {lib/mutagen => mutagen}/trueaudio.py | 43 +- {lib/mutagen => mutagen}/wavpack.py | 26 +- 256 files changed, 63907 insertions(+), 8702 deletions(-) rename {lib/beets => beets}/__init__.py (78%) create mode 100644 beets/autotag/__init__.py create mode 100644 beets/autotag/hooks.py create mode 100644 beets/autotag/match.py rename {lib/beets => beets}/autotag/mb.py (61%) create mode 100644 beets/config_default.yaml create mode 100644 beets/dbcore/__init__.py create mode 100644 beets/dbcore/db.py create mode 100644 beets/dbcore/query.py create mode 100644 beets/dbcore/types.py rename {lib/beets => beets}/importer.py (60%) create mode 100644 beets/library.py create mode 100644 beets/mediafile.py rename {lib/beets => beets}/plugins.py (66%) rename {lib/beets => beets}/ui/__init__.py (58%) create mode 100644 beets/ui/commands.py create mode 100644 beets/ui/completion_base.sh create mode 100644 beets/ui/migrate.py rename {lib/beets => beets}/util/__init__.py (65%) create mode 100644 beets/util/artresizer.py rename {lib/beets => beets}/util/bluelet.py (91%) create mode 100644 beets/util/confit.py rename {lib/beets => beets}/util/enumeration.py (99%) rename {lib/beets => beets}/util/functemplate.py (99%) rename {lib/beets => beets}/util/pipeline.py (95%) rename {lib/beets => beets}/vfs.py (93%) delete mode 100644 lib/beets/autotag/__init__.py delete mode 100644 lib/beets/autotag/art.py delete mode 100644 lib/beets/autotag/hooks.py delete mode 100644 lib/beets/autotag/match.py delete mode 100644 lib/beets/library.py delete mode 100644 lib/beets/mediafile.py delete mode 100644 lib/beets/ui/commands.py mode change 100755 => 100644 lib/munkres.py delete mode 100644 lib/mutagen/id3.py delete mode 100644 lib/mutagen/musepack.py create mode 100644 lib/unidecode/__init__.py create mode 100644 lib/unidecode/x000.py create mode 100644 lib/unidecode/x001.py create mode 100644 lib/unidecode/x002.py create mode 100644 lib/unidecode/x003.py create mode 100644 lib/unidecode/x004.py create mode 100644 lib/unidecode/x005.py create mode 100644 lib/unidecode/x006.py create mode 100644 lib/unidecode/x007.py create mode 100644 lib/unidecode/x009.py create mode 100644 lib/unidecode/x00a.py create mode 100644 lib/unidecode/x00b.py create mode 100644 lib/unidecode/x00c.py create mode 100644 lib/unidecode/x00d.py create mode 100644 lib/unidecode/x00e.py create mode 100644 lib/unidecode/x00f.py create mode 100644 lib/unidecode/x010.py create mode 100644 lib/unidecode/x011.py create mode 100644 lib/unidecode/x012.py create mode 100644 lib/unidecode/x013.py create mode 100644 lib/unidecode/x014.py create mode 100644 lib/unidecode/x015.py create mode 100644 lib/unidecode/x016.py create mode 100644 lib/unidecode/x017.py create mode 100644 lib/unidecode/x018.py create mode 100644 lib/unidecode/x01d.py create mode 100644 lib/unidecode/x01e.py create mode 100644 lib/unidecode/x01f.py create mode 100644 lib/unidecode/x020.py create mode 100644 lib/unidecode/x021.py create mode 100644 lib/unidecode/x022.py create mode 100644 lib/unidecode/x023.py create mode 100644 lib/unidecode/x024.py create mode 100644 lib/unidecode/x025.py create mode 100644 lib/unidecode/x026.py create mode 100644 lib/unidecode/x027.py create mode 100644 lib/unidecode/x028.py create mode 100644 lib/unidecode/x029.py create mode 100644 lib/unidecode/x02a.py create mode 100644 lib/unidecode/x02c.py create mode 100644 lib/unidecode/x02e.py create mode 100644 lib/unidecode/x02f.py create mode 100644 lib/unidecode/x030.py create mode 100644 lib/unidecode/x031.py create mode 100644 lib/unidecode/x032.py create mode 100644 lib/unidecode/x033.py create mode 100644 lib/unidecode/x04d.py create mode 100644 lib/unidecode/x04e.py create mode 100644 lib/unidecode/x04f.py create mode 100644 lib/unidecode/x050.py create mode 100644 lib/unidecode/x051.py create mode 100644 lib/unidecode/x052.py create mode 100644 lib/unidecode/x053.py create mode 100644 lib/unidecode/x054.py create mode 100644 lib/unidecode/x055.py create mode 100644 lib/unidecode/x056.py create mode 100644 lib/unidecode/x057.py create mode 100644 lib/unidecode/x058.py create mode 100644 lib/unidecode/x059.py create mode 100644 lib/unidecode/x05a.py create mode 100644 lib/unidecode/x05b.py create mode 100644 lib/unidecode/x05c.py create mode 100644 lib/unidecode/x05d.py create mode 100644 lib/unidecode/x05e.py create mode 100644 lib/unidecode/x05f.py create mode 100644 lib/unidecode/x060.py create mode 100644 lib/unidecode/x061.py create mode 100644 lib/unidecode/x062.py create mode 100644 lib/unidecode/x063.py create mode 100644 lib/unidecode/x064.py create mode 100644 lib/unidecode/x065.py create mode 100644 lib/unidecode/x066.py create mode 100644 lib/unidecode/x067.py create mode 100644 lib/unidecode/x068.py create mode 100644 lib/unidecode/x069.py create mode 100644 lib/unidecode/x06a.py create mode 100644 lib/unidecode/x06b.py create mode 100644 lib/unidecode/x06c.py create mode 100644 lib/unidecode/x06d.py create mode 100644 lib/unidecode/x06e.py create mode 100644 lib/unidecode/x06f.py create mode 100644 lib/unidecode/x070.py create mode 100644 lib/unidecode/x071.py create mode 100644 lib/unidecode/x072.py create mode 100644 lib/unidecode/x073.py create mode 100644 lib/unidecode/x074.py create mode 100644 lib/unidecode/x075.py create mode 100644 lib/unidecode/x076.py create mode 100644 lib/unidecode/x077.py create mode 100644 lib/unidecode/x078.py create mode 100644 lib/unidecode/x079.py create mode 100644 lib/unidecode/x07a.py create mode 100644 lib/unidecode/x07b.py create mode 100644 lib/unidecode/x07c.py create mode 100644 lib/unidecode/x07d.py create mode 100644 lib/unidecode/x07e.py create mode 100644 lib/unidecode/x07f.py create mode 100644 lib/unidecode/x080.py create mode 100644 lib/unidecode/x081.py create mode 100644 lib/unidecode/x082.py create mode 100644 lib/unidecode/x083.py create mode 100644 lib/unidecode/x084.py create mode 100644 lib/unidecode/x085.py create mode 100644 lib/unidecode/x086.py create mode 100644 lib/unidecode/x087.py create mode 100644 lib/unidecode/x088.py create mode 100644 lib/unidecode/x089.py create mode 100644 lib/unidecode/x08a.py create mode 100644 lib/unidecode/x08b.py create mode 100644 lib/unidecode/x08c.py create mode 100644 lib/unidecode/x08d.py create mode 100644 lib/unidecode/x08e.py create mode 100644 lib/unidecode/x08f.py create mode 100644 lib/unidecode/x090.py create mode 100644 lib/unidecode/x091.py create mode 100644 lib/unidecode/x092.py create mode 100644 lib/unidecode/x093.py create mode 100644 lib/unidecode/x094.py create mode 100644 lib/unidecode/x095.py create mode 100644 lib/unidecode/x096.py create mode 100644 lib/unidecode/x097.py create mode 100644 lib/unidecode/x098.py create mode 100644 lib/unidecode/x099.py create mode 100644 lib/unidecode/x09a.py create mode 100644 lib/unidecode/x09b.py create mode 100644 lib/unidecode/x09c.py create mode 100644 lib/unidecode/x09d.py create mode 100644 lib/unidecode/x09e.py create mode 100644 lib/unidecode/x09f.py create mode 100644 lib/unidecode/x0a0.py create mode 100644 lib/unidecode/x0a1.py create mode 100644 lib/unidecode/x0a2.py create mode 100644 lib/unidecode/x0a3.py create mode 100644 lib/unidecode/x0a4.py create mode 100644 lib/unidecode/x0ac.py create mode 100644 lib/unidecode/x0ad.py create mode 100644 lib/unidecode/x0ae.py create mode 100644 lib/unidecode/x0af.py create mode 100644 lib/unidecode/x0b0.py create mode 100644 lib/unidecode/x0b1.py create mode 100644 lib/unidecode/x0b2.py create mode 100644 lib/unidecode/x0b3.py create mode 100644 lib/unidecode/x0b4.py create mode 100644 lib/unidecode/x0b5.py create mode 100644 lib/unidecode/x0b6.py create mode 100644 lib/unidecode/x0b7.py create mode 100644 lib/unidecode/x0b8.py create mode 100644 lib/unidecode/x0b9.py create mode 100644 lib/unidecode/x0ba.py create mode 100644 lib/unidecode/x0bb.py create mode 100644 lib/unidecode/x0bc.py create mode 100644 lib/unidecode/x0bd.py create mode 100644 lib/unidecode/x0be.py create mode 100644 lib/unidecode/x0bf.py create mode 100644 lib/unidecode/x0c0.py create mode 100644 lib/unidecode/x0c1.py create mode 100644 lib/unidecode/x0c2.py create mode 100644 lib/unidecode/x0c3.py create mode 100644 lib/unidecode/x0c4.py create mode 100644 lib/unidecode/x0c5.py create mode 100644 lib/unidecode/x0c6.py create mode 100644 lib/unidecode/x0c7.py create mode 100644 lib/unidecode/x0c8.py create mode 100644 lib/unidecode/x0c9.py create mode 100644 lib/unidecode/x0ca.py create mode 100644 lib/unidecode/x0cb.py create mode 100644 lib/unidecode/x0cc.py create mode 100644 lib/unidecode/x0cd.py create mode 100644 lib/unidecode/x0ce.py create mode 100644 lib/unidecode/x0cf.py create mode 100644 lib/unidecode/x0d0.py create mode 100644 lib/unidecode/x0d1.py create mode 100644 lib/unidecode/x0d2.py create mode 100644 lib/unidecode/x0d3.py create mode 100644 lib/unidecode/x0d4.py create mode 100644 lib/unidecode/x0d5.py create mode 100644 lib/unidecode/x0d6.py create mode 100644 lib/unidecode/x0d7.py create mode 100644 lib/unidecode/x0f9.py create mode 100644 lib/unidecode/x0fa.py create mode 100644 lib/unidecode/x0fb.py create mode 100644 lib/unidecode/x0fc.py create mode 100644 lib/unidecode/x0fd.py create mode 100644 lib/unidecode/x0fe.py create mode 100644 lib/unidecode/x0ff.py create mode 100644 lib/unidecode/x1d4.py create mode 100644 lib/unidecode/x1d5.py create mode 100644 lib/unidecode/x1d6.py create mode 100644 lib/unidecode/x1d7.py rename {lib/mutagen => mutagen}/__init__.py (66%) rename {lib/mutagen => mutagen}/_constants.py (71%) create mode 100644 mutagen/_id3frames.py create mode 100644 mutagen/_id3specs.py create mode 100644 mutagen/_id3util.py rename {lib/mutagen => mutagen}/_util.py (88%) rename {lib/mutagen => mutagen}/_vorbis.py (76%) rename {lib/mutagen => mutagen}/apev2.py (84%) rename {lib/mutagen => mutagen}/asf.py (92%) rename {lib/mutagen => mutagen}/easyid3.py (86%) rename {lib/mutagen => mutagen}/easymp4.py (89%) rename {lib/mutagen => mutagen}/flac.py (61%) create mode 100644 mutagen/id3.py rename {lib/mutagen => mutagen}/m4a.py (91%) rename {lib/mutagen => mutagen}/monkeysaudio.py (83%) rename {lib/mutagen => mutagen}/mp3.py (71%) rename {lib/mutagen => mutagen}/mp4.py (72%) create mode 100644 mutagen/musepack.py rename {lib/mutagen => mutagen}/ogg.py (86%) rename {lib/mutagen => mutagen}/oggflac.py (82%) create mode 100644 mutagen/oggopus.py rename {lib/mutagen => mutagen}/oggspeex.py (87%) rename {lib/mutagen => mutagen}/oggtheora.py (80%) rename {lib/mutagen => mutagen}/oggvorbis.py (85%) rename {lib/mutagen => mutagen}/optimfrog.py (82%) rename {lib/mutagen => mutagen}/trueaudio.py (67%) rename {lib/mutagen => mutagen}/wavpack.py (78%) diff --git a/lib/beets/__init__.py b/beets/__init__.py similarity index 78% rename from lib/beets/__init__.py rename to beets/__init__.py index 3ef490cf..6bdbf3bf 100644 --- a/lib/beets/__init__.py +++ b/beets/__init__.py @@ -1,5 +1,5 @@ # This file is part of beets. -# Copyright 2012, Adrian Sampson. +# Copyright 2013, Adrian Sampson. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -12,11 +12,12 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -# -# MODIFIED TO WORK WITH HEADPHONES!! -# - -__version__ = '1.0b15' +__version__ = '1.3.4' __author__ = 'Adrian Sampson ' -from lib.beets.library import Library +import beets.library +from beets.util import confit + +Library = beets.library.Library + +config = confit.LazyConfig('beets', __name__) diff --git a/beets/autotag/__init__.py b/beets/autotag/__init__.py new file mode 100644 index 00000000..6b0c1185 --- /dev/null +++ b/beets/autotag/__init__.py @@ -0,0 +1,244 @@ +# This file is part of beets. +# Copyright 2013, Adrian Sampson. +# +# 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. + +"""Facilities for automatically determining files' correct metadata. +""" +import os +import logging +import re + +from beets import library, mediafile, config +from beets.util import sorted_walk, ancestry, displayable_path + +# Parts of external interface. +from .hooks import AlbumInfo, TrackInfo, AlbumMatch, TrackMatch +from .match import tag_item, tag_album +from .match import recommendation + +# Global logger. +log = logging.getLogger('beets') + +# Constants for directory walker. +MULTIDISC_MARKERS = (r'dis[ck]', r'cd') +MULTIDISC_PAT_FMT = r'^(.*%s[\W_]*)\d' + + +# Additional utilities for the main interface. + +def albums_in_dir(path): + """Recursively searches the given directory and returns an iterable + of (paths, items) where paths is a list of directories and items is + a list of Items that is probably an album. Specifically, any folder + containing any media files is an album. + """ + collapse_pat = collapse_paths = collapse_items = None + + for root, dirs, files in sorted_walk(path, + ignore=config['ignore'].as_str_seq(), + logger=log): + # Get a list of items in the directory. + items = [] + for filename in files: + try: + i = library.Item.from_path(os.path.join(root, filename)) + except mediafile.FileTypeError: + pass + except mediafile.UnreadableFileError: + log.warn(u'unreadable file: {0}'.format( + displayable_path(filename)) + ) + else: + items.append(i) + + # If we're currently collapsing the constituent directories in a + # multi-disc album, check whether we should continue collapsing + # and add the current directory. If so, just add the directory + # and move on to the next directory. If not, stop collapsing. + if collapse_paths: + if (not collapse_pat and collapse_paths[0] in ancestry(root)) or \ + (collapse_pat and + collapse_pat.match(os.path.basename(root))): + # Still collapsing. + collapse_paths.append(root) + collapse_items += items + continue + else: + # Collapse finished. Yield the collapsed directory and + # proceed to process the current one. + if collapse_items: + yield collapse_paths, collapse_items + collapse_pat = collapse_paths = collapse_items = None + + # Check whether this directory looks like the *first* directory + # in a multi-disc sequence. There are two indicators: the file + # is named like part of a multi-disc sequence (e.g., "Title Disc + # 1") or it contains no items but only directories that are + # named in this way. + start_collapsing = False + for marker in MULTIDISC_MARKERS: + marker_pat = re.compile(MULTIDISC_PAT_FMT % marker, re.I) + match = marker_pat.match(os.path.basename(root)) + + # Is this directory the root of a nested multi-disc album? + if dirs and not items: + # Check whether all subdirectories have the same prefix. + start_collapsing = True + subdir_pat = None + for subdir in dirs: + # The first directory dictates the pattern for + # the remaining directories. + if not subdir_pat: + match = marker_pat.match(subdir) + if match: + subdir_pat = re.compile(r'^%s\d' % + re.escape(match.group(1)), re.I) + else: + start_collapsing = False + break + + # Subsequent directories must match the pattern. + elif not subdir_pat.match(subdir): + start_collapsing = False + break + + # If all subdirectories match, don't check other + # markers. + if start_collapsing: + break + + # Is this directory the first in a flattened multi-disc album? + elif match: + start_collapsing = True + # Set the current pattern to match directories with the same + # prefix as this one, followed by a digit. + collapse_pat = re.compile(r'^%s\d' % + re.escape(match.group(1)), re.I) + break + + # If either of the above heuristics indicated that this is the + # beginning of a multi-disc album, initialize the collapsed + # directory and item lists and check the next directory. + if start_collapsing: + # Start collapsing; continue to the next iteration. + collapse_paths = [root] + collapse_items = items + continue + + # If it's nonempty, yield it. + if items: + yield [root], items + + # Clear out any unfinished collapse. + if collapse_paths and collapse_items: + yield collapse_paths, collapse_items + +def apply_item_metadata(item, track_info): + """Set an item's metadata from its matched TrackInfo object. + """ + item.artist = track_info.artist + item.artist_sort = track_info.artist_sort + item.artist_credit = track_info.artist_credit + item.title = track_info.title + item.mb_trackid = track_info.track_id + if track_info.artist_id: + item.mb_artistid = track_info.artist_id + # At the moment, the other metadata is left intact (including album + # and track number). Perhaps these should be emptied? + +def apply_metadata(album_info, mapping): + """Set the items' metadata to match an AlbumInfo object using a + mapping from Items to TrackInfo objects. + """ + for item, track_info in mapping.iteritems(): + # Album, artist, track count. + if track_info.artist: + item.artist = track_info.artist + else: + item.artist = album_info.artist + item.albumartist = album_info.artist + item.album = album_info.album + + # Artist sort and credit names. + item.artist_sort = track_info.artist_sort or album_info.artist_sort + item.artist_credit = track_info.artist_credit or \ + album_info.artist_credit + item.albumartist_sort = album_info.artist_sort + item.albumartist_credit = album_info.artist_credit + + # Release date. + for prefix in '', 'original_': + if config['original_date'] and not prefix: + # Ignore specific release date. + continue + + for suffix in 'year', 'month', 'day': + key = prefix + suffix + value = getattr(album_info, key) or 0 + + # If we don't even have a year, apply nothing. + if suffix == 'year' and not value: + break + + # Otherwise, set the fetched value (or 0 for the month + # and day if not available). + item[key] = value + + # If we're using original release date for both fields, + # also set item.year = info.original_year, etc. + if config['original_date']: + item[suffix] = value + + # Title. + item.title = track_info.title + + if config['per_disc_numbering']: + item.track = track_info.medium_index or track_info.index + item.tracktotal = track_info.medium_total or len(album_info.tracks) + else: + item.track = track_info.index + item.tracktotal = len(album_info.tracks) + + # Disc and disc count. + item.disc = track_info.medium + item.disctotal = album_info.mediums + + # MusicBrainz IDs. + item.mb_trackid = track_info.track_id + item.mb_albumid = album_info.album_id + if track_info.artist_id: + item.mb_artistid = track_info.artist_id + else: + item.mb_artistid = album_info.artist_id + item.mb_albumartistid = album_info.artist_id + item.mb_releasegroupid = album_info.releasegroup_id + + # Compilation flag. + item.comp = album_info.va + + # Miscellaneous metadata. + for field in ('albumtype', + 'label', + 'asin', + 'catalognum', + 'script', + 'language', + 'country', + 'albumstatus', + 'media', + 'albumdisambig'): + value = getattr(album_info, field) + if value is not None: + item[field] = value + if track_info.disctitle is not None: + item.disctitle = track_info.disctitle diff --git a/beets/autotag/hooks.py b/beets/autotag/hooks.py new file mode 100644 index 00000000..5ba841bf --- /dev/null +++ b/beets/autotag/hooks.py @@ -0,0 +1,545 @@ +# This file is part of beets. +# Copyright 2013, Adrian Sampson. +# +# 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. + +"""Glue between metadata sources and the matching logic.""" +import logging +from collections import namedtuple +import re + +from beets import plugins +from beets import config +from beets.autotag import mb +from beets.util import levenshtein +from lib.unidecode import unidecode + +log = logging.getLogger('beets') + + +# Classes used to represent candidate options. + +class AlbumInfo(object): + """Describes a canonical release that may be used to match a release + in the library. Consists of these data members: + + - ``album``: the release title + - ``album_id``: MusicBrainz ID; UUID fragment only + - ``artist``: name of the release's primary artist + - ``artist_id`` + - ``tracks``: list of TrackInfo objects making up the release + - ``asin``: Amazon ASIN + - ``albumtype``: string describing the kind of release + - ``va``: boolean: whether the release has "various artists" + - ``year``: release year + - ``month``: release month + - ``day``: release day + - ``label``: music label responsible for the release + - ``mediums``: the number of discs in this release + - ``artist_sort``: name of the release's artist for sorting + - ``releasegroup_id``: MBID for the album's release group + - ``catalognum``: the label's catalog number for the release + - ``script``: character set used for metadata + - ``language``: human language of the metadata + - ``country``: the release country + - ``albumstatus``: MusicBrainz release status (Official, etc.) + - ``media``: delivery mechanism (Vinyl, etc.) + - ``albumdisambig``: MusicBrainz release disambiguation comment + - ``artist_credit``: Release-specific artist name + - ``data_source``: The original data source (MusicBrainz, Discogs, etc.) + - ``data_url``: The data source release URL. + + The fields up through ``tracks`` are required. The others are + optional and may be None. + """ + def __init__(self, album, album_id, artist, artist_id, tracks, asin=None, + albumtype=None, va=False, year=None, month=None, day=None, + label=None, mediums=None, artist_sort=None, + releasegroup_id=None, catalognum=None, script=None, + language=None, country=None, albumstatus=None, media=None, + albumdisambig=None, artist_credit=None, original_year=None, + original_month=None, original_day=None, data_source=None, + data_url=None): + self.album = album + self.album_id = album_id + self.artist = artist + self.artist_id = artist_id + self.tracks = tracks + self.asin = asin + self.albumtype = albumtype + self.va = va + self.year = year + self.month = month + self.day = day + self.label = label + self.mediums = mediums + self.artist_sort = artist_sort + self.releasegroup_id = releasegroup_id + self.catalognum = catalognum + self.script = script + self.language = language + self.country = country + self.albumstatus = albumstatus + self.media = media + self.albumdisambig = albumdisambig + self.artist_credit = artist_credit + self.original_year = original_year + self.original_month = original_month + self.original_day = original_day + self.data_source = data_source + self.data_url = data_url + + # Work around a bug in python-musicbrainz-ngs that causes some + # strings to be bytes rather than Unicode. + # https://github.com/alastair/python-musicbrainz-ngs/issues/85 + def decode(self, codec='utf8'): + """Ensure that all string attributes on this object, and the + constituent `TrackInfo` objects, are decoded to Unicode. + """ + for fld in ['album', 'artist', 'albumtype', 'label', 'artist_sort', + 'catalognum', 'script', 'language', 'country', + 'albumstatus', 'albumdisambig', 'artist_credit', 'media']: + value = getattr(self, fld) + if isinstance(value, str): + setattr(self, fld, value.decode(codec, 'ignore')) + + if self.tracks: + for track in self.tracks: + track.decode(codec) + +class TrackInfo(object): + """Describes a canonical track present on a release. Appears as part + of an AlbumInfo's ``tracks`` list. Consists of these data members: + + - ``title``: name of the track + - ``track_id``: MusicBrainz ID; UUID fragment only + - ``artist``: individual track artist name + - ``artist_id`` + - ``length``: float: duration of the track in seconds + - ``index``: position on the entire release + - ``medium``: the disc number this track appears on in the album + - ``medium_index``: the track's position on the disc + - ``medium_total``: the number of tracks on the item's disc + - ``artist_sort``: name of the track artist for sorting + - ``disctitle``: name of the individual medium (subtitle) + - ``artist_credit``: Recording-specific artist name + + Only ``title`` and ``track_id`` are required. The rest of the fields + may be None. The indices ``index``, ``medium``, and ``medium_index`` + are all 1-based. + """ + def __init__(self, title, track_id, artist=None, artist_id=None, + length=None, index=None, medium=None, medium_index=None, + medium_total=None, artist_sort=None, disctitle=None, + artist_credit=None, data_source=None, data_url=None): + self.title = title + self.track_id = track_id + self.artist = artist + self.artist_id = artist_id + self.length = length + self.index = index + self.medium = medium + self.medium_index = medium_index + self.medium_total = medium_total + self.artist_sort = artist_sort + self.disctitle = disctitle + self.artist_credit = artist_credit + self.data_source = data_source + self.data_url = data_url + + # As above, work around a bug in python-musicbrainz-ngs. + def decode(self, codec='utf8'): + """Ensure that all string attributes on this object are decoded + to Unicode. + """ + for fld in ['title', 'artist', 'medium', 'artist_sort', 'disctitle', + 'artist_credit']: + value = getattr(self, fld) + if isinstance(value, str): + setattr(self, fld, value.decode(codec, 'ignore')) + + +# Candidate distance scoring. + +# Parameters for string distance function. +# Words that can be moved to the end of a string using a comma. +SD_END_WORDS = ['the', 'a', 'an'] +# Reduced weights for certain portions of the string. +SD_PATTERNS = [ + (r'^the ', 0.1), + (r'[\[\(]?(ep|single)[\]\)]?', 0.0), + (r'[\[\(]?(featuring|feat|ft)[\. :].+', 0.1), + (r'\(.*?\)', 0.3), + (r'\[.*?\]', 0.3), + (r'(, )?(pt\.|part) .+', 0.2), +] +# Replacements to use before testing distance. +SD_REPLACE = [ + (r'&', 'and'), +] + +def _string_dist_basic(str1, str2): + """Basic edit distance between two strings, ignoring + non-alphanumeric characters and case. Comparisons are based on a + transliteration/lowering to ASCII characters. Normalized by string + length. + """ + str1 = unidecode(str1) + str2 = unidecode(str2) + str1 = re.sub(r'[^a-z0-9]', '', str1.lower()) + str2 = re.sub(r'[^a-z0-9]', '', str2.lower()) + if not str1 and not str2: + return 0.0 + return levenshtein(str1, str2) / float(max(len(str1), len(str2))) + +def string_dist(str1, str2): + """Gives an "intuitive" edit distance between two strings. This is + an edit distance, normalized by the string length, with a number of + tweaks that reflect intuition about text. + """ + if str1 == None and str2 == None: return 0.0 + if str1 == None or str2 == None: return 1.0 + + str1 = str1.lower() + str2 = str2.lower() + + # Don't penalize strings that move certain words to the end. For + # example, "the something" should be considered equal to + # "something, the". + for word in SD_END_WORDS: + if str1.endswith(', %s' % word): + str1 = '%s %s' % (word, str1[:-len(word)-2]) + if str2.endswith(', %s' % word): + str2 = '%s %s' % (word, str2[:-len(word)-2]) + + # Perform a couple of basic normalizing substitutions. + for pat, repl in SD_REPLACE: + str1 = re.sub(pat, repl, str1) + str2 = re.sub(pat, repl, str2) + + # Change the weight for certain string portions matched by a set + # of regular expressions. We gradually change the strings and build + # up penalties associated with parts of the string that were + # deleted. + base_dist = _string_dist_basic(str1, str2) + penalty = 0.0 + for pat, weight in SD_PATTERNS: + # Get strings that drop the pattern. + case_str1 = re.sub(pat, '', str1) + case_str2 = re.sub(pat, '', str2) + + if case_str1 != str1 or case_str2 != str2: + # If the pattern was present (i.e., it is deleted in the + # the current case), recalculate the distances for the + # modified strings. + case_dist = _string_dist_basic(case_str1, case_str2) + case_delta = max(0.0, base_dist - case_dist) + if case_delta == 0.0: + continue + + # Shift our baseline strings down (to avoid rematching the + # same part of the string) and add a scaled distance + # amount to the penalties. + str1 = case_str1 + str2 = case_str2 + base_dist = case_dist + penalty += weight * case_delta + + return base_dist + penalty + +class Distance(object): + """Keeps track of multiple distance penalties. Provides a single + weighted distance for all penalties as well as a weighted distance + for each individual penalty. + """ + def __init__(self): + self._penalties = {} + + weights_view = config['match']['distance_weights'] + self._weights = {} + for key in weights_view.keys(): + self._weights[key] = weights_view[key].as_number() + + + # Access the components and their aggregates. + + @property + def distance(self): + """Return a weighted and normalized distance across all + penalties. + """ + dist_max = self.max_distance + if dist_max: + return self.raw_distance / self.max_distance + return 0.0 + + @property + def max_distance(self): + """Return the maximum distance penalty (normalization factor). + """ + dist_max = 0.0 + for key, penalty in self._penalties.iteritems(): + dist_max += len(penalty) * self._weights[key] + return dist_max + + @property + def raw_distance(self): + """Return the raw (denormalized) distance. + """ + dist_raw = 0.0 + for key, penalty in self._penalties.iteritems(): + dist_raw += sum(penalty) * self._weights[key] + return dist_raw + + def items(self): + """Return a list of (key, dist) pairs, with `dist` being the + weighted distance, sorted from highest to lowest. Does not + include penalties with a zero value. + """ + list_ = [] + for key in self._penalties: + dist = self[key] + if dist: + list_.append((key, dist)) + # Convert distance into a negative float we can sort items in + # ascending order (for keys, when the penalty is equal) and + # still get the items with the biggest distance first. + return sorted(list_, key=lambda (key, dist): (0-dist, key)) + + + # Behave like a float. + + def __cmp__(self, other): + return cmp(self.distance, other) + + def __float__(self): + return self.distance + def __sub__(self, other): + return self.distance - other + + def __rsub__(self, other): + return other - self.distance + + + # Behave like a dict. + + def __getitem__(self, key): + """Returns the weighted distance for a named penalty. + """ + dist = sum(self._penalties[key]) * self._weights[key] + dist_max = self.max_distance + if dist_max: + return dist / dist_max + return 0.0 + + def __iter__(self): + return iter(self.items()) + + def __len__(self): + return len(self.items()) + + def keys(self): + return [key for key, _ in self.items()] + + def update(self, dist): + """Adds all the distance penalties from `dist`. + """ + if not isinstance(dist, Distance): + raise ValueError( + '`dist` must be a Distance object. It is: %r' % dist) + for key, penalties in dist._penalties.iteritems(): + self._penalties.setdefault(key, []).extend(penalties) + + + # Adding components. + + def _eq(self, value1, value2): + """Returns True if `value1` is equal to `value2`. `value1` may + be a compiled regular expression, in which case it will be + matched against `value2`. + """ + if isinstance(value1, re._pattern_type): + return bool(value1.match(value2)) + return value1 == value2 + + def add(self, key, dist): + """Adds a distance penalty. `key` must correspond with a + configured weight setting. `dist` must be a float between 0.0 + and 1.0, and will be added to any existing distance penalties + for the same key. + """ + if not 0.0 <= dist <= 1.0: + raise ValueError( + '`dist` must be between 0.0 and 1.0. It is: %r' % dist) + self._penalties.setdefault(key, []).append(dist) + + def add_equality(self, key, value, options): + """Adds a distance penalty of 1.0 if `value` doesn't match any + of the values in `options`. If an option is a compiled regular + expression, it will be considered equal if it matches against + `value`. + """ + if not isinstance(options, (list, tuple)): + options = [options] + for opt in options: + if self._eq(opt, value): + dist = 0.0 + break + else: + dist = 1.0 + self.add(key, dist) + + def add_expr(self, key, expr): + """Adds a distance penalty of 1.0 if `expr` evaluates to True, + or 0.0. + """ + if expr: + self.add(key, 1.0) + else: + self.add(key, 0.0) + + def add_number(self, key, number1, number2): + """Adds a distance penalty of 1.0 for each number of difference + between `number1` and `number2`, or 0.0 when there is no + difference. Use this when there is no upper limit on the + difference between the two numbers. + """ + diff = abs(number1 - number2) + if diff: + for i in range(diff): + self.add(key, 1.0) + else: + self.add(key, 0.0) + + def add_priority(self, key, value, options): + """Adds a distance penalty that corresponds to the position at + which `value` appears in `options`. A distance penalty of 0.0 + for the first option, or 1.0 if there is no matching option. If + an option is a compiled regular expression, it will be + considered equal if it matches against `value`. + """ + if not isinstance(options, (list, tuple)): + options = [options] + unit = 1.0 / (len(options) or 1) + for i, opt in enumerate(options): + if self._eq(opt, value): + dist = i * unit + break + else: + dist = 1.0 + self.add(key, dist) + + def add_ratio(self, key, number1, number2): + """Adds a distance penalty for `number1` as a ratio of `number2`. + `number1` is bound at 0 and `number2`. + """ + number = float(max(min(number1, number2), 0)) + if number2: + dist = number / number2 + else: + dist = 0.0 + self.add(key, dist) + + def add_string(self, key, str1, str2): + """Adds a distance penalty based on the edit distance between + `str1` and `str2`. + """ + dist = string_dist(str1, str2) + self.add(key, dist) + + +# Structures that compose all the information for a candidate match. + +AlbumMatch = namedtuple('AlbumMatch', ['distance', 'info', 'mapping', + 'extra_items', 'extra_tracks']) + +TrackMatch = namedtuple('TrackMatch', ['distance', 'info']) + + +# Aggregation of sources. + +def album_for_mbid(release_id): + """Get an AlbumInfo object for a MusicBrainz release ID. Return None + if the ID is not found. + """ + try: + return mb.album_for_id(release_id) + except mb.MusicBrainzAPIError as exc: + exc.log(log) + +def track_for_mbid(recording_id): + """Get a TrackInfo object for a MusicBrainz recording ID. Return None + if the ID is not found. + """ + try: + return mb.track_for_id(recording_id) + except mb.MusicBrainzAPIError as exc: + exc.log(log) + +def albums_for_id(album_id): + """Get a list of albums for an ID.""" + candidates = [album_for_mbid(album_id)] + candidates.extend(plugins.album_for_id(album_id)) + return filter(None, candidates) + +def tracks_for_id(track_id): + """Get a list of tracks for an ID.""" + candidates = [track_for_mbid(track_id)] + candidates.extend(plugins.track_for_id(track_id)) + return filter(None, candidates) + +def album_candidates(items, artist, album, va_likely): + """Search for album matches. ``items`` is a list of Item objects + that make up the album. ``artist`` and ``album`` are the respective + names (strings), which may be derived from the item list or may be + entered by the user. ``va_likely`` is a boolean indicating whether + the album is likely to be a "various artists" release. + """ + out = [] + + # Base candidates if we have album and artist to match. + if artist and album: + try: + out.extend(mb.match_album(artist, album, len(items))) + except mb.MusicBrainzAPIError as exc: + exc.log(log) + + # Also add VA matches from MusicBrainz where appropriate. + if va_likely and album: + try: + out.extend(mb.match_album(None, album, len(items))) + except mb.MusicBrainzAPIError as exc: + exc.log(log) + + # Candidates from plugins. + out.extend(plugins.candidates(items, artist, album, va_likely)) + + return out + +def item_candidates(item, artist, title): + """Search for item matches. ``item`` is the Item to be matched. + ``artist`` and ``title`` are strings and either reflect the item or + are specified by the user. + """ + out = [] + + # MusicBrainz candidates. + if artist and title: + try: + out.extend(mb.match_track(artist, title)) + except mb.MusicBrainzAPIError as exc: + exc.log(log) + + # Plugin candidates. + out.extend(plugins.item_candidates(item, artist, title)) + + return out diff --git a/beets/autotag/match.py b/beets/autotag/match.py new file mode 100644 index 00000000..082a8c2f --- /dev/null +++ b/beets/autotag/match.py @@ -0,0 +1,456 @@ +# This file is part of beets. +# Copyright 2013, Adrian Sampson. +# +# 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. + +"""Matches existing metadata with canonical information to identify +releases and tracks. +""" +from __future__ import division + +import datetime +import logging +import re +from lib.munkres import Munkres + +from beets import plugins +from beets import config +from beets.util import plurality +from beets.util.enumeration import enum +from beets.autotag import hooks + +# Recommendation enumeration. +recommendation = enum('none', 'low', 'medium', 'strong', name='recommendation') + +# Artist signals that indicate "various artists". These are used at the +# album level to determine whether a given release is likely a VA +# release and also on the track level to to remove the penalty for +# differing artists. +VA_ARTISTS = (u'', u'various artists', u'various', u'va', u'unknown') + +# Global logger. +log = logging.getLogger('beets') + + +# Primary matching functionality. + +def current_metadata(items): + """Extract the likely current metadata for an album given a list of its + items. Return two dictionaries: + - The most common value for each field. + - Whether each field's value was unanimous (values are booleans). + """ + assert items # Must be nonempty. + + likelies = {} + consensus = {} + fields = ['artist', 'album', 'albumartist', 'year', 'disctotal', + 'mb_albumid', 'label', 'catalognum', 'country', 'media', + 'albumdisambig'] + for key in fields: + values = [getattr(item, key) for item in items if item] + likelies[key], freq = plurality(values) + consensus[key] = (freq == len(values)) + + # If there's an album artist consensus, use this for the artist. + if consensus['albumartist'] and likelies['albumartist']: + likelies['artist'] = likelies['albumartist'] + + return likelies, consensus + +def assign_items(items, tracks): + """Given a list of Items and a list of TrackInfo objects, find the + best mapping between them. Returns a mapping from Items to TrackInfo + objects, a set of extra Items, and a set of extra TrackInfo + objects. These "extra" objects occur when there is an unequal number + of objects of the two types. + """ + # Construct the cost matrix. + costs = [] + for item in items: + row = [] + for i, track in enumerate(tracks): + row.append(track_distance(item, track)) + costs.append(row) + + # Find a minimum-cost bipartite matching. + matching = Munkres().compute(costs) + + # Produce the output matching. + mapping = dict((items[i], tracks[j]) for (i, j) in matching) + extra_items = list(set(items) - set(mapping.keys())) + extra_items.sort(key=lambda i: (i.disc, i.track, i.title)) + extra_tracks = list(set(tracks) - set(mapping.values())) + extra_tracks.sort(key=lambda t: (t.index, t.title)) + return mapping, extra_items, extra_tracks + +def track_index_changed(item, track_info): + """Returns True if the item and track info index is different. Tolerates + per disc and per release numbering. + """ + return item.track not in (track_info.medium_index, track_info.index) + +def track_distance(item, track_info, incl_artist=False): + """Determines the significance of a track metadata change. Returns a + Distance object. `incl_artist` indicates that a distance component should + be included for the track artist (i.e., for various-artist releases). + """ + dist = hooks.Distance() + + # Length. + if track_info.length: + diff = abs(item.length - track_info.length) - \ + config['match']['track_length_grace'].as_number() + dist.add_ratio('track_length', diff, + config['match']['track_length_max'].as_number()) + + # Title. + dist.add_string('track_title', item.title, track_info.title) + + # Artist. Only check if there is actually an artist in the track data. + if incl_artist and track_info.artist and \ + item.artist.lower() not in VA_ARTISTS: + dist.add_string('track_artist', item.artist, track_info.artist) + + # Track index. + if track_info.index and item.track: + dist.add_expr('track_index', track_index_changed(item, track_info)) + + # Track ID. + if item.mb_trackid: + dist.add_expr('track_id', item.mb_trackid != track_info.track_id) + + # Plugins. + dist.update(plugins.track_distance(item, track_info)) + + return dist + +def distance(items, album_info, mapping): + """Determines how "significant" an album metadata change would be. + Returns a Distance object. `album_info` is an AlbumInfo object + reflecting the album to be compared. `items` is a sequence of all + Item objects that will be matched (order is not important). + `mapping` is a dictionary mapping Items to TrackInfo objects; the + keys are a subset of `items` and the values are a subset of + `album_info.tracks`. + """ + likelies, _ = current_metadata(items) + + dist = hooks.Distance() + + # Artist, if not various. + if not album_info.va: + dist.add_string('artist', likelies['artist'], album_info.artist) + + # Album. + dist.add_string('album', likelies['album'], album_info.album) + + # Current or preferred media. + if album_info.media: + # Preferred media options. + patterns = config['match']['preferred']['media'].as_str_seq() + options = [re.compile(r'(\d+x)?(%s)' % pat, re.I) for pat in patterns] + if options: + dist.add_priority('media', album_info.media, options) + # Current media. + elif likelies['media']: + dist.add_equality('media', album_info.media, likelies['media']) + + # Mediums. + if likelies['disctotal'] and album_info.mediums: + dist.add_number('mediums', likelies['disctotal'], album_info.mediums) + + # Prefer earliest release. + if album_info.year and config['match']['preferred']['original_year']: + # Assume 1889 (earliest first gramophone discs) if we don't know the + # original year. + original = album_info.original_year or 1889 + diff = abs(album_info.year - original) + diff_max = abs(datetime.date.today().year - original) + dist.add_ratio('year', diff, diff_max) + # Year. + elif likelies['year'] and album_info.year: + if likelies['year'] in (album_info.year, album_info.original_year): + # No penalty for matching release or original year. + dist.add('year', 0.0) + elif album_info.original_year: + # Prefer matchest closest to the release year. + diff = abs(likelies['year'] - album_info.year) + diff_max = abs(datetime.date.today().year - + album_info.original_year) + dist.add_ratio('year', diff, diff_max) + else: + # Full penalty when there is no original year. + dist.add('year', 1.0) + + # Preferred countries. + patterns = config['match']['preferred']['countries'].as_str_seq() + options = [re.compile(pat, re.I) for pat in patterns] + if album_info.country and options: + dist.add_priority('country', album_info.country, options) + # Country. + elif likelies['country'] and album_info.country: + dist.add_string('country', likelies['country'], album_info.country) + + # Label. + if likelies['label'] and album_info.label: + dist.add_string('label', likelies['label'], album_info.label) + + # Catalog number. + if likelies['catalognum'] and album_info.catalognum: + dist.add_string('catalognum', likelies['catalognum'], + album_info.catalognum) + + # Disambiguation. + if likelies['albumdisambig'] and album_info.albumdisambig: + dist.add_string('albumdisambig', likelies['albumdisambig'], + album_info.albumdisambig) + + # Album ID. + if likelies['mb_albumid']: + dist.add_equality('album_id', likelies['mb_albumid'], + album_info.album_id) + + # Tracks. + dist.tracks = {} + for item, track in mapping.iteritems(): + dist.tracks[track] = track_distance(item, track, album_info.va) + dist.add('tracks', dist.tracks[track].distance) + + # Missing tracks. + for i in range(len(album_info.tracks) - len(mapping)): + dist.add('missing_tracks', 1.0) + + # Unmatched tracks. + for i in range(len(items) - len(mapping)): + dist.add('unmatched_tracks', 1.0) + + # Plugins. + dist.update(plugins.album_distance(items, album_info, mapping)) + + return dist + +def match_by_id(items): + """If the items are tagged with a MusicBrainz album ID, returns an + AlbumInfo object for the corresponding album. Otherwise, returns + None. + """ + # Is there a consensus on the MB album ID? + albumids = [item.mb_albumid for item in items if item.mb_albumid] + if not albumids: + log.debug('No album IDs found.') + return None + + # If all album IDs are equal, look up the album. + if bool(reduce(lambda x,y: x if x==y else (), albumids)): + albumid = albumids[0] + log.debug('Searching for discovered album ID: ' + albumid) + return hooks.album_for_mbid(albumid) + else: + log.debug('No album ID consensus.') + +def _recommendation(results): + """Given a sorted list of AlbumMatch or TrackMatch objects, return a + recommendation based on the results' distances. + + If the recommendation is higher than the configured maximum for + an applied penalty, the recommendation will be downgraded to the + configured maximum for that penalty. + """ + if not results: + # No candidates: no recommendation. + return recommendation.none + + # Basic distance thresholding. + min_dist = results[0].distance + if min_dist < config['match']['strong_rec_thresh'].as_number(): + # Strong recommendation level. + rec = recommendation.strong + elif min_dist <= config['match']['medium_rec_thresh'].as_number(): + # Medium recommendation level. + rec = recommendation.medium + elif len(results) == 1: + # Only a single candidate. + rec = recommendation.low + elif results[1].distance - min_dist >= \ + config['match']['rec_gap_thresh'].as_number(): + # Gap between first two candidates is large. + rec = recommendation.low + else: + # No conclusion. Return immediately. Can't be downgraded any further. + return recommendation.none + + # Downgrade to the max rec if it is lower than the current rec for an + # applied penalty. + keys = set(min_dist.keys()) + if isinstance(results[0], hooks.AlbumMatch): + for track_dist in min_dist.tracks.values(): + keys.update(track_dist.keys()) + max_rec_view = config['match']['max_rec'] + for key in keys: + if key in max_rec_view.keys(): + max_rec = max_rec_view[key].as_choice({ + 'strong': recommendation.strong, + 'medium': recommendation.medium, + 'low': recommendation.low, + 'none': recommendation.none, + }) + rec = min(rec, max_rec) + + return rec + +def _add_candidate(items, results, info): + """Given a candidate AlbumInfo object, attempt to add the candidate + to the output dictionary of AlbumMatch objects. This involves + checking the track count, ordering the items, checking for + duplicates, and calculating the distance. + """ + log.debug('Candidate: %s - %s' % (info.artist, info.album)) + + # Don't duplicate. + if info.album_id in results: + log.debug('Duplicate.') + return + + # Find mapping between the items and the track info. + mapping, extra_items, extra_tracks = assign_items(items, info.tracks) + + # Get the change distance. + dist = distance(items, info, mapping) + + # Skip matches with ignored penalties. + penalties = [key for _, key in dist] + for penalty in config['match']['ignored'].as_str_seq(): + if penalty in penalties: + log.debug('Ignored. Penalty: %s' % penalty) + return + + log.debug('Success. Distance: %f' % dist) + results[info.album_id] = hooks.AlbumMatch(dist, info, mapping, + extra_items, extra_tracks) + +def tag_album(items, search_artist=None, search_album=None, + search_id=None): + """Bundles together the functionality used to infer tags for a + set of items comprised by an album. Returns everything relevant: + - The current artist. + - The current album. + - A list of AlbumMatch objects. The candidates are sorted by + distance (i.e., best match first). + - A recommendation. + If search_artist and search_album or search_id are provided, then + they are used as search terms in place of the current metadata. + """ + # Get current metadata. + likelies, consensus = current_metadata(items) + cur_artist = likelies['artist'] + cur_album = likelies['album'] + log.debug('Tagging %s - %s' % (cur_artist, cur_album)) + + # The output result (distance, AlbumInfo) tuples (keyed by MB album + # ID). + candidates = {} + + # Search by explicit ID. + if search_id is not None: + log.debug('Searching for album ID: ' + search_id) + search_cands = hooks.albums_for_id(search_id) + + # Use existing metadata or text search. + else: + # Try search based on current ID. + id_info = match_by_id(items) + if id_info: + _add_candidate(items, candidates, id_info) + rec = _recommendation(candidates.values()) + log.debug('Album ID match recommendation is ' + str(rec)) + if candidates and not config['import']['timid']: + # If we have a very good MBID match, return immediately. + # Otherwise, this match will compete against metadata-based + # matches. + if rec == recommendation.strong: + log.debug('ID match.') + return cur_artist, cur_album, candidates.values(), rec + + # Search terms. + if not (search_artist and search_album): + # No explicit search terms -- use current metadata. + search_artist, search_album = cur_artist, cur_album + log.debug(u'Search terms: %s - %s' % (search_artist, search_album)) + + # Is this album likely to be a "various artist" release? + va_likely = ((not consensus['artist']) or + (search_artist.lower() in VA_ARTISTS) or + any(item.comp for item in items)) + log.debug(u'Album might be VA: %s' % str(va_likely)) + + # Get the results from the data sources. + search_cands = hooks.album_candidates(items, search_artist, + search_album, va_likely) + + log.debug(u'Evaluating %i candidates.' % len(search_cands)) + for info in search_cands: + _add_candidate(items, candidates, info) + + # Sort and get the recommendation. + candidates = sorted(candidates.itervalues()) + rec = _recommendation(candidates) + return cur_artist, cur_album, candidates, rec + +def tag_item(item, search_artist=None, search_title=None, + search_id=None): + """Attempts to find metadata for a single track. Returns a + `(candidates, recommendation)` pair where `candidates` is a list of + TrackMatch objects. `search_artist` and `search_title` may be used + to override the current metadata for the purposes of the MusicBrainz + title; likewise `search_id`. + """ + # Holds candidates found so far: keys are MBIDs; values are + # (distance, TrackInfo) pairs. + candidates = {} + + # First, try matching by MusicBrainz ID. + trackid = search_id or item.mb_trackid + if trackid: + log.debug('Searching for track ID: ' + trackid) + for track_info in hooks.tracks_for_id(trackid): + dist = track_distance(item, track_info, incl_artist=True) + candidates[track_info.track_id] = \ + hooks.TrackMatch(dist, track_info) + # If this is a good match, then don't keep searching. + rec = _recommendation(candidates.values()) + if rec == recommendation.strong and not config['import']['timid']: + log.debug('Track ID match.') + return candidates.values(), rec + + # If we're searching by ID, don't proceed. + if search_id is not None: + if candidates: + return candidates.values(), rec + else: + return [], recommendation.none + + # Search terms. + if not (search_artist and search_title): + search_artist, search_title = item.artist, item.title + log.debug(u'Item search terms: %s - %s' % (search_artist, search_title)) + + # Get and evaluate candidate metadata. + for track_info in hooks.item_candidates(item, search_artist, search_title): + dist = track_distance(item, track_info, incl_artist=True) + candidates[track_info.track_id] = hooks.TrackMatch(dist, track_info) + + # Sort by distance and return with recommendation. + log.debug('Found %i candidates.' % len(candidates)) + candidates = sorted(candidates.itervalues()) + rec = _recommendation(candidates) + return candidates, rec diff --git a/lib/beets/autotag/mb.py b/beets/autotag/mb.py similarity index 61% rename from lib/beets/autotag/mb.py rename to beets/autotag/mb.py index b5ad589f..779ec4b3 100644 --- a/lib/beets/autotag/mb.py +++ b/beets/autotag/mb.py @@ -1,5 +1,5 @@ # This file is part of beets. -# Copyright 2012, Adrian Sampson. +# Copyright 2013, Adrian Sampson. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -15,17 +15,21 @@ """Searches for albums in the MusicBrainz database. """ import logging -import lib.musicbrainzngs as musicbrainzngs +import musicbrainzngs +import re import traceback +from urlparse import urljoin -import lib.beets.autotag.hooks -import lib.beets -from lib.beets import util +import beets.autotag.hooks +import beets +from beets import util +from beets import config SEARCH_LIMIT = 5 VARIOUS_ARTISTS_ID = '89ad4ac3-39f7-470e-963a-56509c546377' +BASE_URL = 'http://musicbrainz.org/' -musicbrainzngs.set_useragent('beets', lib.beets.__version__, +musicbrainzngs.set_useragent('beets', beets.__version__, 'http://beets.radbox.org/') class MusicBrainzAPIError(util.HumanReadableException): @@ -44,18 +48,45 @@ class MusicBrainzAPIError(util.HumanReadableException): log = logging.getLogger('beets') RELEASE_INCLUDES = ['artists', 'media', 'recordings', 'release-groups', - 'labels', 'artist-credits'] -TRACK_INCLUDES = ['artists'] + 'labels', 'artist-credits', 'aliases'] +TRACK_INCLUDES = ['artists', 'aliases'] -# python-musicbrainz-ngs search functions: tolerate different API versions. -if hasattr(musicbrainzngs, 'release_search'): - # Old API names. - _mb_release_search = musicbrainzngs.release_search - _mb_recording_search = musicbrainzngs.recording_search -else: - # New API names. - _mb_release_search = musicbrainzngs.search_releases - _mb_recording_search = musicbrainzngs.search_recordings +def track_url(trackid): + return urljoin(BASE_URL, 'recording/' + trackid) + +def album_url(albumid): + return urljoin(BASE_URL, 'release/' + albumid) + +def configure(): + """Set up the python-musicbrainz-ngs module according to settings + from the beets configuration. This should be called at startup. + """ + musicbrainzngs.set_hostname(config['musicbrainz']['host'].get(unicode)) + musicbrainzngs.set_rate_limit( + config['musicbrainz']['ratelimit_interval'].as_number(), + config['musicbrainz']['ratelimit'].get(int), + ) + +def _preferred_alias(aliases): + """Given an list of alias structures for an artist credit, select + and return the user's preferred alias alias or None if no matching + alias is found. + """ + if not aliases: + return + + # Only consider aliases that have locales set. + aliases = [a for a in aliases if 'locale' in a] + + # Search configured locales in order. + for locale in config['import']['languages'].as_str_seq(): + # Find matching primary aliases for this locale. + matches = [a for a in aliases if a['locale'] == locale and 'primary' in a] + # Skip to the next locale if we have no matches + if not matches: + continue + + return matches[0] def _flatten_artist_credit(credit): """Given a list representing an ``artist-credit`` block, flatten the @@ -73,12 +104,19 @@ def _flatten_artist_credit(credit): artist_sort_parts.append(el) else: + alias = _preferred_alias(el['artist'].get('alias-list', ())) + # An artist. - cur_artist_name = el['artist']['name'] + if alias: + cur_artist_name = alias['alias'] + else: + cur_artist_name = el['artist']['name'] artist_parts.append(cur_artist_name) # Artist sort name. - if 'sort-name' in el['artist']: + if alias: + artist_sort_parts.append(alias['sort-name']) + elif 'sort-name' in el['artist']: artist_sort_parts.append(el['artist']['sort-name']) else: artist_sort_parts.append(cur_artist_name) @@ -95,19 +133,24 @@ def _flatten_artist_credit(credit): ''.join(artist_credit_parts), ) -def track_info(recording, index=None, medium=None, medium_index=None): +def track_info(recording, index=None, medium=None, medium_index=None, + medium_total=None): """Translates a MusicBrainz recording result dictionary into a beets ``TrackInfo`` object. Three parameters are optional and are used only for tracks that appear on releases (non-singletons): ``index``, the overall track number; ``medium``, the disc number; - ``medium_index``, the track's index on its medium. Each number is a - 1-based index. + ``medium_index``, the track's index on its medium; ``medium_total``, + the number of tracks on the medium. Each number is a 1-based index. """ - info = lib.beets.autotag.hooks.TrackInfo(recording['title'], - recording['id'], - index=index, - medium=medium, - medium_index=medium_index) + info = beets.autotag.hooks.TrackInfo( + recording['title'], + recording['id'], + index=index, + medium=medium, + medium_index=medium_index, + medium_total=medium_total, + data_url=track_url(recording['id']), + ) if recording.get('artist-credit'): # Get the artist names. @@ -119,19 +162,29 @@ def track_info(recording, index=None, medium=None, medium_index=None): info.artist_id = artist['id'] if recording.get('length'): - info.length = int(recording['length'])/(1000.0) + info.length = int(recording['length']) / (1000.0) + info.decode() return info -def _set_date_str(info, date_str): +def _set_date_str(info, date_str, original=False): """Given a (possibly partial) YYYY-MM-DD string and an AlbumInfo - object, set the object's release date fields appropriately. + object, set the object's release date fields appropriately. If + `original`, then set the original_year, etc., fields. """ if date_str: date_parts = date_str.split('-') for key in ('year', 'month', 'day'): if date_parts: - setattr(info, key, int(date_parts.pop(0))) + date_part = date_parts.pop(0) + try: + date_num = int(date_part) + except ValueError: + continue + + if original: + key = 'original_' + key + setattr(info, key, date_num) def album_info(release): """Takes a MusicBrainz release result dictionary and returns a beets @@ -147,18 +200,31 @@ def album_info(release): for medium in release['medium-list']: disctitle = medium.get('title') for track in medium['track-list']: + # Basic information from the recording. index += 1 - ti = track_info(track['recording'], - index, - int(medium['position']), - int(track['position'])) - if track.get('title'): - # Track title may be distinct from underling recording - # title. - ti.title = track['title'] + ti = track_info( + track['recording'], + index, + int(medium['position']), + int(track['position']), + len(medium['track-list']), + ) ti.disctitle = disctitle + + # Prefer track data, where present, over recording data. + if track.get('title'): + ti.title = track['title'] + if track.get('artist-credit'): + # Get the artist names. + ti.artist, ti.artist_sort, ti.artist_credit = \ + _flatten_artist_credit(track['artist-credit']) + ti.artist_id = track['artist-credit'][0]['artist']['id'] + if track.get('length'): + ti.length = int(track['length']) / (1000.0) + track_infos.append(ti) - info = lib.beets.autotag.hooks.AlbumInfo( + + info = beets.autotag.hooks.AlbumInfo( release['title'], release['id'], artist_name, @@ -167,27 +233,37 @@ def album_info(release): mediums=len(release['medium-list']), artist_sort=artist_sort_name, artist_credit=artist_credit_name, + data_source='MusicBrainz', + data_url=album_url(release['id']), ) info.va = info.artist_id == VARIOUS_ARTISTS_ID info.asin = release.get('asin') info.releasegroup_id = release['release-group']['id'] - info.albumdisambig = release['release-group'].get('disambiguation') info.country = release.get('country') info.albumstatus = release.get('status') + # Build up the disambiguation string from the release group and release. + disambig = [] + if release['release-group'].get('disambiguation'): + disambig.append(release['release-group'].get('disambiguation')) + if release.get('disambiguation'): + disambig.append(release.get('disambiguation')) + info.albumdisambig = u', '.join(disambig) + # Release type not always populated. if 'type' in release['release-group']: reltype = release['release-group']['type'] if reltype: info.albumtype = reltype.lower() - # Release date. - if 'first-release-date' in release['release-group']: - # Try earliest release date for the entire group first. - _set_date_str(info, release['release-group']['first-release-date']) - elif 'date' in release: - # Fall back to release-specific date. - _set_date_str(info, release['date']) + # Release dates. + release_date = release.get('date') + release_group_date = release['release-group'].get('first-release-date') + if not release_date: + # Fall back if release-specific date is not available. + release_date = release_group_date + _set_date_str(info, release_date, False) + _set_date_str(info, release_group_date, True) # Label name. if release.get('label-info-list'): @@ -209,6 +285,7 @@ def album_info(release): first_medium = release['medium-list'][0] info.media = first_medium.get('format') + info.decode() return info def match_album(artist, album, tracks=None, limit=SEARCH_LIMIT): @@ -234,7 +311,7 @@ def match_album(artist, album, tracks=None, limit=SEARCH_LIMIT): return try: - res = _mb_release_search(limit=limit, **criteria) + res = musicbrainzngs.search_releases(limit=limit, **criteria) except musicbrainzngs.MusicBrainzError as exc: raise MusicBrainzAPIError(exc, 'release search', criteria, traceback.format_exc()) @@ -242,8 +319,8 @@ def match_album(artist, album, tracks=None, limit=SEARCH_LIMIT): # The search result is missing some data (namely, the tracks), # so we just use the ID and fetch the rest of the information. albuminfo = album_for_id(release['id']) - assert albuminfo is not None - yield albuminfo + if albuminfo is not None: + yield albuminfo def match_track(artist, title, limit=SEARCH_LIMIT): """Searches for a single track and returns an iterable of TrackInfo @@ -258,20 +335,34 @@ def match_track(artist, title, limit=SEARCH_LIMIT): return try: - res = _mb_recording_search(limit=limit, **criteria) + res = musicbrainzngs.search_recordings(limit=limit, **criteria) except musicbrainzngs.MusicBrainzError as exc: raise MusicBrainzAPIError(exc, 'recording search', criteria, traceback.format_exc()) for recording in res['recording-list']: yield track_info(recording) +def _parse_id(s): + """Search for a MusicBrainz ID in the given string and return it. If + no ID can be found, return None. + """ + # Find the first thing that looks like a UUID/MBID. + match = re.search('[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}', s) + if match: + return match.group() + def album_for_id(albumid): """Fetches an album by its MusicBrainz ID and returns an AlbumInfo object or None if the album is not found. May raise a MusicBrainzAPIError. """ + albumid = _parse_id(albumid) + if not albumid: + log.error('Invalid MBID.') + return try: - res = musicbrainzngs.get_release_by_id(albumid, RELEASE_INCLUDES) + res = musicbrainzngs.get_release_by_id(albumid, + RELEASE_INCLUDES) except musicbrainzngs.ResponseError: log.debug('Album ID match failed.') return None @@ -284,6 +375,10 @@ def track_for_id(trackid): """Fetches a track by its MusicBrainz ID. Returns a TrackInfo object or None if no track is found. May raise a MusicBrainzAPIError. """ + trackid = _parse_id(trackid) + if not trackid: + log.error('Invalid MBID.') + return try: res = musicbrainzngs.get_recording_by_id(trackid, TRACK_INCLUDES) except musicbrainzngs.ResponseError: diff --git a/beets/config_default.yaml b/beets/config_default.yaml new file mode 100644 index 00000000..d35368ea --- /dev/null +++ b/beets/config_default.yaml @@ -0,0 +1,102 @@ +library: library.db +directory: ~/Music + +import: + write: yes + copy: yes + move: no + delete: no + resume: ask + incremental: no + quiet_fallback: skip + none_rec_action: ask + timid: no + log: + autotag: yes + quiet: no + singletons: no + default_action: apply + languages: [] + detail: no + flat: no + group_albums: no + +clutter: ["Thumbs.DB", ".DS_Store"] +ignore: [".*", "*~", "System Volume Information"] +replace: + '[\\/]': _ + '^\.': _ + '[\x00-\x1f]': _ + '[<>:"\?\*\|]': _ + '\.$': _ + '\s+$': '' + '^\s+': '' +path_sep_replace: _ +art_filename: cover +max_filename_length: 0 + +plugins: [] +pluginpath: [] +threaded: yes +color: yes +timeout: 5.0 +per_disc_numbering: no +verbose: no +terminal_encoding: utf8 +original_date: no +id3v23: no + +ui: + terminal_width: 80 + length_diff_thresh: 10.0 + +list_format_item: $artist - $album - $title +list_format_album: $albumartist - $album +time_format: '%Y-%m-%d %H:%M:%S' + +paths: + default: $albumartist/$album%aunique{}/$track $title + singleton: Non-Album/$artist/$title + comp: Compilations/$album%aunique{}/$track $title + +statefile: state.pickle + +musicbrainz: + host: musicbrainz.org + ratelimit: 1 + ratelimit_interval: 1.0 + +match: + strong_rec_thresh: 0.04 + medium_rec_thresh: 0.25 + rec_gap_thresh: 0.25 + max_rec: + missing_tracks: medium + unmatched_tracks: medium + distance_weights: + source: 2.0 + artist: 3.0 + album: 3.0 + media: 1.0 + mediums: 1.0 + year: 1.0 + country: 0.5 + label: 0.5 + catalognum: 0.5 + albumdisambig: 0.5 + album_id: 5.0 + tracks: 2.0 + missing_tracks: 0.9 + unmatched_tracks: 0.6 + track_title: 3.0 + track_artist: 2.0 + track_index: 1.0 + track_length: 2.0 + track_id: 5.0 + preferred: + countries: [] + media: [] + original_year: no + ignored: [] + track_length_grace: 10 + track_length_max: 30 diff --git a/beets/dbcore/__init__.py b/beets/dbcore/__init__.py new file mode 100644 index 00000000..b4f80fb9 --- /dev/null +++ b/beets/dbcore/__init__.py @@ -0,0 +1,20 @@ +# This file is part of beets. +# Copyright 2014, Adrian Sampson. +# +# 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. + +"""DBCore is an abstract database package that forms the basis for beets' +Library. +""" +from .db import Model, Database +from .query import Query, FieldQuery, MatchQuery, AndQuery, OrQuery +from .types import Type diff --git a/beets/dbcore/db.py b/beets/dbcore/db.py new file mode 100644 index 00000000..cbdaf5a7 --- /dev/null +++ b/beets/dbcore/db.py @@ -0,0 +1,727 @@ +# This file is part of beets. +# Copyright 2014, Adrian Sampson. +# +# 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 central Model and Database constructs for DBCore. +""" +import time +import os +from collections import defaultdict +import threading +import sqlite3 +import contextlib + +import beets +from beets.util.functemplate import Template +from .query import MatchQuery + + + +# Abstract base for model classes. + + +class Model(object): + """An abstract object representing an object in the database. Model + objects act like dictionaries (i.e., the allow subscript access like + ``obj['field']``). The same field set is available via attribute + access as a shortcut (i.e., ``obj.field``). Three kinds of attributes are + available: + + * **Fixed attributes** come from a predetermined list of field + names. These fields correspond to SQLite table columns and are + thus fast to read, write, and query. + * **Flexible attributes** are free-form and do not need to be listed + ahead of time. + * **Computed attributes** are read-only fields computed by a getter + function provided by a plugin. + + Access to all three field types is uniform: ``obj.field`` works the + same regardless of whether ``field`` is fixed, flexible, or + computed. + + Model objects can optionally be associated with a `Library` object, + in which case they can be loaded and stored from the database. Dirty + flags are used to track which fields need to be stored. + """ + + # Abstract components (to be provided by subclasses). + + _table = None + """The main SQLite table name. + """ + + _flex_table = None + """The flex field SQLite table name. + """ + + _fields = {} + """A mapping indicating available "fixed" fields on this type. The + keys are field names and the values are Type objects. + """ + + _bytes_keys = () + """Keys whose values should be stored as raw bytes blobs rather than + strings. + """ + + _search_fields = () + """The fields that should be queried by default by unqualified query + terms. + """ + + @classmethod + def _getters(cls): + """Return a mapping from field names to getter functions. + """ + # We could cache this if it becomes a performance problem to + # gather the getter mapping every time. + raise NotImplementedError() + + def _template_funcs(self): + """Return a mapping from function names to text-transformer + functions. + """ + # As above: we could consider caching this result. + raise NotImplementedError() + + + # Basic operation. + + def __init__(self, db=None, **values): + """Create a new object with an optional Database association and + initial field values. + """ + self._db = db + self._dirty = set() + self._values_fixed = {} + self._values_flex = {} + + # Initial contents. + self.update(values) + self.clear_dirty() + + def __repr__(self): + return '{0}({1})'.format( + type(self).__name__, + ', '.join('{0}={1!r}'.format(k, v) for k, v in dict(self).items()), + ) + + def clear_dirty(self): + """Mark all fields as *clean* (i.e., not needing to be stored to + the database). + """ + self._dirty = set() + + def _check_db(self, need_id=True): + """Ensure that this object is associated with a database row: it + has a reference to a database (`_db`) and an id. A ValueError + exception is raised otherwise. + """ + if not self._db: + raise ValueError('{0} has no database'.format(type(self).__name__)) + if need_id and not self.id: + raise ValueError('{0} has no id'.format(type(self).__name__)) + + + # Essential field accessors. + + def __getitem__(self, key): + """Get the value for a field. Raise a KeyError if the field is + not available. + """ + getters = self._getters() + if key in getters: # Computed. + return getters[key](self) + elif key in self._fields: # Fixed. + return self._values_fixed.get(key) + elif key in self._values_flex: # Flexible. + return self._values_flex[key] + else: + raise KeyError(key) + + def __setitem__(self, key, value): + """Assign the value for a field. + """ + source = self._values_fixed if key in self._fields \ + else self._values_flex + old_value = source.get(key) + source[key] = value + if old_value != value: + self._dirty.add(key) + + def __delitem__(self, key): + """Remove a flexible attribute from the model. + """ + if key in self._values_flex: # Flexible. + del self._values_flex[key] + self._dirty.add(key) # Mark for dropping on store. + elif key in self._getters(): # Computed. + raise KeyError('computed field {0} cannot be deleted'.format(key)) + elif key in self._fields: # Fixed. + raise KeyError('fixed field {0} cannot be deleted'.format(key)) + else: + raise KeyError('no such field {0}'.format(key)) + + def keys(self, computed=False): + """Get a list of available field names for this object. The + `computed` parameter controls whether computed (plugin-provided) + fields are included in the key list. + """ + base_keys = list(self._fields) + self._values_flex.keys() + if computed: + return base_keys + self._getters().keys() + else: + return base_keys + + + # Act like a dictionary. + + def update(self, values): + """Assign all values in the given dict. + """ + for key, value in values.items(): + self[key] = value + + def items(self): + """Iterate over (key, value) pairs that this object contains. + Computed fields are not included. + """ + for key in self: + yield key, self[key] + + def get(self, key, default=None): + """Get the value for a given key or `default` if it does not + exist. + """ + if key in self: + return self[key] + else: + return default + + def __contains__(self, key): + """Determine whether `key` is an attribute on this object. + """ + return key in self.keys(True) + + def __iter__(self): + """Iterate over the available field names (excluding computed + fields). + """ + return iter(self.keys()) + + + # Convenient attribute access. + + def __getattr__(self, key): + if key.startswith('_'): + raise AttributeError('model has no attribute {0!r}'.format(key)) + else: + try: + return self[key] + except KeyError: + raise AttributeError('no such field {0!r}'.format(key)) + + def __setattr__(self, key, value): + if key.startswith('_'): + super(Model, self).__setattr__(key, value) + else: + self[key] = value + + def __delattr__(self, key): + if key.startswith('_'): + super(Model, self).__delattr__(key) + else: + del self[key] + + + # Database interaction (CRUD methods). + + def store(self): + """Save the object's metadata into the library database. + """ + self._check_db() + + # Build assignments for query. + assignments = '' + subvars = [] + for key in self._fields: + if key != 'id' and key in self._dirty: + self._dirty.remove(key) + assignments += key + '=?,' + value = self[key] + # Wrap path strings in buffers so they get stored + # "in the raw". + if key in self._bytes_keys and isinstance(value, str): + value = buffer(value) + subvars.append(value) + assignments = assignments[:-1] # Knock off last , + + with self._db.transaction() as tx: + # Main table update. + if assignments: + query = 'UPDATE {0} SET {1} WHERE id=?'.format( + self._table, assignments + ) + subvars.append(self.id) + tx.mutate(query, subvars) + + # Modified/added flexible attributes. + for key, value in self._values_flex.items(): + if key in self._dirty: + self._dirty.remove(key) + tx.mutate( + 'INSERT INTO {0} ' + '(entity_id, key, value) ' + 'VALUES (?, ?, ?);'.format(self._flex_table), + (self.id, key, value), + ) + + # Deleted flexible attributes. + for key in self._dirty: + tx.mutate( + 'DELETE FROM {0} ' + 'WHERE entity_id=? AND key=?'.format(self._flex_table), + (self.id, key) + ) + + self.clear_dirty() + + def load(self): + """Refresh the object's metadata from the library database. + """ + self._check_db() + stored_obj = self._db._get(type(self), self.id) + assert stored_obj is not None, "object {0} not in DB".format(self.id) + self.update(dict(stored_obj)) + self.clear_dirty() + + def remove(self): + """Remove the object's associated rows from the database. + """ + self._check_db() + with self._db.transaction() as tx: + tx.mutate( + 'DELETE FROM {0} WHERE id=?'.format(self._table), + (self.id,) + ) + tx.mutate( + 'DELETE FROM {0} WHERE entity_id=?'.format(self._flex_table), + (self.id,) + ) + + def add(self, db=None): + """Add the object to the library database. This object must be + associated with a database; you can provide one via the `db` + parameter or use the currently associated database. + + The object's `id` and `added` fields are set along with any + current field values. + """ + if db: + self._db = db + self._check_db(False) + + with self._db.transaction() as tx: + new_id = tx.mutate( + 'INSERT INTO {0} DEFAULT VALUES'.format(self._table) + ) + self.id = new_id + self.added = time.time() + + # Mark every non-null field as dirty and store. + for key in self: + if self[key] is not None: + self._dirty.add(key) + self.store() + + + # Formatting and templating. + + @classmethod + def _format(cls, key, value, for_path=False): + """Format a value as the given field for this model. + """ + # Format the value as a string according to its type, if any. + if key in cls._fields: + value = cls._fields[key].format(value) + # Formatting must result in a string. To deal with + # Python2isms, implicitly convert ASCII strings. + assert isinstance(value, basestring), \ + u'field formatter must produce strings' + if isinstance(value, bytes): + value = value.decode('utf8', 'ignore') + + elif not isinstance(value, unicode): + # Fallback formatter. Convert to unicode at all cost. + if value is None: + value = u'' + elif isinstance(value, basestring): + if isinstance(value, bytes): + value = value.decode('utf8', 'ignore') + else: + value = unicode(value) + + if for_path: + sep_repl = beets.config['path_sep_replace'].get(unicode) + for sep in (os.path.sep, os.path.altsep): + if sep: + value = value.replace(sep, sep_repl) + + return value + + def _get_formatted(self, key, for_path=False): + """Get a field value formatted as a string (`unicode` object) + for display to the user. If `for_path` is true, then the value + will be sanitized for inclusion in a pathname (i.e., path + separators will be removed from the value). + """ + return self._format(key, self.get(key), for_path) + + def _formatted_mapping(self, for_path=False): + """Get a mapping containing all values on this object formatted + as human-readable strings. + """ + # In the future, this could be made "lazy" to avoid computing + # fields unnecessarily. + out = {} + for key in self.keys(True): + out[key] = self._get_formatted(key, for_path) + return out + + def evaluate_template(self, template, for_path=False): + """Evaluate a template (a string or a `Template` object) using + the object's fields. If `for_path` is true, then no new path + separators will be added to the template. + """ + # Build value mapping. + mapping = self._formatted_mapping(for_path) + + # Get template functions. + funcs = self._template_funcs() + + # Perform substitution. + if isinstance(template, basestring): + template = Template(template) + return template.substitute(mapping, funcs) + + + # Parsing. + + @classmethod + def _parse(cls, key, string): + """Parse a string as a value for the given key. + """ + if not isinstance(string, basestring): + raise TypeError("_parse() argument must be a string") + + typ = cls._fields.get(key) + if typ: + return typ.parse(string) + else: + # Fall back to unparsed string. + return string + + + +# Database controller and supporting interfaces. + + +class Results(object): + """An item query result set. Iterating over the collection lazily + constructs LibModel objects that reflect database rows. + """ + def __init__(self, model_class, rows, db, query=None): + """Create a result set that will construct objects of type + `model_class`, which should be a subclass of `LibModel`, out of + the query result mapping in `rows`. The new objects are + associated with the database `db`. If `query` is provided, it is + used as a predicate to filter the results for a "slow query" that + cannot be evaluated by the database directly. + """ + self.model_class = model_class + self.rows = rows + self.db = db + self.query = query + + def __iter__(self): + """Construct Python objects for all rows that pass the query + predicate. + """ + for row in self.rows: + # Get the flexible attributes for the object. + with self.db.transaction() as tx: + flex_rows = tx.query( + 'SELECT * FROM {0} WHERE entity_id=?'.format( + self.model_class._flex_table + ), + (row['id'],) + ) + values = dict(row) + values.update( + dict((row['key'], row['value']) for row in flex_rows) + ) + + # Construct the Python object and yield it if it passes the + # predicate. + obj = self.model_class(self.db, **values) + if not self.query or self.query.match(obj): + yield obj + + def __len__(self): + """Get the number of matching objects. + """ + if self.query: + # A slow query. Fall back to testing every object. + count = 0 + for obj in self: + count += 1 + return count + + else: + # A fast query. Just count the rows. + return len(self.rows) + + def __nonzero__(self): + """Does this result contain any objects? + """ + return bool(len(self)) + + def __getitem__(self, n): + """Get the nth item in this result set. This is inefficient: all + items up to n are materialized and thrown away. + """ + it = iter(self) + try: + for i in range(n): + it.next() + return it.next() + except StopIteration: + raise IndexError('result index {0} out of range'.format(n)) + + def get(self): + """Return the first matching object, or None if no objects + match. + """ + it = iter(self) + try: + return it.next() + except StopIteration: + return None + + +class Transaction(object): + """A context manager for safe, concurrent access to the database. + All SQL commands should be executed through a transaction. + """ + def __init__(self, db): + self.db = db + + def __enter__(self): + """Begin a transaction. This transaction may be created while + another is active in a different thread. + """ + with self.db._tx_stack() as stack: + first = not stack + stack.append(self) + if first: + # Beginning a "root" transaction, which corresponds to an + # SQLite transaction. + self.db._db_lock.acquire() + return self + + def __exit__(self, exc_type, exc_value, traceback): + """Complete a transaction. This must be the most recently + entered but not yet exited transaction. If it is the last active + transaction, the database updates are committed. + """ + with self.db._tx_stack() as stack: + assert stack.pop() is self + empty = not stack + if empty: + # Ending a "root" transaction. End the SQLite transaction. + self.db._connection().commit() + self.db._db_lock.release() + + def query(self, statement, subvals=()): + """Execute an SQL statement with substitution values and return + a list of rows from the database. + """ + cursor = self.db._connection().execute(statement, subvals) + return cursor.fetchall() + + def mutate(self, statement, subvals=()): + """Execute an SQL statement with substitution values and return + the row ID of the last affected row. + """ + cursor = self.db._connection().execute(statement, subvals) + return cursor.lastrowid + + def script(self, statements): + """Execute a string containing multiple SQL statements.""" + self.db._connection().executescript(statements) + + +class Database(object): + """A container for Model objects that wraps an SQLite database as + the backend. + """ + _models = () + """The Model subclasses representing tables in this database. + """ + + def __init__(self, path): + self.path = path + + self._connections = {} + self._tx_stacks = defaultdict(list) + + # A lock to protect the _connections and _tx_stacks maps, which + # both map thread IDs to private resources. + self._shared_map_lock = threading.Lock() + + # A lock to protect access to the database itself. SQLite does + # allow multiple threads to access the database at the same + # time, but many users were experiencing crashes related to this + # capability: where SQLite was compiled without HAVE_USLEEP, its + # backoff algorithm in the case of contention was causing + # whole-second sleeps (!) that would trigger its internal + # timeout. Using this lock ensures only one SQLite transaction + # is active at a time. + self._db_lock = threading.Lock() + + # Set up database schema. + for model_cls in self._models: + self._make_table(model_cls._table, model_cls._fields) + self._make_attribute_table(model_cls._flex_table) + + + # Primitive access control: connections and transactions. + + def _connection(self): + """Get a SQLite connection object to the underlying database. + One connection object is created per thread. + """ + thread_id = threading.current_thread().ident + with self._shared_map_lock: + if thread_id in self._connections: + return self._connections[thread_id] + else: + # Make a new connection. + conn = sqlite3.connect( + self.path, + timeout=beets.config['timeout'].as_number(), + ) + + # Access SELECT results like dictionaries. + conn.row_factory = sqlite3.Row + + self._connections[thread_id] = conn + return conn + + @contextlib.contextmanager + def _tx_stack(self): + """A context manager providing access to the current thread's + transaction stack. The context manager synchronizes access to + the stack map. Transactions should never migrate across threads. + """ + thread_id = threading.current_thread().ident + with self._shared_map_lock: + yield self._tx_stacks[thread_id] + + def transaction(self): + """Get a :class:`Transaction` object for interacting directly + with the underlying SQLite database. + """ + return Transaction(self) + + + # Schema setup and migration. + + def _make_table(self, table, fields): + """Set up the schema of the database. `fields` is a mapping + from field names to `Type`s. Columns are added if necessary. + """ + # Get current schema. + with self.transaction() as tx: + rows = tx.query('PRAGMA table_info(%s)' % table) + current_fields = set([row[1] for row in rows]) + + field_names = set(fields.keys()) + if current_fields.issuperset(field_names): + # Table exists and has all the required columns. + return + + if not current_fields: + # No table exists. + columns = [] + for name, typ in fields.items(): + columns.append('{0} {1}'.format(name, typ.sql)) + setup_sql = 'CREATE TABLE {0} ({1});\n'.format(table, + ', '.join(columns)) + + else: + # Table exists does not match the field set. + setup_sql = '' + for name, typ in fields.items(): + if name in current_fields: + continue + setup_sql += 'ALTER TABLE {0} ADD COLUMN {1} {2};\n'.format( + table, name, typ.sql + ) + + with self.transaction() as tx: + tx.script(setup_sql) + + def _make_attribute_table(self, flex_table): + """Create a table and associated index for flexible attributes + for the given entity (if they don't exist). + """ + with self.transaction() as tx: + tx.script(""" + CREATE TABLE IF NOT EXISTS {0} ( + id INTEGER PRIMARY KEY, + entity_id INTEGER, + key TEXT, + value TEXT, + UNIQUE(entity_id, key) ON CONFLICT REPLACE); + CREATE INDEX IF NOT EXISTS {0}_by_entity + ON {0} (entity_id); + """.format(flex_table)) + + + # Querying. + + def _fetch(self, model_cls, query, order_by=None): + """Fetch the objects of type `model_cls` matching the given + query. The query may be given as a string, string sequence, a + Query object, or None (to fetch everything). If provided, + `order_by` is a SQLite ORDER BY clause for sorting. + """ + where, subvals = query.clause() + + sql = "SELECT * FROM {0} WHERE {1}".format( + model_cls._table, + where or '1', + ) + if order_by: + sql += " ORDER BY {0}".format(order_by) + with self.transaction() as tx: + rows = tx.query(sql, subvals) + + return Results(model_cls, rows, self, None if where else query) + + def _get(self, model_cls, id): + """Get a Model object by its id or None if the id does not + exist. + """ + return self._fetch(model_cls, MatchQuery('id', id)).get() diff --git a/beets/dbcore/query.py b/beets/dbcore/query.py new file mode 100644 index 00000000..4c888302 --- /dev/null +++ b/beets/dbcore/query.py @@ -0,0 +1,494 @@ +# This file is part of beets. +# Copyright 2014, Adrian Sampson. +# +# 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 Query type hierarchy for DBCore. +""" +import re +from beets import util +from datetime import datetime, timedelta + + +class Query(object): + """An abstract class representing a query into the item database. + """ + def clause(self): + """Generate an SQLite expression implementing the query. + Return a clause string, a sequence of substitution values for + the clause, and a Query object representing the "remainder" + Returns (clause, subvals) where clause is a valid sqlite + WHERE clause implementing the query and subvals is a list of + items to be substituted for ?s in the clause. + """ + return None, () + + def match(self, item): + """Check whether this query matches a given Item. Can be used to + perform queries on arbitrary sets of Items. + """ + raise NotImplementedError + + +class FieldQuery(Query): + """An abstract query that searches in a specific field for a + pattern. Subclasses must provide a `value_match` class method, which + determines whether a certain pattern string matches a certain value + string. Subclasses may also provide `col_clause` to implement the + same matching functionality in SQLite. + """ + def __init__(self, field, pattern, fast=True): + self.field = field + self.pattern = pattern + self.fast = fast + + def col_clause(self): + return None, () + + def clause(self): + if self.fast: + return self.col_clause() + else: + # Matching a flexattr. This is a slow query. + return None, () + + @classmethod + def value_match(cls, pattern, value): + """Determine whether the value matches the pattern. Both + arguments are strings. + """ + raise NotImplementedError() + + def match(self, item): + return self.value_match(self.pattern, item.get(self.field)) + + +class MatchQuery(FieldQuery): + """A query that looks for exact matches in an item field.""" + def col_clause(self): + return self.field + " = ?", [self.pattern] + + @classmethod + def value_match(cls, pattern, value): + return pattern == value + + +class StringFieldQuery(FieldQuery): + """A FieldQuery that converts values to strings before matching + them. + """ + @classmethod + def value_match(cls, pattern, value): + """Determine whether the value matches the pattern. The value + may have any type. + """ + return cls.string_match(pattern, util.as_string(value)) + + @classmethod + def string_match(cls, pattern, value): + """Determine whether the value matches the pattern. Both + arguments are strings. Subclasses implement this method. + """ + raise NotImplementedError() + + +class SubstringQuery(StringFieldQuery): + """A query that matches a substring in a specific item field.""" + def col_clause(self): + search = '%' + (self.pattern.replace('\\','\\\\').replace('%','\\%') + .replace('_','\\_')) + '%' + clause = self.field + " like ? escape '\\'" + subvals = [search] + return clause, subvals + + @classmethod + def string_match(cls, pattern, value): + return pattern.lower() in value.lower() + + +class RegexpQuery(StringFieldQuery): + """A query that matches a regular expression in a specific item + field. + """ + @classmethod + def string_match(cls, pattern, value): + try: + res = re.search(pattern, value) + except re.error: + # Invalid regular expression. + return False + return res is not None + + +class BooleanQuery(MatchQuery): + """Matches a boolean field. Pattern should either be a boolean or a + string reflecting a boolean. + """ + def __init__(self, field, pattern, fast=True): + super(BooleanQuery, self).__init__(field, pattern, fast) + if isinstance(pattern, basestring): + self.pattern = util.str2bool(pattern) + self.pattern = int(self.pattern) + + +class BytesQuery(MatchQuery): + """Match a raw bytes field (i.e., a path). This is a necessary hack + to work around the `sqlite3` module's desire to treat `str` and + `unicode` equivalently in Python 2. Always use this query instead of + `MatchQuery` when matching on BLOB values. + """ + def __init__(self, field, pattern): + super(BytesQuery, self).__init__(field, pattern) + + # Use a buffer representation of the pattern for SQLite + # matching. This instructs SQLite to treat the blob as binary + # rather than encoded Unicode. + if isinstance(self.pattern, basestring): + # Implicitly coerce Unicode strings to their bytes + # equivalents. + if isinstance(self.pattern, unicode): + self.pattern = self.pattern.encode('utf8') + self.buf_pattern = buffer(self.pattern) + elif isinstance(self.pattern, buffer): + self.buf_pattern = self.pattern + self.pattern = bytes(self.pattern) + + def col_clause(self): + return self.field + " = ?", [self.buf_pattern] + + +class NumericQuery(FieldQuery): + """Matches numeric fields. A syntax using Ruby-style range ellipses + (``..``) lets users specify one- or two-sided ranges. For example, + ``year:2001..`` finds music released since the turn of the century. + """ + def _convert(self, s): + """Convert a string to a numeric type (float or int). If the + string cannot be converted, return None. + """ + # This is really just a bit of fun premature optimization. + try: + return int(s) + except ValueError: + try: + return float(s) + except ValueError: + return None + + def __init__(self, field, pattern, fast=True): + super(NumericQuery, self).__init__(field, pattern, fast) + + parts = pattern.split('..', 1) + if len(parts) == 1: + # No range. + self.point = self._convert(parts[0]) + self.rangemin = None + self.rangemax = None + else: + # One- or two-sided range. + self.point = None + self.rangemin = self._convert(parts[0]) + self.rangemax = self._convert(parts[1]) + + def match(self, item): + value = getattr(item, self.field) + if isinstance(value, basestring): + value = self._convert(value) + + if self.point is not None: + return value == self.point + else: + if self.rangemin is not None and value < self.rangemin: + return False + if self.rangemax is not None and value > self.rangemax: + return False + return True + + def col_clause(self): + if self.point is not None: + return self.field + '=?', (self.point,) + else: + if self.rangemin is not None and self.rangemax is not None: + return (u'{0} >= ? AND {0} <= ?'.format(self.field), + (self.rangemin, self.rangemax)) + elif self.rangemin is not None: + return u'{0} >= ?'.format(self.field), (self.rangemin,) + elif self.rangemax is not None: + return u'{0} <= ?'.format(self.field), (self.rangemax,) + else: + return '1', () + + +class CollectionQuery(Query): + """An abstract query class that aggregates other queries. Can be + indexed like a list to access the sub-queries. + """ + def __init__(self, subqueries=()): + self.subqueries = subqueries + + # Act like a sequence. + def __len__(self): + return len(self.subqueries) + def __getitem__(self, key): + return self.subqueries[key] + def __iter__(self): + return iter(self.subqueries) + def __contains__(self, item): + return item in self.subqueries + + def clause_with_joiner(self, joiner): + """Returns a clause created by joining together the clauses of + all subqueries with the string joiner (padded by spaces). + """ + clause_parts = [] + subvals = [] + for subq in self.subqueries: + subq_clause, subq_subvals = subq.clause() + if not subq_clause: + # Fall back to slow query. + return None, () + clause_parts.append('(' + subq_clause + ')') + subvals += subq_subvals + clause = (' ' + joiner + ' ').join(clause_parts) + return clause, subvals + + +class AnyFieldQuery(CollectionQuery): + """A query that matches if a given FieldQuery subclass matches in + any field. The individual field query class is provided to the + constructor. + """ + def __init__(self, pattern, fields, cls): + self.pattern = pattern + self.fields = fields + self.query_class = cls + + subqueries = [] + for field in self.fields: + subqueries.append(cls(field, pattern, True)) + super(AnyFieldQuery, self).__init__(subqueries) + + def clause(self): + return self.clause_with_joiner('or') + + def match(self, item): + for subq in self.subqueries: + if subq.match(item): + return True + return False + + +class MutableCollectionQuery(CollectionQuery): + """A collection query whose subqueries may be modified after the + query is initialized. + """ + def __setitem__(self, key, value): + self.subqueries[key] = value + + def __delitem__(self, key): + del self.subqueries[key] + + +class AndQuery(MutableCollectionQuery): + """A conjunction of a list of other queries.""" + def clause(self): + return self.clause_with_joiner('and') + + def match(self, item): + return all([q.match(item) for q in self.subqueries]) + + +class OrQuery(MutableCollectionQuery): + """A conjunction of a list of other queries.""" + def clause(self): + return self.clause_with_joiner('or') + + def match(self, item): + return any([q.match(item) for q in self.subqueries]) + + +class TrueQuery(Query): + """A query that always matches.""" + def clause(self): + return '1', () + + def match(self, item): + return True + + +class FalseQuery(Query): + """A query that never matches.""" + def clause(self): + return '0', () + + def match(self, item): + return False + + + +# Time/date queries. + + +def _to_epoch_time(date): + """Convert a `datetime` object to an integer number of seconds since + the (local) Unix epoch. + """ + epoch = datetime.fromtimestamp(0) + delta = date - epoch + try: + return int(delta.total_seconds()) + except AttributeError: + # datetime.timedelta.total_seconds() is not available on Python 2.6 + return delta.seconds + delta.days * 24 * 3600 + + +def _parse_periods(pattern): + """Parse a string containing two dates separated by two dots (..). + Return a pair of `Period` objects. + """ + parts = pattern.split('..', 1) + if len(parts) == 1: + instant = Period.parse(parts[0]) + return (instant, instant) + else: + start = Period.parse(parts[0]) + end = Period.parse(parts[1]) + return (start, end) + + +class Period(object): + """A period of time given by a date, time and precision. + + Example: 2014-01-01 10:50:30 with precision 'month' represents all + instants of time during January 2014. + """ + + precisions = ('year', 'month', 'day') + date_formats = ('%Y', '%Y-%m', '%Y-%m-%d') + + def __init__(self, date, precision): + """Create a period with the given date (a `datetime` object) and + precision (a string, one of "year", "month", or "day"). + """ + if precision not in Period.precisions: + raise ValueError('Invalid precision ' + str(precision)) + self.date = date + self.precision = precision + + @classmethod + def parse(cls, string): + """Parse a date and return a `Period` object or `None` if the + string is empty. + """ + if not string: + return None + ordinal = string.count('-') + if ordinal >= len(cls.date_formats): + raise ValueError('date is not in one of the formats ' + + ', '.join(cls.date_formats)) + date_format = cls.date_formats[ordinal] + date = datetime.strptime(string, date_format) + precision = cls.precisions[ordinal] + return cls(date, precision) + + def open_right_endpoint(self): + """Based on the precision, convert the period to a precise + `datetime` for use as a right endpoint in a right-open interval. + """ + precision = self.precision + date = self.date + if 'year' == self.precision: + return date.replace(year=date.year + 1, month=1) + elif 'month' == precision: + if (date.month < 12): + return date.replace(month=date.month + 1) + else: + return date.replace(year=date.year + 1, month=1) + elif 'day' == precision: + return date + timedelta(days=1) + else: + raise ValueError('unhandled precision ' + str(precision)) + + +class DateInterval(object): + """A closed-open interval of dates. + + A left endpoint of None means since the beginning of time. + A right endpoint of None means towards infinity. + """ + + def __init__(self, start, end): + if start is not None and end is not None and not start < end: + raise ValueError("start date {0} is not before end date {1}" + .format(start, end)) + self.start = start + self.end = end + + @classmethod + def from_periods(cls, start, end): + """Create an interval with two Periods as the endpoints. + """ + end_date = end.open_right_endpoint() if end is not None else None + start_date = start.date if start is not None else None + return cls(start_date, end_date) + + def contains(self, date): + if self.start is not None and date < self.start: + return False + if self.end is not None and date >= self.end: + return False + return True + + def __str__(self): + return'[{0}, {1})'.format(self.start, self.end) + + +class DateQuery(FieldQuery): + """Matches date fields stored as seconds since Unix epoch time. + + Dates can be specified as ``year-month-day`` strings where only year + is mandatory. + + The value of a date field can be matched against a date interval by + using an ellipsis interval syntax similar to that of NumericQuery. + """ + def __init__(self, field, pattern, fast=True): + super(DateQuery, self).__init__(field, pattern, fast) + start, end = _parse_periods(pattern) + self.interval = DateInterval.from_periods(start, end) + + def match(self, item): + timestamp = float(item[self.field]) + date = datetime.utcfromtimestamp(timestamp) + return self.interval.contains(date) + + _clause_tmpl = "{0} {1} ?" + + def col_clause(self): + clause_parts = [] + subvals = [] + + if self.interval.start: + clause_parts.append(self._clause_tmpl.format(self.field, ">=")) + subvals.append(_to_epoch_time(self.interval.start)) + + if self.interval.end: + clause_parts.append(self._clause_tmpl.format(self.field, "<")) + subvals.append(_to_epoch_time(self.interval.end)) + + if clause_parts: + # One- or two-sided interval. + clause = ' AND '.join(clause_parts) + else: + # Match any date. + clause = '1' + return clause, subvals diff --git a/beets/dbcore/types.py b/beets/dbcore/types.py new file mode 100644 index 00000000..165c0b60 --- /dev/null +++ b/beets/dbcore/types.py @@ -0,0 +1,140 @@ +# This file is part of beets. +# Copyright 2014, Adrian Sampson. +# +# 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. + +"""Representation of type information for DBCore model fields. +""" +from . import query +from beets.util import str2bool + + + +# Abstract base. + + +class Type(object): + """An object encapsulating the type of a model field. Includes + information about how to store the value in the database, query, + format, and parse a given field. + """ + + sql = None + """The SQLite column type for the value. + """ + + query = None + """The `Query` subclass to be used when querying the field. + """ + + def format(self, value): + """Given a value of this type, produce a Unicode string + representing the value. This is used in template evaluation. + """ + raise NotImplementedError() + + def parse(self, string): + """Parse a (possibly human-written) string and return the + indicated value of this type. + """ + raise NotImplementedError() + + + +# Reusable types. + + +class Integer(Type): + """A basic integer type. + """ + sql = u'INTEGER' + query = query.NumericQuery + + def format(self, value): + return unicode(value or 0) + + def parse(self, string): + try: + return int(string) + except ValueError: + return 0 + + +class PaddedInt(Integer): + """An integer field that is formatted with a given number of digits, + padded with zeroes. + """ + def __init__(self, digits): + self.digits = digits + + def format(self, value): + return u'{0:0{1}d}'.format(value or 0, self.digits) + + +class ScaledInt(Integer): + """An integer whose formatting operation scales the number by a + constant and adds a suffix. Good for units with large magnitudes. + """ + def __init__(self, unit, suffix=u''): + self.unit = unit + self.suffix = suffix + + def format(self, value): + return u'{0}{1}'.format((value or 0) // self.unit, self.suffix) + + +class Id(Integer): + """An integer used as the row key for a SQLite table. + """ + sql = u'INTEGER PRIMARY KEY' + + +class Float(Type): + """A basic floating-point type. + """ + sql = u'REAL' + query = query.NumericQuery + + def format(self, value): + return u'{0:.1f}'.format(value or 0.0) + + def parse(self, string): + try: + return float(string) + except ValueError: + return 0.0 + + +class String(Type): + """A Unicode string type. + """ + sql = u'TEXT' + query = query.SubstringQuery + + def format(self, value): + return unicode(value) if value else u'' + + def parse(self, string): + return string + + +class Boolean(Type): + """A boolean type. + """ + sql = u'INTEGER' + query = query.BooleanQuery + + def format(self, value): + return unicode(bool(value)) + + def parse(self, string): + return str2bool(string) diff --git a/lib/beets/importer.py b/beets/importer.py similarity index 60% rename from lib/beets/importer.py rename to beets/importer.py index 048077b8..f997770c 100644 --- a/lib/beets/importer.py +++ b/beets/importer.py @@ -1,5 +1,5 @@ # This file is part of beets. -# Copyright 2011, Adrian Sampson. +# Copyright 2013, Adrian Sampson. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,23 +20,26 @@ from __future__ import print_function import os import logging import pickle +import itertools from collections import defaultdict -from lib.beets import autotag -from lib.beets import library -from lib.beets import plugins -from lib.beets import util -from lib.beets.util import pipeline -from lib.beets.util import syspath, normpath, displayable_path -from lib.beets.util.enumeration import enum +from beets import autotag +from beets import library +from beets import dbcore +from beets import plugins +from beets import util +from beets import config +from beets.util import pipeline +from beets.util import syspath, normpath, displayable_path +from beets.util.enumeration import enum +from beets import mediafile action = enum( 'SKIP', 'ASIS', 'TRACKS', 'MANUAL', 'APPLY', 'MANUAL_ID', - name='action' + 'ALBUMS', name='action' ) QUEUE_SIZE = 128 -STATE_FILE = os.path.expanduser('~/.beetsstate') SINGLE_ARTIST_THRESH = 0.25 VARIOUS_ARTISTS = u'Various Artists' @@ -51,35 +54,6 @@ class ImportAbort(Exception): # Utilities. -def tag_log(logfile, status, path): - """Log a message about a given album to logfile. The status should - reflect the reason the album couldn't be tagged. - """ - if logfile: - print('{0} {1}'.format(status, path), file=logfile) - logfile.flush() - -def log_choice(config, task, duplicate=False): - """Logs the task's current choice if it should be logged. If - ``duplicate``, then this is a secondary choice after a duplicate was - detected and a decision was made. - """ - path = task.path if task.is_album else task.item.path - if duplicate: - # Duplicate: log all three choices (skip, keep both, and trump). - if task.remove_duplicates: - tag_log(config.logfile, 'duplicate-replace', path) - elif task.choice_flag in (action.ASIS, action.APPLY): - tag_log(config.logfile, 'duplicate-keep', path) - elif task.choice_flag is (action.SKIP): - tag_log(config.logfile, 'duplicate-skip', path) - else: - # Non-duplicate: log "skip" and "asis" choices. - if task.choice_flag is action.ASIS: - tag_log(config.logfile, 'asis', path) - elif task.choice_flag is action.SKIP: - tag_log(config.logfile, 'skip', path) - def _duplicate_check(lib, task): """Check whether an album already exists in the library. Returns a list of Album objects (empty if no duplicates are found). @@ -93,7 +67,7 @@ def _duplicate_check(lib, task): found_albums = [] cur_paths = set(i.path for i in task.items if i) - for album_cand in lib.albums(artist=artist): + for album_cand in lib.albums(dbcore.MatchQuery('albumartist', artist)): if album_cand.album == album: # Check whether the album is identical in contents, in which # case it is not a duplicate (will be replaced). @@ -111,7 +85,11 @@ def _item_duplicate_check(lib, task): artist, title = task.chosen_ident() found_items = [] - for other_item in lib.items(artist=artist, title=title): + query = dbcore.AndQuery(( + dbcore.MatchQuery('artist', artist), + dbcore.MatchQuery('title', title), + )) + for other_item in lib.items(query): # Existing items not considered duplicates. if other_item.path == task.item.path: continue @@ -130,11 +108,12 @@ def _infer_album_fields(task): if task.choice_flag == action.ASIS: # Taking metadata "as-is". Guess whether this album is VA. - plur_artist, freq = util.plurality([i.artist for i in task.items]) + plur_albumartist, freq = util.plurality( + [i.albumartist or i.artist for i in task.items]) if freq == len(task.items) or (freq > 1 and float(freq) / len(task.items) >= SINGLE_ARTIST_THRESH): # Single-artist album. - changes['albumartist'] = plur_artist + changes['albumartist'] = plur_albumartist changes['comp'] = False else: # VA. @@ -164,17 +143,23 @@ def _infer_album_fields(task): for k, v in changes.iteritems(): setattr(item, k, v) +def _resume(): + """Check whether an import should resume and return a boolean or the + string 'ask' indicating that the user should be queried. + """ + return config['import']['resume'].as_choice([True, False, 'ask']) + def _open_state(): """Reads the state file, returning a dictionary.""" try: - with open(STATE_FILE) as f: + with open(config['statefile'].as_filename()) as f: return pickle.load(f) except (IOError, EOFError): return {} def _save_state(state): """Writes the state dictionary out to disk.""" try: - with open(STATE_FILE, 'w') as f: + with open(config['statefile'].as_filename(), 'w') as f: pickle.dump(state, f) except IOError as exc: log.error(u'state file could not be written: %s' % unicode(exc)) @@ -183,21 +168,21 @@ def _save_state(state): # Utilities for reading and writing the beets progress file, which # allows long tagging tasks to be resumed when they pause (or crash). PROGRESS_KEY = 'tagprogress' -def progress_set(toppath, path): +def progress_set(toppath, paths): """Record that tagging for the given `toppath` was successful up to - `path`. If path is None, then clear the progress value (indicating + `paths`. If paths is None, then clear the progress value (indicating that the tagging completed). """ state = _open_state() if PROGRESS_KEY not in state: state[PROGRESS_KEY] = {} - if path is None: + if paths is None: # Remove progress from file. if toppath in state[PROGRESS_KEY]: del state[PROGRESS_KEY][toppath] else: - state[PROGRESS_KEY][toppath] = path + state[PROGRESS_KEY][toppath] = paths _save_state(state) def progress_get(toppath): @@ -214,19 +199,19 @@ def progress_get(toppath): # This keeps track of all directories that were ever imported, which # allows the importer to only import new stuff. HISTORY_KEY = 'taghistory' -def history_add(path): - """Indicate that the import of `path` is completed and should not - be repeated in incremental imports. +def history_add(paths): + """Indicate that the import of the album in `paths` is completed and + should not be repeated in incremental imports. """ state = _open_state() if HISTORY_KEY not in state: state[HISTORY_KEY] = set() - state[HISTORY_KEY].add(path) + state[HISTORY_KEY].add(tuple(paths)) _save_state(state) def history_get(): - """Get the set of completed paths in incremental imports. + """Get the set of completed path tuples in incremental imports. """ state = _open_state() if HISTORY_KEY not in state: @@ -234,45 +219,137 @@ def history_get(): return state[HISTORY_KEY] -# The configuration structure. +# Abstract session class. -class ImportConfig(object): - """Contains all the settings used during an import session. Should - be used in a "write-once" way -- everything is set up initially and - then never touched again. +class ImportSession(object): + """Controls an import action. Subclasses should implement methods to + communicate with the user or otherwise make decisions. """ - _fields = ['lib', 'paths', 'resume', 'logfile', 'color', 'quiet', - 'quiet_fallback', 'copy', 'move', 'write', 'delete', - 'choose_match_func', 'should_resume_func', 'threaded', - 'autot', 'singletons', 'timid', 'choose_item_func', - 'query', 'incremental', 'ignore', - 'resolve_duplicate_func', 'per_disc_numbering'] - def __init__(self, **kwargs): - for slot in self._fields: - setattr(self, slot, kwargs[slot]) + def __init__(self, lib, logfile, paths, query): + """Create a session. `lib` is a Library object. `logfile` is a + file-like object open for writing or None if no logging is to be + performed. Either `paths` or `query` is non-null and indicates + the source of files to be imported. + """ + self.lib = lib + self.logfile = logfile + self.paths = paths + self.query = query # Normalize the paths. if self.paths: self.paths = map(normpath, self.paths) + def _amend_config(self): + """Make implied changes the importer configuration. + """ + # FIXME: Maybe this function should not exist and should instead + # provide "decision wrappers" like "should_resume()", etc. + iconfig = config['import'] + # Incremental and progress are mutually exclusive. - if self.incremental: - self.resume = False + if iconfig['incremental']: + iconfig['resume'] = False # When based on a query instead of directories, never # save progress or try to resume. if self.query is not None: - self.paths = None - self.resume = False - self.incremental = False + iconfig['resume'] = False + iconfig['incremental'] = False # Copy and move are mutually exclusive. - if self.move: - self.copy = False + if iconfig['move']: + iconfig['copy'] = False # Only delete when copying. - if not self.copy: - self.delete = False + if not iconfig['copy']: + iconfig['delete'] = False + + def tag_log(self, status, paths): + """Log a message about a given album to logfile. The status should + reflect the reason the album couldn't be tagged. + """ + if self.logfile: + print(u'{0} {1}'.format(status, displayable_path(paths)), + file=self.logfile) + self.logfile.flush() + + def log_choice(self, task, duplicate=False): + """Logs the task's current choice if it should be logged. If + ``duplicate``, then this is a secondary choice after a duplicate was + detected and a decision was made. + """ + paths = task.paths if task.is_album else [task.item.path] + if duplicate: + # Duplicate: log all three choices (skip, keep both, and trump). + if task.remove_duplicates: + self.tag_log('duplicate-replace', paths) + elif task.choice_flag in (action.ASIS, action.APPLY): + self.tag_log('duplicate-keep', paths) + elif task.choice_flag is (action.SKIP): + self.tag_log('duplicate-skip', paths) + else: + # Non-duplicate: log "skip" and "asis" choices. + if task.choice_flag is action.ASIS: + self.tag_log('asis', paths) + elif task.choice_flag is action.SKIP: + self.tag_log('skip', paths) + + def should_resume(self, path): + raise NotImplementedError + + def choose_match(self, task): + raise NotImplementedError + + def resolve_duplicate(self, task): + raise NotImplementedError + + def choose_item(self, task): + raise NotImplementedError + + def run(self): + """Run the import task. + """ + self._amend_config() + + # Set up the pipeline. + if self.query is None: + stages = [read_tasks(self)] + else: + stages = [query_tasks(self)] + if config['import']['singletons']: + # Singleton importer. + if config['import']['autotag']: + stages += [item_lookup(self), item_query(self)] + else: + stages += [item_progress(self)] + else: + # Whole-album importer. + if config['import']['group_albums']: + # Split directory tasks into one task for each album + stages += [group_albums(self)] + if config['import']['autotag']: + # Only look up and query the user when autotagging. + stages += [initial_lookup(self), user_query(self)] + else: + # When not autotagging, just display progress. + stages += [show_progress(self)] + stages += [apply_choices(self)] + for stage_func in plugins.import_stages(): + stages.append(plugin_stage(self, stage_func)) + stages += [manipulate_files(self)] + stages += [finalize(self)] + pl = pipeline.Pipeline(stages) + + # Run the pipeline. + try: + if config['threaded']: + pl.run_parallel(QUEUE_SIZE) + else: + pl.run_sequential() + except ImportAbort: + # User aborted operation. Silently stop. + pass # The importer task class. @@ -281,13 +358,14 @@ class ImportTask(object): """Represents a single set of items to be imported along with its intermediate state. May represent an album or a single item. """ - def __init__(self, toppath=None, path=None, items=None): + def __init__(self, toppath=None, paths=None, items=None): self.toppath = toppath - self.path = path + self.paths = paths self.items = items self.sentinel = False self.remove_duplicates = False self.is_album = True + self.choice_flag = None @classmethod def done_sentinel(cls, toppath): @@ -299,12 +377,12 @@ class ImportTask(object): return obj @classmethod - def progress_sentinel(cls, toppath, path): + def progress_sentinel(cls, toppath, paths): """Create a task indicating that a single directory in a larger import has finished. This is only required for singleton imports; progress is implied for album imports. """ - obj = cls(toppath, path) + obj = cls(toppath, paths) obj.sentinel = True return obj @@ -350,7 +428,7 @@ class ImportTask(object): # Not part of the task structure: assert choice not in (action.MANUAL, action.MANUAL_ID) assert choice != action.APPLY # Only used internally. - if choice in (action.SKIP, action.ASIS, action.TRACKS): + if choice in (action.SKIP, action.ASIS, action.TRACKS, action.ALBUMS): self.choice_flag = choice self.match = None else: @@ -365,19 +443,19 @@ class ImportTask(object): """Updates the progress state to indicate that this album has finished. """ - if self.sentinel and self.path is None: + if self.sentinel and self.paths is None: # "Done" sentinel. progress_set(self.toppath, None) elif self.sentinel or self.is_album: # "Directory progress" sentinel for singletons or a real # album task, which implies the same. - progress_set(self.toppath, self.path) + progress_set(self.toppath, self.paths) def save_history(self): """Save the directory in the history for incremental imports. """ - if self.sentinel or self.is_album: - history_add(self.path) + if self.is_album and self.paths and not self.sentinel: + history_add(self.paths) # Logical decisions. @@ -446,30 +524,31 @@ class ImportTask(object): call when the file in question may not have been removed. """ if self.toppath and not os.path.exists(filename): - util.prune_dirs(os.path.dirname(filename), self.toppath) + util.prune_dirs(os.path.dirname(filename), + self.toppath, + clutter=config['clutter'].as_str_seq()) # Full-album pipeline stages. -def read_tasks(config): +def read_tasks(session): """A generator yielding all the albums (as ImportTask objects) found in the user-specified list of paths. In the case of a singleton import, yields single-item tasks instead. """ # Look for saved progress. - progress = config.resume is not False - if progress: + if _resume(): resume_dirs = {} - for path in config.paths: + for path in session.paths: resume_dir = progress_get(path) if resume_dir: # Either accept immediately or prompt for input to decide. - if config.resume: + if _resume() is True: do_resume = True log.warn('Resuming interrupted import of %s' % path) else: - do_resume = config.should_resume_func(config, path) + do_resume = session.should_resume(path) if do_resume: resume_dirs[path] = resume_dir @@ -478,23 +557,39 @@ def read_tasks(config): progress_set(path, None) # Look for saved incremental directories. - if config.incremental: + if config['import']['incremental']: incremental_skipped = 0 history_dirs = history_get() - for toppath in config.paths: + for toppath in session.paths: # Check whether the path is to a file. - if config.singletons and not os.path.isdir(syspath(toppath)): - item = library.Item.from_path(toppath) + if config['import']['singletons'] and \ + not os.path.isdir(syspath(toppath)): + try: + item = library.Item.from_path(toppath) + except mediafile.UnreadableFileError: + log.warn(u'unreadable file: {0}'.format( + util.displayable_path(toppath) + )) + continue yield ImportTask.item_task(item) continue + # A flat album import merges all items into one album. + if config['import']['flat'] and not config['import']['singletons']: + all_items = [] + for _, items in autotag.albums_in_dir(toppath): + all_items += items + yield ImportTask(toppath, toppath, all_items) + yield ImportTask.done_sentinel(toppath) + continue + # Produce paths under this directory. - if progress: + if _resume(): resume_dir = resume_dirs.get(toppath) - for path, items in autotag.albums_in_dir(toppath, config.ignore): + for path, items in autotag.albums_in_dir(toppath): # Skip according to progress. - if progress and resume_dir: + if _resume() and resume_dir: # We're fast-forwarding to resume a previous tagging. if path == resume_dir: # We've hit the last good path! Turn off the @@ -503,14 +598,14 @@ def read_tasks(config): continue # When incremental, skip paths in the history. - if config.incremental and path in history_dirs: + if config['import']['incremental'] and tuple(path) in history_dirs: log.debug(u'Skipping previously-imported path: %s' % displayable_path(path)) incremental_skipped += 1 continue # Yield all the necessary tasks. - if config.singletons: + if config['import']['singletons']: for item in items: yield ImportTask.item_task(item) yield ImportTask.progress_sentinel(toppath, path) @@ -521,29 +616,29 @@ def read_tasks(config): yield ImportTask.done_sentinel(toppath) # Show skipped directories. - if config.incremental and incremental_skipped: + if config['import']['incremental'] and incremental_skipped: log.info(u'Incremental import: skipped %i directories.' % incremental_skipped) -def query_tasks(config): +def query_tasks(session): """A generator that works as a drop-in-replacement for read_tasks. Instead of finding files from the filesystem, a query is used to match items from the library. """ - if config.singletons: + if config['import']['singletons']: # Search for items. - for item in config.lib.items(config.query): + for item in session.lib.items(session.query): yield ImportTask.item_task(item) else: # Search for albums. - for album in config.lib.albums(config.query): + for album in session.lib.albums(session.query): log.debug('yielding album %i: %s - %s' % (album.id, album.albumartist, album.album)) items = list(album.items()) - yield ImportTask(None, album.item_dir(), items) + yield ImportTask(None, [album.item_dir()], items) -def initial_lookup(config): +def initial_lookup(session): """A coroutine for performing the initial MusicBrainz lookup for an album. It accepts lists of Items and yields (items, cur_artist, cur_album, candidates, rec) tuples. If no match @@ -552,52 +647,70 @@ def initial_lookup(config): task = None while True: task = yield task - if task.sentinel: + if task.should_skip(): continue - plugins.send('import_task_start', task=task, config=config) + plugins.send('import_task_start', session=session, task=task) - log.debug('Looking up: %s' % task.path) - try: - task.set_candidates(*autotag.tag_album(task.items, config.timid)) - except autotag.AutotagError: - task.set_null_candidates() + log.debug('Looking up: %s' % displayable_path(task.paths)) + task.set_candidates( + *autotag.tag_album(task.items) + ) -def user_query(config): +def user_query(session): """A coroutine for interfacing with the user about the tagging - process. lib is the Library to import into and logfile may be - a file-like object for logging the import process. The coroutine - accepts and yields ImportTask objects. + process. + + The coroutine accepts an ImportTask objects. It uses the + session's ``choose_match`` method to determine the ``action`` for + this task. Depending on the action additional stages are exectuted + and the processed task is yielded. + + It emits the ``import_task_choice`` event for plugins. Plugins have + acces to the choice via the ``taks.choice_flag`` property and may + choose to change it. """ recent = set() task = None while True: task = yield task - if task.sentinel: + if task.should_skip(): continue # Ask the user for a choice. - choice = config.choose_match_func(task, config) + choice = session.choose_match(task) task.set_choice(choice) - log_choice(config, task) - plugins.send('import_task_choice', task=task, config=config) + session.log_choice(task) + plugins.send('import_task_choice', session=session, task=task) # As-tracks: transition to singleton workflow. - if choice is action.TRACKS: + if task.choice_flag is action.TRACKS: # Set up a little pipeline for dealing with the singletons. - item_tasks = [] - def emitter(): + def emitter(task): for item in task.items: yield ImportTask.item_task(item) - yield ImportTask.progress_sentinel(task.toppath, task.path) - def collector(): - while True: - item_task = yield - item_tasks.append(item_task) - ipl = pipeline.Pipeline((emitter(), item_lookup(config), - item_query(config), collector())) - ipl.run_sequential() - task = pipeline.multiple(item_tasks) + yield ImportTask.progress_sentinel(task.toppath, task.paths) + + ipl = pipeline.Pipeline([ + emitter(task), + item_lookup(session), + item_query(session), + ]) + task = pipeline.multiple(ipl.pull()) + continue + + # As albums: group items by albums and create task for each album + if task.choice_flag is action.ALBUMS: + def emitter(task): + yield task + + ipl = pipeline.Pipeline([ + emitter(task), + group_albums(session), + initial_lookup(session), + user_query(session) + ]) + task = pipeline.multiple(ipl.pull()) continue # Check for duplicates if we have a match (or ASIS). @@ -606,12 +719,12 @@ def user_query(config): # The "recent" set keeps track of identifiers for recently # imported albums -- those that haven't reached the database # yet. - if ident in recent or _duplicate_check(config.lib, task): - config.resolve_duplicate_func(task, config) - log_choice(config, task, True) + if ident in recent or _duplicate_check(session.lib, task): + session.resolve_duplicate(task) + session.log_choice(task, True) recent.add(ident) -def show_progress(config): +def show_progress(session): """This stage replaces the initial_lookup and user_query stages when the importer is run without autotagging. It displays the album name and artist as the files are added. @@ -619,16 +732,16 @@ def show_progress(config): task = None while True: task = yield task - if task.sentinel: + if task.should_skip(): continue - log.info(task.path) + log.info(displayable_path(task.paths)) # Behave as if ASIS were selected. task.set_null_candidates() task.set_choice(action.ASIS) -def apply_choices(config): +def apply_choices(session): """A coroutine for applying changes to albums and singletons during the autotag process. """ @@ -648,12 +761,11 @@ def apply_choices(config): if task.should_write_tags(): if task.is_album: autotag.apply_metadata( - task.match.info, task.match.mapping, - per_disc_numbering=config.per_disc_numbering + task.match.info, task.match.mapping ) else: autotag.apply_item_metadata(task.item, task.match.info) - plugins.send('import_task_apply', config=config, task=task) + plugins.send('import_task_apply', session=session, task=task) # Infer album-level fields. if task.is_album: @@ -664,7 +776,9 @@ def apply_choices(config): # when the last item is removed. task.replaced_items = defaultdict(list) for item in items: - dup_items = config.lib.items(library.MatchQuery('path', item.path)) + dup_items = session.lib.items( + dbcore.query.BytesQuery('path', item.path) + ) for dup_item in dup_items: task.replaced_items[item].append(dup_item) log.debug('replacing item %i: %s' % @@ -677,45 +791,44 @@ def apply_choices(config): duplicate_items = [] if task.remove_duplicates: if task.is_album: - for album in _duplicate_check(config.lib, task): + for album in _duplicate_check(session.lib, task): duplicate_items += album.items() else: - duplicate_items = _item_duplicate_check(config.lib, task) + duplicate_items = _item_duplicate_check(session.lib, task) log.debug('removing %i old duplicated items' % len(duplicate_items)) # Delete duplicate files that are located inside the library # directory. + task.duplicate_paths = [] for duplicate_path in [i.path for i in duplicate_items]: - if config.lib.directory in util.ancestry(duplicate_path): - log.debug(u'deleting replaced duplicate %s' % - util.displayable_path(duplicate_path)) - util.remove(duplicate_path) - util.prune_dirs(os.path.dirname(duplicate_path), - config.lib.directory) + if session.lib.directory in util.ancestry(duplicate_path): + # Mark the path for deletion in the manipulate_files + # stage. + task.duplicate_paths.append(duplicate_path) # Add items -- before path changes -- to the library. We add the # items now (rather than at the end) so that album structures # are in place before calls to destination(). - with config.lib.transaction(): + with session.lib.transaction(): # Remove old items. for replaced in task.replaced_items.itervalues(): for item in replaced: - config.lib.remove(item) + item.remove() for item in duplicate_items: - config.lib.remove(item) + item.remove() # Add new ones. if task.is_album: # Add an album. - album = config.lib.add_album(items) + album = session.lib.add_album(items) task.album_id = album.id else: # Add tracks. for item in items: - config.lib.add(item) + session.lib.add(item) -def plugin_stage(config, func): +def plugin_stage(session, func): """A coroutine (pipeline stage) that calls the given function with each non-skipped import task. These stages occur between applying metadata changes and moving/copying/writing files. @@ -725,9 +838,13 @@ def plugin_stage(config, func): task = yield task if task.should_skip(): continue - func(config, task) + func(session, task) -def manipulate_files(config): + # Stage may modify DB, so re-load cached item data. + for item in task.imported_items(): + item.load() + +def manipulate_files(session): """A coroutine (pipeline stage) that performs necessary file manipulations *after* items have been added to the library. """ @@ -737,16 +854,25 @@ def manipulate_files(config): if task.should_skip(): continue - # Move/copy files. + # Remove duplicate files marked for deletion. + if task.remove_duplicates: + for duplicate_path in task.duplicate_paths: + log.debug(u'deleting replaced duplicate %s' % + util.displayable_path(duplicate_path)) + util.remove(duplicate_path) + util.prune_dirs(os.path.dirname(duplicate_path), + session.lib.directory) + + # Move/copy/write files. items = task.imported_items() - task.old_paths = [item.path for item in items] # For deletion. + # Save the original paths of all items for deletion and pruning + # in the next step (finalization). + task.old_paths = [item.path for item in items] for item in items: - if config.move: + if config['import']['move']: # Just move the file. - old_path = item.path - config.lib.move(item, False) - task.prune(old_path) - elif config.copy: + item.move(False) + elif config['import']['copy']: # If it's a reimport, move in-library files and copy # out-of-library files. Otherwise, copy and keep track # of the old path. @@ -754,30 +880,33 @@ def manipulate_files(config): if task.replaced_items[item]: # This is a reimport. Move in-library files and copy # out-of-library files. - if config.lib.directory in util.ancestry(old_path): - config.lib.move(item, False) + if session.lib.directory in util.ancestry(old_path): + item.move(False) # We moved the item, so remove the # now-nonexistent file from old_paths. task.old_paths.remove(old_path) else: - config.lib.move(item, True) + item.move(True) else: # A normal import. Just copy files and keep track of # old paths. - config.lib.move(item, True) + item.move(True) - if config.write and task.should_write_tags(): - item.write() + if config['import']['write'] and task.should_write_tags(): + try: + item.write() + except library.FileOperationError as exc: + log.error(exc) # Save new paths. - with config.lib.transaction(): + with session.lib.transaction(): for item in items: - config.lib.store(item) + item.store() # Plugin event. - plugins.send('import_task_files', config=config, task=task) + plugins.send('import_task_files', session=session, task=task) -def finalize(config): +def finalize(session): """A coroutine that finishes up importer tasks. In particular, the coroutine sends plugin events, deletes old files, and saves progress. This is a "terminal" coroutine (it yields None). @@ -785,9 +914,9 @@ def finalize(config): while True: task = yield if task.should_skip(): - if config.resume is not False: + if _resume(): task.save_progress() - if config.incremental: + if config['import']['incremental']: task.save_history() continue @@ -795,16 +924,16 @@ def finalize(config): # Announce that we've added an album. if task.is_album: - album = config.lib.get_album(task.album_id) + album = session.lib.get_album(task.album_id) plugins.send('album_imported', - lib=config.lib, album=album, config=config) + lib=session.lib, album=album) else: for item in items: plugins.send('item_imported', - lib=config.lib, item=item, config=config) + lib=session.lib, item=item) - # Finally, delete old files. - if config.copy and config.delete: + # When copying and deleting originals, delete old files. + if config['import']['copy'] and config['import']['delete']: new_paths = [os.path.realpath(item.path) for item in items] for old_path in task.old_paths: # Only delete files that were actually copied. @@ -812,30 +941,36 @@ def finalize(config): util.remove(syspath(old_path), False) task.prune(old_path) + # When moving, prune empty directories containing the original + # files. + elif config['import']['move']: + for old_path in task.old_paths: + task.prune(old_path) + # Update progress. - if config.resume is not False: + if _resume(): task.save_progress() - if config.incremental: + if config['import']['incremental']: task.save_history() # Singleton pipeline stages. -def item_lookup(config): +def item_lookup(session): """A coroutine used to perform the initial MusicBrainz lookup for an item task. """ task = None while True: task = yield task - if task.sentinel: + if task.should_skip(): continue - plugins.send('import_task_start', task=task, config=config) + plugins.send('import_task_start', session=session, task=task) - task.set_item_candidates(*autotag.tag_item(task.item, config.timid)) + task.set_item_candidates(*autotag.tag_item(task.item)) -def item_query(config): +def item_query(session): """A coroutine that queries the user for input on single-item lookups. """ @@ -843,23 +978,23 @@ def item_query(config): recent = set() while True: task = yield task - if task.sentinel: + if task.should_skip(): continue - choice = config.choose_item_func(task, config) + choice = session.choose_item(task) task.set_choice(choice) - log_choice(config, task) - plugins.send('import_task_choice', task=task, config=config) + session.log_choice(task) + plugins.send('import_task_choice', session=session, task=task) # Duplicate check. if task.choice_flag in (action.ASIS, action.APPLY): ident = task.chosen_ident() - if ident in recent or _item_duplicate_check(config.lib, task): - config.resolve_duplicate_func(task, config) - log_choice(config, task, True) + if ident in recent or _item_duplicate_check(session.lib, task): + session.resolve_duplicate(task) + session.log_choice(task, True) recent.add(ident) -def item_progress(config): +def item_progress(session): """Skips the lookup and query stages in a non-autotagged singleton import. Just shows progress. """ @@ -867,7 +1002,7 @@ def item_progress(config): log.info('Importing items:') while True: task = yield task - if task.sentinel: + if task.should_skip(): continue log.info(displayable_path(task.item.path)) @@ -875,46 +1010,21 @@ def item_progress(config): task.set_choice(action.ASIS) -# Main driver. - -def run_import(**kwargs): - """Run an import. The keyword arguments are the same as those to - ImportConfig. +def group_albums(session): + """Group the items of a task by albumartist and album name and create a new + task for each album. Yield the tasks as a multi message. """ - config = ImportConfig(**kwargs) + def group(item): + return (item.albumartist or item.artist, item.album) - # Set up the pipeline. - if config.query is None: - stages = [read_tasks(config)] - else: - stages = [query_tasks(config)] - if config.singletons: - # Singleton importer. - if config.autot: - stages += [item_lookup(config), item_query(config)] - else: - stages += [item_progress(config)] - else: - # Whole-album importer. - if config.autot: - # Only look up and query the user when autotagging. - stages += [initial_lookup(config), user_query(config)] - else: - # When not autotagging, just display progress. - stages += [show_progress(config)] - stages += [apply_choices(config)] - for stage_func in plugins.import_stages(): - stages.append(plugin_stage(config, stage_func)) - stages += [manipulate_files(config)] - stages += [finalize(config)] - pl = pipeline.Pipeline(stages) + task = None + while True: + task = yield task + if task.should_skip(): + continue + tasks = [] + for _, items in itertools.groupby(task.items, group): + tasks.append(ImportTask(items=list(items))) + tasks.append(ImportTask.progress_sentinel(task.toppath, task.paths)) - # Run the pipeline. - try: - if config.threaded: - pl.run_parallel(QUEUE_SIZE) - else: - pl.run_sequential() - except ImportAbort: - # User aborted operation. Silently stop. - pass + task = pipeline.multiple(tasks) diff --git a/beets/library.py b/beets/library.py new file mode 100644 index 00000000..9102aff7 --- /dev/null +++ b/beets/library.py @@ -0,0 +1,1216 @@ +# This file is part of beets. +# Copyright 2013, Adrian Sampson. +# +# 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 core data store and collection logic for beets. +""" +import os +import re +import sys +import logging +import shlex +import unicodedata +import time +from lib.unidecode import unidecode +from beets.mediafile import MediaFile, MutagenError +from beets import plugins +from beets import util +from beets.util import bytestring_path, syspath, normpath, samefile +from beets.util.functemplate import Template +from beets import dbcore +from beets.dbcore import types +import beets + + + +# Library-specific query types. + + +class PathQuery(dbcore.FieldQuery): + """A query that matches all items under a given path.""" + def __init__(self, field, pattern, fast=True): + super(PathQuery, self).__init__(field, pattern, fast) + + # Match the path as a single file. + self.file_path = util.bytestring_path(util.normpath(pattern)) + # As a directory (prefix). + self.dir_path = util.bytestring_path(os.path.join(self.file_path, '')) + + def match(self, item): + return (item.path == self.file_path) or \ + item.path.startswith(self.dir_path) + + def clause(self): + dir_pat = buffer(self.dir_path + '%') + file_blob = buffer(self.file_path) + return '({0} = ?) || ({0} LIKE ?)'.format(self.field), \ + (file_blob, dir_pat) + + +class SingletonQuery(dbcore.Query): + """Matches either singleton or non-singleton items.""" + def __init__(self, sense): + self.sense = sense + + def clause(self): + if self.sense: + return "album_id ISNULL", () + else: + return "NOT album_id ISNULL", () + + def match(self, item): + return (not item.album_id) == self.sense + + + +# Library-specific field types. + + +class DateType(types.Type): + sql = u'REAL' + query = dbcore.query.DateQuery + + def format(self, value): + return time.strftime(beets.config['time_format'].get(unicode), + time.localtime(value or 0)) + + def parse(self, string): + try: + # Try a formatted date string. + return time.mktime( + time.strptime(string, beets.config['time_format'].get(unicode)) + ) + except ValueError: + # Fall back to a plain timestamp number. + try: + return float(string) + except ValueError: + return 0.0 + + +class PathType(types.Type): + sql = u'BLOB' + query = PathQuery + + def format(self, value): + return util.displayable_path(value) + + def parse(self, string): + return normpath(bytestring_path(string)) + + + +# Model field lists. + + +# Fields in the "items" database table; all the metadata available for +# items in the library. These are used directly in SQL; they are +# vulnerable to injection if accessible to the user. +# Each tuple has the following values: +# - The name of the field. +# - The (Python) type of the field. +# - Is the field writable? +# - Does the field reflect an attribute of a MediaFile? +ITEM_FIELDS = [ + ('id', types.Id(), False, False), + ('path', PathType(), False, False), + ('album_id', types.Integer(), False, False), + + ('title', types.String(), True, True), + ('artist', types.String(), True, True), + ('artist_sort', types.String(), True, True), + ('artist_credit', types.String(), True, True), + ('album', types.String(), True, True), + ('albumartist', types.String(), True, True), + ('albumartist_sort', types.String(), True, True), + ('albumartist_credit', types.String(), True, True), + ('genre', types.String(), True, True), + ('composer', types.String(), True, True), + ('grouping', types.String(), True, True), + ('year', types.PaddedInt(4), True, True), + ('month', types.PaddedInt(2), True, True), + ('day', types.PaddedInt(2), True, True), + ('track', types.PaddedInt(2), True, True), + ('tracktotal', types.PaddedInt(2), True, True), + ('disc', types.PaddedInt(2), True, True), + ('disctotal', types.PaddedInt(2), True, True), + ('lyrics', types.String(), True, True), + ('comments', types.String(), True, True), + ('bpm', types.Integer(), True, True), + ('comp', types.Boolean(), True, True), + ('mb_trackid', types.String(), True, True), + ('mb_albumid', types.String(), True, True), + ('mb_artistid', types.String(), True, True), + ('mb_albumartistid', types.String(), True, True), + ('albumtype', types.String(), True, True), + ('label', types.String(), True, True), + ('acoustid_fingerprint', types.String(), True, True), + ('acoustid_id', types.String(), True, True), + ('mb_releasegroupid', types.String(), True, True), + ('asin', types.String(), True, True), + ('catalognum', types.String(), True, True), + ('script', types.String(), True, True), + ('language', types.String(), True, True), + ('country', types.String(), True, True), + ('albumstatus', types.String(), True, True), + ('media', types.String(), True, True), + ('albumdisambig', types.String(), True, True), + ('disctitle', types.String(), True, True), + ('encoder', types.String(), True, True), + ('rg_track_gain', types.Float(), True, True), + ('rg_track_peak', types.Float(), True, True), + ('rg_album_gain', types.Float(), True, True), + ('rg_album_peak', types.Float(), True, True), + ('original_year', types.PaddedInt(4), True, True), + ('original_month', types.PaddedInt(2), True, True), + ('original_day', types.PaddedInt(2), True, True), + + ('length', types.Float(), False, True), + ('bitrate', types.ScaledInt(1000, u'kbps'), False, True), + ('format', types.String(), False, True), + ('samplerate', types.ScaledInt(1000, u'kHz'), False, True), + ('bitdepth', types.Integer(), False, True), + ('channels', types.Integer(), False, True), + ('mtime', DateType(), False, False), + ('added', DateType(), False, False), +] +ITEM_KEYS_WRITABLE = [f[0] for f in ITEM_FIELDS if f[3] and f[2]] +ITEM_KEYS_META = [f[0] for f in ITEM_FIELDS if f[3]] +ITEM_KEYS = [f[0] for f in ITEM_FIELDS] + +# Database fields for the "albums" table. +# The third entry in each tuple indicates whether the field reflects an +# identically-named field in the items table. +ALBUM_FIELDS = [ + ('id', types.Id(), False), + ('artpath', PathType(), False), + ('added', DateType(), True), + + ('albumartist', types.String(), True), + ('albumartist_sort', types.String(), True), + ('albumartist_credit', types.String(), True), + ('album', types.String(), True), + ('genre', types.String(), True), + ('year', types.PaddedInt(4), True), + ('month', types.PaddedInt(2), True), + ('day', types.PaddedInt(2), True), + ('tracktotal', types.PaddedInt(2), True), + ('disctotal', types.PaddedInt(2), True), + ('comp', types.Boolean(), True), + ('mb_albumid', types.String(), True), + ('mb_albumartistid', types.String(), True), + ('albumtype', types.String(), True), + ('label', types.String(), True), + ('mb_releasegroupid', types.String(), True), + ('asin', types.String(), True), + ('catalognum', types.String(), True), + ('script', types.String(), True), + ('language', types.String(), True), + ('country', types.String(), True), + ('albumstatus', types.String(), True), + ('media', types.String(), True), + ('albumdisambig', types.String(), True), + ('rg_album_gain', types.Float(), True), + ('rg_album_peak', types.Float(), True), + ('original_year', types.PaddedInt(4), True), + ('original_month', types.PaddedInt(2), True), + ('original_day', types.PaddedInt(2), True), +] +ALBUM_KEYS = [f[0] for f in ALBUM_FIELDS] +ALBUM_KEYS_ITEM = [f[0] for f in ALBUM_FIELDS if f[2]] + + +# Default search fields for each model. +ALBUM_DEFAULT_FIELDS = ('album', 'albumartist', 'genre') +ITEM_DEFAULT_FIELDS = ALBUM_DEFAULT_FIELDS + ('artist', 'title', 'comments') + + +# Special path format key. +PF_KEY_DEFAULT = 'default' + + +# Logger. +log = logging.getLogger('beets') +if not log.handlers: + log.addHandler(logging.StreamHandler()) +log.propagate = False # Don't propagate to root handler. + + +# A little SQL utility. +def _orelse(exp1, exp2): + """Generates an SQLite expression that evaluates to exp1 if exp1 is + non-null and non-empty or exp2 otherwise. + """ + return ('(CASE {0} WHEN NULL THEN {1} ' + 'WHEN "" THEN {1} ' + 'ELSE {0} END)').format(exp1, exp2) + + + +# Exceptions. + + +class FileOperationError(Exception): + """Indicates an error when interacting with a file on disk. + Possibilities include an unsupported media type, a permissions + error, and an unhandled Mutagen exception. + """ + def __init__(self, path, reason): + """Create an exception describing an operation on the file at + `path` with the underlying (chained) exception `reason`. + """ + super(FileOperationError, self).__init__(path, reason) + self.path = path + self.reason = reason + + def __unicode__(self): + """Get a string representing the error. Describes both the + underlying reason and the file path in question. + """ + return u'{0}: {1}'.format( + util.displayable_path(self.path), + unicode(self.reason) + ) + + def __str__(self): + return unicode(self).encode('utf8') + + +class ReadError(FileOperationError): + """An error while reading a file (i.e. in `Item.read`). + """ + def __unicode__(self): + return u'error reading ' + super(ReadError, self).__unicode__() + + +class WriteError(FileOperationError): + """An error while writing a file (i.e. in `Item.write`). + """ + def __unicode__(self): + return u'error writing ' + super(WriteError, self).__unicode__() + + + +# Item and Album model classes. + + +class LibModel(dbcore.Model): + """Shared concrete functionality for Items and Albums. + """ + _bytes_keys = ('path', 'artpath') + + def _template_funcs(self): + funcs = DefaultTemplateFunctions(self, self._db).functions() + funcs.update(plugins.template_funcs()) + return funcs + + def store(self): + super(LibModel, self).store() + plugins.send('database_change', lib=self._db) + + def remove(self): + super(LibModel, self).remove() + plugins.send('database_change', lib=self._db) + + def add(self, lib=None): + super(LibModel, self).add(lib) + plugins.send('database_change', lib=self._db) + + +class Item(LibModel): + _fields = dict((name, typ) for (name, typ, _, _) in ITEM_FIELDS) + _table = 'items' + _flex_table = 'item_attributes' + _search_fields = ITEM_DEFAULT_FIELDS + + @classmethod + def _getters(cls): + return plugins.item_field_getters() + + @classmethod + def from_path(cls, path): + """Creates a new item from the media file at the specified path. + """ + # Initiate with values that aren't read from files. + i = cls(album_id=None) + i.read(path) + i.mtime = i.current_mtime() # Initial mtime. + return i + + def __setitem__(self, key, value): + """Set the item's value for a standard field or a flexattr. + """ + # Encode unicode paths and read buffers. + if key == 'path': + if isinstance(value, unicode): + value = bytestring_path(value) + elif isinstance(value, buffer): + value = str(value) + + if key in ITEM_KEYS_WRITABLE: + self.mtime = 0 # Reset mtime on dirty. + + super(Item, self).__setitem__(key, value) + + def update(self, values): + """Sett all key/value pairs in the mapping. If mtime is + specified, it is not reset (as it might otherwise be). + """ + super(Item, self).update(values) + if self.mtime == 0 and 'mtime' in values: + self.mtime = values['mtime'] + + def get_album(self): + """Get the Album object that this item belongs to, if any, or + None if the item is a singleton or is not associated with a + library. + """ + if not self._db: + return None + return self._db.get_album(self) + + + # Interaction with file metadata. + + def read(self, read_path=None): + """Read the metadata from the associated file. If read_path is + specified, read metadata from that file instead. + + Raises a `ReadError` if the file could not be read. + """ + if read_path is None: + read_path = self.path + else: + read_path = normpath(read_path) + try: + f = MediaFile(syspath(read_path)) + except (OSError, IOError) as exc: + raise ReadError(read_path, exc) + + for key in ITEM_KEYS_META: + value = getattr(f, key) + if isinstance(value, (int, long)): + # Filter values wider than 64 bits (in signed + # representation). SQLite cannot store them. + # py26: Post transition, we can use: + # value.bit_length() > 63 + if abs(value) >= 2 ** 63: + value = 0 + setattr(self, key, value) + + # Database's mtime should now reflect the on-disk value. + if read_path == self.path: + self.mtime = self.current_mtime() + + self.path = read_path + + def write(self): + """Write the item's metadata to the associated file. + + Can raise either a `ReadError` or a `WriteError`. + """ + try: + f = MediaFile(syspath(self.path)) + except (OSError, IOError) as exc: + raise ReadError(self.path, exc) + + plugins.send('write', item=self) + + for key in ITEM_KEYS_WRITABLE: + setattr(f, key, self[key]) + try: + f.save(id3v23=beets.config['id3v23'].get(bool)) + except (OSError, IOError, MutagenError) as exc: + raise WriteError(self.path, exc) + + # The file has a new mtime. + self.mtime = self.current_mtime() + plugins.send('after_write', item=self) + + + # Files themselves. + + def move_file(self, dest, copy=False): + """Moves or copies the item's file, updating the path value if + the move succeeds. If a file exists at ``dest``, then it is + slightly modified to be unique. + """ + if not util.samefile(self.path, dest): + dest = util.unique_path(dest) + if copy: + util.copy(self.path, dest) + plugins.send("item_copied", item=self, source=self.path, + destination=dest) + else: + util.move(self.path, dest) + plugins.send("item_moved", item=self, source=self.path, + destination=dest) + + # Either copying or moving succeeded, so update the stored path. + self.path = dest + + def current_mtime(self): + """Returns the current mtime of the file, rounded to the nearest + integer. + """ + return int(os.path.getmtime(syspath(self.path))) + + + # Model methods. + + def remove(self, delete=False, with_album=True): + """Removes the item. If `delete`, then the associated file is + removed from disk. If `with_album`, then the item's album (if + any) is removed if it the item was the last in the album. + """ + super(Item, self).remove() + + # Remove the album if it is empty. + if with_album: + album = self.get_album() + if album and not album.items(): + album.remove(delete, False) + + # Send a 'item_removed' signal to plugins + plugins.send('item_removed', item=self) + + # Delete the associated file. + if delete: + util.remove(self.path) + util.prune_dirs(os.path.dirname(self.path), self._db.directory) + + self._db._memotable = {} + + def move(self, copy=False, basedir=None, with_album=True): + """Move the item to its designated location within the library + directory (provided by destination()). Subdirectories are + created as needed. If the operation succeeds, the item's path + field is updated to reflect the new location. + + If copy is True, moving the file is copied rather than moved. + + basedir overrides the library base directory for the + destination. + + If the item is in an album, the album is given an opportunity to + move its art. (This can be disabled by passing + with_album=False.) + + The item is stored to the database if it is in the database, so + any dirty fields prior to the move() call will be written as a + side effect. You probably want to call save() to commit the DB + transaction. + """ + self._check_db() + dest = self.destination(basedir=basedir) + + # Create necessary ancestry for the move. + util.mkdirall(dest) + + # Perform the move and store the change. + old_path = self.path + self.move_file(dest, copy) + self.store() + + # If this item is in an album, move its art. + if with_album: + album = self.get_album() + if album: + album.move_art(copy) + album.store() + + # Prune vacated directory. + if not copy: + util.prune_dirs(os.path.dirname(old_path), self._db.directory) + + + # Templating. + + def _formatted_mapping(self, for_path=False): + """Get a mapping containing string-formatted values from either + this item or the associated album, if any. + """ + mapping = super(Item, self)._formatted_mapping(for_path) + + # Merge in album-level fields. + album = self.get_album() + if album: + for key in album.keys(True): + if key in ALBUM_KEYS_ITEM or key not in ITEM_KEYS: + mapping[key] = album._get_formatted(key, for_path) + + # Use the album artist if the track artist is not set and + # vice-versa. + if not mapping['artist']: + mapping['artist'] = mapping['albumartist'] + if not mapping['albumartist']: + mapping['albumartist'] = mapping['artist'] + + return mapping + + def destination(self, fragment=False, basedir=None, platform=None, + path_formats=None): + """Returns the path in the library directory designated for the + item (i.e., where the file ought to be). fragment makes this + method return just the path fragment underneath the root library + directory; the path is also returned as Unicode instead of + encoded as a bytestring. basedir can override the library's base + directory for the destination. + """ + self._check_db() + platform = platform or sys.platform + basedir = basedir or self._db.directory + path_formats = path_formats or self._db.path_formats + + # Use a path format based on a query, falling back on the + # default. + for query, path_format in path_formats: + if query == PF_KEY_DEFAULT: + continue + query = get_query(query, type(self)) + if query.match(self): + # The query matches the item! Use the corresponding path + # format. + break + else: + # No query matched; fall back to default. + for query, path_format in path_formats: + if query == PF_KEY_DEFAULT: + break + else: + assert False, "no default path format" + if isinstance(path_format, Template): + subpath_tmpl = path_format + else: + subpath_tmpl = Template(path_format) + + # Evaluate the selected template. + subpath = self.evaluate_template(subpath_tmpl, True) + + # Prepare path for output: normalize Unicode characters. + if platform == 'darwin': + subpath = unicodedata.normalize('NFD', subpath) + else: + subpath = unicodedata.normalize('NFC', subpath) + # Truncate components and remove forbidden characters. + subpath = util.sanitize_path(subpath, self._db.replacements) + # Encode for the filesystem. + if not fragment: + subpath = bytestring_path(subpath) + + # Preserve extension. + _, extension = os.path.splitext(self.path) + if fragment: + # Outputting Unicode. + extension = extension.decode('utf8', 'ignore') + subpath += extension.lower() + + # Truncate too-long components. + maxlen = beets.config['max_filename_length'].get(int) + if not maxlen: + # When zero, try to determine from filesystem. + maxlen = util.max_filename_length(self._db.directory) + subpath = util.truncate_path(subpath, maxlen) + + if fragment: + return subpath + else: + return normpath(os.path.join(basedir, subpath)) + + +class Album(LibModel): + """Provides access to information about albums stored in a + library. Reflects the library's "albums" table, including album + art. + """ + _fields = dict((name, typ) for (name, typ, _) in ALBUM_FIELDS) + _table = 'albums' + _flex_table = 'album_attributes' + _search_fields = ALBUM_DEFAULT_FIELDS + + @classmethod + def _getters(cls): + # In addition to plugin-provided computed fields, also expose + # the album's directory as `path`. + getters = plugins.album_field_getters() + getters['path'] = Album.item_dir + return getters + + def __setitem__(self, key, value): + """Set the value of an album attribute.""" + if key == 'artpath': + if isinstance(value, unicode): + value = bytestring_path(value) + elif isinstance(value, buffer): + value = bytes(value) + super(Album, self).__setitem__(key, value) + + def items(self): + """Returns an iterable over the items associated with this + album. + """ + return self._db.items(dbcore.MatchQuery('album_id', self.id)) + + def remove(self, delete=False, with_items=True): + """Removes this album and all its associated items from the + library. If delete, then the items' files are also deleted + from disk, along with any album art. The directories + containing the album are also removed (recursively) if empty. + Set with_items to False to avoid removing the album's items. + """ + super(Album, self).remove() + + # Delete art file. + if delete: + artpath = self.artpath + if artpath: + util.remove(artpath) + + # Remove (and possibly delete) the constituent items. + if with_items: + for item in self.items(): + item.remove(delete, False) + + def move_art(self, copy=False): + """Move or copy any existing album art so that it remains in the + same directory as the items. + """ + old_art = self.artpath + if not old_art: + return + + new_art = self.art_destination(old_art) + if new_art == old_art: + return + + new_art = util.unique_path(new_art) + log.debug('moving album art %s to %s' % (old_art, new_art)) + if copy: + util.copy(old_art, new_art) + else: + util.move(old_art, new_art) + self.artpath = new_art + + # Prune old path when moving. + if not copy: + util.prune_dirs(os.path.dirname(old_art), + self._db.directory) + + def move(self, copy=False, basedir=None): + """Moves (or copies) all items to their destination. Any album + art moves along with them. basedir overrides the library base + directory for the destination. The album is stored to the + database, persisting any modifications to its metadata. + """ + basedir = basedir or self._db.directory + + # Ensure new metadata is available to items for destination + # computation. + self.store() + + # Move items. + items = list(self.items()) + for item in items: + item.move(copy, basedir=basedir, with_album=False) + + # Move art. + self.move_art(copy) + self.store() + + def item_dir(self): + """Returns the directory containing the album's first item, + provided that such an item exists. + """ + item = self.items().get() + if not item: + raise ValueError('empty album') + return os.path.dirname(item.path) + + def art_destination(self, image, item_dir=None): + """Returns a path to the destination for the album art image + for the album. `image` is the path of the image that will be + moved there (used for its extension). + + The path construction uses the existing path of the album's + items, so the album must contain at least one item or + item_dir must be provided. + """ + image = bytestring_path(image) + item_dir = item_dir or self.item_dir() + + filename_tmpl = Template(beets.config['art_filename'].get(unicode)) + subpath = self.evaluate_template(filename_tmpl, True) + subpath = util.sanitize_path(subpath, + replacements=self._db.replacements) + subpath = bytestring_path(subpath) + + _, ext = os.path.splitext(image) + dest = os.path.join(item_dir, subpath + ext) + + return bytestring_path(dest) + + def set_art(self, path, copy=True): + """Sets the album's cover art to the image at the given path. + The image is copied (or moved) into place, replacing any + existing art. + """ + path = bytestring_path(path) + oldart = self.artpath + artdest = self.art_destination(path) + + if oldart and samefile(path, oldart): + # Art already set. + return + elif samefile(path, artdest): + # Art already in place. + self.artpath = path + return + + # Normal operation. + if oldart == artdest: + util.remove(oldart) + artdest = util.unique_path(artdest) + if copy: + util.copy(path, artdest) + else: + util.move(path, artdest) + self.artpath = artdest + + def store(self): + """Update the database with the album information. The album's + tracks are also updated. + """ + # Get modified track fields. + track_updates = {} + for key in ALBUM_KEYS_ITEM: + if key in self._dirty: + track_updates[key] = self[key] + + with self._db.transaction(): + super(Album, self).store() + if track_updates: + for item in self.items(): + for key, value in track_updates.items(): + item[key] = value + item.store() + + + +# Query construction and parsing helpers. + + +PARSE_QUERY_PART_REGEX = re.compile( + # Non-capturing optional segment for the keyword. + r'(?:' + r'(\S+?)' # The field key. + r'(? (None, 'stapler', SubstringQuery) + 'color:red' -> ('color', 'red', SubstringQuery) + ':^Quiet' -> (None, '^Quiet', RegexpQuery) + 'color::b..e' -> ('color', 'b..e', RegexpQuery) + + Prefixes may be "escaped" with a backslash to disable the keying + behavior. + """ + part = part.strip() + match = PARSE_QUERY_PART_REGEX.match(part) + + assert match # Regex should always match. + key = match.group(1) + term = match.group(2).replace('\:', ':') + + # Match the search term against the list of prefixes. + for pre, query_class in prefixes.items(): + if term.startswith(pre): + return key, term[len(pre):], query_class + + # No matching prefix: use type-based or fallback/default query. + query_class = query_classes.get(key, default_class) + return key, term, query_class + + +def construct_query_part(query_part, model_cls): + """Create a query from a single query component, `query_part`, for + querying instances of `model_cls`. Return a `Query` instance. + """ + # Shortcut for empty query parts. + if not query_part: + return dbcore.query.TrueQuery() + + # Set up and parse the string. + query_classes = dict((k, t.query) for (k, t) in model_cls._fields.items()) + prefixes = {':': dbcore.query.RegexpQuery} + prefixes.update(plugins.queries()) + key, pattern, query_class = \ + parse_query_part(query_part, query_classes, prefixes) + + # No key specified. + if key is None: + if os.sep in pattern and 'path' in model_cls._fields: + # This looks like a path. + return PathQuery('path', pattern) + elif issubclass(query_class, dbcore.FieldQuery): + # The query type matches a specific field, but none was + # specified. So we use a version of the query that matches + # any field. + return dbcore.query.AnyFieldQuery(pattern, + model_cls._search_fields, + query_class) + else: + # Other query type. + return query_class(pattern) + + key = key.lower() + + # Singleton query (not a real field). + if key == 'singleton': + return SingletonQuery(util.str2bool(pattern)) + + # Other field. + else: + return query_class(key.lower(), pattern, key in model_cls._fields) + + +def query_from_strings(query_cls, model_cls, query_parts): + """Creates a collection query of type `query_cls` from a list of + strings in the format used by parse_query_part. `model_cls` + determines how queries are constructed from strings. + """ + subqueries = [] + for part in query_parts: + subqueries.append(construct_query_part(part, model_cls)) + if not subqueries: # No terms in query. + subqueries = [dbcore.query.TrueQuery()] + return query_cls(subqueries) + + +def get_query(val, model_cls): + """Takes a value which may be None, a query string, a query string + list, or a Query object, and returns a suitable Query object. + `model_cls` is the subclass of Model indicating which entity this + is a query for (i.e., Album or Item) and is used to determine which + fields are searched. + """ + # Convert a single string into a list of space-separated + # criteria. + if isinstance(val, basestring): + # A bug in Python < 2.7.3 prevents correct shlex splitting of + # Unicode strings. + # http://bugs.python.org/issue6988 + if isinstance(val, unicode): + val = val.encode('utf8') + val = [s.decode('utf8') for s in shlex.split(val)] + + if val is None: + return dbcore.query.TrueQuery() + elif isinstance(val, list) or isinstance(val, tuple): + return query_from_strings(dbcore.AndQuery, model_cls, val) + elif isinstance(val, dbcore.Query): + return val + else: + raise ValueError('query must be None or have type Query or str') + + + +# The Library: interface to the database. + + +class Library(dbcore.Database): + """A database of music containing songs and albums. + """ + _models = (Item, Album) + + def __init__(self, path='library.blb', + directory='~/Music', + path_formats=((PF_KEY_DEFAULT, + '$artist/$album/$track $title'),), + replacements=None): + if path != ':memory:': + self.path = bytestring_path(normpath(path)) + super(Library, self).__init__(path) + + self.directory = bytestring_path(normpath(directory)) + self.path_formats = path_formats + self.replacements = replacements + + self._memotable = {} # Used for template substitution performance. + + + # Adding objects to the database. + + def add(self, obj): + """Add the :class:`Item` or :class:`Album` object to the library + database. Return the object's new id. + """ + obj.add(self) + self._memotable = {} + return obj.id + + def add_album(self, items): + """Create a new album consisting of a list of items. The items + are added to the database if they don't yet have an ID. Return a + new :class:`Album` object. + """ + # Create the album structure using metadata from the first item. + values = dict((key, items[0][key]) for key in ALBUM_KEYS_ITEM) + album = Album(self, **values) + + # Add the album structure and set the items' album_id fields. + # Store or add the items. + with self.transaction(): + album.add(self) + for item in items: + item.album_id = album.id + if item.id is None: + item.add(self) + else: + item.store() + + return album + + + # Querying. + + def _fetch(self, model_cls, query, order_by=None): + """Parse a query and fetch. + """ + return super(Library, self)._fetch( + model_cls, get_query(query, model_cls), order_by + ) + + def albums(self, query=None): + """Get a sorted list of :class:`Album` objects matching the + given query. + """ + order = '{0}, album'.format( + _orelse("albumartist_sort", "albumartist") + ) + return self._fetch(Album, query, order) + + def items(self, query=None): + """Get a sorted list of :class:`Item` objects matching the given + query. + """ + order = '{0}, album, disc, track'.format( + _orelse("artist_sort", "artist") + ) + return self._fetch(Item, query, order) + + + # Convenience accessors. + + def get_item(self, id): + """Fetch an :class:`Item` by its ID. Returns `None` if no match is + found. + """ + return self._get(Item, id) + + def get_album(self, item_or_id): + """Given an album ID or an item associated with an album, return + an :class:`Album` object for the album. If no such album exists, + returns `None`. + """ + if isinstance(item_or_id, int): + album_id = item_or_id + else: + album_id = item_or_id.album_id + if album_id is None: + return None + return self._get(Album, album_id) + + + +# Default path template resources. + + +def _int_arg(s): + """Convert a string argument to an integer for use in a template + function. May raise a ValueError. + """ + return int(s.strip()) + + +class DefaultTemplateFunctions(object): + """A container class for the default functions provided to path + templates. These functions are contained in an object to provide + additional context to the functions -- specifically, the Item being + evaluated. + """ + _prefix = 'tmpl_' + + def __init__(self, item=None, lib=None): + """Paramaterize the functions. If `item` or `lib` is None, then + some functions (namely, ``aunique``) will always evaluate to the + empty string. + """ + self.item = item + self.lib = lib + + def functions(self): + """Returns a dictionary containing the functions defined in this + object. The keys are function names (as exposed in templates) + and the values are Python functions. + """ + out = {} + for key in self._func_names: + out[key[len(self._prefix):]] = getattr(self, key) + return out + + @staticmethod + def tmpl_lower(s): + """Convert a string to lower case.""" + return s.lower() + + @staticmethod + def tmpl_upper(s): + """Covert a string to upper case.""" + return s.upper() + + @staticmethod + def tmpl_title(s): + """Convert a string to title case.""" + return s.title() + + @staticmethod + def tmpl_left(s, chars): + """Get the leftmost characters of a string.""" + return s[0:_int_arg(chars)] + + @staticmethod + def tmpl_right(s, chars): + """Get the rightmost characters of a string.""" + return s[-_int_arg(chars):] + + @staticmethod + def tmpl_if(condition, trueval, falseval=u''): + """If ``condition`` is nonempty and nonzero, emit ``trueval``; + otherwise, emit ``falseval`` (if provided). + """ + try: + condition = _int_arg(condition) + except ValueError: + condition = condition.strip() + if condition: + return trueval + else: + return falseval + + @staticmethod + def tmpl_asciify(s): + """Translate non-ASCII characters to their ASCII equivalents. + """ + return unidecode(s) + + @staticmethod + def tmpl_time(s, format): + """Format a time value using `strftime`. + """ + cur_fmt = beets.config['time_format'].get(unicode) + return time.strftime(format, time.strptime(s, cur_fmt)) + + def tmpl_aunique(self, keys=None, disam=None): + """Generate a string that is guaranteed to be unique among all + albums in the library who share the same set of keys. A fields + from "disam" is used in the string if one is sufficient to + disambiguate the albums. Otherwise, a fallback opaque value is + used. Both "keys" and "disam" should be given as + whitespace-separated lists of field names. + """ + # Fast paths: no album, no item or library, or memoized value. + if not self.item or not self.lib: + return u'' + if self.item.album_id is None: + return u'' + memokey = ('aunique', keys, disam, self.item.album_id) + memoval = self.lib._memotable.get(memokey) + if memoval is not None: + return memoval + + keys = keys or 'albumartist album' + disam = disam or 'albumtype year label catalognum albumdisambig' + keys = keys.split() + disam = disam.split() + + album = self.lib.get_album(self.item) + if not album: + # Do nothing for singletons. + self.lib._memotable[memokey] = u'' + return u'' + + # Find matching albums to disambiguate with. + subqueries = [] + for key in keys: + value = getattr(album, key) + subqueries.append(dbcore.MatchQuery(key, value)) + albums = self.lib.albums(dbcore.AndQuery(subqueries)) + + # If there's only one album to matching these details, then do + # nothing. + if len(albums) == 1: + self.lib._memotable[memokey] = u'' + return u'' + + # Find the first disambiguator that distinguishes the albums. + for disambiguator in disam: + # Get the value for each album for the current field. + disam_values = set([getattr(a, disambiguator) for a in albums]) + + # If the set of unique values is equal to the number of + # albums in the disambiguation set, we're done -- this is + # sufficient disambiguation. + if len(disam_values) == len(albums): + break + + else: + # No disambiguator distinguished all fields. + res = u' {0}'.format(album.id) + self.lib._memotable[memokey] = res + return res + + # Flatten disambiguation value into a string. + disam_value = album._get_formatted(disambiguator, True) + res = u' [{0}]'.format(disam_value) + self.lib._memotable[memokey] = res + return res + + +# Get the name of tmpl_* functions in the above class. +DefaultTemplateFunctions._func_names = \ + [s for s in dir(DefaultTemplateFunctions) + if s.startswith(DefaultTemplateFunctions._prefix)] diff --git a/beets/mediafile.py b/beets/mediafile.py new file mode 100644 index 00000000..301e0f37 --- /dev/null +++ b/beets/mediafile.py @@ -0,0 +1,1672 @@ +# This file is part of beets. +# Copyright 2014, Adrian Sampson. +# +# 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. + +"""Handles low-level interfacing for files' tags. Wraps Mutagen to +automatically detect file types and provide a unified interface for a +useful subset of music files' tags. + +Usage: + + >>> f = MediaFile('Lucy.mp3') + >>> f.title + u'Lucy in the Sky with Diamonds' + >>> f.artist = 'The Beatles' + >>> f.save() + +A field will always return a reasonable value of the correct type, even +if no tag is present. If no value is available, the value will be false +(e.g., zero or the empty string). + +Internally ``MediaFile`` uses ``MediaField`` descriptors to access the +data from the tags. In turn ``MediaField`` uses a number of +``StorageStyle`` strategies to handle format specific logic. +""" +import mutagen +import mutagen.mp3 +import mutagen.oggopus +import mutagen.oggvorbis +import mutagen.mp4 +import mutagen.flac +import mutagen.monkeysaudio +import mutagen.asf +import datetime +import re +import base64 +import math +import struct +import imghdr +import os +import logging +import traceback +from beets.util.enumeration import enum + +__all__ = ['UnreadableFileError', 'FileTypeError', 'MediaFile'] + + + +# Logger. +log = logging.getLogger('beets') + + + +# Exceptions. + +class UnreadableFileError(Exception): + """Indicates a file that MediaFile can't read. + """ + pass + +class FileTypeError(UnreadableFileError): + """Raised for files that don't seem to have a type MediaFile + supports. + """ + pass + +class MutagenError(UnreadableFileError): + """Raised when Mutagen fails unexpectedly---probably due to a bug. + """ + + + +# Constants. + +# Human-readable type names. +TYPES = { + 'mp3': 'MP3', + 'aac': 'AAC', + 'alac': 'ALAC', + 'ogg': 'OGG', + 'opus': 'Opus', + 'flac': 'FLAC', + 'ape': 'APE', + 'wv': 'WavPack', + 'mpc': 'Musepack', + 'asf': 'Windows Media', +} + + + +# Utility. + +def _safe_cast(out_type, val): + """Try to covert val to out_type but never raise an exception. If + the value can't be converted, then a sensible default value is + returned. out_type should be bool, int, or unicode; otherwise, the + value is just passed through. + """ + if out_type == int: + if val is None: + return 0 + elif isinstance(val, int) or isinstance(val, float): + # Just a number. + return int(val) + else: + # Process any other type as a string. + if not isinstance(val, basestring): + val = unicode(val) + # Get a number from the front of the string. + val = re.match(r'[0-9]*', val.strip()).group(0) + if not val: + return 0 + else: + return int(val) + + elif out_type == bool: + if val is None: + return False + else: + try: + # Should work for strings, bools, ints: + return bool(int(val)) + except ValueError: + return False + + elif out_type == unicode: + if val is None: + return u'' + else: + if isinstance(val, str): + return val.decode('utf8', 'ignore') + elif isinstance(val, unicode): + return val + else: + return unicode(val) + + elif out_type == float: + if val is None: + return 0.0 + elif isinstance(val, int) or isinstance(val, float): + return float(val) + else: + if not isinstance(val, basestring): + val = unicode(val) + val = re.match(r'[\+-]?[0-9\.]*', val.strip()).group(0) + if not val: + return 0.0 + else: + return float(val) + + else: + return val + + + +# Image coding for ASF/WMA. + +def _unpack_asf_image(data): + """Unpack image data from a WM/Picture tag. Return a tuple + containing the MIME type, the raw image data, a type indicator, and + the image's description. + + This function is treated as "untrusted" and could throw all manner + of exceptions (out-of-bounds, etc.). We should clean this up + sometime so that the failure modes are well-defined. + """ + type, size = struct.unpack_from(" 0: + gain = math.log10(maxgain / 1000.0) * -10 + else: + # Invalid gain value found. + gain = 0.0 + + # SoundCheck stores peak values as the actual value of the sample, + # and again separately for the left and right channels. We need to + # convert this to a percentage of full scale, which is 32768 for a + # 16 bit sample. Once again, we play it safe by using the larger of + # the two values. + peak = max(soundcheck[6:8]) / 32768.0 + + return round(gain, 2), round(peak, 6) + +def _sc_encode(gain, peak): + """Encode ReplayGain gain/peak values as a Sound Check string. + """ + # SoundCheck stores the peak value as the actual value of the + # sample, rather than the percentage of full scale that RG uses, so + # we do a simple conversion assuming 16 bit samples. + peak *= 32768.0 + + # SoundCheck stores absolute RMS values in some unknown units rather + # than the dB values RG uses. We can calculate these absolute values + # from the gain ratio using a reference value of 1000 units. We also + # enforce the maximum value here, which is equivalent to about + # -18.2dB. + g1 = min(round((10 ** (gain / -10)) * 1000), 65534) + # Same as above, except our reference level is 2500 units. + g2 = min(round((10 ** (gain / -10)) * 2500), 65534) + + # The purpose of these values are unknown, but they also seem to be + # unused so we just use zero. + uk = 0 + values = (g1, g1, g2, g2, uk, uk, peak, peak, uk, uk) + return (u' %08X' * 10) % values + + + +# Cover art and other images. + + +def _image_mime_type(data): + """Return the MIME type of the image data (a bytestring). + """ + kind = imghdr.what(None, h=data) + if kind in ['gif', 'jpeg', 'png', 'tiff', 'bmp']: + return 'image/{0}'.format(kind) + elif kind == 'pgm': + return 'image/x-portable-graymap' + elif kind == 'pbm': + return 'image/x-portable-bitmap' + elif kind == 'ppm': + return 'image/x-portable-pixmap' + elif kind == 'xbm': + return 'image/x-xbitmap' + else: + return 'image/x-{0}'.format(kind) + + +class Image(object): + """Strucuture representing image data and metadata that can be + stored and retrieved from tags. + + The structure has four properties. + * ``data`` The binary data of the image + * ``desc`` An optional descritpion of the image + * ``type`` A string denoting the type in relation to the music. + Must be one of the ``TYPES`` enum. + * ``mime_type`` Read-only property that contains the mime type of + the binary data + """ + TYPES = enum([ + 'other', + 'icon', + 'other icon', + 'front', + 'back', + 'leaflet', + 'media', + 'lead artist', + 'artist', + 'conductor', + 'group', + 'composer', + 'lyricist', + 'recording location', + 'recording session', + 'performance', + 'screen capture', + 'fish', + 'illustration', + 'artist logo', + 'publisher logo', + ], name='TageImage.TYPES') + + def __init__(self, data, desc=None, type=None): + self.data = data + self.desc = desc + if isinstance(type, int): + type = self.TYPES[type] + self.type = type + + @property + def mime_type(self): + if self.data: + return _image_mime_type(self.data) + + @property + def type_index(self): + if self.type is None: + return None + return list(self.TYPES).index(self.type) + + + +# StorageStyle classes describe strategies for accessing values in +# Mutagen file objects. + +class StorageStyle(object): + """A strategy for storing a value for a certain tag format (or set + of tag formats). This basic StorageStyle describes simple 1:1 + mapping from raw values to keys in a Mutagen file object; subclasses + describe more sophisticated translations or format-specific access + strategies. + + MediaFile uses a StorageStyle via two methods: ``get()`` and + ``set()``. It passes a Mutagen file object to each. + + Internally, the StorageStyle implements ``get()`` and ``set()`` + using two steps that may be overridden by subtypes. To get a value, + the StorageStyle first calls ``fetch()`` to retrieve the value + corresponding to a key and then ``deserialize()`` to convert the raw + Mutagen value to a consumable Python value. Similarly, to set a + field, we call ``serialize()`` to encode the value and then + ``store()`` to assign the result into the Mutagen object. + + Each StorageStyle type has a class-level `formats` attribute that is + a list of strings indicating the formats that the style applies to. + MediaFile only uses StorageStyles that apply to the correct type for + a given audio file. + """ + + formats = ['FLAC', 'OggOpus', 'OggTheora', 'OggSpeex', 'OggVorbis', + 'OggFlac', 'APEv2File', 'WavPack', 'Musepack', 'MonkeysAudio'] + """List of mutagen classes the StorageStyle can handle. + """ + + def __init__(self, key, as_type=unicode, suffix=None, float_places=2): + """Create a basic storage strategy. Parameters: + + - `key`: The key on the Mutagen file object used to access the + field's data. + - `as_type`: The Python type that the value is stored as + internally (`unicode`, `int`, `bool`, or `bytes`). + - `suffix`: When `as_type` is a string type, append this before + storing the value. + - `float_places`: When the value is a floating-point number and + encoded as a string, the number of digits to store after the + decimal point. + """ + self.key = key + self.as_type = as_type + self.suffix = suffix + self.float_places = float_places + + # Convert suffix to correct string type. + if self.suffix and self.as_type is unicode: + self.suffix = self.as_type(self.suffix) + + # Getter. + + def get(self, mutagen_file): + """Get the value for the field using this style. + """ + return self.deserialize(self.fetch(mutagen_file)) + + def fetch(self, mutagen_file): + """Retrieve the raw value of for this tag from the Mutagen file + object. + """ + try: + return mutagen_file[self.key][0] + except KeyError: + return None + + def deserialize(self, mutagen_value): + """Given a raw value stored on a Mutagen object, decode and + return the represented value. + """ + if self.suffix and isinstance(mutagen_value, unicode) \ + and mutagen_value.endswith(self.suffix): + return mutagen_value[:-len(self.suffix)] + else: + return mutagen_value + + # Setter. + + def set(self, mutagen_file, value): + """Assign the value for the field using this style. + """ + self.store(mutagen_file, self.serialize(value)) + + def store(self, mutagen_file, value): + """Store a serialized value in the Mutagen file object. + """ + mutagen_file[self.key] = [value] + + def serialize(self, value): + """Convert the external Python value to a type that is suitable for + storing in a Mutagen file object. + """ + if isinstance(value, float) and self.as_type is unicode: + value = u'{0:.{1}f}'.format(value, self.float_places) + value = self.as_type(value) + elif self.as_type is unicode: + if isinstance(value, bool): + # Store bools as 1/0 instead of True/False. + value = unicode(int(bool(value))) + elif isinstance(value, str): + value = value.decode('utf8', 'ignore') + else: + value = unicode(value) + else: + value = self.as_type(value) + + if self.suffix: + value += self.suffix + + return value + + +class ListStorageStyle(StorageStyle): + """Abstract storage style that provides access to lists. + + The ListMediaField descriptor uses a ListStorageStyle via two + methods: ``get_list()`` and ``set_list()``. It passes a Mutagen file + object to each. + + Subclasses may overwrite ``fetch`` and ``store``. ``fetch`` must + return a (possibly empty) list and ``store`` receives a serialized + list of values as the second argument. + + The `serialize` and `deserialize` methods (from the base + `StorageStyle`) are still called with individual values. This class + handles packing and unpacking the values into lists. + """ + def get(self, mutagen_file): + """Get the first value in the field's value list. + """ + try: + return self.get_list(mutagen_file)[0] + except IndexError: + return None + + def get_list(self, mutagen_file): + """Get a list of all values for the field using this style. + """ + return [self.deserialize(item) for item in self.fetch(mutagen_file)] + + def fetch(self, mutagen_file): + """Get the list of raw (serialized) values. + """ + try: + return mutagen_file[self.key] + except KeyError: + return [] + + def set(self, mutagen_file, value): + """Set an individual value as the only value for the field using + this style. + """ + self.set_list(mutagen_file, [value]) + + def set_list(self, mutagen_file, values): + """Set all values for the field using this style. `values` + should be an iterable. + """ + self.store(mutagen_file, [self.serialize(value) for value in values]) + + def store(self, mutagen_file, values): + """Set the list of all raw (serialized) values for this field. + """ + mutagen_file[self.key] = values + + +class SoundCheckStorageStyleMixin(object): + """A mixin for storage styles that read and write iTunes SoundCheck + analysis values. The object must have an `index` field that + indicates which half of the gain/peak pair---0 or 1---the field + represents. + """ + def get(self, mutagen_file): + data = self.fetch(mutagen_file) + if data is None: + return 0 + else: + return _sc_decode(data)[self.index] + + def set(self, mutagen_file, value): + data = self.fetch(mutagen_file) + if data is None: + gain_peak = [0, 0] + else: + gain_peak = list(_sc_decode(data)) + gain_peak[self.index] = value or 0 + data = self.serialize(_sc_encode(*gain_peak)) + self.store(mutagen_file, data) + + +class ASFStorageStyle(ListStorageStyle): + """A general storage style for Windows Media/ASF files. + """ + formats = ['ASF'] + + def deserialize(self, data): + if isinstance(data, mutagen.asf.ASFBaseAttribute): + data = data.value + return data + + +class MP4StorageStyle(StorageStyle): + """A general storage style for MPEG-4 tags. + """ + formats = ['MP4'] + + def serialize(self, value): + value = super(MP4StorageStyle, self).serialize(value) + if self.key.startswith('----:') and isinstance(value, unicode): + value = value.encode('utf8') + return value + + +class MP4TupleStorageStyle(MP4StorageStyle): + """A style for storing values as part of a pair of numbers in an + MPEG-4 file. + """ + def __init__(self, key, index=0, **kwargs): + super(MP4TupleStorageStyle, self).__init__(key, **kwargs) + self.index = index + + def deserialize(self, mutagen_value): + items = mutagen_value or [] + packing_length = 2 + return list(items) + [0] * (packing_length - len(items)) + + def get(self, mutagen_file): + return super(MP4TupleStorageStyle, self).get(mutagen_file)[self.index] + + def set(self, mutagen_file, value): + if value is None: + value = 0 + items = self.deserialize(self.fetch(mutagen_file)) + items[self.index] = int(value) + self.store(mutagen_file, items) + + +class MP4ListStorageStyle(ListStorageStyle, MP4StorageStyle): + pass + + +class MP4SoundCheckStorageStyle(SoundCheckStorageStyleMixin, MP4StorageStyle): + def __init__(self, index=0, **kwargs): + super(MP4SoundCheckStorageStyle, self).__init__(**kwargs) + self.index = index + +class MP4BoolStorageStyle(MP4StorageStyle): + """A style for booleans in MPEG-4 files. (MPEG-4 has an atom type + specifically for representing booleans.) + """ + def get(self, mutagen_file): + try: + return mutagen_file[self.key] + except KeyError: + return None + + def get_list(self, mutagen_file): + raise NotImplementedError('MP4 bool storage does not support lists') + + def set(self, mutagen_file, value): + mutagen_file[self.key] = value + + def set_list(self, mutagen_file, values): + raise NotImplementedError('MP4 bool storage does not support lists') + + +class MP4ImageStorageStyle(MP4ListStorageStyle): + """Store images as MPEG-4 image atoms. Values are `Image` objects. + """ + def __init__(self, **kwargs): + super(MP4ImageStorageStyle, self).__init__(key='covr', **kwargs) + + def deserialize(self, data): + return Image(data) + + def serialize(self, image): + if image.mime_type == 'image/png': + kind = mutagen.mp4.MP4Cover.FORMAT_PNG + elif image.mime_type == 'image/jpeg': + kind = mutagen.mp4.MP4Cover.FORMAT_JPEG + else: + raise ValueError('MP4 files only supports PNG and JPEG images') + return mutagen.mp4.MP4Cover(image.data, kind) + + +class MP3StorageStyle(StorageStyle): + """Store data in ID3 frames. + """ + formats = ['MP3'] + + def __init__(self, key, id3_lang=None, **kwargs): + """Create a new ID3 storage style. `id3_lang` is the value for + the language field of newly created frames. + """ + self.id3_lang = id3_lang + super(MP3StorageStyle, self).__init__(key, **kwargs) + + def fetch(self, mutagen_file): + try: + return mutagen_file[self.key].text[0] + except KeyError: + return None + + def store(self, mutagen_file, value): + frame = mutagen.id3.Frames[self.key](encoding=3, text=[value]) + mutagen_file.tags.setall(self.key, [frame]) + + +class MP3ListStorageStyle(ListStorageStyle, MP3StorageStyle): + """Store lists of data in multiple ID3 frames. + """ + def fetch(self, mutagen_file): + try: + return mutagen_file[self.key].text + except KeyError: + return [] + + def store(self, mutagen_file, values): + frame = mutagen.id3.Frames[self.key](encoding=3, text=values) + mutagen_file.tags.setall(self.key, [frame]) + + +class MP3UFIDStorageStyle(MP3StorageStyle): + """Store data in a UFID ID3 frame with a particular owner. + """ + def __init__(self, owner, **kwargs): + self.owner = owner + super(MP3UFIDStorageStyle, self).__init__('UFID:' + owner, **kwargs) + + def fetch(self, mutagen_file): + try: + return mutagen_file[self.key].data + except KeyError: + return None + + def store(self, mutagen_file, value): + frames = mutagen_file.tags.getall(self.key) + for frame in frames: + # Replace existing frame data. + if frame.owner == self.owner: + frame.data = value + else: + # New frame. + frame = mutagen.id3.UFID(owner=self.owner, data=value) + mutagen_file.tags.setall(self.key, [frame]) + + +class MP3DescStorageStyle(MP3StorageStyle): + """Store data in a TXXX (or similar) ID3 frame. The frame is + selected based its ``desc`` field. + """ + def __init__(self, desc=u'', key='TXXX', **kwargs): + self.description = desc + super(MP3DescStorageStyle, self).__init__(key=key, **kwargs) + + def store(self, mutagen_file, value): + frames = mutagen_file.tags.getall(self.key) + if self.key != 'USLT': + value = [value] + + # try modifying in place + found = False + for frame in frames: + if frame.desc.lower() == self.description.lower(): + frame.text = value + found = True + + # need to make a new frame? + if not found: + frame = mutagen.id3.Frames[self.key]( + desc=str(self.description), text=value, encoding=3) + if self.id3_lang: + frame.lang = self.id3_lang + mutagen_file.tags.add(frame) + + def fetch(self, mutagen_file): + for frame in mutagen_file.tags.getall(self.key): + if frame.desc.lower() == self.description.lower(): + if self.key == 'USLT': + return frame.text + try: + return frame.text[0] + except IndexError: + return None + + +class MP3SlashPackStorageStyle(MP3StorageStyle): + """Store value as part of pair that is serialized as a slash- + separated string. + """ + def __init__(self, key, pack_pos=0, **kwargs): + super(MP3SlashPackStorageStyle, self).__init__(key, **kwargs) + self.pack_pos = pack_pos + + def _fetch_unpacked(self, mutagen_file): + data = self.fetch(mutagen_file) or '' + items = unicode(data).split('/') + packing_length = 2 + return list(items) + [None] * (packing_length - len(items)) + + def get(self, mutagen_file): + return self._fetch_unpacked(mutagen_file)[self.pack_pos] or 0 + + def set(self, mutagen_file, value): + items = self._fetch_unpacked(mutagen_file) + items[self.pack_pos] = value + if items[0] is None: + items[0] = 0 + if items[1] is None: + items.pop() # Do not store last value + self.store(mutagen_file, '/'.join(map(unicode, items))) + + +class MP3ImageStorageStyle(ListStorageStyle, MP3StorageStyle): + """Converts between APIC frames and ``Image`` instances. + + The `get_list` method inherited from ``ListStorageStyle`` returns a + list of ``Image``s. Similarily the `set_list` method accepts a + list of ``Image``s as its ``values`` arguemnt. + """ + def __init__(self): + super(MP3ImageStorageStyle, self).__init__(key='APIC') + self.as_type = str + + def deserialize(self, apic_frame): + """Convert APIC frame into Image.""" + return Image(data=apic_frame.data, desc=apic_frame.desc, + type=apic_frame.type) + + def fetch(self, mutagen_file): + return mutagen_file.tags.getall(self.key) + + def store(self, mutagen_file, frames): + mutagen_file.tags.setall(self.key, frames) + + def serialize(self, image): + """Return an APIC frame populated with data from ``image``. + """ + assert isinstance(image, Image) + frame = mutagen.id3.Frames[self.key]() + frame.data = image.data + frame.mime = image.mime_type + frame.desc = (image.desc or u'').encode('utf8') + frame.encoding = 3 # UTF-8 encoding of desc + frame.type = image.type_index or 3 # front cover + return frame + + +class MP3SoundCheckStorageStyle(SoundCheckStorageStyleMixin, + MP3DescStorageStyle): + def __init__(self, index=0, **kwargs): + super(MP3SoundCheckStorageStyle, self).__init__(**kwargs) + self.index = index + + +class ASFImageStorageStyle(ListStorageStyle): + """Store images packed into Windows Media/ASF byte array attributes. + Values are `Image` objects. + """ + formats = ['ASF'] + + def __init__(self): + super(ASFImageStorageStyle, self).__init__(key='WM/Picture') + + def deserialize(self, asf_picture): + mime, data, type, desc = _unpack_asf_image(asf_picture.value) + return Image(data, desc=desc, type=type) + + def serialize(self, image): + pic = mutagen.asf.ASFByteArrayAttribute() + pic.value = _pack_asf_image(image.mime_type, image.data, + type=image.type_index or 3, + description=image.desc or u'') + return pic + + +class VorbisImageStorageStyle(ListStorageStyle): + """Store images in Vorbis comments. Both legacy COVERART fields and + modern METADATA_BLOCK_PICTURE tags are supported. Data is + base64-encoded. Values are `Image` objects. + """ + formats = ['OggOpus', 'OggTheora', 'OggSpeex', 'OggVorbis', + 'OggFlac', 'APEv2File', 'WavPack', 'Musepack', 'MonkeysAudio'] + + def __init__(self): + super(VorbisImageStorageStyle, self).__init__( + key='metadata_block_picture') + self.as_type = str + + def fetch(self, mutagen_file): + images = [] + if 'metadata_block_picture' not in mutagen_file: + # Try legacy COVERART tags. + if 'coverart' in mutagen_file: + for data in mutagen_file['coverart']: + images.append(Image(base64.b64decode(data))) + return images + for data in mutagen_file["metadata_block_picture"]: + try: + pic = mutagen.flac.Picture(base64.b64decode(data)) + except (TypeError, AttributeError): + continue + images.append(Image(data=pic.data, desc=pic.desc, + type=pic.type)) + return images + + def store(self, mutagen_file, image_data): + # Strip all art, including legacy COVERART. + if 'coverart' in mutagen_file: + del mutagen_file['coverart'] + if 'coverartmime' in mutagen_file: + del mutagen_file['coverartmime'] + super(VorbisImageStorageStyle, self).store(mutagen_file, image_data) + + def serialize(self, image): + """Turn a Image into a base64 encoded FLAC picture block. + """ + pic = mutagen.flac.Picture() + pic.data = image.data + pic.type = image.type_index or 3 # Front cover + pic.mime = image.mime_type + pic.desc = image.desc or u'' + return base64.b64encode(pic.write()) + + +class FlacImageStorageStyle(ListStorageStyle): + """Converts between ``mutagen.flac.Picture`` and ``Image`` instances. + """ + formats = ['FLAC'] + + def __init__(self): + super(FlacImageStorageStyle, self).__init__(key='') + + def fetch(self, mutagen_file): + return mutagen_file.pictures + + def deserialize(self, flac_picture): + return Image(data=flac_picture.data, desc=flac_picture.desc, + type=flac_picture.type) + + def store(self, mutagen_file, pictures): + """``pictures`` is a list of mutagen.flac.Picture instances. + """ + mutagen_file.clear_pictures() + for pic in pictures: + mutagen_file.add_picture(pic) + + def serialize(self, image): + """Turn a Image into a mutagen.flac.Picture. + """ + pic = mutagen.flac.Picture() + pic.data = image.data + pic.type = image.type_index or 3 # Front cover + pic.mime = image.mime_type + pic.desc = image.desc or u'' + return pic + + + +# MediaField is a descriptor that represents a single logical field. It +# aggregates several StorageStyles describing how to access the data for +# each file type. + +class MediaField(object): + """A descriptor providing access to a particular (abstract) metadata + field. + """ + def __init__(self, *styles, **kwargs): + """Creates a new MediaField. + + - `styles`: `StorageStyle` instances that describe the strategy + for reading and writing the field in particular formats. + There must be at least one style for each possible file + format. + - `out_type`: the type of the value that should be returned when + getting this property. + """ + self.out_type = kwargs.get('out_type', unicode) + self._styles = styles + + def styles(self, mutagen_file): + """Yields the list of storage styles of this field that can + handle the MediaFile's format. + """ + for style in self._styles: + if mutagen_file.__class__.__name__ in style.formats: + yield style + + def __get__(self, mediafile, owner=None): + out = None + for style in self.styles(mediafile.mgfile): + out = style.get(mediafile.mgfile) + if out: + break + return _safe_cast(self.out_type, out) + + def __set__(self, mediafile, value): + if value is None: + value = self._none_value() + for style in self.styles(mediafile.mgfile): + style.set(mediafile.mgfile, value) + + def _none_value(self): + """Get an appropriate "null" value for this field's type. This + is used internally when setting the field to None. + """ + if self.out_type == int: + return 0 + elif self.out_type == float: + return 0.0 + elif self.out_type == bool: + return False + elif self.out_type == unicode: + return u'' + + +class ListMediaField(MediaField): + """Property descriptor that retrieves a list of multiple values from + a tag. + + Uses ``get_list`` and set_list`` methods of its ``StorageStyle`` + strategies to do the actual work. + """ + def __get__(self, mediafile, _): + values = [] + for style in self.styles(mediafile.mgfile): + values.extend(style.get_list(mediafile.mgfile)) + return [_safe_cast(self.out_type, value) for value in values] + + def __set__(self, mediafile, values): + for style in self.styles(mediafile.mgfile): + style.set_list(mediafile.mgfile, values) + + def single_field(self): + """Returns a ``MediaField`` descriptor that gets and sets the + first item. + """ + options = {'out_type': self.out_type} + return MediaField(*self._styles, **options) + + +class DateField(MediaField): + """Descriptor that handles serializing and deserializing dates + + The getter parses value from tags into a ``datetime.date`` instance + and setter serializes such an instance into a string. + + For granular access to year, month, and day, use the ``*_field`` + methods to create corresponding `DateItemField`s. + """ + def __init__(self, *date_styles, **kwargs): + """``date_styles`` is a list of ``StorageStyle``s to store and + retrieve the whole date from. The ``year`` option is an + additional list of fallback styles for the year. The year is + always set on this style, but is only retrieved if the main + storage styles do not return a value. + """ + super(DateField, self).__init__(*date_styles) + year_style = kwargs.get('year', None) + if year_style: + self._year_field = MediaField(*year_style) + + def __get__(self, mediafile, owner=None): + year, month, day = self._get_date_tuple(mediafile) + try: + return datetime.date( + year or datetime.MINYEAR, + month or 1, + day or 1 + ) + except ValueError: # Out of range values. + return datetime.date.min + + def __set__(self, mediafile, date): + self._set_date_tuple(mediafile, date.year, date.month, date.day) + + def _get_date_tuple(self, mediafile): + """Get a 3-item sequence representing the date consisting of a + year, month, and day number. Each number is either an integer or + None. + """ + # Get the underlying data and split on hyphens. + datestring = super(DateField, self).__get__(mediafile, None) + datestring = re.sub(r'[Tt ].*$', '', unicode(datestring)) + items = unicode(datestring).split('-') + + # Ensure that we have exactly 3 components, possibly by + # truncating or padding. + items = items[:3] + if len(items) < 3: + items += [None] * (3 - len(items)) + + # Use year field if year is missing. + if not items[0] and hasattr(self, '_year_field'): + items[0] = self._year_field.__get__(mediafile) + + # Convert each component to an integer if possible. + return [_safe_cast(int, item) for item in items] + + def _set_date_tuple(self, mediafile, year, month=None, day=None): + """Set the value of the field given a year, month, and day + number. Each number can be an integer or None to indicate an + unset component. + """ + date = [year or 0] + if month: + date.append(month) + if month and day: + date.append(day) + date = map(unicode, date) + super(DateField, self).__set__(mediafile, '-'.join(date)) + + if hasattr(self, '_year_field'): + self._year_field.__set__(mediafile, year) + + def year_field(self): + return DateItemField(self, 0) + + def month_field(self): + return DateItemField(self, 1) + + def day_field(self): + return DateItemField(self, 2) + + +class DateItemField(MediaField): + """Descriptor that gets and sets constituent parts of a `DateField`: + the month, day, or year. + """ + def __init__(self, date_field, item_pos): + self.date_field = date_field + self.item_pos = item_pos + + def __get__(self, mediafile, _): + return self.date_field._get_date_tuple(mediafile)[self.item_pos] + + def __set__(self, mediafile, value): + items = self.date_field._get_date_tuple(mediafile) + items[self.item_pos] = value + self.date_field._set_date_tuple(mediafile, *items) + + +class CoverArtField(MediaField): + """A descriptor that provides access to the *raw image data* for the + first image on a file. This is used for backwards compatibility: the + full `ImageListField` provides richer `Image` objects. + """ + def __init__(self): + pass + + def __get__(self, mediafile, _): + try: + return mediafile.images[0].data + except IndexError: + return None + + def __set__(self, mediafile, data): + if data: + mediafile.images = [Image(data=data)] + else: + mediafile.images = [] + + +class ImageListField(MediaField): + """Descriptor to access the list of images embedded in tags. + + The getter returns a list of `Image` instances obtained from + the tags. The setter accepts a list of `Image` instances to be + written to the tags. + """ + def __init__(self): + # The storage styles used here must implement the + # `ListStorageStyle` interface and get and set lists of + # `Image`s. + super(ImageListField, self).__init__( + MP3ImageStorageStyle(), + MP4ImageStorageStyle(), + ASFImageStorageStyle(), + VorbisImageStorageStyle(), + FlacImageStorageStyle(), + ) + + def __get__(self, mediafile, _): + images = [] + for style in self.styles(mediafile.mgfile): + images.extend(style.get_list(mediafile.mgfile)) + return images + + def __set__(self, mediafile, images): + for style in self.styles(mediafile.mgfile): + style.set_list(mediafile.mgfile, images) + + + +# MediaFile is a collection of fields. + + +class MediaFile(object): + """Represents a multimedia file on disk and provides access to its + metadata. + """ + def __init__(self, path): + """Constructs a new MediaFile reflecting the file at path. May + throw UnreadableFileError. + """ + self.path = path + + unreadable_exc = ( + mutagen.mp3.error, + mutagen.id3.error, + mutagen.flac.error, + mutagen.monkeysaudio.MonkeysAudioHeaderError, + mutagen.mp4.error, + mutagen.oggopus.error, + mutagen.oggvorbis.error, + mutagen.ogg.error, + mutagen.asf.error, + mutagen.apev2.error, + ) + try: + self.mgfile = mutagen.File(path) + except unreadable_exc as exc: + log.debug(u'header parsing failed: {0}'.format(unicode(exc))) + raise UnreadableFileError('Mutagen could not read file') + except IOError as exc: + if type(exc) == IOError: + # This is a base IOError, not a subclass from Mutagen or + # anywhere else. + raise + else: + log.debug(traceback.format_exc()) + raise MutagenError('Mutagen raised an exception') + except Exception as exc: + # Isolate bugs in Mutagen. + log.debug(traceback.format_exc()) + log.error('uncaught Mutagen exception in open: {0}'.format(exc)) + raise MutagenError('Mutagen raised an exception') + + if self.mgfile is None: # Mutagen couldn't guess the type + raise FileTypeError('file type unsupported by Mutagen') + elif type(self.mgfile).__name__ == 'M4A' or \ + type(self.mgfile).__name__ == 'MP4': + # This hack differentiates AAC and ALAC until we find a more + # deterministic approach. Mutagen only sets the sample rate + # for AAC files. See: + # https://github.com/sampsyo/beets/pull/295 + if hasattr(self.mgfile.info, 'sample_rate') and \ + self.mgfile.info.sample_rate > 0: + self.type = 'aac' + else: + self.type = 'alac' + elif type(self.mgfile).__name__ == 'ID3' or \ + type(self.mgfile).__name__ == 'MP3': + self.type = 'mp3' + elif type(self.mgfile).__name__ == 'FLAC': + self.type = 'flac' + elif type(self.mgfile).__name__ == 'OggOpus': + self.type = 'opus' + elif type(self.mgfile).__name__ == 'OggVorbis': + self.type = 'ogg' + elif type(self.mgfile).__name__ == 'MonkeysAudio': + self.type = 'ape' + elif type(self.mgfile).__name__ == 'WavPack': + self.type = 'wv' + elif type(self.mgfile).__name__ == 'Musepack': + self.type = 'mpc' + elif type(self.mgfile).__name__ == 'ASF': + self.type = 'asf' + else: + raise FileTypeError('file type %s unsupported by MediaFile' % + type(self.mgfile).__name__) + + # add a set of tags if it's missing + if self.mgfile.tags is None: + self.mgfile.add_tags() + + def save(self, id3v23=False): + """Write the object's tags back to the file. + + By default, MP3 files are saved with ID3v2.4 tags. You can use + the older ID3v2.3 standard by specifying the `id3v23` option. + """ + kwargs = {} + if id3v23 and self.type == 'mp3': + id3 = self.mgfile + if hasattr(id3, 'tags'): + # In case this is an MP3 object, not an ID3 object. + id3 = id3.tags + id3.update_to_v23() + kwargs['v2_version'] = 3 + + # Isolate bugs in Mutagen. + try: + self.mgfile.save(**kwargs) + except (IOError, OSError): + # Propagate these through: they don't represent Mutagen bugs. + raise + except Exception as exc: + log.debug(traceback.format_exc()) + log.error('uncaught Mutagen exception in save: {0}'.format(exc)) + raise MutagenError('Mutagen raised an exception') + + def delete(self): + """Remove the current metadata tag from the file. + """ + try: + self.mgfile.delete() + except NotImplementedError: + # For Mutagen types that don't support deletion (notably, + # ASF), just delete each tag individually. + for tag in self.mgfile.keys(): + del self.mgfile[tag] + + + # Field definitions. + + title = MediaField( + MP3StorageStyle('TIT2'), + MP4StorageStyle("\xa9nam"), + StorageStyle('TITLE'), + ASFStorageStyle('Title'), + ) + artist = MediaField( + MP3StorageStyle('TPE1'), + MP4StorageStyle("\xa9ART"), + StorageStyle('ARTIST'), + ASFStorageStyle('Author'), + ) + album = MediaField( + MP3StorageStyle('TALB'), + MP4StorageStyle("\xa9alb"), + StorageStyle('ALBUM'), + ASFStorageStyle('WM/AlbumTitle'), + ) + genres = ListMediaField( + MP3ListStorageStyle('TCON'), + MP4ListStorageStyle("\xa9gen"), + ListStorageStyle('GENRE'), + ASFStorageStyle('WM/Genre'), + ) + genre = genres.single_field() + + composer = MediaField( + MP3StorageStyle('TCOM'), + MP4StorageStyle("\xa9wrt"), + StorageStyle('COMPOSER'), + ASFStorageStyle('WM/Composer'), + ) + grouping = MediaField( + MP3StorageStyle('TIT1'), + MP4StorageStyle("\xa9grp"), + StorageStyle('GROUPING'), + ASFStorageStyle('WM/ContentGroupDescription'), + ) + track = MediaField( + MP3SlashPackStorageStyle('TRCK', pack_pos=0), + MP4TupleStorageStyle('trkn', index=0), + StorageStyle('TRACK'), + StorageStyle('TRACKNUMBER'), + ASFStorageStyle('WM/TrackNumber'), + out_type=int, + ) + tracktotal = MediaField( + MP3SlashPackStorageStyle('TRCK', pack_pos=1), + MP4TupleStorageStyle('trkn', index=1), + StorageStyle('TRACKTOTAL'), + StorageStyle('TRACKC'), + StorageStyle('TOTALTRACKS'), + ASFStorageStyle('TotalTracks'), + out_type=int, + ) + disc = MediaField( + MP3SlashPackStorageStyle('TPOS', pack_pos=0), + MP4TupleStorageStyle('disk', index=0), + StorageStyle('DISC'), + StorageStyle('DISCNUMBER'), + ASFStorageStyle('WM/PartOfSet'), + out_type=int, + ) + disctotal = MediaField( + MP3SlashPackStorageStyle('TPOS', pack_pos=1), + MP4TupleStorageStyle('disk', index=1), + StorageStyle('DISCTOTAL'), + StorageStyle('DISCC'), + StorageStyle('TOTALDISCS'), + ASFStorageStyle('TotalDiscs'), + out_type=int, + ) + lyrics = MediaField( + MP3DescStorageStyle(key='USLT'), + MP4StorageStyle("\xa9lyr"), + StorageStyle('LYRICS'), + ASFStorageStyle('WM/Lyrics'), + ) + comments = MediaField( + MP3DescStorageStyle(key='COMM'), + MP4StorageStyle("\xa9cmt"), + StorageStyle('DESCRIPTION'), + StorageStyle('COMMENT'), + ASFStorageStyle('WM/Comments'), + ) + bpm = MediaField( + MP3StorageStyle('TBPM'), + MP4StorageStyle('tmpo', as_type=int), + StorageStyle('BPM'), + ASFStorageStyle('WM/BeatsPerMinute'), + out_type=int, + ) + comp = MediaField( + MP3StorageStyle('TCMP'), + MP4BoolStorageStyle('cpil'), + StorageStyle('COMPILATION'), + ASFStorageStyle('WM/IsCompilation', as_type=bool), + out_type=bool, + ) + albumartist = MediaField( + MP3StorageStyle('TPE2'), + MP4StorageStyle('aART'), + StorageStyle('ALBUM ARTIST'), + StorageStyle('ALBUMARTIST'), + ASFStorageStyle('WM/AlbumArtist'), + ) + albumtype = MediaField( + MP3DescStorageStyle(u'MusicBrainz Album Type'), + MP4StorageStyle('----:com.apple.iTunes:MusicBrainz Album Type'), + StorageStyle('MUSICBRAINZ_ALBUMTYPE'), + ASFStorageStyle('MusicBrainz/Album Type'), + ) + label = MediaField( + MP3StorageStyle('TPUB'), + MP4StorageStyle('----:com.apple.iTunes:Label'), + MP4StorageStyle('----:com.apple.iTunes:publisher'), + StorageStyle('LABEL'), + StorageStyle('PUBLISHER'), # Traktor + ASFStorageStyle('WM/Publisher'), + ) + artist_sort = MediaField( + MP3StorageStyle('TSOP'), + MP4StorageStyle("soar"), + StorageStyle('ARTISTSORT'), + ASFStorageStyle('WM/ArtistSortOrder'), + ) + albumartist_sort = MediaField( + MP3DescStorageStyle(u'ALBUMARTISTSORT'), + MP4StorageStyle("soaa"), + StorageStyle('ALBUMARTISTSORT'), + ASFStorageStyle('WM/AlbumArtistSortOrder'), + ) + asin = MediaField( + MP3DescStorageStyle(u'ASIN'), + MP4StorageStyle("----:com.apple.iTunes:ASIN"), + StorageStyle('ASIN'), + ASFStorageStyle('MusicBrainz/ASIN'), + ) + catalognum = MediaField( + MP3DescStorageStyle(u'CATALOGNUMBER'), + MP4StorageStyle("----:com.apple.iTunes:CATALOGNUMBER"), + StorageStyle('CATALOGNUMBER'), + ASFStorageStyle('WM/CatalogNo'), + ) + disctitle = MediaField( + MP3StorageStyle('TSST'), + MP4StorageStyle("----:com.apple.iTunes:DISCSUBTITLE"), + StorageStyle('DISCSUBTITLE'), + ASFStorageStyle('WM/SetSubTitle'), + ) + encoder = MediaField( + MP3StorageStyle('TENC'), + MP4StorageStyle("\xa9too"), + StorageStyle('ENCODEDBY'), + StorageStyle('ENCODER'), + ASFStorageStyle('WM/EncodedBy'), + ) + script = MediaField( + MP3DescStorageStyle(u'Script'), + MP4StorageStyle("----:com.apple.iTunes:SCRIPT"), + StorageStyle('SCRIPT'), + ASFStorageStyle('WM/Script'), + ) + language = MediaField( + MP3StorageStyle('TLAN'), + MP4StorageStyle("----:com.apple.iTunes:LANGUAGE"), + StorageStyle('LANGUAGE'), + ASFStorageStyle('WM/Language'), + ) + country = MediaField( + MP3DescStorageStyle('MusicBrainz Album Release Country'), + MP4StorageStyle("----:com.apple.iTunes:MusicBrainz Album " + "Release Country"), + StorageStyle('RELEASECOUNTRY'), + ASFStorageStyle('MusicBrainz/Album Release Country'), + ) + albumstatus = MediaField( + MP3DescStorageStyle(u'MusicBrainz Album Status'), + MP4StorageStyle("----:com.apple.iTunes:MusicBrainz Album Status"), + StorageStyle('MUSICBRAINZ_ALBUMSTATUS'), + ASFStorageStyle('MusicBrainz/Album Status'), + ) + media = MediaField( + MP3StorageStyle('TMED'), + MP4StorageStyle("----:com.apple.iTunes:MEDIA"), + StorageStyle('MEDIA'), + ASFStorageStyle('WM/Media'), + ) + albumdisambig = MediaField( + # This tag mapping was invented for beets (not used by Picard, etc). + MP3DescStorageStyle(u'MusicBrainz Album Comment'), + MP4StorageStyle("----:com.apple.iTunes:MusicBrainz Album Comment"), + StorageStyle('MUSICBRAINZ_ALBUMCOMMENT'), + ASFStorageStyle('MusicBrainz/Album Comment'), + ) + + # Release date. + date = DateField( + MP3StorageStyle('TDRC'), + MP4StorageStyle("\xa9day"), + StorageStyle('DATE'), + ASFStorageStyle('WM/Year'), + year=(StorageStyle('YEAR'),)) + + year = date.year_field() + month = date.month_field() + day = date.day_field() + + # *Original* release date. + original_date = DateField( + MP3StorageStyle('TDOR'), + MP4StorageStyle('----:com.apple.iTunes:ORIGINAL YEAR'), + StorageStyle('ORIGINALDATE'), + ASFStorageStyle('WM/OriginalReleaseYear')) + + original_year = original_date.year_field() + original_month = original_date.month_field() + original_day = original_date.day_field() + + # Nonstandard metadata. + artist_credit = MediaField( + MP3DescStorageStyle(u'Artist Credit'), + MP4StorageStyle("----:com.apple.iTunes:Artist Credit"), + StorageStyle('ARTIST_CREDIT'), + ASFStorageStyle('beets/Artist Credit'), + ) + albumartist_credit = MediaField( + MP3DescStorageStyle(u'Album Artist Credit'), + MP4StorageStyle("----:com.apple.iTunes:Album Artist Credit"), + StorageStyle('ALBUMARTIST_CREDIT'), + ASFStorageStyle('beets/Album Artist Credit'), + ) + + # Legacy album art field + art = CoverArtField() + + # Image list + images = ImageListField() + + # MusicBrainz IDs. + mb_trackid = MediaField( + MP3UFIDStorageStyle(owner='http://musicbrainz.org'), + MP4StorageStyle('----:com.apple.iTunes:MusicBrainz Track Id'), + StorageStyle('MUSICBRAINZ_TRACKID'), + ASFStorageStyle('MusicBrainz/Track Id'), + ) + mb_albumid = MediaField( + MP3DescStorageStyle(u'MusicBrainz Album Id'), + MP4StorageStyle('----:com.apple.iTunes:MusicBrainz Album Id'), + StorageStyle('MUSICBRAINZ_ALBUMID'), + ASFStorageStyle('MusicBrainz/Album Id'), + ) + mb_artistid = MediaField( + MP3DescStorageStyle(u'MusicBrainz Artist Id'), + MP4StorageStyle('----:com.apple.iTunes:MusicBrainz Artist Id'), + StorageStyle('MUSICBRAINZ_ARTISTID'), + ASFStorageStyle('MusicBrainz/Artist Id'), + ) + mb_albumartistid = MediaField( + MP3DescStorageStyle(u'MusicBrainz Album Artist Id'), + MP4StorageStyle('----:com.apple.iTunes:MusicBrainz Album Artist Id'), + StorageStyle('MUSICBRAINZ_ALBUMARTISTID'), + ASFStorageStyle('MusicBrainz/Album Artist Id'), + ) + mb_releasegroupid = MediaField( + MP3DescStorageStyle(u'MusicBrainz Release Group Id'), + MP4StorageStyle('----:com.apple.iTunes:MusicBrainz Release Group Id'), + StorageStyle('MUSICBRAINZ_RELEASEGROUPID'), + ASFStorageStyle('MusicBrainz/Release Group Id'), + ) + + # Acoustid fields. + acoustid_fingerprint = MediaField( + MP3DescStorageStyle(u'Acoustid Fingerprint'), + MP4StorageStyle('----:com.apple.iTunes:Acoustid Fingerprint'), + StorageStyle('ACOUSTID_FINGERPRINT'), + ASFStorageStyle('Acoustid/Fingerprint'), + ) + acoustid_id = MediaField( + MP3DescStorageStyle(u'Acoustid Id'), + MP4StorageStyle('----:com.apple.iTunes:Acoustid Id'), + StorageStyle('ACOUSTID_ID'), + ASFStorageStyle('Acoustid/Id'), + ) + + # ReplayGain fields. + rg_track_gain = MediaField( + MP3DescStorageStyle(u'REPLAYGAIN_TRACK_GAIN', + float_places=2, suffix=u' dB'), + MP3DescStorageStyle(u'replaygain_track_gain', + float_places=2, suffix=u' dB'), + MP3SoundCheckStorageStyle(key='COMM', index=0, desc=u'iTunNORM', + id3_lang='eng'), + MP4StorageStyle(key='----:com.apple.iTunes:replaygain_track_gain', + float_places=2, suffix=b' dB'), + MP4SoundCheckStorageStyle(key='----:com.apple.iTunes:iTunNORM', + index=0), + StorageStyle(u'REPLAYGAIN_TRACK_GAIN', + float_places=2, suffix=u' dB'), + ASFStorageStyle(u'replaygain_track_gain', + float_places=2, suffix=u' dB'), + out_type=float + ) + rg_album_gain = MediaField( + MP3DescStorageStyle(u'REPLAYGAIN_ALBUM_GAIN', + float_places=2, suffix=u' dB'), + MP3DescStorageStyle(u'replaygain_album_gain', + float_places=2, suffix=u' dB'), + MP4SoundCheckStorageStyle(key='----:com.apple.iTunes:iTunNORM', + index=1), + StorageStyle(u'REPLAYGAIN_ALBUM_GAIN', + float_places=2, suffix=u' dB'), + ASFStorageStyle(u'replaygain_album_gain', + float_places=2, suffix=u' dB'), + out_type=float + ) + rg_track_peak = MediaField( + MP3DescStorageStyle(u'REPLAYGAIN_TRACK_PEAK', + float_places=6), + MP3DescStorageStyle(u'replaygain_track_peak', + float_places=6), + MP3SoundCheckStorageStyle(key='COMM', index=1, desc=u'iTunNORM', + id3_lang='eng'), + MP4StorageStyle('----:com.apple.iTunes:replaygain_track_peak', + float_places=6), + MP4SoundCheckStorageStyle(key='----:com.apple.iTunes:iTunNORM', + index=1), + StorageStyle(u'REPLAYGAIN_TRACK_PEAK', + float_places=6), + ASFStorageStyle(u'replaygain_track_peak', + float_places=6), + out_type=float, + ) + rg_album_peak = MediaField( + MP3DescStorageStyle(u'REPLAYGAIN_ALBUM_PEAK', + float_places=6), + MP3DescStorageStyle(u'replaygain_album_peak', + float_places=6), + MP4StorageStyle('----:com.apple.iTunes:replaygain_album_peak', + float_places=6), + StorageStyle(u'REPLAYGAIN_ALBUM_PEAK', + float_places=6), + ASFStorageStyle(u'replaygain_album_peak', + float_places=6), + out_type=float, + ) + + @property + def length(self): + """The duration of the audio in seconds (a float).""" + return self.mgfile.info.length + + @property + def samplerate(self): + """The audio's sample rate (an int).""" + if hasattr(self.mgfile.info, 'sample_rate'): + return self.mgfile.info.sample_rate + elif self.type == 'opus': + # Opus is always 48kHz internally. + return 48000 + return 0 + + @property + def bitdepth(self): + """The number of bits per sample in the audio encoding (an int). + Only available for certain file formats (zero where + unavailable). + """ + if hasattr(self.mgfile.info, 'bits_per_sample'): + return self.mgfile.info.bits_per_sample + return 0 + + @property + def channels(self): + """The number of channels in the audio (an int).""" + if isinstance(self.mgfile.info, mutagen.mp3.MPEGInfo): + return { + mutagen.mp3.STEREO: 2, + mutagen.mp3.JOINTSTEREO: 2, + mutagen.mp3.DUALCHANNEL: 2, + mutagen.mp3.MONO: 1, + }[self.mgfile.info.mode] + if hasattr(self.mgfile.info, 'channels'): + return self.mgfile.info.channels + return 0 + + @property + def bitrate(self): + """The number of bits per seconds used in the audio coding (an + int). If this is provided explicitly by the compressed file + format, this is a precise reflection of the encoding. Otherwise, + it is estimated from the on-disk file size. In this case, some + imprecision is possible because the file header is incorporated + in the file size. + """ + if hasattr(self.mgfile.info, 'bitrate') and self.mgfile.info.bitrate: + # Many formats provide it explicitly. + return self.mgfile.info.bitrate + else: + # Otherwise, we calculate bitrate from the file size. (This + # is the case for all of the lossless formats.) + if not self.length: + # Avoid division by zero if length is not available. + return 0 + size = os.path.getsize(self.path) + return int(size * 8 / self.length) + + @property + def format(self): + """A string describing the file format/codec.""" + return TYPES[self.type] diff --git a/lib/beets/plugins.py b/beets/plugins.py similarity index 66% rename from lib/beets/plugins.py rename to beets/plugins.py index b6ceabc7..6a58777c 100755 --- a/lib/beets/plugins.py +++ b/beets/plugins.py @@ -1,5 +1,5 @@ # This file is part of beets. -# Copyright 2011, Adrian Sampson. +# Copyright 2013, Adrian Sampson. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -15,14 +15,13 @@ """Support for beets plugins.""" import logging -import itertools import traceback from collections import defaultdict -from lib.beets import mediafile +import beets +from beets import mediafile PLUGIN_NAMESPACE = 'beetsplug' -DEFAULT_PLUGINS = [] # Plugins using the Last.fm API can share the same API key. LASTFM_KEY = '2dc3914abf35f0d9c92d97d8f8e42b43' @@ -38,12 +37,19 @@ class BeetsPlugin(object): functionality by defining a subclass of BeetsPlugin and overriding the abstract methods defined here. """ - def __init__(self): - """Perform one-time plugin setup. There is probably no reason to - override this method. + def __init__(self, name=None): + """Perform one-time plugin setup. """ _add_media_fields(self.item_fields()) self.import_stages = [] + self.name = name or self.__module__.split('.')[-1] + self.config = beets.config[self.name] + if not self.template_funcs: + self.template_funcs = {} + if not self.template_fields: + self.template_fields = {} + if not self.album_template_fields: + self.album_template_fields = {} def commands(self): """Should return a list of beets.ui.Subcommand objects for @@ -51,36 +57,35 @@ class BeetsPlugin(object): """ return () + def queries(self): + """Should return a dict mapping prefixes to Query subclasses. + """ + return {} + def track_distance(self, item, info): - """Should return a (distance, distance_max) pair to be added - to the distance value for every track comparison. + """Should return a Distance object to be added to the + distance for every track comparison. """ - return 0.0, 0.0 + return beets.autotag.hooks.Distance() - def album_distance(self, items, info): - """Should return a (distance, distance_max) pair to be added - to the distance value for every album-level comparison. + def album_distance(self, items, album_info, mapping): + """Should return a Distance object to be added to the + distance for every album-level comparison. """ - return 0.0, 0.0 + return beets.autotag.hooks.Distance() - def candidates(self, items): + def candidates(self, items, artist, album, va_likely): """Should return a sequence of AlbumInfo objects that match the album whose items are provided. """ return () - def item_candidates(self, item): + def item_candidates(self, item, artist, title): """Should return a sequence of TrackInfo objects that match the item provided. """ return () - def configure(self, config): - """This method is called with the ConfigParser object after - the CLI starts up. - """ - pass - def item_fields(self): """Returns field descriptors to be added to the MediaFile class, in the form of a dictionary whose keys are field names and whose @@ -89,6 +94,19 @@ class BeetsPlugin(object): """ return {} + def album_for_id(self, album_id): + """Return an AlbumInfo object or None if no matching release was + found. + """ + return None + + def track_for_id(self, track_id): + """Return a TrackInfo object or None if no matching release was + found. + """ + return None + + listeners = None @classmethod @@ -123,6 +141,7 @@ class BeetsPlugin(object): template_funcs = None template_fields = None + album_template_fields = None @classmethod def template_func(cls, name): @@ -151,24 +170,30 @@ class BeetsPlugin(object): return func return helper +_classes = set() def load_plugins(names=()): """Imports the modules for a sequence of plugin names. Each name must be the name of a Python module under the "beetsplug" namespace package in sys.path; the module indicated should contain the - BeetsPlugin subclasses desired. A default set of plugins is also - loaded. + BeetsPlugin subclasses desired. """ - for name in itertools.chain(names, DEFAULT_PLUGINS): + for name in names: modname = '%s.%s' % (PLUGIN_NAMESPACE, name) try: try: - __import__(modname, None, None) + namespace = __import__(modname, None, None) except ImportError as exc: # Again, this is hacky: if exc.args[0].endswith(' ' + name): log.warn('** plugin %s not found' % name) else: raise + else: + for obj in getattr(namespace, name).__dict__.values(): + if isinstance(obj, type) and issubclass(obj, BeetsPlugin) \ + and obj != BeetsPlugin and obj not in _classes: + _classes.add(obj) + except: log.warn('** error loading plugin %s' % name) log.warn(traceback.format_exc()) @@ -181,7 +206,7 @@ def find_plugins(): """ load_plugins() plugins = [] - for cls in BeetsPlugin.__subclasses__(): + for cls in _classes: # Only instantiate each plugin class once. if cls not in _instances: _instances[cls] = cls() @@ -199,48 +224,68 @@ def commands(): out += plugin.commands() return out +def queries(): + """Returns a dict mapping prefix strings to Query subclasses all loaded + plugins. + """ + out = {} + for plugin in find_plugins(): + out.update(plugin.queries()) + return out + def track_distance(item, info): """Gets the track distance calculated by all loaded plugins. - Returns a (distance, distance_max) pair. + Returns a Distance object. """ - dist = 0.0 - dist_max = 0.0 + from beets.autotag.hooks import Distance + dist = Distance() for plugin in find_plugins(): - d, dm = plugin.track_distance(item, info) - dist += d - dist_max += dm - return dist, dist_max + dist.update(plugin.track_distance(item, info)) + return dist -def album_distance(items, info): +def album_distance(items, album_info, mapping): """Returns the album distance calculated by plugins.""" - dist = 0.0 - dist_max = 0.0 + from beets.autotag.hooks import Distance + dist = Distance() for plugin in find_plugins(): - d, dm = plugin.album_distance(items, info) - dist += d - dist_max += dm - return dist, dist_max + dist.update(plugin.album_distance(items, album_info, mapping)) + return dist -def candidates(items): +def candidates(items, artist, album, va_likely): """Gets MusicBrainz candidates for an album from each plugin. """ out = [] for plugin in find_plugins(): - out.extend(plugin.candidates(items)) + out.extend(plugin.candidates(items, artist, album, va_likely)) return out -def item_candidates(item): +def item_candidates(item, artist, title): """Gets MusicBrainz candidates for an item from the plugins. """ out = [] for plugin in find_plugins(): - out.extend(plugin.item_candidates(item)) + out.extend(plugin.item_candidates(item, artist, title)) return out -def configure(config): - """Sends the configuration object to each plugin.""" +def album_for_id(album_id): + """Get AlbumInfo objects for a given ID string. + """ + out = [] for plugin in find_plugins(): - plugin.configure(config) + res = plugin.album_for_id(album_id) + if res: + out.append(res) + return out + +def track_for_id(track_id): + """Get TrackInfo objects for a given ID string. + """ + out = [] + for plugin in find_plugins(): + res = plugin.track_for_id(track_id) + if res: + out.append(res) + return out def template_funcs(): """Get all the template functions declared by plugins as a @@ -252,17 +297,6 @@ def template_funcs(): funcs.update(plugin.template_funcs) return funcs -def template_values(item): - """Get all the template values computed for a given Item by - registered field computations. - """ - values = {} - for plugin in find_plugins(): - if plugin.template_fields: - for name, func in plugin.template_fields.iteritems(): - values[name] = unicode(func(item)) - return values - def _add_media_fields(fields): """Adds a {name: descriptor} dictionary of fields to the MediaFile class. Called during the plugin initialization. @@ -279,6 +313,28 @@ def import_stages(): return stages +# New-style (lazy) plugin-provided fields. + +def item_field_getters(): + """Get a dictionary mapping field names to unary functions that + compute the field's value. + """ + funcs = {} + for plugin in find_plugins(): + if plugin.template_fields: + funcs.update(plugin.template_fields) + return funcs + +def album_field_getters(): + """As above, for album fields. + """ + funcs = {} + for plugin in find_plugins(): + if plugin.album_template_fields: + funcs.update(plugin.album_template_fields) + return funcs + + # Event dispatch. def event_handlers(): @@ -297,10 +353,7 @@ def send(event, **arguments): name of the event to send, all other named arguments go to the event handler(s). - Returns the number of handlers called. + Returns a list of return values from the handlers. """ log.debug('Sending event: %s' % event) - handlers = event_handlers()[event] - for handler in handlers: - handler(**arguments) - return len(handlers) + return [handler(**arguments) for handler in event_handlers()[event]] diff --git a/lib/beets/ui/__init__.py b/beets/ui/__init__.py similarity index 58% rename from lib/beets/ui/__init__.py rename to beets/ui/__init__.py index b18eec87..2df74ea7 100644 --- a/lib/beets/ui/__init__.py +++ b/beets/ui/__init__.py @@ -1,5 +1,5 @@ # This file is part of beets. -# Copyright 2012, Adrian Sampson. +# Copyright 2014, Adrian Sampson. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -18,25 +18,29 @@ CLI commands are implemented in the ui.commands module. """ from __future__ import print_function -import os import locale import optparse import textwrap -import ConfigParser import sys from difflib import SequenceMatcher import logging import sqlite3 import errno import re -import codecs +import struct +import traceback + +from beets import library +from beets import plugins +from beets import util +from beets.util.functemplate import Template +from beets import config +from beets.util import confit +from beets.autotag import mb -from lib.beets import library -from lib.beets import plugins -from lib.beets import util -from lib.beets.util.functemplate import Template # On Windows platforms, use colorama to support "ANSI" terminal colors. + if sys.platform == 'win32': try: import colorama @@ -46,40 +50,36 @@ if sys.platform == 'win32': colorama.init() + # Constants. -CONFIG_PATH_VAR = 'BEETSCONFIG' -DEFAULT_CONFIG_FILENAME_UNIX = '.beetsconfig' -DEFAULT_CONFIG_FILENAME_WINDOWS = 'beetsconfig.ini' -DEFAULT_LIBRARY_FILENAME_UNIX = '.beetsmusic.blb' -DEFAULT_LIBRARY_FILENAME_WINDOWS = 'beetsmusic.blb' -DEFAULT_DIRECTORY_NAME = 'Music' -WINDOWS_BASEDIR = os.environ.get('APPDATA') or '~' + + PF_KEY_QUERIES = { 'comp': 'comp:true', 'singleton': 'singleton:true', } -DEFAULT_PATH_FORMATS = [ - (library.PF_KEY_DEFAULT, - Template('$albumartist/$album%aunique{}/$track $title')), - (PF_KEY_QUERIES['singleton'], - Template('Non-Album/$artist/$title')), - (PF_KEY_QUERIES['comp'], - Template('Compilations/$album%aunique{}/$track $title')), -] -DEFAULT_ART_FILENAME = 'cover' -DEFAULT_TIMEOUT = 5.0 -NULL_REPLACE = '' # UI exception. Commands should throw this in order to display # nonrecoverable errors to the user. class UserError(Exception): pass +# Main logger. +log = logging.getLogger('beets') + + # Utilities. + def _encoding(): - """Tries to guess the encoding uses by the terminal.""" + """Tries to guess the encoding used by the terminal.""" + # Configured override? + encoding = config['terminal_encoding'].get() + if encoding: + return encoding + + # Determine from locale settings. try: return locale.getdefaultlocale()[1] or 'utf8' except ValueError: @@ -87,12 +87,14 @@ def _encoding(): # failing entirely for no good reason, assume UTF-8. return 'utf8' + def decargs(arglist): """Given a list of command-line argument bytestrings, attempts to decode them to Unicode strings. """ return [s.decode(_encoding()) for s in arglist] + def print_(*strings): """Like print, but rather than raising an error when a character is not in the terminal's encoding's character set, just silently @@ -109,6 +111,7 @@ def print_(*strings): txt = txt.encode(_encoding(), 'replace') print(txt) + def input_(prompt=None): """Like `raw_input`, but decodes the result to a Unicode string. Raises a UserError if stdin is not available. The prompt is sent to @@ -128,10 +131,11 @@ def input_(prompt=None): except EOFError: raise UserError('stdin stream ended while input required') - return resp.decode(sys.stdin.encoding, 'ignore') + return resp.decode(sys.stdin.encoding or 'utf8', 'ignore') + def input_options(options, require=False, prompt=None, fallback_prompt=None, - numrange=None, default=None, color=False, max_width=72): + numrange=None, default=None, max_width=72): """Prompts a user for input. The sequence of `options` defines the choices the user has. A single-letter shortcut is inferred for each option; the user's choice is returned as that single, lower-case @@ -139,10 +143,9 @@ def input_options(options, require=False, prompt=None, fallback_prompt=None, a particular shortcut is desired; in that case, only that letter should be capitalized. - By default, the first option is the default. If `require` is - provided, then there is no default. `default` can be provided to - override this. The prompt and fallback prompt are also inferred but - can be overridden. + By default, the first option is the default. `default` can be provided to + override this. If `require` is provided, then there is no default. The + prompt and fallback prompt are also inferred but can be overridden. If numrange is provided, it is a pair of `(high, low)` (both ints) indicating that, in addition to `options`, the user may enter an @@ -178,9 +181,9 @@ def input_options(options, require=False, prompt=None, fallback_prompt=None, index = option.index(found_letter) # Mark the option's shortcut letter for display. - if (default is None and not numrange and first) \ - or (isinstance(default, basestring) and - found_letter.lower() == default.lower()): + if not require and ((default is None and not numrange and first) or + (isinstance(default, basestring) and + found_letter.lower() == default.lower())): # The first option is the default; mark it. show_letter = '[%s]' % found_letter.upper() is_default = True @@ -188,24 +191,23 @@ def input_options(options, require=False, prompt=None, fallback_prompt=None, show_letter = found_letter.upper() is_default = False - # Possibly colorize the letter shortcut. - if color: - color = 'turquoise' if is_default else 'blue' - show_letter = colorize(color, show_letter) + # Colorize the letter shortcut. + show_letter = colorize('turquoise' if is_default else 'blue', + show_letter) # Insert the highlighted letter back into the word. capitalized.append( - option[:index] + show_letter + option[index+1:] + option[:index] + show_letter + option[index + 1:] ) display_letters.append(found_letter.upper()) first = False # The default is just the first option if unspecified. - if default is None: - if require: - default = None - elif numrange: + if require: + default = None + elif default is None: + if numrange: default = numrange[0] else: default = display_letters[0].lower() @@ -217,8 +219,7 @@ def input_options(options, require=False, prompt=None, fallback_prompt=None, if numrange: if isinstance(default, int): default_name = str(default) - if color: - default_name = colorize('turquoise', default_name) + default_name = colorize('turquoise', default_name) tmpl = '# selection (default %s)' prompt_parts.append(tmpl % default_name) prompt_part_lengths.append(len(tmpl % str(default))) @@ -291,35 +292,16 @@ def input_options(options, require=False, prompt=None, fallback_prompt=None, # Prompt for new input. resp = input_(fallback_prompt) -def input_yn(prompt, require=False, color=False): + +def input_yn(prompt, require=False): """Prompts the user for a "yes" or "no" response. The default is "yes" unless `require` is `True`, in which case there is no default. """ sel = input_options( - ('y', 'n'), require, prompt, 'Enter Y or N:', color=color + ('y', 'n'), require, prompt, 'Enter Y or N:' ) return sel == 'y' -def config_val(config, section, name, default, vtype=None): - """Queries the configuration file for a value (given by the section - and name). If no value is present, returns default. vtype - optionally specifies the return type (although only ``bool`` and - ``list`` are supported for now). - """ - if not config.has_section(section): - config.add_section(section) - - try: - if vtype is bool: - return config.getboolean(section, name) - elif vtype is list: - # Whitespace-separated strings. - strval = config.get(section, name, True) - return strval.split() - else: - return config.get(section, name, True) - except ConfigParser.NoOptionError: - return default def human_bytes(size): """Formats size, a number of bytes, in a human-readable way.""" @@ -330,6 +312,7 @@ def human_bytes(size): size /= 1024.0 return "big" + def human_seconds(interval): """Formats interval, a number of seconds, as a human-readable time interval using English words. @@ -343,9 +326,9 @@ def human_seconds(interval): (52, 'year'), (10, 'decade'), ] - for i in range(len(units)-1): + for i in range(len(units) - 1): increment, suffix = units[i] - next_increment, _ = units[i+1] + next_increment, _ = units[i + 1] interval /= float(increment) if interval < next_increment: break @@ -356,6 +339,7 @@ def human_seconds(interval): return "%3.1f %ss" % (interval, suffix) + def human_seconds_short(interval): """Formats a number of seconds as a short human-readable M:SS string. @@ -363,6 +347,7 @@ def human_seconds_short(interval): interval = int(interval) return u'%i:%02i' % (interval // 60, interval % 60) + # ANSI terminal colorization code heavily inspired by pygments: # http://dev.pocoo.org/hg/pygments-main/file/b2deea5b5030/pygments/console.py # (pygments is by Tim Hatch, Armin Ronacher, et al.) @@ -372,7 +357,7 @@ DARK_COLORS = ["black", "darkred", "darkgreen", "brown", "darkblue", LIGHT_COLORS = ["darkgray", "red", "green", "yellow", "blue", "fuchsia", "turquoise", "white"] RESET_COLOR = COLOR_ESCAPE + "39;49;00m" -def colorize(color, text): +def _colorize(color, text): """Returns a string that prints the given text in the given color in a terminal that is ANSI color-aware. The color must be something in DARK_COLORS or LIGHT_COLORS. @@ -385,7 +370,18 @@ def colorize(color, text): raise ValueError('no such color %s', color) return escape + text + RESET_COLOR -def colordiff(a, b, highlight='red'): + +def colorize(color, text): + """Colorize text if colored output is enabled. (Like _colorize but + conditional.) + """ + if config['color']: + return _colorize(color, text) + else: + return text + + +def _colordiff(a, b, highlight='red', minor_highlight='lightgray'): """Given two values, return the same pair of strings except with their differences highlighted in the specified color. Strings are highlighted intelligently to show differences; other values are @@ -400,6 +396,11 @@ def colordiff(a, b, highlight='red'): else: return colorize(highlight, a), colorize(highlight, b) + if isinstance(a, bytes) or isinstance(b, bytes): + # A path field. + a = util.displayable_path(a) + b = util.displayable_path(b) + a_out = [] b_out = [] @@ -416,100 +417,220 @@ def colordiff(a, b, highlight='red'): # Left only. a_out.append(colorize(highlight, a[a_start:a_end])) elif op == 'replace': - # Right and left differ. - a_out.append(colorize(highlight, a[a_start:a_end])) - b_out.append(colorize(highlight, b[b_start:b_end])) + # Right and left differ. Colorise with second highlight if + # it's just a case change. + if a[a_start:a_end].lower() != b[b_start:b_end].lower(): + color = highlight + else: + color = minor_highlight + a_out.append(colorize(color, a[a_start:a_end])) + b_out.append(colorize(color, b[b_start:b_end])) else: assert(False) return u''.join(a_out), u''.join(b_out) -def default_paths(pathmod=None): - """Produces the appropriate default config, library, and directory - paths for the current system. On Unix, this is always in ~. On - Windows, tries ~ first and then $APPDATA for the config and library - files (for backwards compatibility). + +def colordiff(a, b, highlight='red'): + """Colorize differences between two values if color is enabled. + (Like _colordiff but conditional.) """ - pathmod = pathmod or os.path - windows = pathmod.__name__ == 'ntpath' - if windows: - windata = os.environ.get('APPDATA') or '~' - - # Shorthand for joining paths. - def exp(*vals): - return pathmod.expanduser(pathmod.join(*vals)) - - config = exp('~', DEFAULT_CONFIG_FILENAME_UNIX) - if windows and not pathmod.exists(config): - config = exp(windata, DEFAULT_CONFIG_FILENAME_WINDOWS) - - libpath = exp('~', DEFAULT_LIBRARY_FILENAME_UNIX) - if windows and not pathmod.exists(libpath): - libpath = exp(windata, DEFAULT_LIBRARY_FILENAME_WINDOWS) - - libdir = exp('~', DEFAULT_DIRECTORY_NAME) - - return config, libpath, libdir - -def _get_replacements(config): - """Given a ConfigParser, get the list of replacement pairs. If no - replacements are specified, returns None. Otherwise, returns a list - of (compiled regex, replacement string) pairs. - """ - repl_string = config_val(config, 'beets', 'replace', None) - if not repl_string: - return - if not isinstance(repl_string, unicode): - repl_string = repl_string.decode('utf8') - - parts = repl_string.strip().split() - if not parts: - return - if len(parts) % 2 != 0: - # Must have an even number of parts. - raise UserError(u'"replace" config value must consist of' - u' pattern/replacement pairs') - - out = [] - for index in xrange(0, len(parts), 2): - pattern = parts[index] - replacement = parts[index+1] - if replacement.lower() == NULL_REPLACE: - replacement = '' - out.append((re.compile(pattern), replacement)) - return out - -def _get_path_formats(config): - """Returns a list of path formats (query/template pairs); reflecting - the config's specified path formats. - """ - legacy_path_format = config_val(config, 'beets', 'path_format', None) - if legacy_path_format: - # Old path formats override the default values. - path_formats = [(library.PF_KEY_DEFAULT, - Template(legacy_path_format))] + if config['color']: + return _colordiff(a, b, highlight) else: - # If no legacy path format, use the defaults instead. - path_formats = DEFAULT_PATH_FORMATS + return unicode(a), unicode(b) - if config.has_section('paths'): - custom_path_formats = [] - for key, value in config.items('paths', True): - if key in PF_KEY_QUERIES: - # Special values that indicate simple queries. - key = PF_KEY_QUERIES[key] - elif key != library.PF_KEY_DEFAULT: - # For non-special keys (literal queries), the _ - # character denotes a :. - key = key.replace('_', ':') - custom_path_formats.append((key, Template(value))) - path_formats = custom_path_formats + path_formats +def color_diff_suffix(a, b, highlight='red'): + """Colorize the differing suffix between two strings.""" + a, b = unicode(a), unicode(b) + if not config['color']: + return a, b + + # Fast path. + if a == b: + return a, b + + # Find the longest common prefix. + first_diff = None + for i in range(min(len(a), len(b))): + if a[i] != b[i]: + first_diff = i + break + else: + first_diff = min(len(a), len(b)) + + # Colorize from the first difference on. + return a[:first_diff] + colorize(highlight, a[first_diff:]), \ + b[:first_diff] + colorize(highlight, b[first_diff:]) + + +def get_path_formats(subview=None): + """Get the configuration's path formats as a list of query/template + pairs. + """ + path_formats = [] + subview = subview or config['paths'] + for query, view in subview.items(): + query = PF_KEY_QUERIES.get(query, query) # Expand common queries. + path_formats.append((query, Template(view.get(unicode)))) return path_formats +def get_replacements(): + """Confit validation function that reads regex/string pairs. + """ + replacements = [] + for pattern, repl in config['replace'].get(dict).items(): + repl = repl or '' + try: + replacements.append((re.compile(pattern), repl)) + except re.error: + raise UserError( + u'malformed regular expression in replace: {0}'.format( + pattern + ) + ) + return replacements + + +def get_plugin_paths(): + """Get the list of search paths for plugins from the config file. + The value for "pluginpath" may be a single string or a list of + strings. + """ + pluginpaths = config['pluginpath'].get() + if isinstance(pluginpaths, basestring): + pluginpaths = [pluginpaths] + if not isinstance(pluginpaths, list): + raise confit.ConfigTypeError( + u'pluginpath must be string or a list of strings' + ) + return map(util.normpath, pluginpaths) + + +def _pick_format(album, fmt=None): + """Pick a format string for printing Album or Item objects, + falling back to config options and defaults. + """ + if fmt: + return fmt + if album: + return config['list_format_album'].get(unicode) + else: + return config['list_format_item'].get(unicode) + + +def print_obj(obj, lib, fmt=None): + """Print an Album or Item object. If `fmt` is specified, use that + format string. Otherwise, use the configured template. + """ + album = isinstance(obj, library.Album) + fmt = _pick_format(album, fmt) + if isinstance(fmt, Template): + template = fmt + else: + template = Template(fmt) + print_(obj.evaluate_template(template)) + + +def term_width(): + """Get the width (columns) of the terminal.""" + fallback = config['ui']['terminal_width'].get(int) + + # The fcntl and termios modules are not available on non-Unix + # platforms, so we fall back to a constant. + try: + import fcntl + import termios + except ImportError: + return fallback + + try: + buf = fcntl.ioctl(0, termios.TIOCGWINSZ, ' ' * 4) + except IOError: + return fallback + try: + height, width = struct.unpack('hh', buf) + except struct.error: + return fallback + return width + + +FLOAT_EPSILON = 0.01 +def _field_diff(field, old, new): + """Given two Model objects, format their values for `field` and + highlight changes among them. Return a human-readable string. If the + value has not changed, return None instead. + """ + oldval = old.get(field) + newval = new.get(field) + + # If no change, abort. + if isinstance(oldval, float) and isinstance(newval, float) and \ + abs(oldval - newval) < FLOAT_EPSILON: + return None + elif oldval == newval: + return None + + # Get formatted values for output. + oldstr = old._get_formatted(field) + newstr = new._get_formatted(field) + + # For strings, highlight changes. For others, colorize the whole + # thing. + if isinstance(oldval, basestring): + oldstr, newstr = colordiff(oldval, newval) + else: + oldstr, newstr = colorize('red', oldstr), colorize('red', newstr) + + return u'{0} -> {1}'.format(oldstr, newstr) + + +def show_model_changes(new, old=None, fields=None, always=False): + """Given a Model object, print a list of changes from its pristine + version stored in the database. Return a boolean indicating whether + any changes were found. + + `old` may be the "original" object to avoid using the pristine + version from the database. `fields` may be a list of fields to + restrict the detection to. `always` indicates whether the object is + always identified, regardless of whether any changes are present. + """ + old = old or new._db._get(type(new), new.id) + + # Build up lines showing changed fields. + changes = [] + for field in old: + # Subset of the fields. Never show mtime. + if field == 'mtime' or (fields and field not in fields): + continue + + # Detect and show difference for this field. + line = _field_diff(field, old, new) + if line: + changes.append(u' {0}: {1}'.format(field, line)) + + # New fields. + for field in set(new) - set(old): + changes.append(u' {0}: {1}'.format( + field, + colorize('red', new._get_formatted(field)) + )) + + # Print changes. + if changes or always: + print_obj(old, old._db) + if changes: + print_(u'\n'.join(changes)) + + return bool(changes) + + + # Subcommand parsing infrastructure. + # This is a fairly generic subcommand parser for optparse. It is # maintained externally here: # http://gist.github.com/462717 @@ -520,7 +641,7 @@ class Subcommand(object): """A subcommand of a root command-line application that may be invoked by a SubcommandOptionParser. """ - def __init__(self, name, parser=None, help='', aliases=()): + def __init__(self, name, parser=None, help='', aliases=(), hide=False): """Creates a new subcommand. name is the primary way to invoke the subcommand; aliases are alternate names. parser is an OptionParser responsible for parsing the subcommand's options. @@ -531,6 +652,7 @@ class Subcommand(object): self.parser = parser or optparse.OptionParser() self.aliases = aliases self.help = help + self.hide = hide class SubcommandsOptionParser(optparse.OptionParser): """A variant of OptionParser that parses subcommands and their @@ -588,7 +710,8 @@ class SubcommandsOptionParser(optparse.OptionParser): # Also determine the help position. disp_names = [] help_position = 0 - for subcommand in self.subcommands: + subcommands = [c for c in self.subcommands if not c.hide] + for subcommand in subcommands: name = subcommand.name if subcommand.aliases: name += ' (%s)' % ', '.join(subcommand.aliases) @@ -600,7 +723,7 @@ class SubcommandsOptionParser(optparse.OptionParser): help_position = max(help_position, proposed_help_position) # Add each subcommand to the output. - for subcommand, name in zip(self.subcommands, disp_names): + for subcommand, name in zip(subcommands, disp_names): # Lifted directly from optparse.py. name_width = help_position - formatter.current_indent - 2 if len(name) > name_width: @@ -641,7 +764,14 @@ class SubcommandsOptionParser(optparse.OptionParser): - subargs: the positional arguments passed to the subcommand """ options, args = optparse.OptionParser.parse_args(self, a, v) + subcommand, suboptions, subargs = self._parse_sub(args) + return options, subcommand, suboptions, subargs + def _parse_sub(self, args): + """Given the `args` left unused by a typical OptionParser + `parse_args`, return the invoked subcommand, the subcommand + options, and the subcommand arguments. + """ if not args: # No command given. self.print_help() @@ -668,108 +798,183 @@ class SubcommandsOptionParser(optparse.OptionParser): self.print_help() self.exit() - return options, subcommand, suboptions, subargs + return subcommand, suboptions, subargs -# The root parser and its main function. +optparse.Option.ALWAYS_TYPED_ACTIONS += ('callback',) +def vararg_callback(option, opt_str, value, parser): + """Callback for an option with variable arguments. + Manually collect arguments right of a callback-action + option (ie. with action="callback"), and add the resulting + list to the destination var. -def main(args=None, configfh=None): - """Run the main command-line interface for beets.""" - # Get the default subcommands. - from lib.beets.ui.commands import default_commands + Usage: + parser.add_option("-c", "--callback", dest="vararg_attr", + action="callback", callback=vararg_callback) - # Get default file paths. - default_config, default_libpath, default_dir = default_paths() + Details: + http://docs.python.org/2/library/optparse.html#callback-example-6-variable + -arguments + """ + value = [value] - # Read defaults from config file. - config = ConfigParser.SafeConfigParser() - if configfh: - configpath = None - elif CONFIG_PATH_VAR in os.environ: - configpath = os.path.expanduser(os.environ[CONFIG_PATH_VAR]) - else: - configpath = default_config - if configpath: - configpath = util.syspath(configpath) - if os.path.exists(util.syspath(configpath)): - configfh = codecs.open(configpath, 'r', encoding='utf-8') - else: - configfh = None - if configfh: - config.readfp(configfh) + def floatable(str): + try: + float(str) + return True + except ValueError: + return False + for arg in parser.rargs: + # stop on --foo like options + if arg[:2] == "--" and len(arg) > 2: + break + # stop on -a, but not on -3 or -3.0 + if arg[:1] == "-" and len(arg) > 1 and not floatable(arg): + break + value.append(arg) + + del parser.rargs[:len(value) - 1] + setattr(parser.values, option.dest, value) + + + +# The main entry point and bootstrapping. + + +def _load_plugins(): + """Load the plugins specified in the configuration. + """ # Add plugin paths. - plugpaths = config_val(config, 'beets', 'pluginpath', '') - for plugpath in plugpaths.split(':'): - sys.path.append(os.path.expanduser(plugpath)) + import beetsplug + beetsplug.__path__ = get_plugin_paths() + beetsplug.__path__ + + # For backwards compatibility. + sys.path += get_plugin_paths() + # Load requested plugins. - plugnames = config_val(config, 'beets', 'plugins', '') - plugins.load_plugins(plugnames.split()) + plugins.load_plugins(config['plugins'].as_str_seq()) plugins.send("pluginload") - plugins.configure(config) + + +def _configure(args): + """Parse the command line, load configuration files (including + loading any indicated plugins), and return the invoked subcomand, + the subcommand options, and the subcommand arguments. + """ + # Temporary: Migrate from 1.0-style configuration. + from beets.ui import migrate + migrate.automigrate() + + # Get the default subcommands. + from beets.ui.commands import default_commands # Construct the root parser. commands = list(default_commands) - commands += plugins.commands() + commands.append(migrate.migrate_cmd) # Temporary. parser = SubcommandsOptionParser(subcommands=commands) - parser.add_option('-l', '--library', dest='libpath', + parser.add_option('-l', '--library', dest='library', help='library database file to use') parser.add_option('-d', '--directory', dest='directory', help="destination music directory") parser.add_option('-v', '--verbose', dest='verbose', action='store_true', help='print debugging information') + parser.add_option('-c', '--config', dest='config', + help='path to configuration file') # Parse the command-line! - options, subcommand, suboptions, subargs = parser.parse_args(args) + options, args = optparse.OptionParser.parse_args(parser, args) + + # Add any additional config files specified with --config. This + # special handling lets specified plugins get loaded before we + # finish parsing the command line. + if getattr(options, 'config', None) is not None: + config_path = options.config + del options.config + config.set_file(config_path) + config.set_args(options) + + # Now add the plugin commands to the parser. + _load_plugins() + for cmd in plugins.commands(): + parser.add_subcommand(cmd) + + # Parse the remainder of the command line with loaded plugins. + return parser._parse_sub(args) + + +def _raw_main(args): + """A helper function for `main` without top-level exception + handling. + """ + subcommand, suboptions, subargs = _configure(args) # Open library file. - libpath = options.libpath or \ - config_val(config, 'beets', 'library', default_libpath) - directory = options.directory or \ - config_val(config, 'beets', 'directory', default_dir) - path_formats = _get_path_formats(config) - art_filename = \ - config_val(config, 'beets', 'art_filename', DEFAULT_ART_FILENAME) - lib_timeout = config_val(config, 'beets', 'timeout', DEFAULT_TIMEOUT) - replacements = _get_replacements(config) + dbpath = config['library'].as_filename() try: - lib_timeout = float(lib_timeout) - except ValueError: - lib_timeout = DEFAULT_TIMEOUT - db_path = os.path.expanduser(libpath) - try: - lib = library.Library(db_path, - directory, - path_formats, - art_filename, - lib_timeout, - replacements) + lib = library.Library( + dbpath, + config['directory'].as_filename(), + get_path_formats(), + get_replacements(), + ) except sqlite3.OperationalError: - raise UserError("database file %s could not be opened" % db_path) + raise UserError(u"database file {0} could not be opened".format( + util.displayable_path(dbpath) + )) plugins.send("library_opened", lib=lib) # Configure the logger. - log = logging.getLogger('beets') - if options.verbose: + if config['verbose'].get(bool): log.setLevel(logging.DEBUG) else: log.setLevel(logging.INFO) - log.debug(u'config file: %s' % util.displayable_path(configpath)) - log.debug(u'library database: %s' % util.displayable_path(lib.path)) - log.debug(u'library directory: %s' % util.displayable_path(lib.directory)) + log.debug(u'data directory: {0}\n' + u'library database: {1}\n' + u'library directory: {2}' + .format( + util.displayable_path(config.config_dir()), + util.displayable_path(lib.path), + util.displayable_path(lib.directory), + ) + ) + + # Configure the MusicBrainz API. + mb.configure() # Invoke the subcommand. + subcommand.func(lib, suboptions, subargs) + plugins.send('cli_exit', lib=lib) + + +def main(args=None): + """Run the main command-line interface for beets. Includes top-level + exception handlers that print friendly error messages. + """ try: - subcommand.func(lib, config, suboptions, subargs) + _raw_main(args) except UserError as exc: message = exc.args[0] if exc.args else None - subcommand.parser.error(message) + log.error(u'error: {0}'.format(message)) + sys.exit(1) except util.HumanReadableException as exc: exc.log(log) sys.exit(1) + except library.FileOperationError as exc: + # These errors have reasonable human-readable descriptions, but + # we still want to log their tracebacks for debugging. + log.debug(traceback.format_exc()) + log.error(exc) + sys.exit(1) + except confit.ConfigError as exc: + log.error(u'configuration error: {0}'.format(exc)) + sys.exit(1) except IOError as exc: if exc.errno == errno.EPIPE: # "Broken pipe". End silently. pass else: raise + except KeyboardInterrupt: + # Silently ignore ^C except in verbose mode. + log.debug(traceback.format_exc()) diff --git a/beets/ui/commands.py b/beets/ui/commands.py new file mode 100644 index 00000000..d0ff320a --- /dev/null +++ b/beets/ui/commands.py @@ -0,0 +1,1404 @@ +# This file is part of beets. +# Copyright 2014, Adrian Sampson. +# +# 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. + +"""This module provides the default commands for beets' command-line +interface. +""" +from __future__ import print_function + +import logging +import os +import time +import itertools +import codecs +import platform + +import beets +from beets import ui +from beets.ui import print_, input_, decargs +from beets import autotag +from beets.autotag import recommendation +from beets.autotag import hooks +from beets import plugins +from beets import importer +from beets import util +from beets.util import syspath, normpath, ancestry, displayable_path +from beets.util.functemplate import Template +from beets import library +from beets import config +from beets.util.confit import _package_path + +# Global logger. +log = logging.getLogger('beets') + +# The list of default subcommands. This is populated with Subcommand +# objects that can be fed to a SubcommandsOptionParser. +default_commands = [] + + + +# Utilities. + + +def _do_query(lib, query, album, also_items=True): + """For commands that operate on matched items, performs a query + and returns a list of matching items and a list of matching + albums. (The latter is only nonempty when album is True.) Raises + a UserError if no items match. also_items controls whether, when + fetching albums, the associated items should be fetched also. + """ + if album: + albums = list(lib.albums(query)) + items = [] + if also_items: + for al in albums: + items += al.items() + + else: + albums = [] + items = list(lib.items(query)) + + if album and not albums: + raise ui.UserError('No matching albums found.') + elif not album and not items: + raise ui.UserError('No matching items found.') + + return items, albums + + +# fields: Shows a list of available fields for queries and format strings. + +fields_cmd = ui.Subcommand('fields', + help='show fields available for queries and format strings') + +def fields_func(lib, opts, args): + def _print_rows(names): + print(" " + "\n ".join(names)) + + def _show_plugin_fields(album): + plugin_fields = [] + for plugin in plugins.find_plugins(): + if album: + fdict = plugin.album_template_fields + else: + fdict = plugin.template_fields + plugin_fields += fdict.keys() + if plugin_fields: + print("Template fields from plugins:") + _print_rows(plugin_fields) + + print("Item fields:") + _print_rows(library.ITEM_KEYS) + _show_plugin_fields(False) + + print("\nAlbum fields:") + _print_rows(library.ALBUM_KEYS) + _show_plugin_fields(True) + +fields_cmd.func = fields_func +default_commands.append(fields_cmd) + + +# import: Autotagger and importer. + +VARIOUS_ARTISTS = u'Various Artists' + +# Importer utilities and support. + +def disambig_string(info): + """Generate a string for an AlbumInfo or TrackInfo object that + provides context that helps disambiguate similar-looking albums and + tracks. + """ + disambig = [] + if info.data_source and info.data_source != 'MusicBrainz': + disambig.append(info.data_source) + + if isinstance(info, hooks.AlbumInfo): + if info.media: + if info.mediums > 1: + disambig.append(u'{0}x{1}'.format( + info.mediums, info.media + )) + else: + disambig.append(info.media) + if info.year: + disambig.append(unicode(info.year)) + if info.country: + disambig.append(info.country) + if info.label: + disambig.append(info.label) + if info.albumdisambig: + disambig.append(info.albumdisambig) + + if disambig: + return u', '.join(disambig) + +def dist_string(dist): + """Formats a distance (a float) as a colorized similarity percentage + string. + """ + out = '%.1f%%' % ((1 - dist) * 100) + if dist <= config['match']['strong_rec_thresh'].as_number(): + out = ui.colorize('green', out) + elif dist <= config['match']['medium_rec_thresh'].as_number(): + out = ui.colorize('yellow', out) + else: + out = ui.colorize('red', out) + return out + +def penalty_string(distance, limit=None): + """Returns a colorized string that indicates all the penalties + applied to a distance object. + """ + penalties = [] + for key in distance.keys(): + key = key.replace('album_', '') + key = key.replace('track_', '') + key = key.replace('_', ' ') + penalties.append(key) + if penalties: + if limit and len(penalties) > limit: + penalties = penalties[:limit] + ['...'] + return ui.colorize('yellow', '(%s)' % ', '.join(penalties)) + +def show_change(cur_artist, cur_album, match): + """Print out a representation of the changes that will be made if an + album's tags are changed according to `match`, which must be an AlbumMatch + object. + """ + def show_album(artist, album): + if artist: + album_description = u' %s - %s' % (artist, album) + elif album: + album_description = u' %s' % album + else: + album_description = u' (unknown album)' + print_(album_description) + + def format_index(track_info): + """Return a string representing the track index of the given + TrackInfo or Item object. + """ + if isinstance(track_info, hooks.TrackInfo): + index = track_info.index + medium_index = track_info.medium_index + medium = track_info.medium + mediums = match.info.mediums + else: + index = medium_index = track_info.track + medium = track_info.disc + mediums = track_info.disctotal + if config['per_disc_numbering']: + if mediums > 1: + return u'{0}-{1}'.format(medium, medium_index) + else: + return unicode(medium_index) + else: + return unicode(index) + + # Identify the album in question. + if cur_artist != match.info.artist or \ + (cur_album != match.info.album and + match.info.album != VARIOUS_ARTISTS): + artist_l, artist_r = cur_artist or '', match.info.artist + album_l, album_r = cur_album or '', match.info.album + if artist_r == VARIOUS_ARTISTS: + # Hide artists for VA releases. + artist_l, artist_r = u'', u'' + + artist_l, artist_r = ui.colordiff(artist_l, artist_r) + album_l, album_r = ui.colordiff(album_l, album_r) + + print_("Correcting tags from:") + show_album(artist_l, album_l) + print_("To:") + show_album(artist_r, album_r) + else: + print_(u"Tagging:\n {0.artist} - {0.album}".format(match.info)) + + # Data URL. + if match.info.data_url: + print_('URL:\n %s' % match.info.data_url) + + # Info line. + info = [] + # Similarity. + info.append('(Similarity: %s)' % dist_string(match.distance)) + # Penalties. + penalties = penalty_string(match.distance) + if penalties: + info.append(penalties) + # Disambiguation. + disambig = disambig_string(match.info) + if disambig: + info.append(ui.colorize('lightgray', '(%s)' % disambig)) + print_(' '.join(info)) + + # Tracks. + pairs = match.mapping.items() + pairs.sort(key=lambda (_, track_info): track_info.index) + + # Build up LHS and RHS for track difference display. The `lines` list + # contains ``(lhs, rhs, width)`` tuples where `width` is the length (in + # characters) of the uncolorized LHS. + lines = [] + medium = disctitle = None + for item, track_info in pairs: + + # Medium number and title. + if medium != track_info.medium or disctitle != track_info.disctitle: + media = match.info.media or 'Media' + if match.info.mediums > 1 and track_info.disctitle: + lhs = '%s %s: %s' % (media, track_info.medium, + track_info.disctitle) + elif match.info.mediums > 1: + lhs = '%s %s' % (media, track_info.medium) + elif track_info.disctitle: + lhs = '%s: %s' % (media, track_info.disctitle) + else: + lhs = None + if lhs: + lines.append((lhs, '', 0)) + medium, disctitle = track_info.medium, track_info.disctitle + + # Titles. + new_title = track_info.title + if not item.title.strip(): + # If there's no title, we use the filename. + cur_title = displayable_path(os.path.basename(item.path)) + lhs, rhs = cur_title, new_title + else: + cur_title = item.title.strip() + lhs, rhs = ui.colordiff(cur_title, new_title) + lhs_width = len(cur_title) + + # Track number change. + cur_track, new_track = format_index(item), format_index(track_info) + if cur_track != new_track: + if item.track in (track_info.index, track_info.medium_index): + color = 'lightgray' + else: + color = 'red' + if (cur_track + new_track).count('-') == 1: + lhs_track, rhs_track = ui.colorize(color, cur_track), \ + ui.colorize(color, new_track) + else: + color = 'red' + lhs_track, rhs_track = ui.color_diff_suffix(cur_track, + new_track) + templ = ui.colorize(color, u' (#') + u'{0}' + \ + ui.colorize(color, u')') + lhs += templ.format(lhs_track) + rhs += templ.format(rhs_track) + lhs_width += len(cur_track) + 4 + + # Length change. + if item.length and track_info.length and \ + abs(item.length - track_info.length) > \ + config['ui']['length_diff_thresh'].as_number(): + cur_length = ui.human_seconds_short(item.length) + new_length = ui.human_seconds_short(track_info.length) + lhs_length, rhs_length = ui.color_diff_suffix(cur_length, + new_length) + templ = ui.colorize('red', u' (') + u'{0}' + \ + ui.colorize('red', u')') + lhs += templ.format(lhs_length) + rhs += templ.format(rhs_length) + lhs_width += len(cur_length) + 3 + + # Penalties. + penalties = penalty_string(match.distance.tracks[track_info]) + if penalties: + rhs += ' %s' % penalties + + if lhs != rhs: + lines.append((' * %s' % lhs, rhs, lhs_width)) + elif config['import']['detail']: + lines.append((' * %s' % lhs, '', lhs_width)) + + # Print each track in two columns, or across two lines. + col_width = (ui.term_width() - len(''.join([' * ', ' -> ']))) // 2 + if lines: + max_width = max(w for _, _, w in lines) + for lhs, rhs, lhs_width in lines: + if not rhs: + print_(lhs) + elif max_width > col_width: + print_(u'%s ->\n %s' % (lhs, rhs)) + else: + pad = max_width - lhs_width + print_(u'%s%s -> %s' % (lhs, ' ' * pad, rhs)) + + # Missing and unmatched tracks. + if match.extra_tracks: + print_('Missing tracks:') + for track_info in match.extra_tracks: + line = ' ! %s (#%s)' % (track_info.title, format_index(track_info)) + if track_info.length: + line += ' (%s)' % ui.human_seconds_short(track_info.length) + print_(ui.colorize('yellow', line)) + if match.extra_items: + print_('Unmatched tracks:') + for item in match.extra_items: + line = ' ! %s (#%s)' % (item.title, format_index(item)) + if item.length: + line += ' (%s)' % ui.human_seconds_short(item.length) + print_(ui.colorize('yellow', line)) + +def show_item_change(item, match): + """Print out the change that would occur by tagging `item` with the + metadata from `match`, a TrackMatch object. + """ + cur_artist, new_artist = item.artist, match.info.artist + cur_title, new_title = item.title, match.info.title + + if cur_artist != new_artist or cur_title != new_title: + cur_artist, new_artist = ui.colordiff(cur_artist, new_artist) + cur_title, new_title = ui.colordiff(cur_title, new_title) + + print_("Correcting track tags from:") + print_(" %s - %s" % (cur_artist, cur_title)) + print_("To:") + print_(" %s - %s" % (new_artist, new_title)) + + else: + print_("Tagging track: %s - %s" % (cur_artist, cur_title)) + + # Data URL. + if match.info.data_url: + print_('URL:\n %s' % match.info.data_url) + + # Info line. + info = [] + # Similarity. + info.append('(Similarity: %s)' % dist_string(match.distance)) + # Penalties. + penalties = penalty_string(match.distance) + if penalties: + info.append(penalties) + # Disambiguation. + disambig = disambig_string(match.info) + if disambig: + info.append(ui.colorize('lightgray', '(%s)' % disambig)) + print_(' '.join(info)) + +def _summary_judment(rec): + """Determines whether a decision should be made without even asking + the user. This occurs in quiet mode and when an action is chosen for + NONE recommendations. Return an action or None if the user should be + queried. May also print to the console if a summary judgment is + made. + """ + if config['import']['quiet']: + if rec == recommendation.strong: + return importer.action.APPLY + else: + action = config['import']['quiet_fallback'].as_choice({ + 'skip': importer.action.SKIP, + 'asis': importer.action.ASIS, + }) + + elif rec == recommendation.none: + action = config['import']['none_rec_action'].as_choice({ + 'skip': importer.action.SKIP, + 'asis': importer.action.ASIS, + 'ask': None, + }) + + else: + return None + + if action == importer.action.SKIP: + print_('Skipping.') + elif action == importer.action.ASIS: + print_('Importing as-is.') + return action + +def choose_candidate(candidates, singleton, rec, cur_artist=None, + cur_album=None, item=None, itemcount=None): + """Given a sorted list of candidates, ask the user for a selection + of which candidate to use. Applies to both full albums and + singletons (tracks). Candidates are either AlbumMatch or TrackMatch + objects depending on `singleton`. for albums, `cur_artist`, + `cur_album`, and `itemcount` must be provided. For singletons, + `item` must be provided. + + Returns the result of the choice, which may SKIP, ASIS, TRACKS, or + MANUAL or a candidate (an AlbumMatch/TrackMatch object). + """ + # Sanity check. + if singleton: + assert item is not None + else: + assert cur_artist is not None + assert cur_album is not None + + # Zero candidates. + if not candidates: + if singleton: + print_("No matching recordings found.") + opts = ('Use as-is', 'Skip', 'Enter search', 'enter Id', + 'aBort') + else: + print_("No matching release found for {0} tracks." + .format(itemcount)) + print_('For help, see: ' + 'http://beets.readthedocs.org/en/latest/faq.html#nomatch') + opts = ('Use as-is', 'as Tracks', 'Group albums', 'Skip', + 'Enter search', 'enter Id', 'aBort') + sel = ui.input_options(opts) + if sel == 'u': + return importer.action.ASIS + elif sel == 't': + assert not singleton + return importer.action.TRACKS + elif sel == 'e': + return importer.action.MANUAL + elif sel == 's': + return importer.action.SKIP + elif sel == 'b': + raise importer.ImportAbort() + elif sel == 'i': + return importer.action.MANUAL_ID + elif sel == 'g': + return importer.action.ALBUMS + else: + assert False + + # Is the change good enough? + bypass_candidates = False + if rec != recommendation.none: + match = candidates[0] + bypass_candidates = True + + while True: + # Display and choose from candidates. + require = rec <= recommendation.low + + if not bypass_candidates: + # Display list of candidates. + print_(u'Finding tags for {0} "{1} - {2}".'.format( + u'track' if singleton else u'album', + item.artist if singleton else cur_artist, + item.title if singleton else cur_album, + )) + + print_(u'Candidates:') + for i, match in enumerate(candidates): + # Index, metadata, and distance. + line = [ + u'{0}.'.format(i + 1), + u'{0} - {1}'.format( + match.info.artist, + match.info.title if singleton else match.info.album, + ), + u'({0})'.format(dist_string(match.distance)), + ] + + # Penalties. + penalties = penalty_string(match.distance, 3) + if penalties: + line.append(penalties) + + # Disambiguation + disambig = disambig_string(match.info) + if disambig: + line.append(ui.colorize('lightgray', '(%s)' % disambig)) + + print_(' '.join(line)) + + # Ask the user for a choice. + if singleton: + opts = ('Skip', 'Use as-is', 'Enter search', 'enter Id', + 'aBort') + else: + opts = ('Skip', 'Use as-is', 'as Tracks', 'Group albums', + 'Enter search', 'enter Id', 'aBort') + sel = ui.input_options(opts, numrange=(1, len(candidates))) + if sel == 's': + return importer.action.SKIP + elif sel == 'u': + return importer.action.ASIS + elif sel == 'm': + pass + elif sel == 'e': + return importer.action.MANUAL + elif sel == 't': + assert not singleton + return importer.action.TRACKS + elif sel == 'b': + raise importer.ImportAbort() + elif sel == 'i': + return importer.action.MANUAL_ID + elif sel == 'g': + return importer.action.ALBUMS + else: # Numerical selection. + match = candidates[sel - 1] + if sel != 1: + # When choosing anything but the first match, + # disable the default action. + require = True + bypass_candidates = False + + # Show what we're about to do. + if singleton: + show_item_change(item, match) + else: + show_change(cur_artist, cur_album, match) + + # Exact match => tag automatically if we're not in timid mode. + if rec == recommendation.strong and not config['import']['timid']: + return match + + # Ask for confirmation. + if singleton: + opts = ('Apply', 'More candidates', 'Skip', 'Use as-is', + 'Enter search', 'enter Id', 'aBort') + else: + opts = ('Apply', 'More candidates', 'Skip', 'Use as-is', + 'as Tracks', 'Group albums', 'Enter search', 'enter Id', + 'aBort') + default = config['import']['default_action'].as_choice({ + 'apply': 'a', + 'skip': 's', + 'asis': 'u', + 'none': None, + }) + if default is None: + require = True + sel = ui.input_options(opts, require=require, default=default) + if sel == 'a': + return match + elif sel == 'g': + return importer.action.ALBUMS + elif sel == 's': + return importer.action.SKIP + elif sel == 'u': + return importer.action.ASIS + elif sel == 't': + assert not singleton + return importer.action.TRACKS + elif sel == 'e': + return importer.action.MANUAL + elif sel == 'b': + raise importer.ImportAbort() + elif sel == 'i': + return importer.action.MANUAL_ID + +def manual_search(singleton): + """Input either an artist and album (for full albums) or artist and + track name (for singletons) for manual search. + """ + artist = input_('Artist:') + name = input_('Track:' if singleton else 'Album:') + return artist.strip(), name.strip() + +def manual_id(singleton): + """Input an ID, either for an album ("release") or a track ("recording"). + """ + prompt = u'Enter {0} ID:'.format('recording' if singleton else 'release') + return input_(prompt).strip() + +class TerminalImportSession(importer.ImportSession): + """An import session that runs in a terminal. + """ + def choose_match(self, task): + """Given an initial autotagging of items, go through an interactive + dance with the user to ask for a choice of metadata. Returns an + AlbumMatch object, ASIS, or SKIP. + """ + # Show what we're tagging. + print_() + print_(displayable_path(task.paths, u'\n') + + u' ({0} items)'.format(len(task.items))) + + # Take immediate action if appropriate. + action = _summary_judment(task.rec) + if action == importer.action.APPLY: + match = task.candidates[0] + show_change(task.cur_artist, task.cur_album, match) + return match + elif action is not None: + return action + + # Loop until we have a choice. + candidates, rec = task.candidates, task.rec + while True: + # Ask for a choice from the user. + choice = choose_candidate(candidates, False, rec, task.cur_artist, + task.cur_album, itemcount=len(task.items)) + + # Choose which tags to use. + if choice in (importer.action.SKIP, importer.action.ASIS, + importer.action.TRACKS, importer.action.ALBUMS): + # Pass selection to main control flow. + return choice + elif choice is importer.action.MANUAL: + # Try again with manual search terms. + search_artist, search_album = manual_search(False) + _, _, candidates, rec = autotag.tag_album( + task.items, search_artist, search_album + ) + elif choice is importer.action.MANUAL_ID: + # Try a manually-entered ID. + search_id = manual_id(False) + if search_id: + _, _, candidates, rec = autotag.tag_album( + task.items, search_id=search_id + ) + else: + # We have a candidate! Finish tagging. Here, choice is an + # AlbumMatch object. + assert isinstance(choice, autotag.AlbumMatch) + return choice + + def choose_item(self, task): + """Ask the user for a choice about tagging a single item. Returns + either an action constant or a TrackMatch object. + """ + print_() + print_(task.item.path) + candidates, rec = task.candidates, task.rec + + # Take immediate action if appropriate. + action = _summary_judment(task.rec) + if action == importer.action.APPLY: + match = candidates[0] + show_item_change(task.item, match) + return match + elif action is not None: + return action + + while True: + # Ask for a choice. + choice = choose_candidate(candidates, True, rec, item=task.item) + + if choice in (importer.action.SKIP, importer.action.ASIS): + return choice + elif choice == importer.action.TRACKS: + assert False # TRACKS is only legal for albums. + elif choice == importer.action.MANUAL: + # Continue in the loop with a new set of candidates. + search_artist, search_title = manual_search(True) + candidates, rec = autotag.tag_item(task.item, search_artist, + search_title) + elif choice == importer.action.MANUAL_ID: + # Ask for a track ID. + search_id = manual_id(True) + if search_id: + candidates, rec = autotag.tag_item(task.item, + search_id=search_id) + else: + # Chose a candidate. + assert isinstance(choice, autotag.TrackMatch) + return choice + + def resolve_duplicate(self, task): + """Decide what to do when a new album or item seems similar to one + that's already in the library. + """ + log.warn("This %s is already in the library!" % + ("album" if task.is_album else "item")) + + if config['import']['quiet']: + # In quiet mode, don't prompt -- just skip. + log.info('Skipping.') + sel = 's' + else: + sel = ui.input_options( + ('Skip new', 'Keep both', 'Remove old') + ) + + if sel == 's': + # Skip new. + task.set_choice(importer.action.SKIP) + elif sel == 'k': + # Keep both. Do nothing; leave the choice intact. + pass + elif sel == 'r': + # Remove old. + task.remove_duplicates = True + else: + assert False + + def should_resume(self, path): + return ui.input_yn(u"Import of the directory:\n{0}\n" + "was interrupted. Resume (Y/n)?" + .format(displayable_path(path))) + +# The import command. + +def import_files(lib, paths, query): + """Import the files in the given list of paths or matching the + query. + """ + # Check the user-specified directories. + for path in paths: + fullpath = syspath(normpath(path)) + if not config['import']['singletons'] and not os.path.isdir(fullpath): + raise ui.UserError(u'not a directory: {0}'.format( + displayable_path(path))) + elif config['import']['singletons'] and not os.path.exists(fullpath): + raise ui.UserError(u'no such file: {0}'.format( + displayable_path(path))) + + # Check parameter consistency. + if config['import']['quiet'] and config['import']['timid']: + raise ui.UserError("can't be both quiet and timid") + + # Open the log. + if config['import']['log'].get() is not None: + logpath = config['import']['log'].as_filename() + try: + logfile = codecs.open(syspath(logpath), 'a', 'utf8') + except IOError: + raise ui.UserError(u"could not open log file for writing: %s" % + displayable_path(logpath)) + print(u'import started', time.asctime(), file=logfile) + else: + logfile = None + + # Never ask for input in quiet mode. + if config['import']['resume'].get() == 'ask' and \ + config['import']['quiet']: + config['import']['resume'] = False + + session = TerminalImportSession(lib, logfile, paths, query) + try: + session.run() + finally: + # If we were logging, close the file. + if logfile: + print(u'', file=logfile) + logfile.close() + + # Emit event. + plugins.send('import', lib=lib, paths=paths) + +import_cmd = ui.Subcommand('import', help='import new music', + aliases=('imp', 'im')) +import_cmd.parser.add_option('-c', '--copy', action='store_true', + default=None, help="copy tracks into library directory (default)") +import_cmd.parser.add_option('-C', '--nocopy', action='store_false', + dest='copy', help="don't copy tracks (opposite of -c)") +import_cmd.parser.add_option('-w', '--write', action='store_true', + default=None, help="write new metadata to files' tags (default)") +import_cmd.parser.add_option('-W', '--nowrite', action='store_false', + dest='write', help="don't write metadata (opposite of -w)") +import_cmd.parser.add_option('-a', '--autotag', action='store_true', + dest='autotag', help="infer tags for imported files (default)") +import_cmd.parser.add_option('-A', '--noautotag', action='store_false', + dest='autotag', + help="don't infer tags for imported files (opposite of -a)") +import_cmd.parser.add_option('-p', '--resume', action='store_true', + default=None, help="resume importing if interrupted") +import_cmd.parser.add_option('-P', '--noresume', action='store_false', + dest='resume', help="do not try to resume importing") +import_cmd.parser.add_option('-q', '--quiet', action='store_true', + dest='quiet', help="never prompt for input: skip albums instead") +import_cmd.parser.add_option('-l', '--log', dest='log', + help='file to log untaggable albums for later review') +import_cmd.parser.add_option('-s', '--singletons', action='store_true', + help='import individual tracks instead of full albums') +import_cmd.parser.add_option('-t', '--timid', dest='timid', + action='store_true', help='always confirm all actions') +import_cmd.parser.add_option('-L', '--library', dest='library', + action='store_true', help='retag items matching a query') +import_cmd.parser.add_option('-i', '--incremental', dest='incremental', + action='store_true', help='skip already-imported directories') +import_cmd.parser.add_option('-I', '--noincremental', dest='incremental', + action='store_false', help='do not skip already-imported directories') +import_cmd.parser.add_option('--flat', dest='flat', + action='store_true', help='import an entire tree as a single album') +import_cmd.parser.add_option('-g', '--group-albums', dest='group_albums', + action='store_true', help='group tracks in a folder into seperate albums') +def import_func(lib, opts, args): + config['import'].set_args(opts) + + # Special case: --copy flag suppresses import_move (which would + # otherwise take precedence). + if opts.copy: + config['import']['move'] = False + + if opts.library: + query = decargs(args) + paths = [] + else: + query = None + paths = args + if not paths: + raise ui.UserError('no path specified') + + import_files(lib, paths, query) +import_cmd.func = import_func +default_commands.append(import_cmd) + + +# list: Query and show library contents. + +def list_items(lib, query, album, fmt): + """Print out items in lib matching query. If album, then search for + albums instead of single items. + """ + tmpl = Template(ui._pick_format(album, fmt)) + if album: + for album in lib.albums(query): + ui.print_obj(album, lib, tmpl) + else: + for item in lib.items(query): + ui.print_obj(item, lib, tmpl) + +list_cmd = ui.Subcommand('list', help='query the library', aliases=('ls',)) +list_cmd.parser.add_option('-a', '--album', action='store_true', + help='show matching albums instead of tracks') +list_cmd.parser.add_option('-p', '--path', action='store_true', + help='print paths for matched items or albums') +list_cmd.parser.add_option('-f', '--format', action='store', + help='print with custom format', default=None) +def list_func(lib, opts, args): + if opts.path: + fmt = '$path' + else: + fmt = opts.format + list_items(lib, decargs(args), opts.album, fmt) +list_cmd.func = list_func +default_commands.append(list_cmd) + + +# update: Update library contents according to on-disk tags. + +def update_items(lib, query, album, move, pretend): + """For all the items matched by the query, update the library to + reflect the item's embedded tags. + """ + with lib.transaction(): + items, _ = _do_query(lib, query, album) + + # Walk through the items and pick up their changes. + affected_albums = set() + for item in items: + # Item deleted? + if not os.path.exists(syspath(item.path)): + ui.print_obj(item, lib) + ui.print_(ui.colorize('red', u' deleted')) + if not pretend: + item.remove(True) + affected_albums.add(item.album_id) + continue + + # Did the item change since last checked? + if item.current_mtime() <= item.mtime: + log.debug(u'skipping %s because mtime is up to date (%i)' % + (displayable_path(item.path), item.mtime)) + continue + + # Read new data. + try: + item.read() + except Exception as exc: + log.error(u'error reading {0}: {1}'.format( + displayable_path(item.path), exc)) + continue + + # Special-case album artist when it matches track artist. (Hacky + # but necessary for preserving album-level metadata for non- + # autotagged imports.) + if not item.albumartist: + old_item = lib.get_item(item.id) + if old_item.albumartist == old_item.artist == item.artist: + item.albumartist = old_item.albumartist + item._dirty.discard('albumartist') + + # Check for and display changes. + changed = ui.show_model_changes(item, + fields=library.ITEM_KEYS_META) + + # Save changes. + if not pretend: + if changed: + # Move the item if it's in the library. + if move and lib.directory in ancestry(item.path): + item.move() + + item.store() + affected_albums.add(item.album_id) + else: + # The file's mtime was different, but there were no + # changes to the metadata. Store the new mtime, + # which is set in the call to read(), so we don't + # check this again in the future. + item.store() + + # Skip album changes while pretending. + if pretend: + return + + # Modify affected albums to reflect changes in their items. + for album_id in affected_albums: + if album_id is None: # Singletons. + continue + album = lib.get_album(album_id) + if not album: # Empty albums have already been removed. + log.debug('emptied album %i' % album_id) + continue + first_item = album.items().get() + + # Update album structure to reflect an item in it. + for key in library.ALBUM_KEYS_ITEM: + album[key] = first_item[key] + album.store() + + # Move album art (and any inconsistent items). + if move and lib.directory in ancestry(first_item.path): + log.debug('moving album %i' % album_id) + album.move() + +update_cmd = ui.Subcommand('update', + help='update the library', aliases=('upd','up',)) +update_cmd.parser.add_option('-a', '--album', action='store_true', + help='match albums instead of tracks') +update_cmd.parser.add_option('-M', '--nomove', action='store_false', + default=True, dest='move', help="don't move files in library") +update_cmd.parser.add_option('-p', '--pretend', action='store_true', + help="show all changes but do nothing") +update_cmd.parser.add_option('-f', '--format', action='store', + help='print with custom format', default=None) +def update_func(lib, opts, args): + update_items(lib, decargs(args), opts.album, opts.move, opts.pretend) +update_cmd.func = update_func +default_commands.append(update_cmd) + + +# remove: Remove items from library, delete files. + +def remove_items(lib, query, album, delete): + """Remove items matching query from lib. If album, then match and + remove whole albums. If delete, also remove files from disk. + """ + # Get the matching items. + items, albums = _do_query(lib, query, album) + + # Show all the items. + for item in items: + ui.print_obj(item, lib) + + # Confirm with user. + print_() + if delete: + prompt = 'Really DELETE %i files (y/n)?' % len(items) + else: + prompt = 'Really remove %i items from the library (y/n)?' % \ + len(items) + if not ui.input_yn(prompt, True): + return + + # Remove (and possibly delete) items. + with lib.transaction(): + for obj in (albums if album else items): + obj.remove(delete) + +remove_cmd = ui.Subcommand('remove', + help='remove matching items from the library', aliases=('rm',)) +remove_cmd.parser.add_option("-d", "--delete", action="store_true", + help="also remove files from disk") +remove_cmd.parser.add_option('-a', '--album', action='store_true', + help='match albums instead of tracks') +def remove_func(lib, opts, args): + remove_items(lib, decargs(args), opts.album, opts.delete) +remove_cmd.func = remove_func +default_commands.append(remove_cmd) + + +# stats: Show library/query statistics. + +def show_stats(lib, query, exact): + """Shows some statistics about the matched items.""" + items = lib.items(query) + + total_size = 0 + total_time = 0.0 + total_items = 0 + artists = set() + albums = set() + + for item in items: + if exact: + total_size += os.path.getsize(item.path) + else: + total_size += int(item.length * item.bitrate / 8) + total_time += item.length + total_items += 1 + artists.add(item.artist) + albums.add(item.album) + + size_str = '' + ui.human_bytes(total_size) + if exact: + size_str += ' ({0} bytes)'.format(total_size) + + print_("""Tracks: {0} +Total time: {1} ({2:.2f} seconds) +Total size: {3} +Artists: {4} +Albums: {5}""".format(total_items, ui.human_seconds(total_time), total_time, + size_str, len(artists), len(albums))) + +stats_cmd = ui.Subcommand('stats', + help='show statistics about the library or a query') +stats_cmd.parser.add_option('-e', '--exact', action='store_true', + help='get exact file sizes') +def stats_func(lib, opts, args): + show_stats(lib, decargs(args), opts.exact) +stats_cmd.func = stats_func +default_commands.append(stats_cmd) + + +# version: Show current beets version. + +def show_version(lib, opts, args): + print_('beets version %s' % beets.__version__) + # Show plugins. + names = [p.name for p in plugins.find_plugins()] + if names: + print_('plugins:', ', '.join(names)) + else: + print_('no plugins loaded') +version_cmd = ui.Subcommand('version', + help='output version information') +version_cmd.func = show_version +default_commands.append(version_cmd) + + +# modify: Declaratively change metadata. + +def modify_items(lib, mods, query, write, move, album, confirm): + """Modifies matching items according to key=value assignments.""" + # Parse key=value specifications into a dictionary. + model_cls = library.Album if album else library.Item + fsets = {} + for mod in mods: + key, value = mod.split('=', 1) + fsets[key] = model_cls._parse(key, value) + + # Get the items to modify. + items, albums = _do_query(lib, query, album, False) + objs = albums if album else items + + # Apply changes *temporarily*, preview them, and collect modified + # objects. + print_('Modifying %i %ss.' % (len(objs), 'album' if album else 'item')) + changed = set() + for obj in objs: + for field, value in fsets.iteritems(): + obj[field] = value + if ui.show_model_changes(obj): + changed.add(obj) + + # Still something to do? + if not changed: + print_('No changes to make.') + return + + # Confirm action. + if confirm: + extra = ' and write tags' if write else '' + if not ui.input_yn('Really modify%s (Y/n)?' % extra): + return + + # Apply changes to database. + with lib.transaction(): + for obj in changed: + if move: + cur_path = obj.path + if lib.directory in ancestry(cur_path): # In library? + log.debug('moving object %s' % cur_path) + obj.move() + + obj.store() + + # Apply tags if requested. + if write: + if album: + changed_items = itertools.chain(*(a.items() for a in changed)) + else: + changed_items = changed + for item in changed_items: + try: + item.write() + except library.FileOperationError as exc: + log.error(exc) + +modify_cmd = ui.Subcommand('modify', + help='change metadata fields', aliases=('mod',)) +modify_cmd.parser.add_option('-M', '--nomove', action='store_false', + default=True, dest='move', help="don't move files in library") +modify_cmd.parser.add_option('-w', '--write', action='store_true', + default=None, help="write new metadata to files' tags (default)") +modify_cmd.parser.add_option('-W', '--nowrite', action='store_false', + dest='write', help="don't write metadata (opposite of -w)") +modify_cmd.parser.add_option('-a', '--album', action='store_true', + help='modify whole albums instead of tracks') +modify_cmd.parser.add_option('-y', '--yes', action='store_true', + help='skip confirmation') +modify_cmd.parser.add_option('-f', '--format', action='store', + help='print with custom format', default=None) +def modify_func(lib, opts, args): + args = decargs(args) + mods = [a for a in args if '=' in a] + query = [a for a in args if '=' not in a] + if not mods: + raise ui.UserError('no modifications specified') + write = opts.write if opts.write is not None else \ + config['import']['write'].get(bool) + modify_items(lib, mods, query, write, opts.move, opts.album, not opts.yes) +modify_cmd.func = modify_func +default_commands.append(modify_cmd) + + +# move: Move/copy files to the library or a new base directory. + +def move_items(lib, dest, query, copy, album): + """Moves or copies items to a new base directory, given by dest. If + dest is None, then the library's base directory is used, making the + command "consolidate" files. + """ + items, albums = _do_query(lib, query, album, False) + objs = albums if album else items + + action = 'Copying' if copy else 'Moving' + entity = 'album' if album else 'item' + log.info('%s %i %ss.' % (action, len(objs), entity)) + for obj in objs: + log.debug('moving: %s' % obj.path) + + obj.move(copy, basedir=dest) + obj.store() + +move_cmd = ui.Subcommand('move', + help='move or copy items', aliases=('mv',)) +move_cmd.parser.add_option('-d', '--dest', metavar='DIR', dest='dest', + help='destination directory') +move_cmd.parser.add_option('-c', '--copy', default=False, action='store_true', + help='copy instead of moving') +move_cmd.parser.add_option('-a', '--album', default=False, action='store_true', + help='match whole albums instead of tracks') +def move_func(lib, opts, args): + dest = opts.dest + if dest is not None: + dest = normpath(dest) + if not os.path.isdir(dest): + raise ui.UserError('no such directory: %s' % dest) + + move_items(lib, dest, decargs(args), opts.copy, opts.album) +move_cmd.func = move_func +default_commands.append(move_cmd) + + +# write: Write tags into files. + +def write_items(lib, query, pretend): + """Write tag information from the database to the respective files + in the filesystem. + """ + items, albums = _do_query(lib, query, False, False) + + for item in items: + # Item deleted? + if not os.path.exists(syspath(item.path)): + log.info(u'missing file: {0}'.format( + util.displayable_path(item.path) + )) + continue + + # Get an Item object reflecting the "clean" (on-disk) state. + try: + clean_item = library.Item.from_path(item.path) + except Exception as exc: + log.error(u'error reading {0}: {1}'.format( + displayable_path(item.path), exc + )) + continue + + # Check for and display changes. + changed = ui.show_model_changes(item, clean_item, + library.ITEM_KEYS_WRITABLE, always=True) + if changed and not pretend: + try: + item.write() + except library.FileOperationError as exc: + log.error(exc) + +write_cmd = ui.Subcommand('write', help='write tag information to files') +write_cmd.parser.add_option('-p', '--pretend', action='store_true', + help="show all changes but do nothing") +def write_func(lib, opts, args): + write_items(lib, decargs(args), opts.pretend) +write_cmd.func = write_func +default_commands.append(write_cmd) + + +# config: Show and edit user configuration. + +config_cmd = ui.Subcommand('config', + help='show or edit the user configuration') +config_cmd.parser.add_option('-p', '--paths', action='store_true', + help='show files that configuration was loaded from') +config_cmd.parser.add_option('-e', '--edit', action='store_true', + help='edit user configuration with $EDITOR') +config_cmd.parser.add_option('-d', '--defaults', action='store_true', + help='include the default configuration') +def config_func(lib, opts, args): + # Make sure lazy configuration is loaded + config.resolve() + + # Print paths. + if opts.paths: + filenames = [] + for source in config.sources: + if not opts.defaults and source.default: + continue + if source.filename: + filenames.append(source.filename) + + # In case the user config file does not exist, prepend it to the + # list. + user_path = config.user_config_path() + if user_path not in filenames: + filenames.insert(0, user_path) + + for filename in filenames: + print(filename) + + # Open in editor. + elif opts.edit: + path = config.user_config_path() + + if 'EDITOR' in os.environ: + editor = os.environ['EDITOR'] + args = [editor, editor, path] + elif platform.system() == 'Darwin': + args = ['open', 'open', '-n', path] + elif platform.system() == 'Windows': + # On windows we can execute arbitrary files. The os will + # take care of starting an appropriate application + args = [path, path] + else: + # Assume Unix + args = ['xdg-open', 'xdg-open', path] + + try: + os.execlp(*args) + except OSError: + raise ui.UserError("Could not edit configuration. Please" + "set the EDITOR environment variable.") + + # Dump configuration. + else: + print(config.dump(full=opts.defaults)) + +config_cmd.func = config_func +default_commands.append(config_cmd) + + +# completion: print completion script + +completion_cmd = ui.Subcommand('completion', + help='print shell script that provides command line completion') +def print_completion(*args): + for line in completion_script(default_commands + plugins.commands()): + print(line, end='') + if not (os.path.isfile(u'/etc/bash_completion') or + os.path.isfile(u'/usr/share/bash-completion/bash_completion') or + os.path.isfile(u'/usr/share/local/bash-completion/bash_completion')): + log.warn(u'Warning: Unable to find the bash-completion package. ' + u'Command line completion might not work.') + +def completion_script(commands): + """Yield the full completion shell script as strings. + + ``commands`` is alist of ``ui.Subcommand`` instances to generate + completion data for. + """ + base_script = os.path.join(_package_path('beets.ui'), 'completion_base.sh') + with open(base_script, 'r') as base_script: + yield base_script.read() + + options = {} + aliases = {} + command_names = [] + + # Collect subcommands + for cmd in commands: + name = cmd.name + command_names.append(name) + + for alias in cmd.aliases: + aliases[alias] = name + + options[name] = {'flags': [], 'opts': []} + for opts in cmd.parser._get_all_options()[1:]: + if opts.action in ('store_true', 'store_false'): + option_type = 'flags' + else: + option_type = 'opts' + + options[name][option_type].extend( + opts._short_opts + opts._long_opts + ) + + # Add global options + options['_global'] = { + 'flags': ['-v', '--verbose'], + 'opts': '-l --library -c --config -d --directory -h --help'.split(' ') + } + + # Help subcommand + command_names.append('help') + + # Add flags common to all commands + options['_common'] = { + 'flags': ['-h', '--help'] + } + + # Start generating the script + yield "_beet() {\n" + + # Command names + yield " local commands='%s'\n" % ' '.join(command_names) + yield "\n" + + # Command aliases + yield " local aliases='%s'\n" % ' '.join(aliases.keys()) + for alias, cmd in aliases.items(): + yield " local alias__%s=%s\n" % (alias, cmd) + yield '\n' + + # Fields + yield " fields='%s'\n" % ' '.join( + set(library.ITEM_KEYS + library.ALBUM_KEYS)) + + # Command options + for cmd, opts in options.items(): + for option_type, option_list in opts.items(): + if option_list: + option_list = ' '.join(option_list) + yield " local %s__%s='%s'\n" % (option_type, cmd, option_list) + + yield ' _beet_dispatch\n' + yield '}\n' + + +completion_cmd.func = print_completion +completion_cmd.hide = True +default_commands.append(completion_cmd) diff --git a/beets/ui/completion_base.sh b/beets/ui/completion_base.sh new file mode 100644 index 00000000..ce3fb6e2 --- /dev/null +++ b/beets/ui/completion_base.sh @@ -0,0 +1,162 @@ +# This file is part of beets. +# Copyright (c) 2014, Thomas Scholtes. +# +# 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. + + + +# Completion for the `beet` command +# ================================= +# +# Load this script to complete beets subcommands, options, and +# queries. +# +# If a beets command is found on the command line it completes filenames and +# the subcommand's options. Otherwise it will complete global options and +# subcommands. If the previous option on the command line expects an argument, +# it also completes filenames or directories. Options are only +# completed if '-' has already been typed on the command line. +# +# Note that completion of plugin commands only works for those plugins +# that were enabled when running `beet completion`. It does not check +# plugins dynamically +# +# Currently, only Bash 3.2 and newer is supported and the +# `bash-completion` package is requied. +# +# TODO +# ---- +# +# * There are some issues with arguments that are quoted on the command line. +# +# * Complete arguments for the `--format` option by expanding field variables. +# +# beet ls -f "$tit[TAB] +# beet ls -f "$title +# +# * Support long options with `=`, e.g. `--config=file`. Debian's bash +# completion package can handle this. +# + + +# Determines the beets subcommand and dispatches the completion +# accordingly. +_beet_dispatch() { + local cur prev cmd= + + COMPREPLY=() + _get_comp_words_by_ref -n : cur prev + + # Look for the beets subcommand + local arg + for (( i=1; i < COMP_CWORD; i++ )); do + arg="${COMP_WORDS[i]}" + if _list_include_item "${opts___global}" $arg; then + ((i++)) + elif [[ "$arg" != -* ]]; then + cmd="$arg" + break + fi + done + + # Replace command shortcuts + if [[ -n $cmd ]] && _list_include_item "$aliases" "$cmd"; then + eval "cmd=\$alias__$cmd" + fi + + case $cmd in + help) + COMPREPLY+=( $(compgen -W "$commands" -- $cur) ) + ;; + list|remove|move|update|write|stats) + _beet_complete_query + ;; + "") + _beet_complete_global + ;; + *) + _beet_complete + ;; + esac +} + + +# Adds option and file completion to COMPREPLY for the subcommand $cmd +_beet_complete() { + if [[ $cur == -* ]]; then + local opts flags completions + eval "opts=\$opts__$cmd" + eval "flags=\$flags__$cmd" + completions="${flags___common} ${opts} ${flags}" + COMPREPLY+=( $(compgen -W "$completions" -- $cur) ) + else + _filedir + fi +} + + +# Add global options and subcommands to the completion +_beet_complete_global() { + case $prev in + -h|--help) + # Complete commands + COMPREPLY+=( $(compgen -W "$commands" -- $cur) ) + return + ;; + -l|--library|-c|--config) + # Filename completion + _filedir + return + ;; + -d|--directory) + # Directory completion + _filedir -d + return + ;; + esac + + if [[ $cur == -* ]]; then + local completions="$opts___global $flags___global" + COMPREPLY+=( $(compgen -W "$completions" -- $cur) ) + elif [[ -n $cur ]] && _list_include_item "$aliases" "$cur"; then + local cmd + eval "cmd=\$alias__$cur" + COMPREPLY+=( "$cmd" ) + else + COMPREPLY+=( $(compgen -W "$commands" -- $cur) ) + fi +} + +_beet_complete_query() { + local opts + eval "opts=\$opts__$cmd" + + if [[ $cur == -* ]] || _list_include_item "$opts" "$prev"; then + _beet_complete + elif [[ $cur != \'* && $cur != \"* && + $cur != *:* ]]; then + # Do not complete quoted queries or those who already have a field + # set. + compopt -o nospace + COMPREPLY+=( $(compgen -S : -W "$fields" -- $cur) ) + return 0 + fi +} + +# Returns true if the space separated list $1 includes $2 +_list_include_item() { + [[ " $1 " == *[[:space:]]$2[[:space:]]* ]] +} + +# This is where beets dynamically adds the _beet function. This +# function sets the variables $flags, $opts, $commands, and $aliases. +complete -o filenames -F _beet beet diff --git a/beets/ui/migrate.py b/beets/ui/migrate.py new file mode 100644 index 00000000..784d7c82 --- /dev/null +++ b/beets/ui/migrate.py @@ -0,0 +1,401 @@ +# This file is part of beets. +# Copyright 2013, Adrian Sampson. +# +# 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. + +"""Conversion from legacy (pre-1.1) configuration to Confit/YAML +configuration. +""" +import os +import ConfigParser +import codecs +import yaml +import logging +import time +import itertools +import re + +import beets +from beets import util +from beets import ui +from beets.util import confit + +CONFIG_PATH_VAR = 'BEETSCONFIG' +DEFAULT_CONFIG_FILENAME_UNIX = '.beetsconfig' +DEFAULT_CONFIG_FILENAME_WINDOWS = 'beetsconfig.ini' +DEFAULT_LIBRARY_FILENAME_UNIX = '.beetsmusic.blb' +DEFAULT_LIBRARY_FILENAME_WINDOWS = 'beetsmusic.blb' +WINDOWS_BASEDIR = os.environ.get('APPDATA') or '~' + +OLD_CONFIG_SUFFIX = '.old' +PLUGIN_NAMES = { + 'rdm': 'random', + 'fuzzy_search': 'fuzzy', +} +AUTO_KEYS = ('automatic', 'autofetch', 'autoembed', 'autoscrub') +IMPORTFEEDS_PREFIX = 'feeds_' +CONFIG_MIGRATED_MESSAGE = u""" +You appear to be upgrading from beets 1.0 (or earlier) to 1.1. Your +configuration file has been migrated automatically to: +{newconfig} +Edit this file to configure beets. You might want to remove your +old-style ".beetsconfig" file now. See the documentation for more +details on the new configuration system: +http://beets.readthedocs.org/page/reference/config.html +""".strip() +DB_MIGRATED_MESSAGE = u'Your database file has also been copied to:\n{newdb}' +YAML_COMMENT = '# Automatically migrated from legacy .beetsconfig.\n\n' + +log = logging.getLogger('beets') + +# An itertools recipe. +def grouper(n, iterable): + args = [iter(iterable)] * n + return itertools.izip_longest(*args) + +def _displace(fn): + """Move a file aside using a timestamp suffix so a new file can be + put in its place. + """ + util.move( + fn, + u'{0}.old.{1}'.format(fn, int(time.time())), + True + ) + +def default_paths(): + """Produces the appropriate default config and library database + paths for the current system. On Unix, this is always in ~. On + Windows, tries ~ first and then $APPDATA for the config and library + files (for backwards compatibility). + """ + windows = os.path.__name__ == 'ntpath' + if windows: + windata = os.environ.get('APPDATA') or '~' + + # Shorthand for joining paths. + def exp(*vals): + return os.path.expanduser(os.path.join(*vals)) + + config = exp('~', DEFAULT_CONFIG_FILENAME_UNIX) + if windows and not os.path.exists(config): + config = exp(windata, DEFAULT_CONFIG_FILENAME_WINDOWS) + + libpath = exp('~', DEFAULT_LIBRARY_FILENAME_UNIX) + if windows and not os.path.exists(libpath): + libpath = exp(windata, DEFAULT_LIBRARY_FILENAME_WINDOWS) + + return config, libpath + +def get_config(): + """Using the same logic as beets 1.0, locate and read the + .beetsconfig file. Return a ConfigParser instance or None if no + config is found. + """ + default_config, default_libpath = default_paths() + if CONFIG_PATH_VAR in os.environ: + configpath = os.path.expanduser(os.environ[CONFIG_PATH_VAR]) + else: + configpath = default_config + + config = ConfigParser.SafeConfigParser() + if os.path.exists(util.syspath(configpath)): + with codecs.open(configpath, 'r', encoding='utf-8') as f: + config.readfp(f) + return config, configpath + else: + return None, configpath + +def flatten_config(config): + """Given a ConfigParser, flatten the values into a dict-of-dicts + representation where each section gets its own dictionary of values. + """ + out = confit.OrderedDict() + for section in config.sections(): + sec_dict = out[section] = confit.OrderedDict() + for option in config.options(section): + sec_dict[option] = config.get(section, option, True) + return out + +def transform_value(value): + """Given a string read as the value of a config option, return a + massaged version of that value (possibly with a different type). + """ + # Booleans. + if value.lower() in ('false', 'no', 'off'): + return False + elif value.lower() in ('true', 'yes', 'on'): + return True + + # Integers. + try: + return int(value) + except ValueError: + pass + + # Floats. + try: + return float(value) + except ValueError: + pass + + return value + +def transform_data(data): + """Given a dict-of-dicts representation of legacy config data, tweak + the data into a new form. This new form is suitable for dumping as + YAML. + """ + out = confit.OrderedDict() + + for section, pairs in data.items(): + if section == 'beets': + # The "main" section. In the new config system, these values + # are in the "root": no section at all. + for key, value in pairs.items(): + value = transform_value(value) + + if key.startswith('import_'): + # Importer config is now under an "import:" key. + if 'import' not in out: + out['import'] = confit.OrderedDict() + out['import'][key[7:]] = value + + elif key == 'plugins': + # Renamed plugins. + plugins = value.split() + new_plugins = [PLUGIN_NAMES.get(p, p) for p in plugins] + out['plugins'] = ' '.join(new_plugins) + + elif key == 'replace': + # YAMLy representation for character replacements. + replacements = confit.OrderedDict() + for pat, repl in grouper(2, value.split()): + if repl == '': + repl = '' + replacements[pat] = repl + out['replace'] = replacements + + elif key == 'pluginpath': + # Used to be a colon-separated string. Now a list. + out['pluginpath'] = value.split(':') + + else: + out[key] = value + + elif pairs: + # Other sections (plugins, etc). + sec_out = out[section] = confit.OrderedDict() + for key, value in pairs.items(): + + # Standardized "auto" option. + if key in AUTO_KEYS: + key = 'auto' + + # Unnecessary : hack in queries. + if section == 'paths': + key = key.replace('_', ':') + + # Changed option names for importfeeds plugin. + if section == 'importfeeds': + if key.startswith(IMPORTFEEDS_PREFIX): + key = key[len(IMPORTFEEDS_PREFIX):] + + sec_out[key] = transform_value(value) + + return out + +class Dumper(yaml.SafeDumper): + """A PyYAML Dumper that represents OrderedDicts as ordinary mappings + (in order, of course). + """ + # From http://pyyaml.org/attachment/ticket/161/use_ordered_dict.py + def represent_mapping(self, tag, mapping, flow_style=None): + value = [] + node = yaml.MappingNode(tag, value, flow_style=flow_style) + if self.alias_key is not None: + self.represented_objects[self.alias_key] = node + best_style = True + if hasattr(mapping, 'items'): + mapping = list(mapping.items()) + for item_key, item_value in mapping: + node_key = self.represent_data(item_key) + node_value = self.represent_data(item_value) + if not (isinstance(node_key, yaml.ScalarNode) and \ + not node_key.style): + best_style = False + if not (isinstance(node_value, yaml.ScalarNode) and \ + not node_value.style): + best_style = False + value.append((node_key, node_value)) + if flow_style is None: + if self.default_flow_style is not None: + node.flow_style = self.default_flow_style + else: + node.flow_style = best_style + return node +Dumper.add_representer(confit.OrderedDict, Dumper.represent_dict) + +def migrate_config(replace=False): + """Migrate a legacy beetsconfig file to a new-style config.yaml file + in an appropriate place. If `replace` is enabled, then any existing + config.yaml will be moved aside. Otherwise, the process is aborted + when the file exists. + """ + + # Load legacy configuration data, if any. + config, configpath = get_config() + if not config: + log.debug(u'no config file found at {0}'.format( + util.displayable_path(configpath) + )) + return + + # Get the new configuration file path and possibly move it out of + # the way. + destfn = os.path.join(beets.config.config_dir(), confit.CONFIG_FILENAME) + if os.path.exists(destfn): + if replace: + log.debug(u'moving old config aside: {0}'.format( + util.displayable_path(destfn) + )) + _displace(destfn) + else: + # File exists and we won't replace it. We're done. + return + + log.debug(u'migrating config file {0}'.format( + util.displayable_path(configpath) + )) + + # Convert the configuration to a data structure ready to be dumped + # as the new Confit file. + data = transform_data(flatten_config(config)) + + # Encode result as YAML. + yaml_out = yaml.dump( + data, + Dumper=Dumper, + default_flow_style=False, + indent=4, + width=1000, + ) + # A ridiculous little hack to add some whitespace between "sections" + # in the YAML output. I hope this doesn't break any YAML syntax. + yaml_out = re.sub(r'(\n\w+:\n [^-\s])', '\n\\1', yaml_out) + yaml_out = YAML_COMMENT + yaml_out + + # Write the data to the new config destination. + log.debug(u'writing migrated config to {0}'.format( + util.displayable_path(destfn) + )) + with open(destfn, 'w') as f: + f.write(yaml_out) + return destfn + +def migrate_db(replace=False): + """Copy the beets library database file to the new location (e.g., + from ~/.beetsmusic.blb to ~/.config/beets/library.db). + """ + _, srcfn = default_paths() + destfn = beets.config['library'].as_filename() + + if not os.path.exists(srcfn) or srcfn == destfn: + # Old DB does not exist or we're configured to point to the same + # database. Do nothing. + return + + if os.path.exists(destfn): + if replace: + log.debug(u'moving old database aside: {0}'.format( + util.displayable_path(destfn) + )) + _displace(destfn) + else: + return + + log.debug(u'copying database from {0} to {1}'.format( + util.displayable_path(srcfn), util.displayable_path(destfn) + )) + util.copy(srcfn, destfn) + return destfn + +def migrate_state(replace=False): + """Copy the beets runtime state file from the old path (i.e., + ~/.beetsstate) to the new path (i.e., ~/.config/beets/state.pickle). + """ + srcfn = os.path.expanduser(os.path.join('~', '.beetsstate')) + if not os.path.exists(srcfn): + return + + destfn = beets.config['statefile'].as_filename() + if os.path.exists(destfn): + if replace: + _displace(destfn) + else: + return + + log.debug(u'copying state file from {0} to {1}'.format( + util.displayable_path(srcfn), util.displayable_path(destfn) + )) + util.copy(srcfn, destfn) + return destfn + + +# Automatic migration when beets starts. + +def automigrate(): + """Migrate the configuration, database, and state files. If any + migration occurs, print out a notice with some helpful next steps. + """ + config_fn = migrate_config() + db_fn = migrate_db() + migrate_state() + + if config_fn: + ui.print_(ui.colorize('fuchsia', u'MIGRATED CONFIGURATION')) + + ui.print_(CONFIG_MIGRATED_MESSAGE.format( + newconfig=util.displayable_path(config_fn)) + ) + if db_fn: + ui.print_(DB_MIGRATED_MESSAGE.format( + newdb=util.displayable_path(db_fn) + )) + + ui.input_(ui.colorize('fuchsia', u'Press ENTER to continue:')) + ui.print_() + + +# CLI command for explicit migration. + +migrate_cmd = ui.Subcommand('migrate', help='convert legacy config') +def migrate_func(lib, opts, args): + """Explicit command for migrating files. Existing files in each + destination are moved aside. + """ + config_fn = migrate_config(replace=True) + if config_fn: + log.info(u'Migrated configuration to: {0}'.format( + util.displayable_path(config_fn) + )) + db_fn = migrate_db(replace=True) + if db_fn: + log.info(u'Migrated library database to: {0}'.format( + util.displayable_path(db_fn) + )) + state_fn = migrate_state(replace=True) + if state_fn: + log.info(u'Migrated state file to: {0}'.format( + util.displayable_path(state_fn) + )) +migrate_cmd.func = migrate_func diff --git a/lib/beets/util/__init__.py b/beets/util/__init__.py similarity index 65% rename from lib/beets/util/__init__.py rename to beets/util/__init__.py index 380bfaf8..f5810ff3 100644 --- a/lib/beets/util/__init__.py +++ b/beets/util/__init__.py @@ -1,5 +1,5 @@ # This file is part of beets. -# Copyright 2012, Adrian Sampson. +# Copyright 2013, Adrian Sampson. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -22,8 +22,10 @@ import shutil import fnmatch from collections import defaultdict import traceback +import subprocess MAX_FILENAME_LENGTH = 200 +WINDOWS_MAGIC_PREFIX = u'\\\\?\\' class HumanReadableException(Exception): """An Exception that can include a human-readable error message to @@ -57,12 +59,14 @@ class HumanReadableException(Exception): def _reasonstr(self): """Get the reason as a string.""" - if isinstance(self.reason, basestring): + if isinstance(self.reason, unicode): return self.reason + elif isinstance(self.reason, basestring): # Byte string. + return self.reason.decode('utf8', 'ignore') elif hasattr(self.reason, 'strerror'): # i.e., EnvironmentError return self.reason.strerror else: - return u'"{0}"'.format(self.reason) + return u'"{0}"'.format(unicode(self.reason)) def get_message(self): """Create the human-readable description of the error, sans @@ -90,16 +94,19 @@ class FilesystemError(HumanReadableException): def get_message(self): # Use a nicer English phrasing for some specific verbs. if self.verb in ('move', 'copy', 'rename'): - clause = 'while {0} {1} to {2}'.format( - self._gerund(), repr(self.paths[0]), repr(self.paths[1]) + clause = u'while {0} {1} to {2}'.format( + self._gerund(), + displayable_path(self.paths[0]), + displayable_path(self.paths[1]) ) - elif self.verb in ('delete',): - clause = 'while {0} {1}'.format( - self._gerund(), repr(self.paths[0]) + elif self.verb in ('delete', 'write', 'create', 'read'): + clause = u'while {0} {1}'.format( + self._gerund(), + displayable_path(self.paths[0]) ) else: - clause = 'during {0} of paths {1}'.format( - self.verb, u', '.join(repr(p) for p in self.paths) + clause = u'during {0} of paths {1}'.format( + self.verb, u', '.join(displayable_path(p) for p in self.paths) ) return u'{0} {1}'.format(self._reasonstr(), clause) @@ -108,19 +115,23 @@ def normpath(path): """Provide the canonical form of the path suitable for storing in the database. """ - return os.path.normpath(os.path.abspath(os.path.expanduser(path))) + path = syspath(path, prefix=False) + path = os.path.normpath(os.path.abspath(os.path.expanduser(path))) + return bytestring_path(path) -def ancestry(path, pathmod=None): +def ancestry(path): """Return a list consisting of path's parent directory, its grandparent, and so on. For instance: + >>> ancestry('/a/b/c') ['/', '/a', '/a/b'] + + The argument should *not* be the result of a call to `syspath`. """ - pathmod = pathmod or os.path out = [] last_path = None while path: - path = pathmod.dirname(path) + path = os.path.dirname(path) if path == last_path: break @@ -130,18 +141,27 @@ def ancestry(path, pathmod=None): out.insert(0, path) return out -def sorted_walk(path, ignore=()): - """Like ``os.walk``, but yields things in sorted, breadth-first - order. Directory and file names matching any glob pattern in - ``ignore`` are skipped. +def sorted_walk(path, ignore=(), logger=None): + """Like `os.walk`, but yields things in case-insensitive sorted, + breadth-first order. Directory and file names matching any glob + pattern in `ignore` are skipped. If `logger` is provided, then + warning messages are logged there when a directory cannot be listed. """ # Make sure the path isn't a Unicode string. path = bytestring_path(path) # Get all the directories and files at this level. + try: + contents = os.listdir(syspath(path)) + except OSError as exc: + if logger: + logger.warn(u'could not list directory {0}: {1}'.format( + displayable_path(path), exc.strerror + )) + return dirs = [] files = [] - for base in os.listdir(syspath(path)): + for base in contents: base = bytestring_path(base) # Skip ignored filenames. @@ -160,16 +180,16 @@ def sorted_walk(path, ignore=()): else: files.append(base) - # Sort lists and yield the current level. - dirs.sort() - files.sort() + # Sort lists (case-insensitive) and yield the current level. + dirs.sort(key=bytes.lower) + files.sort(key=bytes.lower) yield (path, dirs, files) # Recurse into directories. for base in dirs: cur = os.path.join(path, base) # yield from sorted_walk(...) - for res in sorted_walk(cur, ignore): + for res in sorted_walk(cur, ignore, logger): yield res def mkdirall(path): @@ -178,13 +198,31 @@ def mkdirall(path): """ for ancestor in ancestry(path): if not os.path.isdir(syspath(ancestor)): - os.mkdir(syspath(ancestor)) + try: + os.mkdir(syspath(ancestor)) + except (OSError, IOError) as exc: + raise FilesystemError(exc, 'create', (ancestor,), + traceback.format_exc()) + +def fnmatch_all(names, patterns): + """Determine whether all strings in `names` match at least one of + the `patterns`, which should be shell glob expressions. + """ + for name in names: + matches = False + for pattern in patterns: + matches = fnmatch.fnmatch(name, pattern) + if matches: + break + if not matches: + return False + return True def prune_dirs(path, root=None, clutter=('.DS_Store', 'Thumbs.db')): """If path is an empty directory, then remove it. Recursively remove path's ancestry up to root (which is never removed) where there are empty directories. If path is not contained in root, then nothing is - removed. Filenames in clutter are ignored when determining + removed. Glob patterns in clutter are ignored when determining emptiness. If root is not provided, then only path may be removed (i.e., no recursive removal). """ @@ -211,8 +249,7 @@ def prune_dirs(path, root=None, clutter=('.DS_Store', 'Thumbs.db')): if not os.path.exists(directory): # Directory gone already. continue - - if all(fn in clutter for fn in os.listdir(directory)): + if fnmatch_all(os.listdir(directory), clutter): # Directory contains only clutter (or nothing). try: shutil.rmtree(directory) @@ -221,27 +258,43 @@ def prune_dirs(path, root=None, clutter=('.DS_Store', 'Thumbs.db')): else: break -def components(path, pathmod=None): +def components(path): """Return a list of the path components in path. For instance: + >>> components('/a/b/c') ['a', 'b', 'c'] + + The argument should *not* be the result of a call to `syspath`. """ - pathmod = pathmod or os.path comps = [] - ances = ancestry(path, pathmod) + ances = ancestry(path) for anc in ances: - comp = pathmod.basename(anc) + comp = os.path.basename(anc) if comp: comps.append(comp) else: # root comps.append(anc) - last = pathmod.basename(path) + last = os.path.basename(path) if last: comps.append(last) return comps +def _fsencoding(): + """Get the system's filesystem encoding. On Windows, this is always + UTF-8 (not MBCS). + """ + encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() + if encoding == 'mbcs': + # On Windows, a broken encoding known to Python as "MBCS" is + # used for the filesystem. However, we only use the Unicode API + # for Windows paths, so the encoding is actually immaterial so + # we can avoid dealing with this nastiness. We arbitrarily + # choose UTF-8. + encoding = 'utf8' + return encoding + def bytestring_path(path): """Given a path, which is either a str or a unicode, returns a str path (ensuring that we never deal with Unicode pathnames). @@ -250,46 +303,45 @@ def bytestring_path(path): if isinstance(path, str): return path + # On Windows, remove the magic prefix added by `syspath`. This makes + # ``bytestring_path(syspath(X)) == X``, i.e., we can safely + # round-trip through `syspath`. + if os.path.__name__ == 'ntpath' and path.startswith(WINDOWS_MAGIC_PREFIX): + path = path[len(WINDOWS_MAGIC_PREFIX):] + # Try to encode with default encodings, but fall back to UTF8. - encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() - if encoding == 'mbcs': - # On Windows, a broken encoding known to Python as "MBCS" is - # used for the filesystem. However, we only use the Unicode API - # for Windows paths, so the encoding is actually immaterial so - # we can avoid dealing with this nastiness. We arbitrarily - # choose UTF-8. - encoding = 'utf8' try: - return path.encode(encoding) + return path.encode(_fsencoding()) except (UnicodeError, LookupError): return path.encode('utf8') -def displayable_path(path): +def displayable_path(path, separator=u'; '): """Attempts to decode a bytestring path to a unicode object for the - purpose of displaying it to the user. + purpose of displaying it to the user. If the `path` argument is a + list or a tuple, the elements are joined with `separator`. """ - if isinstance(path, unicode): + if isinstance(path, (list, tuple)): + return separator.join(displayable_path(p) for p in path) + elif isinstance(path, unicode): return path elif not isinstance(path, str): # A non-string object: just get its unicode representation. return unicode(path) - encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() try: - return path.decode(encoding, 'ignore') + return path.decode(_fsencoding(), 'ignore') except (UnicodeError, LookupError): return path.decode('utf8', 'ignore') -def syspath(path, pathmod=None): +def syspath(path, prefix=True): """Convert a path for use by the operating system. In particular, paths on Windows must receive a magic prefix and must be converted - to unicode before they are sent to the OS. + to Unicode before they are sent to the OS. To disable the magic + prefix on Windows, set `prefix` to False---but only do this if you + *really* know what you're doing. """ - pathmod = pathmod or os.path - windows = pathmod.__name__ == 'ntpath' - # Don't do anything if we're not on windows - if not windows: + if os.path.__name__ != 'ntpath': return path if not isinstance(path, unicode): @@ -305,8 +357,8 @@ def syspath(path, pathmod=None): path = path.decode(encoding, 'replace') # Add the magic prefix if it isn't already there - if not path.startswith(u'\\\\?\\'): - path = u'\\\\?\\' + path + if prefix and not path.startswith(WINDOWS_MAGIC_PREFIX): + path = WINDOWS_MAGIC_PREFIX + path return path @@ -326,7 +378,7 @@ def remove(path, soft=True): except (OSError, IOError) as exc: raise FilesystemError(exc, 'delete', (path,), traceback.format_exc()) -def copy(path, dest, replace=False, pathmod=os.path): +def copy(path, dest, replace=False): """Copy a plain file. Permissions are not copied. If `dest` already exists, raises a FilesystemError unless `replace` is True. Has no effect if `path` is the same as `dest`. Paths are translated to @@ -336,7 +388,7 @@ def copy(path, dest, replace=False, pathmod=os.path): return path = syspath(path) dest = syspath(dest) - if not replace and pathmod.exists(dest): + if not replace and os.path.exists(dest): raise FilesystemError('file exists', 'copy', (path, dest)) try: shutil.copyfile(path, dest) @@ -344,7 +396,7 @@ def copy(path, dest, replace=False, pathmod=os.path): raise FilesystemError(exc, 'copy', (path, dest), traceback.format_exc()) -def move(path, dest, replace=False, pathmod=os.path): +def move(path, dest, replace=False): """Rename a file. `dest` may not be a directory. If `dest` already exists, raises an OSError unless `replace` is True. Has no effect if `path` is the same as `dest`. If the paths are on different @@ -356,7 +408,7 @@ def move(path, dest, replace=False, pathmod=os.path): return path = syspath(path) dest = syspath(dest) - if pathmod.exists(dest): + if os.path.exists(dest) and not replace: raise FilesystemError('file exists', 'rename', (path, dest), traceback.format_exc()) @@ -405,60 +457,41 @@ CHAR_REPLACE = [ (re.compile(ur'\.$'), u'_'), # Trailing dots. (re.compile(ur'\s+$'), u''), # Trailing whitespace. ] -def sanitize_path(path, pathmod=None, replacements=None): +def sanitize_path(path, replacements=None): """Takes a path (as a Unicode string) and makes sure that it is legal. Returns a new path. Only works with fragments; won't work reliably on Windows when a path begins with a drive letter. Path separators (including altsep!) should already be cleaned from the path components. If replacements is specified, it is used *instead* - of the default set of replacements for the platform; it must be a - list of (compiled regex, replacement string) pairs. + of the default set of replacements; it must be a list of (compiled + regex, replacement string) pairs. """ - pathmod = pathmod or os.path + replacements = replacements or CHAR_REPLACE - # Choose the appropriate replacements. - if not replacements: - replacements = list(CHAR_REPLACE) - - comps = components(path, pathmod) + comps = components(path) if not comps: return '' for i, comp in enumerate(comps): - # Replace special characters. for regex, repl in replacements: comp = regex.sub(repl, comp) - - # Truncate each component. - comp = comp[:MAX_FILENAME_LENGTH] - comps[i] = comp - return pathmod.join(*comps) + return os.path.join(*comps) -def sanitize_for_path(value, pathmod, key=None): - """Sanitize the value for inclusion in a path: replace separators - with _, etc. Doesn't guarantee that the whole path will be valid; - you should still call sanitize_path on the complete path. +def truncate_path(path, length=MAX_FILENAME_LENGTH): + """Given a bytestring path or a Unicode path fragment, truncate the + components to a legal length. In the last component, the extension + is preserved. """ - if isinstance(value, basestring): - for sep in (pathmod.sep, pathmod.altsep): - if sep: - value = value.replace(sep, u'_') - elif key in ('track', 'tracktotal', 'disc', 'disctotal'): - # Pad indices with zeros. - value = u'%02i' % (value or 0) - elif key == 'year': - value = u'%04i' % (value or 0) - elif key in ('month', 'day'): - value = u'%02i' % (value or 0) - elif key == 'bitrate': - # Bitrate gets formatted as kbps. - value = u'%ikbps' % ((value or 0) // 1000) - elif key == 'samplerate': - # Sample rate formatted as kHz. - value = u'%ikHz' % ((value or 0) // 1000) - else: - value = unicode(value) - return value + comps = components(path) + + out = [c[:length] for c in comps] + base, ext = os.path.splitext(comps[-1]) + if ext: + # Last component has an extension. + base = base[:length - len(ext)] + out[-1] = base + ext + + return os.path.join(*out) def str2bool(value): """Returns a boolean reflecting a human-entered string.""" @@ -467,6 +500,19 @@ def str2bool(value): else: return False +def as_string(value): + """Convert a value to a Unicode object for matching with a query. + None becomes the empty string. Bytestrings are silently decoded. + """ + if value is None: + return u'' + elif isinstance(value, buffer): + return str(value).decode('utf8', 'ignore') + elif isinstance(value, str): + return value.decode('utf8', 'ignore') + else: + return unicode(value) + def levenshtein(s1, s2): """A nice DP edit distance implementation from Wikibooks: http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/ @@ -511,3 +557,62 @@ def plurality(objs): res = obj return res, max_freq + +def cpu_count(): + """Return the number of hardware thread contexts (cores or SMT + threads) in the system. + """ + # Adapted from the soundconverter project: + # https://github.com/kassoulet/soundconverter + if sys.platform == 'win32': + try: + num = int(os.environ['NUMBER_OF_PROCESSORS']) + except (ValueError, KeyError): + num = 0 + elif sys.platform == 'darwin': + try: + num = int(os.popen('sysctl -n hw.ncpu').read()) + except ValueError: + num = 0 + else: + try: + num = os.sysconf('SC_NPROCESSORS_ONLN') + except (ValueError, OSError, AttributeError): + num = 0 + if num >= 1: + return num + else: + return 1 + +def command_output(cmd): + """Wraps the `subprocess` module to invoke a command (given as a + list of arguments starting with the command name) and collect + stdout. The stderr stream is ignored. May raise + `subprocess.CalledProcessError` or an `OSError`. + + This replaces `subprocess.check_output`, which isn't available in + Python 2.6 and which can have problems if lots of output is sent to + stderr. + """ + with open(os.devnull, 'w') as devnull: + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=devnull) + stdout, _ = proc.communicate() + if proc.returncode: + raise subprocess.CalledProcessError(proc.returncode, cmd) + return stdout + +def max_filename_length(path, limit=MAX_FILENAME_LENGTH): + """Attempt to determine the maximum filename length for the + filesystem containing `path`. If the value is greater than `limit`, + then `limit` is used instead (to prevent errors when a filesystem + misreports its capacity). If it cannot be determined (e.g., on + Windows), return `limit`. + """ + if hasattr(os, 'statvfs'): + try: + res = os.statvfs(path) + except OSError: + return limit + return min(res[9], limit) + else: + return limit diff --git a/beets/util/artresizer.py b/beets/util/artresizer.py new file mode 100644 index 00000000..6e367a0a --- /dev/null +++ b/beets/util/artresizer.py @@ -0,0 +1,188 @@ +# This file is part of beets. +# Copyright 2013, Fabrice Laporte +# +# 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. + +"""Abstraction layer to resize images using PIL, ImageMagick, or a +public resizing proxy if neither is available. +""" +import urllib +import subprocess +import os +from tempfile import NamedTemporaryFile +import logging +from beets import util + +# Resizing methods +PIL = 1 +IMAGEMAGICK = 2 +WEBPROXY = 3 + +PROXY_URL = 'http://images.weserv.nl/' + +log = logging.getLogger('beets') + + +def resize_url(url, maxwidth): + """Return a proxied image URL that resizes the original image to + maxwidth (preserving aspect ratio). + """ + return '{0}?{1}'.format(PROXY_URL, urllib.urlencode({ + 'url': url.replace('http://',''), + 'w': str(maxwidth), + })) + + +def temp_file_for(path): + """Return an unused filename with the same extension as the + specified path. + """ + ext = os.path.splitext(path)[1] + with NamedTemporaryFile(suffix=ext, delete=False) as f: + return f.name + + +def pil_resize(maxwidth, path_in, path_out=None): + """Resize using Python Imaging Library (PIL). Return the output path + of resized image. + """ + path_out = path_out or temp_file_for(path_in) + from PIL import Image + log.debug(u'artresizer: PIL resizing {0} to {1}'.format( + util.displayable_path(path_in), util.displayable_path(path_out) + )) + + try: + im = Image.open(util.syspath(path_in)) + size = maxwidth, maxwidth + im.thumbnail(size, Image.ANTIALIAS) + im.save(path_out) + return path_out + except IOError: + log.error(u"PIL cannot create thumbnail for '{0}'".format( + util.displayable_path(path_in) + )) + return path_in + + +def im_resize(maxwidth, path_in, path_out=None): + """Resize using ImageMagick's ``convert`` tool. + tool. Return the output path of resized image. + """ + path_out = path_out or temp_file_for(path_in) + log.debug(u'artresizer: ImageMagick resizing {0} to {1}'.format( + util.displayable_path(path_in), util.displayable_path(path_out) + )) + + # "-resize widthxheight>" shrinks images with dimension(s) larger + # than the corresponding width and/or height dimension(s). The > + # "only shrink" flag is prefixed by ^ escape char for Windows + # compatibility. + try: + util.command_output([ + 'convert', util.syspath(path_in), + '-resize', '{0}x^>'.format(maxwidth), path_out + ]) + except subprocess.CalledProcessError: + log.warn(u'artresizer: IM convert failed for {0}'.format( + util.displayable_path(path_in) + )) + return path_in + return path_out + + +BACKEND_FUNCS = { + PIL: pil_resize, + IMAGEMAGICK: im_resize, +} + + +class Shareable(type): + """A pseudo-singleton metaclass that allows both shared and + non-shared instances. The ``MyClass.shared`` property holds a + lazily-created shared instance of ``MyClass`` while calling + ``MyClass()`` to construct a new object works as usual. + """ + def __init__(cls, name, bases, dict): + super(Shareable, cls).__init__(name, bases, dict) + cls._instance = None + + @property + def shared(cls): + if cls._instance is None: + cls._instance = cls() + return cls._instance + + +class ArtResizer(object): + """A singleton class that performs image resizes. + """ + __metaclass__ = Shareable + + def __init__(self, method=None): + """Create a resizer object for the given method or, if none is + specified, with an inferred method. + """ + self.method = method or self._guess_method() + log.debug(u"artresizer: method is {0}".format(self.method)) + + def resize(self, maxwidth, path_in, path_out=None): + """Manipulate an image file according to the method, returning a + new path. For PIL or IMAGEMAGIC methods, resizes the image to a + temporary file. For WEBPROXY, returns `path_in` unmodified. + """ + if self.local: + func = BACKEND_FUNCS[self.method] + return func(maxwidth, path_in, path_out) + else: + return path_in + + def proxy_url(self, maxwidth, url): + """Modifies an image URL according the method, returning a new + URL. For WEBPROXY, a URL on the proxy server is returned. + Otherwise, the URL is returned unmodified. + """ + if self.local: + return url + else: + return resize_url(url, maxwidth) + + @property + def local(self): + """A boolean indicating whether the resizing method is performed + locally (i.e., PIL or IMAGEMAGICK). + """ + return self.method in BACKEND_FUNCS + + @staticmethod + def _guess_method(): + """Determine which resizing method to use. Returns PIL, + IMAGEMAGICK, or WEBPROXY depending on available dependencies. + """ + # Try importing PIL. + try: + __import__('PIL', fromlist=['Image']) + return PIL + except ImportError: + pass + + # Try invoking ImageMagick's "convert". + try: + out = util.command_output(['convert', '--version']) + if 'imagemagick' in out.lower(): + # system32/convert.exe may be interfering + return IMAGEMAGICK + except (subprocess.CalledProcessError, OSError): + pass + + # Fall back to Web proxy method. + return WEBPROXY diff --git a/lib/beets/util/bluelet.py b/beets/util/bluelet.py similarity index 91% rename from lib/beets/util/bluelet.py rename to beets/util/bluelet.py index aee63116..9d9432f2 100644 --- a/lib/beets/util/bluelet.py +++ b/beets/util/bluelet.py @@ -25,7 +25,8 @@ if PY3: else: exec(""" def _reraise(typ, exc, tb): - raise typ, exc, tb""") + raise typ, exc, tb +""") # Basic events used for thread scheduling. @@ -51,7 +52,7 @@ class WaitableEvent(Event): return (), (), () def fire(self): - """Called when an assoicated file descriptor becomes ready + """Called when an associated file descriptor becomes ready (i.e., is returned from a select() call). """ pass @@ -78,6 +79,11 @@ class JoinEvent(Event): def __init__(self, child): self.child = child +class KillEvent(Event): + """Unschedule a child thread.""" + def __init__(self, child): + self.child = child + class DelegationEvent(Event): """Suspend execution of the current thread, start a new thread and, once the child thread finished, return control to the parent @@ -194,7 +200,14 @@ class ThreadException(Exception): _reraise(self.exc_info[0], self.exc_info[1], self.exc_info[2]) SUSPENDED = Event() # Special sentinel placeholder for suspended threads. - + +class Delegated(Event): + """Placeholder indicating that a thread has delegated execution to a + different thread. + """ + def __init__(self, child): + self.child = child + def run(root_coro): """Schedules a coroutine, running it to completion. This encapsulates the Bluelet scheduler, which the root coroutine can @@ -260,6 +273,20 @@ def run(root_coro): next_event = DelegationEvent(next_event) threads[coro] = next_event + def kill_thread(coro): + """Unschedule this thread and its (recursive) delegates. + """ + # Collect all coroutines in the delegation stack. + coros = [coro] + while isinstance(threads[coro], Delegated): + coro = threads[coro].child + coros.append(coro) + + # Complete each coroutine from the top to the bottom of the + # stack. + for coro in reversed(coros): + complete_thread(coro, None) + # Continue advancing threads until root thread exits. exit_te = None while threads: @@ -280,7 +307,7 @@ def run(root_coro): advance_thread(coro, event.exc_info, True) have_ready = True elif isinstance(event, DelegationEvent): - threads[coro] = SUSPENDED # Suspend. + threads[coro] = Delegated(event.spawned) # Suspend. threads[event.spawned] = ValueEvent(None) # Spawn. delegators[event.spawned] = coro have_ready = True @@ -292,6 +319,10 @@ def run(root_coro): threads[coro] = SUSPENDED # Suspend. joiners[event.child].append(coro) have_ready = True + elif isinstance(event, KillEvent): + threads[coro] = ValueEvent(None) + kill_thread(event.child) + have_ready = True # Only start the select when nothing else is ready. if not have_ready: @@ -314,7 +345,7 @@ def run(root_coro): threads[event2coro[event]] = ReturnEvent(None) else: advance_thread(event2coro[event], value) - + except ThreadException as te: # Exception raised from inside a thread. event = ExceptionEvent(te.exc_info) @@ -327,7 +358,7 @@ def run(root_coro): # The thread is root-level. Raise in client code. exit_te = te break - + except: # For instance, KeyboardInterrupt during select(). Raise # into root thread and terminate others. @@ -344,12 +375,16 @@ def run(root_coro): # Sockets and their associated events. +class SocketClosedError(Exception): + pass + class Listener(object): """A socket wrapper object for listening sockets. """ def __init__(self, host, port): """Create a listening socket on the given hostname and port. """ + self._closed = False self.host = host self.port = port self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -362,11 +397,14 @@ class Listener(object): When a connection is made, the event returns a Connection object. """ + if self._closed: + raise SocketClosedError() return AcceptEvent(self) def close(self): """Immediately close the listening socket. (Not an event.) """ + self._closed = True self.sock.close() class Connection(object): @@ -376,13 +414,18 @@ class Connection(object): self.sock = sock self.addr = addr self._buf = b'' + self._closed = False def close(self): """Close the connection.""" + self._closed = True self.sock.close() def recv(self, size): """Read at most size bytes of data from the socket.""" + if self._closed: + raise SocketClosedError() + if self._buf: # We already have data read previously. out = self._buf[:size] @@ -395,14 +438,21 @@ class Connection(object): """Sends data on the socket, returning the number of bytes successfully sent. """ + if self._closed: + raise SocketClosedError() return SendEvent(self, data) def sendall(self, data): """Send all of data on the socket.""" + if self._closed: + raise SocketClosedError() return SendEvent(self, data, True) def readline(self, terminator=b"\n", bufsize=1024): """Reads a line (delimited by terminator) from the socket.""" + if self._closed: + raise SocketClosedError() + while True: if terminator in self._buf: line, self._buf = self._buf.split(terminator, 1) @@ -490,13 +540,13 @@ def call(coro): raise ValueError('%s is not a coroutine' % str(coro)) return DelegationEvent(coro) -def end(value = None): +def end(value=None): """Event: ends the coroutine and returns a value to its delegator. """ return ReturnEvent(value) -def read(fd, bufsize = None): +def read(fd, bufsize=None): """Event: read from a file descriptor asynchronously.""" if bufsize is None: # Read all. @@ -536,6 +586,11 @@ def join(coro): """ return JoinEvent(coro) +def kill(coro): + """Halt the execution of a different `spawn`ed thread. + """ + return KillEvent(coro) + # Convenience function for running socket servers. @@ -550,7 +605,7 @@ def server(host, port, func): yield func(conn) finally: conn.close() - + listener = Listener(host, port) try: while True: diff --git a/beets/util/confit.py b/beets/util/confit.py new file mode 100644 index 00000000..cf8b3629 --- /dev/null +++ b/beets/util/confit.py @@ -0,0 +1,900 @@ +# This file is part of Confit. +# Copyright 2014, Adrian Sampson. +# +# 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. + +"""Worry-free YAML configuration files. +""" +from __future__ import unicode_literals +import platform +import os +import pkgutil +import sys +import yaml +import types +try: + from collections import OrderedDict +except ImportError: + from ordereddict import OrderedDict + +UNIX_DIR_VAR = 'XDG_CONFIG_HOME' +UNIX_DIR_FALLBACK = '~/.config' +WINDOWS_DIR_VAR = 'APPDATA' +WINDOWS_DIR_FALLBACK = '~\\AppData\\Roaming' +MAC_DIR = '~/Library/Application Support' + +CONFIG_FILENAME = 'config.yaml' +DEFAULT_FILENAME = 'config_default.yaml' +ROOT_NAME = 'root' + +YAML_TAB_PROBLEM = "found character '\\t' that cannot start any token" + + +# Utilities. + +PY3 = sys.version_info[0] == 3 +STRING = str if PY3 else unicode +BASESTRING = str if PY3 else basestring +NUMERIC_TYPES = (int, float) if PY3 else (int, float, long) +TYPE_TYPES = (type,) if PY3 else (type, types.ClassType) + +def iter_first(sequence): + """Get the first element from an iterable or raise a ValueError if + the iterator generates no values. + """ + it = iter(sequence) + try: + if PY3: + return next(it) + else: + return it.next() + except StopIteration: + raise ValueError() + + +# Exceptions. + +class ConfigError(Exception): + """Base class for exceptions raised when querying a configuration. + """ + +class NotFoundError(ConfigError): + """A requested value could not be found in the configuration trees. + """ + +class ConfigTypeError(ConfigError, TypeError): + """The value in the configuration did not match the expected type. + """ + +class ConfigValueError(ConfigError, ValueError): + """The value in the configuration is illegal.""" + +class ConfigReadError(ConfigError): + """A configuration file could not be read.""" + def __init__(self, filename, reason=None): + self.filename = filename + self.reason = reason + + message = 'file {0} could not be read'.format(filename) + if isinstance(reason, yaml.scanner.ScannerError) and \ + reason.problem == YAML_TAB_PROBLEM: + # Special-case error message for tab indentation in YAML markup. + message += ': found tab character at line {0}, column {1}'.format( + reason.problem_mark.line + 1, + reason.problem_mark.column + 1, + ) + elif reason: + # Generic error message uses exception's message. + message += ': {0}'.format(reason) + + super(ConfigReadError, self).__init__(message) + + +# Views and sources. + +class ConfigSource(dict): + """A dictionary augmented with metadata about the source of the + configuration. + """ + def __init__(self, value, filename=None, default=False): + super(ConfigSource, self).__init__(value) + if filename is not None and not isinstance(filename, BASESTRING): + raise TypeError('filename must be a string or None') + self.filename = filename + self.default = default + + def __repr__(self): + return 'ConfigSource({0}, {1}, {2})'.format( + super(ConfigSource, self).__repr__(), + repr(self.filename), + repr(self.default) + ) + + @classmethod + def of(self, value): + """Given either a dictionary or a `ConfigSource` object, return + a `ConfigSource` object. This lets a function accept either type + of object as an argument. + """ + if isinstance(value, ConfigSource): + return value + elif isinstance(value, dict): + return ConfigSource(value) + else: + raise TypeError('source value must be a dict') + +class ConfigView(object): + """A configuration "view" is a query into a program's configuration + data. A view represents a hypothetical location in the configuration + tree; to extract the data from the location, a client typically + calls the ``view.get()`` method. The client can access children in + the tree (subviews) by subscripting the parent view (i.e., + ``view[key]``). + """ + + name = None + """The name of the view, depicting the path taken through the + configuration in Python-like syntax (e.g., ``foo['bar'][42]``). + """ + + def resolve(self): + """The core (internal) data retrieval method. Generates (value, + source) pairs for each source that contains a value for this + view. May raise ConfigTypeError if a type error occurs while + traversing a source. + """ + raise NotImplementedError + + def first(self): + """Return a (value, source) pair for the first object found for + this view. This amounts to the first element returned by + `resolve`. If no values are available, a NotFoundError is + raised. + """ + pairs = self.resolve() + try: + return iter_first(pairs) + except ValueError: + raise NotFoundError("{0} not found".format(self.name)) + + def exists(self): + """Determine whether the view has a setting in any source. + """ + try: + self.first() + except NotFoundError: + return False + return True + + def add(self, value): + """Set the *default* value for this configuration view. The + specified value is added as the lowest-priority configuration + data source. + """ + raise NotImplementedError + + def set(self, value): + """*Override* the value for this configuration view. The + specified value is added as the highest-priority configuration + data source. + """ + raise NotImplementedError + + def root(self): + """The RootView object from which this view is descended. + """ + raise NotImplementedError + + def __repr__(self): + return '' % self.name + + def __getitem__(self, key): + """Get a subview of this view.""" + return Subview(self, key) + + def __setitem__(self, key, value): + """Create an overlay source to assign a given key under this + view. + """ + self.set({key: value}) + + def set_args(self, namespace): + """Overlay parsed command-line arguments, generated by a library + like argparse or optparse, onto this view's value. + """ + args = {} + for key, value in namespace.__dict__.items(): + if value is not None: # Avoid unset options. + args[key] = value + self.set(args) + + # Magical conversions. These special methods make it possible to use + # View objects somewhat transparently in certain circumstances. For + # example, rather than using ``view.get(bool)``, it's possible to + # just say ``bool(view)`` or use ``view`` in a conditional. + + def __str__(self): + """Gets the value for this view as a byte string.""" + return str(self.get()) + + def __unicode__(self): + """Gets the value for this view as a unicode string. (Python 2 + only.) + """ + return unicode(self.get()) + + def __nonzero__(self): + """Gets the value for this view as a boolean. (Python 2 only.) + """ + return self.__bool__() + + def __bool__(self): + """Gets the value for this view as a boolean. (Python 3 only.) + """ + return bool(self.get()) + + # Dictionary emulation methods. + + def keys(self): + """Returns a list containing all the keys available as subviews + of the current views. This enumerates all the keys in *all* + dictionaries matching the current view, in contrast to + ``view.get(dict).keys()``, which gets all the keys for the + *first* dict matching the view. If the object for this view in + any source is not a dict, then a ConfigTypeError is raised. The + keys are ordered according to how they appear in each source. + """ + keys = [] + + for dic, _ in self.resolve(): + try: + cur_keys = dic.keys() + except AttributeError: + raise ConfigTypeError( + '{0} must be a dict, not {1}'.format( + self.name, type(dic).__name__ + ) + ) + + for key in cur_keys: + if key not in keys: + keys.append(key) + + return keys + + def items(self): + """Iterates over (key, subview) pairs contained in dictionaries + from *all* sources at this view. If the object for this view in + any source is not a dict, then a ConfigTypeError is raised. + """ + for key in self.keys(): + yield key, self[key] + + def values(self): + """Iterates over all the subviews contained in dictionaries from + *all* sources at this view. If the object for this view in any + source is not a dict, then a ConfigTypeError is raised. + """ + for key in self.keys(): + yield self[key] + + # List/sequence emulation. + + def all_contents(self): + """Iterates over all subviews from collections at this view from + *all* sources. If the object for this view in any source is not + iterable, then a ConfigTypeError is raised. This method is + intended to be used when the view indicates a list; this method + will concatenate the contents of the list from all sources. + """ + for collection, _ in self.resolve(): + try: + it = iter(collection) + except TypeError: + raise ConfigTypeError( + '{0} must be an iterable, not {1}'.format( + self.name, type(collection).__name__ + ) + ) + for value in it: + yield value + + # Validation and conversion. + + def get(self, typ=None): + """Returns the canonical value for the view, checked against the + passed-in type. If the value is not an instance of the given + type, a ConfigTypeError is raised. May also raise a + NotFoundError. + """ + value, _ = self.first() + + if typ is not None: + if not isinstance(typ, TYPE_TYPES): + raise TypeError('argument to get() must be a type') + + if not isinstance(value, typ): + raise ConfigTypeError( + "{0} must be of type {1}, not {2}".format( + self.name, typ.__name__, type(value).__name__ + ) + ) + + return value + + def as_filename(self): + """Get a string as a normalized as an absolute, tilde-free path. + + Relative paths are relative to the configuration directory (see + the `config_dir` method) if they come from a file. Otherwise, + they are relative to the current working directory. This helps + attain the expected behavior when using command-line options. + """ + path, source = self.first() + if not isinstance(path, BASESTRING): + raise ConfigTypeError('{0} must be a filename, not {1}'.format( + self.name, type(path).__name__ + )) + path = os.path.expanduser(STRING(path)) + + if not os.path.isabs(path) and source.filename: + # From defaults: relative to the app's directory. + path = os.path.join(self.root().config_dir(), path) + + return os.path.abspath(path) + + def as_choice(self, choices): + """Ensure that the value is among a collection of choices and + return it. If `choices` is a dictionary, then return the + corresponding value rather than the value itself (the key). + """ + value = self.get() + + if value not in choices: + raise ConfigValueError( + '{0} must be one of {1}, not {2}'.format( + self.name, repr(list(choices)), repr(value) + ) + ) + + if isinstance(choices, dict): + return choices[value] + else: + return value + + def as_number(self): + """Ensure that a value is of numeric type.""" + value = self.get() + if isinstance(value, NUMERIC_TYPES): + return value + raise ConfigTypeError( + '{0} must be numeric, not {1}'.format( + self.name, type(value).__name__ + ) + ) + + def as_str_seq(self): + """Get the value as a list of strings. The underlying configured + value can be a sequence or a single string. In the latter case, + the string is treated as a white-space separated list of words. + """ + value = self.get() + if isinstance(value, bytes): + value = value.decode('utf8', 'ignore') + + if isinstance(value, STRING): + return value.split() + else: + try: + return list(value) + except TypeError: + raise ConfigTypeError( + '{0} must be a whitespace-separated string or ' + 'a list'.format(self.name) + ) + + def flatten(self): + """Create a hierarchy of OrderedDicts containing the data from + this view, recursively reifying all views to get their + represented values. + """ + od = OrderedDict() + for key, view in self.items(): + try: + od[key] = view.flatten() + except ConfigTypeError: + od[key] = view.get() + return od + + +class RootView(ConfigView): + """The base of a view hierarchy. This view keeps track of the + sources that may be accessed by subviews. + """ + def __init__(self, sources): + """Create a configuration hierarchy for a list of sources. At + least one source must be provided. The first source in the list + has the highest priority. + """ + self.sources = list(sources) + self.name = ROOT_NAME + + def add(self, obj): + self.sources.append(ConfigSource.of(obj)) + + def set(self, value): + self.sources.insert(0, ConfigSource.of(value)) + + def resolve(self): + return ((dict(s), s) for s in self.sources) + + def clear(self): + """Remove all sources from this configuration.""" + del self.sources[:] + + def root(self): + return self + + +class Subview(ConfigView): + """A subview accessed via a subscript of a parent view.""" + def __init__(self, parent, key): + """Make a subview of a parent view for a given subscript key. + """ + self.parent = parent + self.key = key + + # Choose a human-readable name for this view. + if isinstance(self.parent, RootView): + self.name = '' + else: + self.name = self.parent.name + if not isinstance(self.key, int): + self.name += '.' + if isinstance(self.key, int): + self.name += '#{0}'.format(self.key) + elif isinstance(self.key, BASESTRING): + self.name += '{0}'.format(self.key) + else: + self.name += '{0}'.format(repr(self.key)) + + def resolve(self): + for collection, source in self.parent.resolve(): + try: + value = collection[self.key] + except IndexError: + # List index out of bounds. + continue + except KeyError: + # Dict key does not exist. + continue + except TypeError: + # Not subscriptable. + raise ConfigTypeError( + "{0} must be a collection, not {1}".format( + self.parent.name, type(collection).__name__ + ) + ) + yield value, source + + def set(self, value): + self.parent.set({self.key: value}) + + def add(self, value): + self.parent.add({self.key: value}) + + def root(self): + return self.parent.root() + + +# Config file paths, including platform-specific paths and in-package +# defaults. + +# Based on get_root_path from Flask by Armin Ronacher. +def _package_path(name): + """Returns the path to the package containing the named module or + None if the path could not be identified (e.g., if + ``name == "__main__"``). + """ + loader = pkgutil.get_loader(name) + if loader is None or name == '__main__': + return None + + if hasattr(loader, 'get_filename'): + filepath = loader.get_filename(name) + else: + # Fall back to importing the specified module. + __import__(name) + filepath = sys.modules[name].__file__ + + return os.path.dirname(os.path.abspath(filepath)) + +def config_dirs(): + """Return a platform-specific list of candidates for user + configuration directories on the system. + + The candidates are in order of priority, from highest to lowest. The + last element is the "fallback" location to be used when no + higher-priority config file exists. + """ + paths = [] + + if platform.system() == 'Darwin': + paths.append(MAC_DIR) + paths.append(UNIX_DIR_FALLBACK) + if UNIX_DIR_VAR in os.environ: + paths.append(os.environ[UNIX_DIR_VAR]) + + elif platform.system() == 'Windows': + paths.append(WINDOWS_DIR_FALLBACK) + if WINDOWS_DIR_VAR in os.environ: + paths.append(os.environ[WINDOWS_DIR_VAR]) + + else: + # Assume Unix. + paths.append(UNIX_DIR_FALLBACK) + if UNIX_DIR_VAR in os.environ: + paths.append(os.environ[UNIX_DIR_VAR]) + + # Expand and deduplicate paths. + out = [] + for path in paths: + path = os.path.abspath(os.path.expanduser(path)) + if path not in out: + out.append(path) + return out + + +# YAML loading. + +class Loader(yaml.SafeLoader): + """A customized YAML loader. This loader deviates from the official + YAML spec in a few convenient ways: + + - All strings as are Unicode objects. + - All maps are OrderedDicts. + - Strings can begin with % without quotation. + """ + # All strings should be Unicode objects, regardless of contents. + def _construct_unicode(self, node): + return self.construct_scalar(node) + + # Use ordered dictionaries for every YAML map. + # From https://gist.github.com/844388 + def construct_yaml_map(self, node): + data = OrderedDict() + yield data + value = self.construct_mapping(node) + data.update(value) + + def construct_mapping(self, node, deep=False): + if isinstance(node, yaml.MappingNode): + self.flatten_mapping(node) + else: + raise yaml.constructor.ConstructorError( + None, None, + 'expected a mapping node, but found %s' % node.id, + node.start_mark + ) + + mapping = OrderedDict() + for key_node, value_node in node.value: + key = self.construct_object(key_node, deep=deep) + try: + hash(key) + except TypeError as exc: + raise yaml.constructor.ConstructorError( + 'while constructing a mapping', + node.start_mark, 'found unacceptable key (%s)' % exc, + key_node.start_mark + ) + value = self.construct_object(value_node, deep=deep) + mapping[key] = value + return mapping + + # Allow bare strings to begin with %. Directives are still detected. + def check_plain(self): + plain = super(Loader, self).check_plain() + return plain or self.peek() == '%' + +Loader.add_constructor('tag:yaml.org,2002:str', Loader._construct_unicode) +Loader.add_constructor('tag:yaml.org,2002:map', Loader.construct_yaml_map) +Loader.add_constructor('tag:yaml.org,2002:omap', Loader.construct_yaml_map) + +def load_yaml(filename): + """Read a YAML document from a file. If the file cannot be read or + parsed, a ConfigReadError is raised. + """ + try: + with open(filename, 'r') as f: + return yaml.load(f, Loader=Loader) + except (IOError, yaml.error.YAMLError) as exc: + raise ConfigReadError(filename, exc) + + +# YAML dumping. + +class Dumper(yaml.SafeDumper): + """A PyYAML Dumper that represents OrderedDicts as ordinary mappings + (in order, of course). + """ + # From http://pyyaml.org/attachment/ticket/161/use_ordered_dict.py + def represent_mapping(self, tag, mapping, flow_style=None): + value = [] + node = yaml.MappingNode(tag, value, flow_style=flow_style) + if self.alias_key is not None: + self.represented_objects[self.alias_key] = node + best_style = False + if hasattr(mapping, 'items'): + mapping = list(mapping.items()) + for item_key, item_value in mapping: + node_key = self.represent_data(item_key) + node_value = self.represent_data(item_value) + if not (isinstance(node_key, yaml.ScalarNode) + and not node_key.style): + best_style = False + if not (isinstance(node_value, yaml.ScalarNode) + and not node_value.style): + best_style = False + value.append((node_key, node_value)) + if flow_style is None: + if self.default_flow_style is not None: + node.flow_style = self.default_flow_style + else: + node.flow_style = best_style + return node + + def represent_list(self, data): + """If a list has less than 4 items, represent it in inline style + (i.e. comma separated, within square brackets). + """ + node = super(Dumper, self).represent_list(data) + length = len(data) + if self.default_flow_style is None and length < 4: + node.flow_style = True + elif self.default_flow_style is None: + node.flow_style = False + return node + + def represent_bool(self, data): + """Represent bool as 'yes' or 'no' instead of 'true' or 'false'. + """ + if data: + value = 'yes' + else: + value = 'no' + return self.represent_scalar('tag:yaml.org,2002:bool', value) + + def represent_none(self, data): + """Represent a None value with nothing instead of 'none'. + """ + return self.represent_scalar('tag:yaml.org,2002:null', '') + +Dumper.add_representer(OrderedDict, Dumper.represent_dict) +Dumper.add_representer(bool, Dumper.represent_bool) +Dumper.add_representer(type(None), Dumper.represent_none) +Dumper.add_representer(list, Dumper.represent_list) + +def restore_yaml_comments(data, default_data): + """Scan default_data for comments (we include empty lines in our + definition of comments) and place them before the same keys in data. + Only works with comments that are on one or more own lines, i.e. + not next to a yaml mapping. + """ + comment_map = dict() + default_lines = iter(default_data.splitlines()) + for line in default_lines: + if not line: + comment = "\n" + elif line.startswith("#"): + comment = "{0}\n".format(line) + else: + continue + while True: + line = next(default_lines) + if line and not line.startswith("#"): + break + comment += "{0}\n".format(line) + key = line.split(':')[0].strip() + comment_map[key] = comment + out_lines = iter(data.splitlines()) + out_data = "" + for line in out_lines: + key = line.split(':')[0].strip() + if key in comment_map: + out_data += comment_map[key] + out_data += "{0}\n".format(line) + return out_data + + +# Main interface. + +class Configuration(RootView): + def __init__(self, appname, modname=None, read=True): + """Create a configuration object by reading the + automatically-discovered config files for the application for a + given name. If `modname` is specified, it should be the import + name of a module whose package will be searched for a default + config file. (Otherwise, no defaults are used.) Pass `False` for + `read` to disable automatic reading of all discovered + configuration files. Use this when creating a configuration + object at module load time and then call the `read` method + later. + """ + super(Configuration, self).__init__([]) + self.appname = appname + self.modname = modname + + self._env_var = '{0}DIR'.format(self.appname.upper()) + + if read: + self.read() + + def user_config_path(self): + """Points to the location of the user configuration. + + The file may not exist. + """ + return os.path.join(self.config_dir(), CONFIG_FILENAME) + + def _add_user_source(self): + """Add the configuration options from the YAML file in the + user's configuration directory (given by `config_dir`) if it + exists. + """ + filename = self.user_config_path() + if os.path.isfile(filename): + self.add(ConfigSource(load_yaml(filename) or {}, filename)) + + def _add_default_source(self): + """Add the package's default configuration settings. This looks + for a YAML file located inside the package for the module + `modname` if it was given. + """ + if self.modname: + pkg_path = _package_path(self.modname) + if pkg_path: + filename = os.path.join(pkg_path, DEFAULT_FILENAME) + if os.path.isfile(filename): + self.add(ConfigSource(load_yaml(filename), filename, True)) + + def read(self, user=True, defaults=True): + """Find and read the files for this configuration and set them + as the sources for this configuration. To disable either + discovered user configuration files or the in-package defaults, + set `user` or `defaults` to `False`. + """ + if user: + self._add_user_source() + if defaults: + self._add_default_source() + + def config_dir(self): + """Get the path to the user configuration directory. The + directory is guaranteed to exist as a postcondition (one may be + created if none exist). + + If the application's ``...DIR`` environment variable is set, it + is used as the configuration directory. Otherwise, + platform-specific standard configuration locations are searched + for a ``config.yaml`` file. If no configuration file is found, a + fallback path is used. + """ + # If environment variable is set, use it. + if self._env_var in os.environ: + appdir = os.environ[self._env_var] + appdir = os.path.abspath(os.path.expanduser(appdir)) + if os.path.isfile(appdir): + raise ConfigError('{0} must be a directory'.format( + self._env_var + )) + + else: + # Search platform-specific locations. If no config file is + # found, fall back to the final directory in the list. + for confdir in config_dirs(): + appdir = os.path.join(confdir, self.appname) + if os.path.isfile(os.path.join(appdir, CONFIG_FILENAME)): + break + + # Ensure that the directory exists. + if not os.path.isdir(appdir): + os.makedirs(appdir) + return appdir + + def set_file(self, filename): + """Parses the file as YAML and inserts it into the configuration + sources with highest priority. + """ + filename = os.path.abspath(filename) + self.set(ConfigSource(load_yaml(filename), filename)) + + def dump(self, full=True): + """Dump the Configuration object to a YAML file. + + The order of the keys is determined from the default + configuration file. All keys not in the default configuration + will be appended to the end of the file. + + :param filename: The file to dump the configuration to, or None + if the YAML string should be returned instead + :type filename: unicode + :param full: Dump settings that don't differ from the defaults + as well + """ + if full: + out_dict = self.flatten() + else: + # Exclude defaults when flattening. + sources = [s for s in self.sources if not s.default] + out_dict = RootView(sources).flatten() + + yaml_out = yaml.dump(out_dict, Dumper=Dumper, + default_flow_style=None, indent=4, + width=1000) + + # Restore comments to the YAML text. + default_source = None + for source in self.sources: + if source.default: + default_source = source + break + if default_source: + with open(default_source.filename, 'r') as fp: + default_data = fp.read() + yaml_out = restore_yaml_comments(yaml_out, default_data) + + return yaml_out + + +class LazyConfig(Configuration): + """A Configuration at reads files on demand when it is first + accessed. This is appropriate for using as a global config object at + the module level. + """ + def __init__(self, appname, modname=None): + super(LazyConfig, self).__init__(appname, modname, False) + self._materialized = False # Have we read the files yet? + self._lazy_prefix = [] # Pre-materialization calls to set(). + self._lazy_suffix = [] # Calls to add(). + + def read(self, user=True, defaults=True): + self._materialized = True + super(LazyConfig, self).read(user, defaults) + + def resolve(self): + if not self._materialized: + # Read files and unspool buffers. + self.read() + self.sources += self._lazy_suffix + self.sources[:0] = self._lazy_prefix + return super(LazyConfig, self).resolve() + + def add(self, value): + super(LazyConfig, self).add(value) + if not self._materialized: + # Buffer additions to end. + self._lazy_suffix += self.sources + del self.sources[:] + + def set(self, value): + super(LazyConfig, self).set(value) + if not self._materialized: + # Buffer additions to beginning. + self._lazy_prefix[:0] = self.sources + del self.sources[:] + + def clear(self): + """Remove all sources from this configuration.""" + del self.sources[:] + self._lazy_suffix = [] + self._lazy_prefix = [] diff --git a/lib/beets/util/enumeration.py b/beets/util/enumeration.py similarity index 99% rename from lib/beets/util/enumeration.py rename to beets/util/enumeration.py index f4968025..e6ec0766 100644 --- a/lib/beets/util/enumeration.py +++ b/beets/util/enumeration.py @@ -1,5 +1,5 @@ # This file is part of beets. -# Copyright 2011, Adrian Sampson. +# Copyright 2013, Adrian Sampson. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the diff --git a/lib/beets/util/functemplate.py b/beets/util/functemplate.py similarity index 99% rename from lib/beets/util/functemplate.py rename to beets/util/functemplate.py index 94cdf6c1..0fce41e5 100644 --- a/lib/beets/util/functemplate.py +++ b/beets/util/functemplate.py @@ -1,5 +1,5 @@ # This file is part of beets. -# Copyright 2011, Adrian Sampson. +# Copyright 2013, Adrian Sampson. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -496,6 +496,9 @@ class Template(object): self.original = template self.compiled = self.translate() + def __eq__(self, other): + return self.original == other.original + def interpret(self, values={}, functions={}): """Like `substitute`, but forces the interpreter (rather than the compiled version) to be used. The interpreter includes diff --git a/lib/beets/util/pipeline.py b/beets/util/pipeline.py similarity index 95% rename from lib/beets/util/pipeline.py rename to beets/util/pipeline.py index b81db3c7..c64454ff 100644 --- a/lib/beets/util/pipeline.py +++ b/beets/util/pipeline.py @@ -1,5 +1,5 @@ # This file is part of beets. -# Copyright 2011, Adrian Sampson. +# Copyright 2013, Adrian Sampson. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -304,32 +304,18 @@ class Pipeline(object): raise ValueError('pipeline must have at least two stages') self.stages = [] for stage in stages: - if isinstance(stage, types.GeneratorType): + if isinstance(stage, (list, tuple)): + self.stages.append(stage) + else: # Default to one thread per stage. self.stages.append((stage,)) - else: - self.stages.append(stage) def run_sequential(self): """Run the pipeline sequentially in the current thread. The stages are run one after the other. Only the first coroutine in each stage is used. """ - coros = [stage[0] for stage in self.stages] - - # "Prime" the coroutines. - for coro in coros[1:]: - coro.next() - - # Begin the pipeline. - for out in coros[0]: - msgs = _allmsgs(out) - for coro in coros[1:]: - next_msgs = [] - for msg in msgs: - out = coro.send(msg) - next_msgs.extend(_allmsgs(out)) - msgs = next_msgs + list(self.pull()) def run_parallel(self, queue_size=DEFAULT_QUEUE_SIZE): """Run the pipeline in parallel using one thread per stage. The @@ -386,6 +372,31 @@ class Pipeline(object): # Make the exception appear as it was raised originally. raise exc_info[0], exc_info[1], exc_info[2] + def pull(self): + """Yield elements from the end of the pipeline. Runs the stages + sequentially until the last yields some messages. Each of the messages + is then yielded by ``pulled.next()``. If the pipeline has a consumer, + that is the last stage does not yield any messages, then pull will not + yield any messages. Only the first coroutine in each stage is used + """ + coros = [stage[0] for stage in self.stages] + + # "Prime" the coroutines. + for coro in coros[1:]: + coro.next() + + # Begin the pipeline. + for out in coros[0]: + msgs = _allmsgs(out) + for coro in coros[1:]: + next_msgs = [] + for msg in msgs: + out = coro.send(msg) + next_msgs.extend(_allmsgs(out)) + msgs = next_msgs + for msg in msgs: + yield msg + # Smoke test. if __name__ == '__main__': import time @@ -432,7 +443,7 @@ if __name__ == '__main__': print('processing %i' % num) time.sleep(3) if num == 3: - raise Exception() + raise Exception() num = yield num * 2 def exc_consume(): while True: diff --git a/lib/beets/vfs.py b/beets/vfs.py similarity index 93% rename from lib/beets/vfs.py rename to beets/vfs.py index 815f8db3..235f3604 100644 --- a/lib/beets/vfs.py +++ b/beets/vfs.py @@ -1,5 +1,5 @@ # This file is part of beets. -# Copyright 2011, Adrian Sampson. +# Copyright 2013, Adrian Sampson. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -16,7 +16,7 @@ libraries. """ from collections import namedtuple -from lib.beets import util +from beets import util Node = namedtuple('Node', ['files', 'dirs']) @@ -42,7 +42,7 @@ def libtree(lib): """ root = Node({}, {}) for item in lib.items(): - dest = lib.destination(item, fragment=True) + dest = item.destination(fragment=True) parts = util.components(dest) _insert(root, parts, item.id) return root diff --git a/headphones/importer.py b/headphones/importer.py index 1d9b2260..d72df323 100644 --- a/headphones/importer.py +++ b/headphones/importer.py @@ -17,7 +17,7 @@ from lib.pyItunes import * import time import threading import os -from lib.beets.mediafile import MediaFile +from beets.mediafile import MediaFile import headphones from headphones import logger, helpers, db, mb, albumart, lastfm diff --git a/headphones/librarysync.py b/headphones/librarysync.py index 8706e0de..dbd54698 100644 --- a/headphones/librarysync.py +++ b/headphones/librarysync.py @@ -16,7 +16,7 @@ import os import glob -from lib.beets.mediafile import MediaFile +from beets.mediafile import MediaFile import headphones from headphones import db, logger, helpers, importer diff --git a/headphones/music_encoder.py b/headphones/music_encoder.py index e37f2d43..f7a3d624 100644 --- a/headphones/music_encoder.py +++ b/headphones/music_encoder.py @@ -20,7 +20,7 @@ import time import subprocess from headphones import logger -from lib.beets.mediafile import MediaFile +from beets.mediafile import MediaFile try: import argparse diff --git a/headphones/postprocessor.py b/headphones/postprocessor.py index 1333936f..31eb1d3e 100644 --- a/headphones/postprocessor.py +++ b/headphones/postprocessor.py @@ -22,9 +22,9 @@ import music_encoder import urllib, shutil, re import uuid from headphones import notifiers -import lib.beets as beets -from lib.beets import autotag -from lib.beets.mediafile import MediaFile +import beets +from beets import autotag +from beets.mediafile import MediaFile import headphones from headphones import db, albumart, librarysync, lyrics, logger, helpers diff --git a/lib/beets/autotag/__init__.py b/lib/beets/autotag/__init__.py deleted file mode 100644 index e4e4d1a0..00000000 --- a/lib/beets/autotag/__init__.py +++ /dev/null @@ -1,191 +0,0 @@ -# This file is part of beets. -# Copyright 2012, Adrian Sampson. -# -# 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. - -"""Facilities for automatically determining files' correct metadata. -""" -import os -import logging -import re - -from lib.beets import library, mediafile -from lib.beets.util import sorted_walk, ancestry - -# Parts of external interface. -from .hooks import AlbumInfo, TrackInfo, AlbumMatch, TrackMatch -from .match import AutotagError -from .match import tag_item, tag_album -from .match import RECOMMEND_STRONG, RECOMMEND_MEDIUM, RECOMMEND_NONE -from .match import STRONG_REC_THRESH, MEDIUM_REC_THRESH, REC_GAP_THRESH - -# Global logger. -log = logging.getLogger('beets') - -# Constants for directory walker. -MULTIDISC_MARKERS = (r'part', r'volume', r'vol\.', r'disc', r'cd') -MULTIDISC_PAT_FMT = r'%s\s*\d' - - -# Additional utilities for the main interface. - -def albums_in_dir(path, ignore=()): - """Recursively searches the given directory and returns an iterable - of (path, items) where path is a containing directory and items is - a list of Items that is probably an album. Specifically, any folder - containing any media files is an album. Directories and file names - that match the glob patterns in ``ignore`` are skipped. - """ - collapse_root = None - collapse_items = None - - for root, dirs, files in sorted_walk(path, ignore): - # Get a list of items in the directory. - items = [] - for filename in files: - try: - i = library.Item.from_path(os.path.join(root, filename)) - except mediafile.FileTypeError: - pass - except mediafile.UnreadableFileError: - log.warn('unreadable file: ' + filename) - else: - items.append(i) - - # If we're collapsing, test to see whether we should continue to - # collapse. If so, just add to the collapsed item set; - # otherwise, end the collapse and continue as normal. - if collapse_root is not None: - if collapse_root in ancestry(root): - # Still collapsing. - collapse_items += items - continue - else: - # Collapse finished. Yield the collapsed directory and - # proceed to process the current one. - if collapse_items: - yield collapse_root, collapse_items - collapse_root = collapse_items = None - - # Does the current directory look like a multi-disc album? If - # so, begin collapsing here. - if dirs and not items: # Must be only directories. - multidisc = False - for marker in MULTIDISC_MARKERS: - pat = MULTIDISC_PAT_FMT % marker - if all(re.search(pat, dirname, re.I) for dirname in dirs): - multidisc = True - break - - # This becomes True only when all directories match a - # pattern for a single marker. - if multidisc: - # Start collapsing; continue to the next iteration. - collapse_root = root - collapse_items = [] - continue - - # If it's nonempty, yield it. - if items: - yield root, items - - # Clear out any unfinished collapse. - if collapse_root is not None and collapse_items: - yield collapse_root, collapse_items - -def apply_item_metadata(item, track_info): - """Set an item's metadata from its matched TrackInfo object. - """ - item.artist = track_info.artist - item.artist_sort = track_info.artist_sort - item.artist_credit = track_info.artist_credit - item.title = track_info.title - item.mb_trackid = track_info.track_id - if track_info.artist_id: - item.mb_artistid = track_info.artist_id - # At the moment, the other metadata is left intact (including album - # and track number). Perhaps these should be emptied? - -def apply_metadata(album_info, mapping, per_disc_numbering=False): - """Set the items' metadata to match an AlbumInfo object using a - mapping from Items to TrackInfo objects. If `per_disc_numbering`, - then the track numbers are per-disc instead of per-release. - """ - for item, track_info in mapping.iteritems(): - # Album, artist, track count. - if not item: - continue - if track_info.artist: - item.artist = track_info.artist - else: - item.artist = album_info.artist - item.albumartist = album_info.artist - item.album = album_info.album - item.tracktotal = len(album_info.tracks) - - # Artist sort and credit names. - item.artist_sort = track_info.artist_sort or album_info.artist_sort - item.artist_credit = track_info.artist_credit or \ - album_info.artist_credit - item.albumartist_sort = album_info.artist_sort - item.albumartist_credit = album_info.artist_credit - - # Release date. - if album_info.year: - item.year = album_info.year - if album_info.month: - item.month = album_info.month - if album_info.day: - item.day = album_info.day - - # Title. - item.title = track_info.title - - if per_disc_numbering: - item.track = track_info.medium_index - else: - item.track = track_info.index - - # Disc and disc count. - item.disc = track_info.medium - item.disctotal = album_info.mediums - - # MusicBrainz IDs. - item.mb_trackid = track_info.track_id - item.mb_albumid = album_info.album_id - if track_info.artist_id: - item.mb_artistid = track_info.artist_id - else: - item.mb_artistid = album_info.artist_id - item.mb_albumartistid = album_info.artist_id - item.mb_releasegroupid = album_info.releasegroup_id - - # Compilation flag. - item.comp = album_info.va - - # Miscellaneous metadata. - item.albumtype = album_info.albumtype - if album_info.label: - item.label = album_info.label - - item.asin = album_info.asin - item.catalognum = album_info.catalognum - item.script = album_info.script - item.language = album_info.language - item.country = album_info.country - item.albumstatus = album_info.albumstatus - item.media = album_info.media - item.albumdisambig = album_info.albumdisambig - item.disctitle = track_info.disctitle - - # Headphones seal of approval - item.comments = 'tagged by headphones/beets' diff --git a/lib/beets/autotag/art.py b/lib/beets/autotag/art.py deleted file mode 100644 index 96ed7113..00000000 --- a/lib/beets/autotag/art.py +++ /dev/null @@ -1,152 +0,0 @@ -# This file is part of beets. -# Copyright 2011, Adrian Sampson. -# -# 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. - -"""Finding album art for tagged albums.""" - -import urllib -import sys -import logging -import os -import re - -from lib.beets.autotag.mb import album_for_id - -IMAGE_EXTENSIONS = ['png', 'jpg', 'jpeg'] -COVER_NAMES = ['cover', 'front', 'art', 'album', 'folder'] - -# The common logger. -log = logging.getLogger('beets') - - -CONTENT_TYPES = ('image/jpeg',) -def _fetch_image(url): - """Downloads an image from a URL and checks whether it seems to - actually be an image. If so, returns a path to the downloaded image. - Otherwise, returns None. - """ - log.debug('Downloading art: %s' % url) - try: - fn, headers = urllib.urlretrieve(url) - except IOError: - log.debug('error fetching art') - return - - # Make sure it's actually an image. - if headers.gettype() in CONTENT_TYPES: - log.debug('Downloaded art to: %s' % fn) - return fn - else: - log.debug('Not an image.') - - -# Art from Amazon. - -AMAZON_URL = 'http://images.amazon.com/images/P/%s.%02i.LZZZZZZZ.jpg' -AMAZON_INDICES = (1,2) -def art_for_asin(asin): - """Fetches art for an Amazon ID (ASIN) string.""" - for index in AMAZON_INDICES: - # Fetch the image. - url = AMAZON_URL % (asin, index) - fn = _fetch_image(url) - if fn: - return fn - - -# AlbumArt.org scraper. - -AAO_URL = 'http://www.albumart.org/index_detail.php' -AAO_PAT = r'href\s*=\s*"([^>"]*)"[^>]*title\s*=\s*"View larger image"' -def aao_art(asin): - # Get the page from albumart.org. - url = '%s?%s' % (AAO_URL, urllib.urlencode({'asin': asin})) - try: - log.debug('Scraping art URL: %s' % url) - page = urllib.urlopen(url).read() - except IOError: - log.debug('Error scraping art page') - return - - # Search the page for the image URL. - m = re.search(AAO_PAT, page) - if m: - image_url = m.group(1) - return _fetch_image(image_url) - else: - log.debug('No image found on page') - - -# Art from the filesystem. - -def art_in_path(path): - """Look for album art files in a specified directory.""" - if not os.path.isdir(path): - return - - # Find all files that look like images in the directory. - images = [] - for fn in os.listdir(path): - for ext in IMAGE_EXTENSIONS: - if fn.lower().endswith('.' + ext): - images.append(fn) - - # Look for "preferred" filenames. - for fn in images: - for name in COVER_NAMES: - if fn.lower().startswith(name): - log.debug('Using well-named art file %s' % fn) - return os.path.join(path, fn) - - # Fall back to any image in the folder. - if images: - log.debug('Using fallback art file %s' % images[0]) - return os.path.join(path, images[0]) - - -# Main interface. - -def art_for_album(album, path): - """Given an album info dictionary from MusicBrainz, returns a path - to downloaded art for the album (or None if no art is found). - """ - if isinstance(path, basestring): - out = art_in_path(path) - if out: - return out - - if album.asin: - log.debug('Fetching album art for ASIN %s.' % album.asin) - out = art_for_asin(album.asin) - if out: - return out - return aao_art(album.asin) - else: - log.debug('No ASIN available: no art found.') - return None - - -# Smoke test. - -if __name__ == '__main__': - aid = sys.argv[1] - album = album_for_id(aid) - if not album: - print 'album not found' - else: - fn = art_for_album(album, None) - if fn: - print fn - print len(open(fn).read())/1024 - else: - print 'no art found' diff --git a/lib/beets/autotag/hooks.py b/lib/beets/autotag/hooks.py deleted file mode 100644 index d0042ce3..00000000 --- a/lib/beets/autotag/hooks.py +++ /dev/null @@ -1,190 +0,0 @@ -# This file is part of beets. -# Copyright 2012, Adrian Sampson. -# -# 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. - -"""Glue between metadata sources and the matching logic.""" -import logging -from collections import namedtuple - -from lib.beets import plugins -from lib.beets.autotag import mb - -log = logging.getLogger('beets') - - -# Classes used to represent candidate options. - -class AlbumInfo(object): - """Describes a canonical release that may be used to match a release - in the library. Consists of these data members: - - - ``album``: the release title - - ``album_id``: MusicBrainz ID; UUID fragment only - - ``artist``: name of the release's primary artist - - ``artist_id`` - - ``tracks``: list of TrackInfo objects making up the release - - ``asin``: Amazon ASIN - - ``albumtype``: string describing the kind of release - - ``va``: boolean: whether the release has "various artists" - - ``year``: release year - - ``month``: release month - - ``day``: release day - - ``label``: music label responsible for the release - - ``mediums``: the number of discs in this release - - ``artist_sort``: name of the release's artist for sorting - - ``releasegroup_id``: MBID for the album's release group - - ``catalognum``: the label's catalog number for the release - - ``script``: character set used for metadata - - ``language``: human language of the metadata - - ``country``: the release country - - ``albumstatus``: MusicBrainz release status (Official, etc.) - - ``media``: delivery mechanism (Vinyl, etc.) - - ``albumdisambig``: MusicBrainz release disambiguation comment - - ``artist_credit``: Release-specific artist name - - The fields up through ``tracks`` are required. The others are - optional and may be None. - """ - def __init__(self, album, album_id, artist, artist_id, tracks, asin=None, - albumtype=None, va=False, year=None, month=None, day=None, - label=None, mediums=None, artist_sort=None, - releasegroup_id=None, catalognum=None, script=None, - language=None, country=None, albumstatus=None, media=None, - albumdisambig=None, artist_credit=None): - self.album = album - self.album_id = album_id - self.artist = artist - self.artist_id = artist_id - self.tracks = tracks - self.asin = asin - self.albumtype = albumtype - self.va = va - self.year = year - self.month = month - self.day = day - self.label = label - self.mediums = mediums - self.artist_sort = artist_sort - self.releasegroup_id = releasegroup_id - self.catalognum = catalognum - self.script = script - self.language = language - self.country = country - self.albumstatus = albumstatus - self.media = media - self.albumdisambig = albumdisambig - self.artist_credit = artist_credit - -class TrackInfo(object): - """Describes a canonical track present on a release. Appears as part - of an AlbumInfo's ``tracks`` list. Consists of these data members: - - - ``title``: name of the track - - ``track_id``: MusicBrainz ID; UUID fragment only - - ``artist``: individual track artist name - - ``artist_id`` - - ``length``: float: duration of the track in seconds - - ``index``: position on the entire release - - ``medium``: the disc number this track appears on in the album - - ``medium_index``: the track's position on the disc - - ``artist_sort``: name of the track artist for sorting - - ``disctitle``: name of the individual medium (subtitle) - - ``artist_credit``: Recording-specific artist name - - Only ``title`` and ``track_id`` are required. The rest of the fields - may be None. The indices ``index``, ``medium``, and ``medium_index`` - are all 1-based. - """ - def __init__(self, title, track_id, artist=None, artist_id=None, - length=None, index=None, medium=None, medium_index=None, - artist_sort=None, disctitle=None, artist_credit=None): - self.title = title - self.track_id = track_id - self.artist = artist - self.artist_id = artist_id - self.length = length - self.index = index - self.medium = medium - self.medium_index = medium_index - self.artist_sort = artist_sort - self.disctitle = disctitle - self.artist_credit = artist_credit - -AlbumMatch = namedtuple('AlbumMatch', ['distance', 'info', 'mapping', - 'extra_items', 'extra_tracks']) - -TrackMatch = namedtuple('TrackMatch', ['distance', 'info']) - - -# Aggregation of sources. - -def _album_for_id(album_id): - """Get an album corresponding to a MusicBrainz release ID.""" - try: - return mb.album_for_id(album_id) - except mb.MusicBrainzAPIError as exc: - exc.log(log) - -def _track_for_id(track_id): - """Get an item for a recording MBID.""" - try: - return mb.track_for_id(track_id) - except mb.MusicBrainzAPIError as exc: - exc.log(log) - -def _album_candidates(items, artist, album, va_likely): - """Search for album matches. ``items`` is a list of Item objects - that make up the album. ``artist`` and ``album`` are the respective - names (strings), which may be derived from the item list or may be - entered by the user. ``va_likely`` is a boolean indicating whether - the album is likely to be a "various artists" release. - """ - out = [] - - # Base candidates if we have album and artist to match. - if artist and album: - try: - out.extend(mb.match_album(artist, album, len(items))) - except mb.MusicBrainzAPIError as exc: - exc.log(log) - - # Also add VA matches from MusicBrainz where appropriate. - if va_likely and album: - try: - out.extend(mb.match_album(None, album, len(items))) - except mb.MusicBrainzAPIError as exc: - exc.log(log) - - # Candidates from plugins. - out.extend(plugins.candidates(items)) - - return out - -def _item_candidates(item, artist, title): - """Search for item matches. ``item`` is the Item to be matched. - ``artist`` and ``title`` are strings and either reflect the item or - are specified by the user. - """ - out = [] - - # MusicBrainz candidates. - if artist and title: - try: - out.extend(mb.match_track(artist, title)) - except mb.MusicBrainzAPIError as exc: - exc.log(log) - - # Plugin candidates. - out.extend(plugins.item_candidates(item)) - - return out diff --git a/lib/beets/autotag/match.py b/lib/beets/autotag/match.py deleted file mode 100644 index 1b42da49..00000000 --- a/lib/beets/autotag/match.py +++ /dev/null @@ -1,497 +0,0 @@ -# This file is part of beets. -# Copyright 2012, Adrian Sampson. -# -# 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. - -"""Matches existing metadata with canonical information to identify -releases and tracks. -""" -from __future__ import division - -import logging -import re -from lib.munkres import Munkres -#from unidecode import unidecode - -from lib.beets import plugins -from lib.beets.util import levenshtein, plurality -from lib.beets.autotag import hooks - -# Distance parameters. -# Text distance weights: proportions on the normalized intuitive edit -# distance. -ARTIST_WEIGHT = 3.0 -ALBUM_WEIGHT = 3.0 -# The weight of the entire distance calculated for a given track. -TRACK_WEIGHT = 1.0 -# The weight of a missing track. -MISSING_WEIGHT = 0.9 -# The weight of an extra (umatched) track. -UNMATCHED_WEIGHT = 0.6 -# These distances are components of the track distance (that is, they -# compete against each other but not ARTIST_WEIGHT and ALBUM_WEIGHT; -# the overall TRACK_WEIGHT does that). -TRACK_TITLE_WEIGHT = 3.0 -# Used instead of a global artist penalty for various-artist matches. -TRACK_ARTIST_WEIGHT = 2.0 -# Added when the indices of tracks don't match. -TRACK_INDEX_WEIGHT = 1.0 -# Track length weights: no penalty before GRACE, maximum (WEIGHT) -# penalty at GRACE+MAX discrepancy. -TRACK_LENGTH_GRACE = 10 -TRACK_LENGTH_MAX = 30 -TRACK_LENGTH_WEIGHT = 2.0 -# MusicBrainz track ID matches. -TRACK_ID_WEIGHT = 5.0 - -# Parameters for string distance function. -# Words that can be moved to the end of a string using a comma. -SD_END_WORDS = ['the', 'a', 'an'] -# Reduced weights for certain portions of the string. -SD_PATTERNS = [ - (r'^the ', 0.1), - (r'[\[\(]?(ep|single)[\]\)]?', 0.0), - (r'[\[\(]?(featuring|feat|ft)[\. :].+', 0.1), - (r'\(.*?\)', 0.3), - (r'\[.*?\]', 0.3), - (r'(, )?(pt\.|part) .+', 0.2), -] -# Replacements to use before testing distance. -SD_REPLACE = [ - (r'&', 'and'), -] - -# Recommendation constants. -RECOMMEND_STRONG = 'RECOMMEND_STRONG' -RECOMMEND_MEDIUM = 'RECOMMEND_MEDIUM' -RECOMMEND_NONE = 'RECOMMEND_NONE' -# Thresholds for recommendations. -STRONG_REC_THRESH = 0.04 -MEDIUM_REC_THRESH = 0.25 -REC_GAP_THRESH = 0.25 - -# Artist signals that indicate "various artists". These are used at the -# album level to determine whether a given release is likely a VA -# release and also on the track level to to remove the penalty for -# differing artists. -VA_ARTISTS = (u'', u'various artists', u'va', u'unknown') - -# Autotagging exceptions. -class AutotagError(Exception): - pass - -# Global logger. -log = logging.getLogger('beets') - - -# Primary matching functionality. - -def _string_dist_basic(str1, str2): - """Basic edit distance between two strings, ignoring - non-alphanumeric characters and case. Comparisons are based on a - transliteration/lowering to ASCII characters. Normalized by string - length. - """ - #str1 = unidecode(str1) - #str2 = unidecode(str2) - str1 = re.sub(r'[^a-z0-9]', '', str1.lower()) - str2 = re.sub(r'[^a-z0-9]', '', str2.lower()) - if not str1 and not str2: - return 0.0 - return levenshtein(str1, str2) / float(max(len(str1), len(str2))) - -def string_dist(str1, str2): - """Gives an "intuitive" edit distance between two strings. This is - an edit distance, normalized by the string length, with a number of - tweaks that reflect intuition about text. - """ - str1 = str1.lower() - str2 = str2.lower() - - # Don't penalize strings that move certain words to the end. For - # example, "the something" should be considered equal to - # "something, the". - for word in SD_END_WORDS: - if str1.endswith(', %s' % word): - str1 = '%s %s' % (word, str1[:-len(word)-2]) - if str2.endswith(', %s' % word): - str2 = '%s %s' % (word, str2[:-len(word)-2]) - - # Perform a couple of basic normalizing substitutions. - for pat, repl in SD_REPLACE: - str1 = re.sub(pat, repl, str1) - str2 = re.sub(pat, repl, str2) - - # Change the weight for certain string portions matched by a set - # of regular expressions. We gradually change the strings and build - # up penalties associated with parts of the string that were - # deleted. - base_dist = _string_dist_basic(str1, str2) - penalty = 0.0 - for pat, weight in SD_PATTERNS: - # Get strings that drop the pattern. - case_str1 = re.sub(pat, '', str1) - case_str2 = re.sub(pat, '', str2) - - if case_str1 != str1 or case_str2 != str2: - # If the pattern was present (i.e., it is deleted in the - # the current case), recalculate the distances for the - # modified strings. - case_dist = _string_dist_basic(case_str1, case_str2) - case_delta = max(0.0, base_dist - case_dist) - if case_delta == 0.0: - continue - - # Shift our baseline strings down (to avoid rematching the - # same part of the string) and add a scaled distance - # amount to the penalties. - str1 = case_str1 - str2 = case_str2 - base_dist = case_dist - penalty += weight * case_delta - dist = base_dist + penalty - - return dist - -def current_metadata(items): - """Returns the most likely artist and album for a set of Items. - Each is determined by tag reflected by the plurality of the Items. - """ - keys = 'artist', 'album' - likelies = {} - consensus = {} - for key in keys: - values = [getattr(item, key) for item in items if item] - likelies[key], freq = plurality(values) - consensus[key] = (freq == len(values)) - return likelies['artist'], likelies['album'], consensus['artist'] - -def assign_items(items, tracks): - """Given a list of Items and a list of TrackInfo objects, find the - best mapping between them. Returns a mapping from Items to TrackInfo - objects, a set of extra Items, and a set of extra TrackInfo - objects. These "extra" objects occur when there is an unequal number - of objects of the two types. - """ - # Construct the cost matrix. - costs = [] - for item in items: - row = [] - for i, track in enumerate(tracks): - row.append(track_distance(item, track)) - costs.append(row) - - # Find a minimum-cost bipartite matching. - matching = Munkres().compute(costs) - - # Produce the output matching. - mapping = dict((items[i], tracks[j]) for (i, j) in matching) - extra_items = set(items) - set(mapping.keys()) - extra_tracks = set(tracks) - set(mapping.values()) - return mapping, extra_items, extra_tracks - -def track_distance(item, track_info, incl_artist=False): - """Determines the significance of a track metadata change. Returns a - float in [0.0,1.0]. `incl_artist` indicates that a distance - component should be included for the track artist (i.e., for - various-artist releases). - """ - # Distance and normalization accumulators. - dist, dist_max = 0.0, 0.0 - - # Check track length. - # If there's no length to check, apply no penalty. - if track_info.length: - diff = abs(item.length - track_info.length) - diff = max(diff - TRACK_LENGTH_GRACE, 0.0) - diff = min(diff, TRACK_LENGTH_MAX) - dist += (diff / TRACK_LENGTH_MAX) * TRACK_LENGTH_WEIGHT - dist_max += TRACK_LENGTH_WEIGHT - - # Track title. - dist += string_dist(item.title, track_info.title) * TRACK_TITLE_WEIGHT - dist_max += TRACK_TITLE_WEIGHT - - # Track artist, if included. - # Attention: MB DB does not have artist info for all compilations, - # so only check artist distance if there is actually an artist in - # the MB track data. - if incl_artist and track_info.artist and \ - item.artist.lower() not in VA_ARTISTS: - dist += string_dist(item.artist, track_info.artist) * \ - TRACK_ARTIST_WEIGHT - dist_max += TRACK_ARTIST_WEIGHT - - # Track index. - if track_info.index and item.track: - if item.track not in (track_info.index, track_info.medium_index): - dist += TRACK_INDEX_WEIGHT - dist_max += TRACK_INDEX_WEIGHT - - # MusicBrainz track ID. - if item.mb_trackid: - if item.mb_trackid != track_info.track_id: - dist += TRACK_ID_WEIGHT - dist_max += TRACK_ID_WEIGHT - - # Plugin distances. - plugin_d, plugin_dm = plugins.track_distance(item, track_info) - dist += plugin_d - dist_max += plugin_dm - - return dist / dist_max - -def distance(items, album_info, mapping): - """Determines how "significant" an album metadata change would be. - Returns a float in [0.0,1.0]. `album_info` is an AlbumInfo object - reflecting the album to be compared. `items` is a sequence of all - Item objects that will be matched (order is not important). - `mapping` is a dictionary mapping Items to TrackInfo objects; the - keys are a subset of `items` and the values are a subset of - `album_info.tracks`. - """ - cur_artist, cur_album, _ = current_metadata(items) - cur_artist = cur_artist or '' - cur_album = cur_album or '' - - # These accumulate the possible distance components. The final - # distance will be dist/dist_max. - dist = 0.0 - dist_max = 0.0 - - # Artist/album metadata. - if not album_info.va: - dist += string_dist(cur_artist, album_info.artist) * ARTIST_WEIGHT - dist_max += ARTIST_WEIGHT - dist += string_dist(cur_album, album_info.album) * ALBUM_WEIGHT - dist_max += ALBUM_WEIGHT - - # Matched track distances. - for item, track in mapping.iteritems(): - dist += track_distance(item, track, album_info.va) * TRACK_WEIGHT - dist_max += TRACK_WEIGHT - - # Extra and unmatched tracks. - for track in set(album_info.tracks) - set(mapping.values()): - dist += MISSING_WEIGHT - dist_max += MISSING_WEIGHT - for item in set(items) - set(mapping.keys()): - dist += UNMATCHED_WEIGHT - dist_max += UNMATCHED_WEIGHT - - # Plugin distances. - plugin_d, plugin_dm = plugins.album_distance(items, album_info) - dist += plugin_d - dist_max += plugin_dm - - # Normalize distance, avoiding divide-by-zero. - if dist_max == 0.0: - return 0.0 - else: - return dist / dist_max - -def match_by_id(items): - """If the items are tagged with a MusicBrainz album ID, returns an - AlbumInfo object for the corresponding album. Otherwise, returns - None. - """ - # Is there a consensus on the MB album ID? - albumids = [item.mb_albumid for item in items if item.mb_albumid] - if not albumids: - log.debug('No album IDs found.') - return None - - # If all album IDs are equal, look up the album. - if bool(reduce(lambda x,y: x if x==y else (), albumids)): - albumid = albumids[0] - log.debug('Searching for discovered album ID: ' + albumid) - return hooks._album_for_id(albumid) - else: - log.debug('No album ID consensus.') - return None - - #fixme In the future, at the expense of performance, we could use - # other IDs (i.e., track and artist) in case the album tag isn't - # present, but that event seems very unlikely. - -def recommendation(results): - """Given a sorted list of AlbumMatch or TrackMatch objects, return a - recommendation flag (RECOMMEND_STRONG, RECOMMEND_MEDIUM, - RECOMMEND_NONE) based on the results' distances. - """ - if not results: - # No candidates: no recommendation. - rec = RECOMMEND_NONE - else: - min_dist = results[0].distance - if min_dist < STRONG_REC_THRESH: - # Strong recommendation level. - rec = RECOMMEND_STRONG - elif len(results) == 1: - # Only a single candidate. Medium recommendation. - rec = RECOMMEND_MEDIUM - elif min_dist <= MEDIUM_REC_THRESH: - # Medium recommendation level. - rec = RECOMMEND_MEDIUM - elif results[1].distance - min_dist >= REC_GAP_THRESH: - # Gap between first two candidates is large. - rec = RECOMMEND_MEDIUM - else: - # No conclusion. - rec = RECOMMEND_NONE - return rec - -def _add_candidate(items, results, info): - """Given a candidate AlbumInfo object, attempt to add the candidate - to the output dictionary of AlbumMatch objects. This involves - checking the track count, ordering the items, checking for - duplicates, and calculating the distance. - """ - log.debug('Candidate: %s - %s' % (info.artist, info.album)) - - # Don't duplicate. - if info.album_id in results: - log.debug('Duplicate.') - return - - # Find mapping between the items and the track info. - mapping, extra_items, extra_tracks = assign_items(items, info.tracks) - - # Get the change distance. - dist = distance(items, info, mapping) - log.debug('Success. Distance: %f' % dist) - - results[info.album_id] = hooks.AlbumMatch(dist, info, mapping, - extra_items, extra_tracks) - -def tag_album(items, timid=False, search_artist=None, search_album=None, - search_id=None): - """Bundles together the functionality used to infer tags for a - set of items comprised by an album. Returns everything relevant: - - The current artist. - - The current album. - - A list of AlbumMatch objects. The candidates are sorted by - distance (i.e., best match first). - - A recommendation, one of RECOMMEND_STRONG, RECOMMEND_MEDIUM, - or RECOMMEND_NONE; indicating that the first candidate is - very likely, it is somewhat likely, or no conclusion could - be reached. - If search_artist and search_album or search_id are provided, then - they are used as search terms in place of the current metadata. - May raise an AutotagError if existing metadata is insufficient. - """ - # Get current metadata. - cur_artist, cur_album, artist_consensus = current_metadata(items) - log.debug('Tagging %s - %s' % (cur_artist, cur_album)) - - # The output result (distance, AlbumInfo) tuples (keyed by MB album - # ID). - candidates = {} - - # Try to find album indicated by MusicBrainz IDs. - if search_id: - log.debug('Searching for album ID: ' + search_id) - id_info = hooks._album_for_id(search_id) - else: - id_info = match_by_id(items) - if id_info: - _add_candidate(items, candidates, id_info) - rec = recommendation(candidates.values()) - log.debug('Album ID match recommendation is ' + str(rec)) - if candidates and not timid: - # If we have a very good MBID match, return immediately. - # Otherwise, this match will compete against metadata-based - # matches. - if rec == RECOMMEND_STRONG: - log.debug('ID match.') - return cur_artist, cur_album, candidates.values(), rec - - # If searching by ID, don't continue to metadata search. - if search_id is not None: - if candidates: - return cur_artist, cur_album, candidates.values(), rec - else: - return cur_artist, cur_album, [], RECOMMEND_NONE - - # Search terms. - if not (search_artist and search_album): - # No explicit search terms -- use current metadata. - search_artist, search_album = cur_artist, cur_album - log.debug(u'Search terms: %s - %s' % (search_artist, search_album)) - - # Is this album likely to be a "various artist" release? - va_likely = ((not artist_consensus) or - (search_artist.lower() in VA_ARTISTS) or - any(item.comp for item in items)) - log.debug(u'Album might be VA: %s' % str(va_likely)) - - # Get the results from the data sources. - search_cands = hooks._album_candidates(items, search_artist, search_album, - va_likely) - log.debug(u'Evaluating %i candidates.' % len(search_cands)) - for info in search_cands: - _add_candidate(items, candidates, info) - - # Sort and get the recommendation. - candidates = sorted(candidates.itervalues()) - rec = recommendation(candidates) - return cur_artist, cur_album, candidates, rec - -def tag_item(item, timid=False, search_artist=None, search_title=None, - search_id=None): - """Attempts to find metadata for a single track. Returns a - `(candidates, recommendation)` pair where `candidates` is a list of - TrackMatch objects. `search_artist` and `search_title` may be used - to override the current metadata for the purposes of the MusicBrainz - title; likewise `search_id`. - """ - # Holds candidates found so far: keys are MBIDs; values are - # (distance, TrackInfo) pairs. - candidates = {} - - # First, try matching by MusicBrainz ID. - trackid = search_id or item.mb_trackid - if trackid: - log.debug('Searching for track ID: ' + trackid) - track_info = hooks._track_for_id(trackid) - if track_info: - dist = track_distance(item, track_info, incl_artist=True) - candidates[track_info.track_id] = \ - hooks.TrackMatch(dist, track_info) - # If this is a good match, then don't keep searching. - rec = recommendation(candidates.values()) - if rec == RECOMMEND_STRONG and not timid: - log.debug('Track ID match.') - return candidates.values(), rec - - # If we're searching by ID, don't proceed. - if search_id is not None: - if candidates: - return candidates.values(), rec - else: - return [], RECOMMEND_NONE - - # Search terms. - if not (search_artist and search_title): - search_artist, search_title = item.artist, item.title - log.debug(u'Item search terms: %s - %s' % (search_artist, search_title)) - - # Get and evaluate candidate metadata. - for track_info in hooks._item_candidates(item, search_artist, search_title): - dist = track_distance(item, track_info, incl_artist=True) - candidates[track_info.track_id] = hooks.TrackMatch(dist, track_info) - - # Sort by distance and return with recommendation. - log.debug('Found %i candidates.' % len(candidates)) - candidates = sorted(candidates.itervalues()) - rec = recommendation(candidates) - return candidates, rec diff --git a/lib/beets/library.py b/lib/beets/library.py deleted file mode 100644 index 31be2460..00000000 --- a/lib/beets/library.py +++ /dev/null @@ -1,1735 +0,0 @@ -# This file is part of beets. -# Copyright 2012, Adrian Sampson. -# -# 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 core data store and collection logic for beets. -""" -import sqlite3 -import os -import re -import sys -import logging -import shlex -import unicodedata -import threading -import contextlib -from collections import defaultdict -# from unidecode import unidecode -from lib.beets.mediafile import MediaFile -from lib.beets import plugins -from lib.beets import util -from lib.beets.util import bytestring_path, syspath, normpath, samefile -from lib.beets.util.functemplate import Template - -MAX_FILENAME_LENGTH = 200 - -# Fields in the "items" database table; all the metadata available for -# items in the library. These are used directly in SQL; they are -# vulnerable to injection if accessible to the user. -# Each tuple has the following values: -# - The name of the field. -# - The (SQLite) type of the field. -# - Is the field writable? -# - Does the field reflect an attribute of a MediaFile? -ITEM_FIELDS = [ - ('id', 'integer primary key', False, False), - ('path', 'blob', False, False), - ('album_id', 'int', False, False), - - ('title', 'text', True, True), - ('artist', 'text', True, True), - ('artist_sort', 'text', True, True), - ('artist_credit', 'text', True, True), - ('album', 'text', True, True), - ('albumartist', 'text', True, True), - ('albumartist_sort', 'text', True, True), - ('albumartist_credit', 'text', True, True), - ('genre', 'text', True, True), - ('composer', 'text', True, True), - ('grouping', 'text', True, True), - ('year', 'int', True, True), - ('month', 'int', True, True), - ('day', 'int', True, True), - ('track', 'int', True, True), - ('tracktotal', 'int', True, True), - ('disc', 'int', True, True), - ('disctotal', 'int', True, True), - ('lyrics', 'text', True, True), - ('comments', 'text', True, True), - ('bpm', 'int', True, True), - ('comp', 'bool', True, True), - ('mb_trackid', 'text', True, True), - ('mb_albumid', 'text', True, True), - ('mb_artistid', 'text', True, True), - ('mb_albumartistid', 'text', True, True), - ('albumtype', 'text', True, True), - ('label', 'text', True, True), - ('acoustid_fingerprint', 'text', True, True), - ('acoustid_id', 'text', True, True), - ('mb_releasegroupid', 'text', True, True), - ('asin', 'text', True, True), - ('catalognum', 'text', True, True), - ('script', 'text', True, True), - ('language', 'text', True, True), - ('country', 'text', True, True), - ('albumstatus', 'text', True, True), - ('media', 'text', True, True), - ('albumdisambig', 'text', True, True), - ('disctitle', 'text', True, True), - ('encoder', 'text', True, True), - - ('length', 'real', False, True), - ('bitrate', 'int', False, True), - ('format', 'text', False, True), - ('samplerate', 'int', False, True), - ('bitdepth', 'int', False, True), - ('channels', 'int', False, True), - ('mtime', 'int', False, False), -] -ITEM_KEYS_WRITABLE = [f[0] for f in ITEM_FIELDS if f[3] and f[2]] -ITEM_KEYS_META = [f[0] for f in ITEM_FIELDS if f[3]] -ITEM_KEYS = [f[0] for f in ITEM_FIELDS] - -# Database fields for the "albums" table. -# The third entry in each tuple indicates whether the field reflects an -# identically-named field in the items table. -ALBUM_FIELDS = [ - ('id', 'integer primary key', False), - ('artpath', 'blob', False), - - ('albumartist', 'text', True), - ('albumartist_sort', 'text', True), - ('albumartist_credit', 'text', True, True), - ('album', 'text', True), - ('genre', 'text', True), - ('year', 'int', True), - ('month', 'int', True), - ('day', 'int', True), - ('tracktotal', 'int', True), - ('disctotal', 'int', True), - ('comp', 'bool', True), - ('mb_albumid', 'text', True), - ('mb_albumartistid', 'text', True), - ('albumtype', 'text', True), - ('label', 'text', True), - ('mb_releasegroupid', 'text', True), - ('asin', 'text', True), - ('catalognum', 'text', True), - ('script', 'text', True), - ('language', 'text', True), - ('country', 'text', True), - ('albumstatus', 'text', True), - ('media', 'text', True), - ('albumdisambig', 'text', True), -] -ALBUM_KEYS = [f[0] for f in ALBUM_FIELDS] -ALBUM_KEYS_ITEM = [f[0] for f in ALBUM_FIELDS if f[2]] - -# Default search fields for various granularities. -ARTIST_DEFAULT_FIELDS = ('artist',) -ALBUM_DEFAULT_FIELDS = ('album', 'albumartist', 'genre') -ITEM_DEFAULT_FIELDS = ARTIST_DEFAULT_FIELDS + ALBUM_DEFAULT_FIELDS + \ - ('title', 'comments') - -# Special path format key. -PF_KEY_DEFAULT = 'default' - - -# Logger. -log = logging.getLogger('beets') -if not log.handlers: - log.addHandler(logging.StreamHandler()) - -# A little SQL utility. -def _orelse(exp1, exp2): - """Generates an SQLite expression that evaluates to exp1 if exp1 is - non-null and non-empty or exp2 otherwise. - """ - return ('(CASE {0} WHEN NULL THEN {1} ' - 'WHEN "" THEN {1} ' - 'ELSE {0} END)').format(exp1, exp2) - -# An SQLite function for regular expression matching. -def _regexp(expr, val): - """Return a boolean indicating whether the regular expression `expr` - matches `val`. - """ - if val is None or expr is None: - return False - if not isinstance(val, basestring): - val = unicode(val) - try: - res = re.search(expr, val) - except re.error: - # Invalid regular expression. - return False - return res is not None - - -# Exceptions. - -class InvalidFieldError(Exception): - pass - - -# Library items (songs). - -class Item(object): - def __init__(self, values): - self.dirty = {} - self._fill_record(values) - self._clear_dirty() - - @classmethod - def from_path(cls, path): - """Creates a new item from the media file at the specified path. - """ - # Initiate with values that aren't read from files. - i = cls({ - 'album_id': None, - }) - i.read(path) - i.mtime = i.current_mtime() # Initial mtime. - return i - - def _fill_record(self, values): - self.record = {} - for key in ITEM_KEYS: - try: - setattr(self, key, values[key]) - except KeyError: - setattr(self, key, None) - - def _clear_dirty(self): - self.dirty = {} - for key in ITEM_KEYS: - self.dirty[key] = False - - def __repr__(self): - return 'Item(' + repr(self.record) + ')' - - - # Item field accessors. - - def __getattr__(self, key): - """If key is an item attribute (i.e., a column in the database), - returns the record entry for that key. - """ - if key in ITEM_KEYS: - return self.record[key] - else: - raise AttributeError(key + ' is not a valid item field') - - def __setattr__(self, key, value): - """If key is an item attribute (i.e., a column in the database), - sets the record entry for that key to value. Note that to change - the attribute in the database or in the file's tags, one must - call store() or write(). - - Otherwise, performs an ordinary setattr. - """ - # Encode unicode paths and read buffers. - if key == 'path': - if isinstance(value, unicode): - value = bytestring_path(value) - elif isinstance(value, buffer): - value = str(value) - - if key in ITEM_KEYS: - # If the value changed, mark the field as dirty. - if (key not in self.record) or (self.record[key] != value): - self.record[key] = value - self.dirty[key] = True - if key in ITEM_KEYS_WRITABLE: - self.mtime = 0 # Reset mtime on dirty. - else: - super(Item, self).__setattr__(key, value) - - - # Interaction with file metadata. - - def read(self, read_path=None): - """Read the metadata from the associated file. If read_path is - specified, read metadata from that file instead. - """ - if read_path is None: - read_path = self.path - else: - read_path = normpath(read_path) - f = MediaFile(syspath(read_path)) - - for key in ITEM_KEYS_META: - setattr(self, key, getattr(f, key)) - self.path = read_path - - # Database's mtime should now reflect the on-disk value. - if read_path == self.path: - self.mtime = self.current_mtime() - - def write(self): - """Writes the item's metadata to the associated file. - """ - f = MediaFile(syspath(self.path)) - plugins.send('write', item=self, mf=f) - for key in ITEM_KEYS_WRITABLE: - setattr(f, key, getattr(self, key)) - f.save() - - # The file has a new mtime. - self.mtime = self.current_mtime() - - - # Files themselves. - - def move(self, dest, copy=False): - """Moves or copies the item's file, updating the path value if - the move succeeds. If a file exists at ``dest``, then it is - slightly modified to be unique. - """ - if not util.samefile(self.path, dest): - dest = util.unique_path(dest) - if copy: - util.copy(self.path, dest) - else: - util.move(self.path, dest) - - # Either copying or moving succeeded, so update the stored path. - self.path = dest - - def current_mtime(self): - """Returns the current mtime of the file, rounded to the nearest - integer. - """ - return int(os.path.getmtime(syspath(self.path))) - - - # Templating. - - def evaluate_template(self, template, lib=None, sanitize=False, - pathmod=None): - """Evaluates a Template object using the item's fields. If `lib` - is provided, it is used to map some fields to the item's album - (if available) and is made available to template functions. If - `sanitize`, then each value will be sanitized for inclusion in a - file path. - """ - pathmod = pathmod or os.path - - # Get the item's Album if it has one. - album = lib.get_album(self) - - # Build the mapping for substitution in the template, - # beginning with the values from the database. - mapping = {} - for key in ITEM_KEYS_META: - # Get the values from either the item or its album. - if key in ALBUM_KEYS_ITEM and album is not None: - # From album. - value = getattr(album, key) - else: - # From Item. - value = getattr(self, key) - if sanitize: - value = util.sanitize_for_path(value, pathmod, key) - mapping[key] = value - - # Use the album artist if the track artist is not set and - # vice-versa. - if not mapping['artist']: - mapping['artist'] = mapping['albumartist'] - if not mapping['albumartist']: - mapping['albumartist'] = mapping['artist'] - - # Get values from plugins. - for key, value in plugins.template_values(self).iteritems(): - if sanitize: - value = util.sanitize_for_path(value, pathmod, key) - mapping[key] = value - - # Get template functions. - funcs = DefaultTemplateFunctions(self, lib, pathmod).functions() - funcs.update(plugins.template_funcs()) - - # Perform substitution. - return template.substitute(mapping, funcs) - - -# Library queries. - -class Query(object): - """An abstract class representing a query into the item database. - """ - def clause(self): - """Returns (clause, subvals) where clause is a valid sqlite - WHERE clause implementing the query and subvals is a list of - items to be substituted for ?s in the clause. - """ - raise NotImplementedError - - def match(self, item): - """Check whether this query matches a given Item. Can be used to - perform queries on arbitrary sets of Items. - """ - raise NotImplementedError - - def statement(self, columns='*'): - """Returns (query, subvals) where clause is a sqlite SELECT - statement to enact this query and subvals is a list of values - to substitute in for ?s in the query. - """ - clause, subvals = self.clause() - return ('SELECT ' + columns + ' FROM items WHERE ' + clause, subvals) - - def count(self, tx): - """Returns `(num, length)` where `num` is the number of items in - the library matching this query and `length` is their total - length in seconds. - """ - clause, subvals = self.clause() - statement = 'SELECT COUNT(id), SUM(length) FROM items WHERE ' + clause - result = tx.query(statement, subvals)[0] - return (result[0], result[1] or 0.0) - -class FieldQuery(Query): - """An abstract query that searches in a specific field for a - pattern. - """ - def __init__(self, field, pattern): - if field not in ITEM_KEYS: - raise InvalidFieldError(field + ' is not an item key') - self.field = field - self.pattern = pattern - -class MatchQuery(FieldQuery): - """A query that looks for exact matches in an item field.""" - def clause(self): - pattern = self.pattern - if self.field == 'path' and isinstance(pattern, str): - pattern = buffer(pattern) - return self.field + " = ?", [pattern] - - def match(self, item): - return self.pattern == getattr(item, self.field) - -class SubstringQuery(FieldQuery): - """A query that matches a substring in a specific item field.""" - def clause(self): - search = '%' + (self.pattern.replace('\\','\\\\').replace('%','\\%') - .replace('_','\\_')) + '%' - clause = self.field + " like ? escape '\\'" - subvals = [search] - return clause, subvals - - def match(self, item): - value = getattr(item, self.field) or '' - return self.pattern.lower() in value.lower() - -class RegexpQuery(FieldQuery): - """A query that matches a regular expression in a specific item field.""" - def __init__(self, field, pattern): - super(RegexpQuery, self).__init__(field, pattern) - self.regexp = re.compile(pattern) - - def clause(self): - clause = self.field + " REGEXP ?" - subvals = [self.pattern] - return clause, subvals - - def match(self, item): - value = getattr(item, self.field) or '' - return self.regexp.search(value) is not None - -class BooleanQuery(MatchQuery): - """Matches a boolean field. Pattern should either be a boolean or a - string reflecting a boolean. - """ - def __init__(self, field, pattern): - super(BooleanQuery, self).__init__(field, pattern) - if isinstance(pattern, basestring): - self.pattern = util.str2bool(pattern) - self.pattern = int(self.pattern) - -class SingletonQuery(Query): - """Matches either singleton or non-singleton items.""" - def __init__(self, sense): - self.sense = sense - - def clause(self): - if self.sense: - return "album_id ISNULL", () - else: - return "NOT album_id ISNULL", () - - def match(self, item): - return (not item.album_id) == self.sense - -class CollectionQuery(Query): - """An abstract query class that aggregates other queries. Can be - indexed like a list to access the sub-queries. - """ - def __init__(self, subqueries=()): - self.subqueries = subqueries - - # is there a better way to do this? - def __len__(self): return len(self.subqueries) - def __getitem__(self, key): return self.subqueries[key] - def __iter__(self): return iter(self.subqueries) - def __contains__(self, item): return item in self.subqueries - - def clause_with_joiner(self, joiner): - """Returns a clause created by joining together the clauses of - all subqueries with the string joiner (padded by spaces). - """ - clause_parts = [] - subvals = [] - for subq in self.subqueries: - subq_clause, subq_subvals = subq.clause() - clause_parts.append('(' + subq_clause + ')') - subvals += subq_subvals - clause = (' ' + joiner + ' ').join(clause_parts) - return clause, subvals - - # Regular expression for _parse_query_part, below. - _pq_regex = re.compile( - # Non-capturing optional segment for the keyword. - r'(?:' - r'(\S+?)' # The field key. - r'(?>> f = MediaFile('Lucy.mp3') - >>> f.title - u'Lucy in the Sky with Diamonds' - >>> f.artist = 'The Beatles' - >>> f.save() - -A field will always return a reasonable value of the correct type, even -if no tag is present. If no value is available, the value will be false -(e.g., zero or the empty string). -""" -import lib.mutagen -import lib.mutagen.mp3 -import lib.mutagen.oggvorbis -import lib.mutagen.mp4 -import lib.mutagen.flac -import lib.mutagen.monkeysaudio -import datetime -import re -import base64 -import imghdr -import os -import logging -import traceback -from lib.beets.util.enumeration import enum - -__all__ = ['UnreadableFileError', 'FileTypeError', 'MediaFile'] - - -# Logger. -log = logging.getLogger('beets') - - -# Exceptions. - -# Raised for any file MediaFile can't read. -class UnreadableFileError(IOError): - pass - -# Raised for files that don't seem to have a type MediaFile supports. -class FileTypeError(UnreadableFileError): - pass - - -# Constants. - -# Human-readable type names. -TYPES = { - 'mp3': 'MP3', - 'mp4': 'AAC', - 'ogg': 'OGG', - 'flac': 'FLAC', - 'ape': 'APE', - 'wv': 'WavPack', - 'mpc': 'Musepack', -} - - -# Utility. - -def _safe_cast(out_type, val): - """Tries to covert val to out_type but will never raise an - exception. If the value can't be converted, then a sensible - default value is returned. out_type should be bool, int, or - unicode; otherwise, the value is just passed through. - """ - if out_type == int: - if val is None: - return 0 - elif isinstance(val, int) or isinstance(val, float): - # Just a number. - return int(val) - else: - # Process any other type as a string. - if not isinstance(val, basestring): - val = unicode(val) - # Get a number from the front of the string. - val = re.match(r'[0-9]*', val.strip()).group(0) - if not val: - return 0 - else: - return int(val) - - elif out_type == bool: - if val is None: - return False - else: - try: - # Should work for strings, bools, ints: - return bool(int(val)) - except ValueError: - return False - - elif out_type == unicode: - if val is None: - return u'' - else: - if isinstance(val, str): - return val.decode('utf8', 'ignore') - elif isinstance(val, unicode): - return val - else: - return unicode(val) - - elif out_type == float: - if val is None: - return 0.0 - elif isinstance(val, int) or isinstance(val, float): - return float(val) - else: - if not isinstance(val, basestring): - val = unicode(val) - val = re.match(r'[\+-]?[0-9\.]*', val.strip()).group(0) - if not val: - return 0.0 - else: - return float(val) - - else: - return val - - -# Flags for encoding field behavior. - -# Determine style of packing, if any. -packing = enum('SLASHED', # pair delimited by / - 'TUPLE', # a python tuple of 2 items - 'DATE', # YYYY-MM-DD - name='packing') - -class StorageStyle(object): - """Parameterizes the storage behavior of a single field for a - certain tag format. - - key: The Mutagen key used to access the field's data. - - list_elem: Store item as a single object or as first element - of a list. - - as_type: Which type the value is stored as (unicode, int, - bool, or str). - - packing: If this value is packed in a multiple-value storage - unit, which type of packing (in the packing enum). Otherwise, - None. (Makes as_type irrelevant). - - pack_pos: If the value is packed, in which position it is - stored. - - ID3 storage only: match against this 'desc' field as well - as the key. - """ - def __init__(self, key, list_elem = True, as_type = unicode, - packing = None, pack_pos = 0, id3_desc = None, - id3_frame_field = 'text'): - self.key = key - self.list_elem = list_elem - self.as_type = as_type - self.packing = packing - self.pack_pos = pack_pos - self.id3_desc = id3_desc - self.id3_frame_field = id3_frame_field - - -# Dealing with packings. - -class Packed(object): - """Makes a packed list of values subscriptable. To access the packed - output after making changes, use packed_thing.items. - """ - def __init__(self, items, packstyle, none_val=0, out_type=int): - """Create a Packed object for subscripting the packed values in - items. The items are packed using packstyle, which is a value - from the packing enum. none_val is returned from a request when - no suitable value is found in the items. Vales are converted to - out_type before they are returned. - """ - self.items = items - self.packstyle = packstyle - self.none_val = none_val - self.out_type = out_type - - def __getitem__(self, index): - if not isinstance(index, int): - raise TypeError('index must be an integer') - - if self.items is None: - return self.none_val - - items = self.items - if self.packstyle == packing.DATE: - # Remove time information from dates. Usually delimited by - # a "T" or a space. - items = re.sub(r'[Tt ].*$', '', unicode(items)) - - # transform from a string packing into a list we can index into - if self.packstyle == packing.SLASHED: - seq = unicode(items).split('/') - elif self.packstyle == packing.DATE: - seq = unicode(items).split('-') - elif self.packstyle == packing.TUPLE: - seq = items # tuple: items is already indexable - - try: - out = seq[index] - except: - out = None - - if out is None or out == self.none_val or out == '': - return _safe_cast(self.out_type, self.none_val) - else: - return _safe_cast(self.out_type, out) - - def __setitem__(self, index, value): - if self.packstyle in (packing.SLASHED, packing.TUPLE): - # SLASHED and TUPLE are always two-item packings - length = 2 - else: - # DATE can have up to three fields - length = 3 - - # make a list of the items we'll pack - new_items = [] - for i in range(length): - if i == index: - next_item = value - else: - next_item = self[i] - new_items.append(next_item) - - if self.packstyle == packing.DATE: - # Truncate the items wherever we reach an invalid (none) - # entry. This prevents dates like 2008-00-05. - for i, item in enumerate(new_items): - if item == self.none_val or item is None: - del(new_items[i:]) # truncate - break - - if self.packstyle == packing.SLASHED: - self.items = '/'.join(map(unicode, new_items)) - elif self.packstyle == packing.DATE: - field_lengths = [4, 2, 2] # YYYY-MM-DD - elems = [] - for i, item in enumerate(new_items): - elems.append( ('%0' + str(field_lengths[i]) + 'i') % item ) - self.items = '-'.join(elems) - elif self.packstyle == packing.TUPLE: - self.items = new_items - - -# The field itself. - -class MediaField(object): - """A descriptor providing access to a particular (abstract) metadata - field. out_type is the type that users of MediaFile should see and - can be unicode, int, or bool. id3, mp4, and flac are StorageStyle - instances parameterizing the field's storage for each type. - """ - def __init__(self, out_type = unicode, **kwargs): - """Creates a new MediaField. - - out_type: The field's semantic (exterior) type. - - kwargs: A hash whose keys are 'mp3', 'mp4', and 'etc' - and whose values are StorageStyle instances - parameterizing the field's storage for each type. - """ - self.out_type = out_type - if not set(['mp3', 'mp4', 'etc']) == set(kwargs): - raise TypeError('MediaField constructor must have keyword ' - 'arguments mp3, mp4, and etc') - self.styles = kwargs - - def _fetchdata(self, obj, style): - """Get the value associated with this descriptor's field stored - with the given StorageStyle. Unwraps from a list if necessary. - """ - # fetch the value, which may be a scalar or a list - if obj.type == 'mp3': - if style.id3_desc is not None: # also match on 'desc' field - frames = obj.mgfile.tags.getall(style.key) - entry = None - for frame in frames: - if frame.desc.lower() == style.id3_desc.lower(): - entry = getattr(frame, style.id3_frame_field) - break - if entry is None: # no desc match - return None - else: - # Get the metadata frame object. - try: - frame = obj.mgfile[style.key] - except KeyError: - return None - - entry = getattr(frame, style.id3_frame_field) - - else: # Not MP3. - try: - entry = obj.mgfile[style.key] - except KeyError: - return None - - # Possibly index the list. - if style.list_elem: - if entry: # List must have at least one value. - # Handle Mutagen bugs when reading values (#356). - try: - return entry[0] - except: - log.error('Mutagen exception when reading field: %s' % - traceback.format_exc) - return None - else: - return None - else: - return entry - - def _storedata(self, obj, val, style): - """Store val for this descriptor's field in the tag dictionary - according to the provided StorageStyle. Store it as a - single-item list if necessary. - """ - # Wrap as a list if necessary. - if style.list_elem: - out = [val] - else: - out = val - - if obj.type == 'mp3': - # Try to match on "desc" field. - if style.id3_desc is not None: - frames = obj.mgfile.tags.getall(style.key) - - # try modifying in place - found = False - for frame in frames: - if frame.desc.lower() == style.id3_desc.lower(): - setattr(frame, style.id3_frame_field, out) - found = True - break - - # need to make a new frame? - if not found: - assert isinstance(style.id3_frame_field, str) # Keyword. - frame = lib.mutagen.id3.Frames[style.key]( - encoding=3, - desc=style.id3_desc, - **{style.id3_frame_field: val} - ) - obj.mgfile.tags.add(frame) - - # Try to match on "owner" field. - elif style.key.startswith('UFID:'): - owner = style.key.split(':', 1)[1] - frames = obj.mgfile.tags.getall(style.key) - - for frame in frames: - # Replace existing frame data. - if frame.owner == owner: - setattr(frame, style.id3_frame_field, val) - else: - # New frame. - assert isinstance(style.id3_frame_field, str) # Keyword. - frame = lib.mutagen.id3.UFID(owner=owner, - **{style.id3_frame_field: val}) - obj.mgfile.tags.setall('UFID', [frame]) - - # Just replace based on key. - else: - assert isinstance(style.id3_frame_field, str) # Keyword. - frame = lib.mutagen.id3.Frames[style.key](encoding = 3, - **{style.id3_frame_field: val}) - obj.mgfile.tags.setall(style.key, [frame]) - - else: # Not MP3. - obj.mgfile[style.key] = out - - def _styles(self, obj): - if obj.type in ('mp3', 'mp4'): - styles = self.styles[obj.type] - else: - styles = self.styles['etc'] # Sane styles. - - # Make sure we always return a list of styles, even when given - # a single style for convenience. - if isinstance(styles, StorageStyle): - return [styles] - else: - return styles - - def __get__(self, obj, owner): - """Retrieve the value of this metadata field. - """ - # Fetch the data using the various StorageStyles. - styles = self._styles(obj) - if styles is None: - out = None - else: - for style in styles: - # Use the first style that returns a reasonable value. - out = self._fetchdata(obj, style) - if out: - break - - if style.packing: - out = Packed(out, style.packing)[style.pack_pos] - - # MPEG-4 freeform frames are (should be?) encoded as UTF-8. - if obj.type == 'mp4' and style.key.startswith('----:') and \ - isinstance(out, str): - out = out.decode('utf8') - - return _safe_cast(self.out_type, out) - - def __set__(self, obj, val): - """Set the value of this metadata field. - """ - # Store using every StorageStyle available. - styles = self._styles(obj) - if styles is None: - return - - for style in styles: - - if style.packing: - p = Packed(self._fetchdata(obj, style), style.packing) - p[style.pack_pos] = val - out = p.items - - else: # unicode, integer, or boolean scalar - out = val - - # deal with Nones according to abstract type if present - if out is None: - if self.out_type == int: - out = 0 - elif self.out_type == bool: - out = False - elif self.out_type == unicode: - out = u'' - # We trust that packed values are handled above. - - # Convert to correct storage type (irrelevant for - # packed values). - if style.as_type == unicode: - if out is None: - out = u'' - else: - if self.out_type == bool: - # store bools as 1,0 instead of True,False - out = unicode(int(out)) - elif isinstance(out, str): - out = out.decode('utf8', 'ignore') - else: - out = unicode(out) - elif style.as_type == int: - if out is None: - out = 0 - else: - out = int(out) - elif style.as_type in (bool, str): - out = style.as_type(out) - - # MPEG-4 "freeform" (----) frames must be encoded as UTF-8 - # byte strings. - if obj.type == 'mp4' and style.key.startswith('----:') and \ - isinstance(out, unicode): - out = out.encode('utf8') - - # Store the data. - self._storedata(obj, out, style) - -class CompositeDateField(object): - """A MediaFile field for conveniently accessing the year, month, and - day fields as a datetime.date object. Allows both getting and - setting of the component fields. - """ - def __init__(self, year_field, month_field, day_field): - """Create a new date field from the indicated MediaFields for - the component values. - """ - self.year_field = year_field - self.month_field = month_field - self.day_field = day_field - - def __get__(self, obj, owner): - """Return a datetime.date object whose components indicating the - smallest valid date whose components are at least as large as - the three component fields (that is, if year == 1999, month == 0, - and day == 0, then date == datetime.date(1999, 1, 1)). If the - components indicate an invalid date (e.g., if month == 47), - datetime.date.min is returned. - """ - try: - return datetime.date( - max(self.year_field.__get__(obj, owner), datetime.MINYEAR), - max(self.month_field.__get__(obj, owner), 1), - max(self.day_field.__get__(obj, owner), 1) - ) - except ValueError: # Out of range values. - return datetime.date.min - - def __set__(self, obj, val): - """Set the year, month, and day fields to match the components of - the provided datetime.date object. - """ - self.year_field.__set__(obj, val.year) - self.month_field.__set__(obj, val.month) - self.day_field.__set__(obj, val.day) - -class ImageField(object): - """A descriptor providing access to a file's embedded album art. - Holds a bytestring reflecting the image data. The image should - either be a JPEG or a PNG for cross-format compatibility. It's - probably a bad idea to use anything but these two formats. - """ - @classmethod - def _mime(cls, data): - """Return the MIME type (either image/png or image/jpeg) of the - image data (a bytestring). - """ - kind = imghdr.what(None, h=data) - if kind == 'png': - return 'image/png' - else: - # Currently just fall back to JPEG. - return 'image/jpeg' - - @classmethod - def _mp4kind(cls, data): - """Return the MPEG-4 image type code of the data. If the image - is not a PNG or JPEG, JPEG is assumed. - """ - kind = imghdr.what(None, h=data) - if kind == 'png': - return lib.mutagen.mp4.MP4Cover.FORMAT_PNG - else: - return lib.mutagen.mp4.MP4Cover.FORMAT_JPEG - - def __get__(self, obj, owner): - if obj.type == 'mp3': - # Look for APIC frames. - for frame in obj.mgfile.tags.values(): - if frame.FrameID == 'APIC': - picframe = frame - break - else: - # No APIC frame. - return None - - return picframe.data - - elif obj.type == 'mp4': - if 'covr' in obj.mgfile: - covers = obj.mgfile['covr'] - if covers: - cover = covers[0] - # cover is an MP4Cover, which is a subclass of str. - return cover - - # No cover found. - return None - elif obj.type == 'flac': - if 'metadata_block_picture' not in obj.mgfile: - return None - - for data in obj.mgfile['metadata_block_picture']: - try: - pic = lib.mutagen.flac.Picture(data) - break - except TypeError: - pass - else: - return None - - return pic.data - - else: - # Here we're assuming everything but MP3, FLAC and MPEG-4 use - # the Xiph/Vorbis Comments standard. This may not be valid. - # http://wiki.xiph.org/VorbisComment#Cover_art - - if 'metadata_block_picture' not in obj.mgfile: - # Try legacy COVERART tags. - if 'coverart' in obj.mgfile and obj.mgfile['coverart']: - return base64.b64decode(obj.mgfile['coverart'][0]) - return None - - for data in obj.mgfile["metadata_block_picture"]: - try: - pic = lib.mutagen.flac.Picture(base64.b64decode(data)) - break - except TypeError: - pass - else: - return None - - return pic.data - - def __set__(self, obj, val): - if val is not None: - if not isinstance(val, str): - raise ValueError('value must be a byte string or None') - - if obj.type == 'mp3': - # Clear all APIC frames. - obj.mgfile.tags.delall('APIC') - if val is None: - # If we're clearing the image, we're done. - return - - picframe = lib.mutagen.id3.APIC( - encoding = 3, - mime = self._mime(val), - type = 3, # front cover - desc = u'', - data = val, - ) - obj.mgfile['APIC'] = picframe - - elif obj.type == 'mp4': - if val is None: - if 'covr' in obj.mgfile: - del obj.mgfile['covr'] - else: - cover = lib.mutagen.mp4.MP4Cover(val, self._mp4kind(val)) - obj.mgfile['covr'] = [cover] - - elif obj.type == 'flac': - if val is None: - pic = lib.mutagen.flac.Picture() - pic.data = val - pic.mime = self._mime(val) - obj.mgfile['metadata_block_picture'] = [pic.write()] - - else: - # Again, assuming Vorbis Comments standard. - - # Strip all art, including legacy COVERART. - if 'metadata_block_picture' in obj.mgfile: - if 'metadata_block_picture' in obj.mgfile: - del obj.mgfile['metadata_block_picture'] - if 'coverart' in obj.mgfile: - del obj.mgfile['coverart'] - if 'coverartmime' in obj.mgfile: - del obj.mgfile['coverartmime'] - - # Add new art if provided. - if val is not None: - pic = lib.mutagen.flac.Picture() - pic.data = val - pic.mime = self._mime(val) - obj.mgfile['metadata_block_picture'] = [ - base64.b64encode(pic.write()) - ] - -class FloatValueField(MediaField): - """A field that stores a floating-point number as a string.""" - def __init__(self, places=2, suffix=None, **kwargs): - """Make a field that stores ``places`` digits after the decimal - point and appends ``suffix`` (if specified) when encoding as a - string. - """ - super(FloatValueField, self).__init__(unicode, **kwargs) - - fmt = ['%.', str(places), 'f'] - if suffix: - fmt += [' ', suffix] - self.fmt = ''.join(fmt) - - def __get__(self, obj, owner): - valstr = super(FloatValueField, self).__get__(obj, owner) - return _safe_cast(float, valstr) - - def __set__(self, obj, val): - if not val: - val = 0.0 - valstr = self.fmt % val - super(FloatValueField, self).__set__(obj, valstr) - - -# The file (a collection of fields). - -class MediaFile(object): - """Represents a multimedia file on disk and provides access to its - metadata. - """ - def __init__(self, path): - """Constructs a new MediaFile reflecting the file at path. May - throw UnreadableFileError. - """ - self.path = path - - unreadable_exc = ( - lib.mutagen.mp3.HeaderNotFoundError, - lib.mutagen.flac.FLACNoHeaderError, - lib.mutagen.monkeysaudio.MonkeysAudioHeaderError, - lib.mutagen.mp4.MP4StreamInfoError, - lib.mutagen.oggvorbis.OggVorbisHeaderError, - ) - try: - self.mgfile = lib.mutagen.File(path) - except unreadable_exc: - log.warn('header parsing failed') - raise UnreadableFileError('Mutagen could not read file') - except IOError: - raise UnreadableFileError('could not read file') - except Exception as exc: - # Hide bugs in Mutagen. - log.debug(traceback.format_exc()) - log.error('uncaught Mutagen exception: {0}'.format(exc)) - raise UnreadableFileError('Mutagen raised an exception') - - if self.mgfile is None: # Mutagen couldn't guess the type - raise FileTypeError('file type unsupported by Mutagen') - elif type(self.mgfile).__name__ == 'M4A' or \ - type(self.mgfile).__name__ == 'MP4': - self.type = 'mp4' - elif type(self.mgfile).__name__ == 'ID3' or \ - type(self.mgfile).__name__ == 'MP3': - self.type = 'mp3' - elif type(self.mgfile).__name__ == 'FLAC': - self.type = 'flac' - elif type(self.mgfile).__name__ == 'OggVorbis': - self.type = 'ogg' - elif type(self.mgfile).__name__ == 'MonkeysAudio': - self.type = 'ape' - elif type(self.mgfile).__name__ == 'WavPack': - self.type = 'wv' - elif type(self.mgfile).__name__ == 'Musepack': - self.type = 'mpc' - else: - raise FileTypeError('file type %s unsupported by MediaFile' % - type(self.mgfile).__name__) - - # add a set of tags if it's missing - if self.mgfile.tags is None: - self.mgfile.add_tags() - - def save(self): - self.mgfile.save() - - - # Field definitions. - - title = MediaField( - mp3 = StorageStyle('TIT2'), - mp4 = StorageStyle("\xa9nam"), - etc = StorageStyle('TITLE'), - ) - artist = MediaField( - mp3 = StorageStyle('TPE1'), - mp4 = StorageStyle("\xa9ART"), - etc = StorageStyle('ARTIST'), - ) - album = MediaField( - mp3 = StorageStyle('TALB'), - mp4 = StorageStyle("\xa9alb"), - etc = StorageStyle('ALBUM'), - ) - genre = MediaField( - mp3 = StorageStyle('TCON'), - mp4 = StorageStyle("\xa9gen"), - etc = StorageStyle('GENRE'), - ) - composer = MediaField( - mp3 = StorageStyle('TCOM'), - mp4 = StorageStyle("\xa9wrt"), - etc = StorageStyle('COMPOSER'), - ) - grouping = MediaField( - mp3 = StorageStyle('TIT1'), - mp4 = StorageStyle("\xa9grp"), - etc = StorageStyle('GROUPING'), - ) - year = MediaField(out_type=int, - mp3 = StorageStyle('TDRC', packing=packing.DATE, pack_pos=0), - mp4 = StorageStyle("\xa9day", packing=packing.DATE, pack_pos=0), - etc = [StorageStyle('DATE', packing=packing.DATE, pack_pos=0), - StorageStyle('YEAR')] - ) - month = MediaField(out_type=int, - mp3 = StorageStyle('TDRC', packing=packing.DATE, pack_pos=1), - mp4 = StorageStyle("\xa9day", packing=packing.DATE, pack_pos=1), - etc = StorageStyle('DATE', packing=packing.DATE, pack_pos=1), - ) - day = MediaField(out_type=int, - mp3 = StorageStyle('TDRC', packing=packing.DATE, pack_pos=2), - mp4 = StorageStyle("\xa9day", packing=packing.DATE, pack_pos=2), - etc = StorageStyle('DATE', packing=packing.DATE, pack_pos=2), - ) - date = CompositeDateField(year, month, day) - track = MediaField(out_type=int, - mp3 = StorageStyle('TRCK', packing=packing.SLASHED, pack_pos=0), - mp4 = StorageStyle('trkn', packing=packing.TUPLE, pack_pos=0), - etc = [StorageStyle('TRACK'), - StorageStyle('TRACKNUMBER')] - ) - tracktotal = MediaField(out_type=int, - mp3 = StorageStyle('TRCK', packing=packing.SLASHED, pack_pos=1), - mp4 = StorageStyle('trkn', packing=packing.TUPLE, pack_pos=1), - etc = [StorageStyle('TRACKTOTAL'), - StorageStyle('TRACKC'), - StorageStyle('TOTALTRACKS')] - ) - disc = MediaField(out_type=int, - mp3 = StorageStyle('TPOS', packing=packing.SLASHED, pack_pos=0), - mp4 = StorageStyle('disk', packing=packing.TUPLE, pack_pos=0), - etc = [StorageStyle('DISC'), - StorageStyle('DISCNUMBER')] - ) - disctotal = MediaField(out_type=int, - mp3 = StorageStyle('TPOS', packing=packing.SLASHED, pack_pos=1), - mp4 = StorageStyle('disk', packing=packing.TUPLE, pack_pos=1), - etc = [StorageStyle('DISCTOTAL'), - StorageStyle('DISCC'), - StorageStyle('TOTALDISCS')] - ) - lyrics = MediaField( - mp3 = StorageStyle('USLT', list_elem=False, id3_desc=u''), - mp4 = StorageStyle("\xa9lyr"), - etc = StorageStyle('LYRICS') - ) - comments = MediaField( - mp3 = StorageStyle('COMM', id3_desc=u''), - mp4 = StorageStyle("\xa9cmt"), - etc = [StorageStyle('DESCRIPTION'), - StorageStyle('COMMENT')] - ) - bpm = MediaField(out_type=int, - mp3 = StorageStyle('TBPM'), - mp4 = StorageStyle('tmpo', as_type=int), - etc = StorageStyle('BPM'), - ) - comp = MediaField(out_type=bool, - mp3 = StorageStyle('TCMP'), - mp4 = StorageStyle('cpil', list_elem=False, as_type=bool), - etc = StorageStyle('COMPILATION'), - ) - albumartist = MediaField( - mp3 = StorageStyle('TPE2'), - mp4 = StorageStyle('aART'), - etc = [StorageStyle('ALBUM ARTIST'), - StorageStyle('ALBUMARTIST')] - ) - albumtype = MediaField( - mp3 = StorageStyle('TXXX', id3_desc=u'MusicBrainz Album Type'), - mp4 = StorageStyle('----:com.apple.iTunes:MusicBrainz Album Type'), - etc = StorageStyle('MUSICBRAINZ_ALBUMTYPE'), - ) - label = MediaField( - mp3 = StorageStyle('TPUB'), - mp4 = [StorageStyle('----:com.apple.iTunes:Label'), - StorageStyle('----:com.apple.iTunes:publisher')], - etc = [StorageStyle('LABEL'), - StorageStyle('PUBLISHER')] # Traktor - ) - artist_sort = MediaField( - mp3 = StorageStyle('TSOP'), - mp4 = StorageStyle("soar"), - etc = StorageStyle('ARTISTSORT'), - ) - albumartist_sort = MediaField( - mp3 = StorageStyle('TXXX', id3_desc=u'ALBUMARTISTSORT'), - mp4 = StorageStyle("soaa"), - etc = StorageStyle('ALBUMARTISTSORT'), - ) - asin = MediaField( - mp3 = StorageStyle('TXXX', id3_desc=u'ASIN'), - mp4 = StorageStyle("----:com.apple.iTunes:ASIN"), - etc = StorageStyle('ASIN'), - ) - catalognum = MediaField( - mp3 = StorageStyle('TXXX', id3_desc=u'CATALOGNUMBER'), - mp4 = StorageStyle("----:com.apple.iTunes:CATALOGNUMBER"), - etc = StorageStyle('CATALOGNUMBER'), - ) - disctitle = MediaField( - mp3 = StorageStyle('TSST'), - mp4 = StorageStyle("----:com.apple.iTunes:DISCSUBTITLE"), - etc = StorageStyle('DISCSUBTITLE'), - ) - encoder = MediaField( - mp3 = StorageStyle('TENC'), - mp4 = StorageStyle("\xa9too"), - etc = [StorageStyle('ENCODEDBY'), - StorageStyle('ENCODER')] - ) - script = MediaField( - mp3 = StorageStyle('TXXX', id3_desc=u'Script'), - mp4 = StorageStyle("----:com.apple.iTunes:SCRIPT"), - etc = StorageStyle('SCRIPT'), - ) - language = MediaField( - mp3 = StorageStyle('TLAN'), - mp4 = StorageStyle("----:com.apple.iTunes:LANGUAGE"), - etc = StorageStyle('LANGUAGE'), - ) - country = MediaField( - mp3 = StorageStyle('TXXX', - id3_desc=u'MusicBrainz Album Release Country'), - mp4 = StorageStyle("----:com.apple.iTunes:MusicBrainz Album " - "Release Country"), - etc = StorageStyle('RELEASECOUNTRY'), - ) - albumstatus = MediaField( - mp3 = StorageStyle('TXXX', id3_desc=u'MusicBrainz Album Status'), - mp4 = StorageStyle("----:com.apple.iTunes:MusicBrainz Album Status"), - etc = StorageStyle('MUSICBRAINZ_ALBUMSTATUS'), - ) - media = MediaField( - mp3 = StorageStyle('TMED'), - mp4 = StorageStyle("----:com.apple.iTunes:MEDIA"), - etc = StorageStyle('MEDIA'), - ) - albumdisambig = MediaField( - # This tag mapping was invented for beets (not used by Picard, etc). - mp3 = StorageStyle('TXXX', id3_desc=u'MusicBrainz Album Comment'), - mp4 = StorageStyle("----:com.apple.iTunes:MusicBrainz Album Comment"), - etc = StorageStyle('MUSICBRAINZ_ALBUMCOMMENT'), - ) - - # Nonstandard metadata. - artist_credit = MediaField( - mp3 = StorageStyle('TXXX', id3_desc=u'Artist Credit'), - mp4 = StorageStyle("----:com.apple.iTunes:Artist Credit"), - etc = StorageStyle('ARTIST_CREDIT'), - ) - albumartist_credit = MediaField( - mp3 = StorageStyle('TXXX', id3_desc=u'Album Artist Credit'), - mp4 = StorageStyle("----:com.apple.iTunes:Album Artist Credit"), - etc = StorageStyle('ALBUMARTIST_CREDIT'), - ) - - # Album art. - art = ImageField() - - # MusicBrainz IDs. - mb_trackid = MediaField( - mp3 = StorageStyle('UFID:http://musicbrainz.org', - list_elem = False, - id3_frame_field = 'data'), - mp4 = StorageStyle('----:com.apple.iTunes:MusicBrainz Track Id', - as_type=str), - etc = StorageStyle('MUSICBRAINZ_TRACKID') - ) - mb_albumid = MediaField( - mp3 = StorageStyle('TXXX', id3_desc=u'MusicBrainz Album Id'), - mp4 = StorageStyle('----:com.apple.iTunes:MusicBrainz Album Id', - as_type=str), - etc = StorageStyle('MUSICBRAINZ_ALBUMID') - ) - mb_artistid = MediaField( - mp3 = StorageStyle('TXXX', id3_desc=u'MusicBrainz Artist Id'), - mp4 = StorageStyle('----:com.apple.iTunes:MusicBrainz Artist Id', - as_type=str), - etc = StorageStyle('MUSICBRAINZ_ARTISTID') - ) - mb_albumartistid = MediaField( - mp3 = StorageStyle('TXXX', - id3_desc=u'MusicBrainz Album Artist Id'), - mp4 = StorageStyle('----:com.apple.iTunes:MusicBrainz Album Artist Id', - as_type=str), - etc = StorageStyle('MUSICBRAINZ_ALBUMARTISTID') - ) - mb_releasegroupid = MediaField( - mp3 = StorageStyle('TXXX', - id3_desc=u'MusicBrainz Release Group Id'), - mp4 = StorageStyle('----:com.apple.iTunes:MusicBrainz Release Group Id', - as_type=str), - etc = StorageStyle('MUSICBRAINZ_RELEASEGROUPID') - ) - - # Acoustid fields. - acoustid_fingerprint = MediaField( - mp3 = StorageStyle('TXXX', - id3_desc=u'Acoustid Fingerprint'), - mp4 = StorageStyle('----:com.apple.iTunes:Acoustid Fingerprint', - as_type=str), - etc = StorageStyle('ACOUSTID_FINGERPRINT') - ) - acoustid_id = MediaField( - mp3 = StorageStyle('TXXX', - id3_desc=u'Acoustid Id'), - mp4 = StorageStyle('----:com.apple.iTunes:Acoustid Id', - as_type=str), - etc = StorageStyle('ACOUSTID_ID') - ) - - # ReplayGain fields. - rg_track_gain = FloatValueField(2, 'dB', - mp3 = StorageStyle('TXXX', id3_desc=u'REPLAYGAIN_TRACK_GAIN'), - mp4 = None, - etc = StorageStyle(u'REPLAYGAIN_TRACK_GAIN') - ) - rg_album_gain = FloatValueField(2, 'dB', - mp3 = StorageStyle('TXXX', id3_desc=u'REPLAYGAIN_ALBUM_GAIN'), - mp4 = None, - etc = StorageStyle(u'REPLAYGAIN_ALBUM_GAIN') - ) - rg_track_peak = FloatValueField(6, None, - mp3 = StorageStyle('TXXX', id3_desc=u'REPLAYGAIN_TRACK_PEAK'), - mp4 = None, - etc = StorageStyle(u'REPLAYGAIN_TRACK_PEAK') - ) - rg_album_peak = FloatValueField(6, None, - mp3 = StorageStyle('TXXX', id3_desc=u'REPLAYGAIN_ALBUM_PEAK'), - mp4 = None, - etc = StorageStyle(u'REPLAYGAIN_ALBUM_PEAK') - ) - - @property - def length(self): - """The duration of the audio in seconds (a float).""" - return self.mgfile.info.length - - @property - def samplerate(self): - """The audio's sample rate (an int).""" - if hasattr(self.mgfile.info, 'sample_rate'): - return self.mgfile.info.sample_rate - return 0 - - @property - def bitdepth(self): - """The number of bits per sample in the audio encoding (an int). - Only available for certain file formats (zero where - unavailable). - """ - if hasattr(self.mgfile.info, 'bits_per_sample'): - return self.mgfile.info.bits_per_sample - return 0 - - @property - def channels(self): - """The number of channels in the audio (an int).""" - if isinstance(self.mgfile.info, lib.mutagen.mp3.MPEGInfo): - return { - lib.mutagen.mp3.STEREO: 2, - lib.mutagen.mp3.JOINTSTEREO: 2, - lib.mutagen.mp3.DUALCHANNEL: 2, - lib.mutagen.mp3.MONO: 1, - }[self.mgfile.info.mode] - if hasattr(self.mgfile.info, 'channels'): - return self.mgfile.info.channels - return 0 - - @property - def bitrate(self): - """The number of bits per seconds used in the audio coding (an - int). If this is provided explicitly by the compressed file - format, this is a precise reflection of the encoding. Otherwise, - it is estimated from the on-disk file size. In this case, some - imprecision is possible because the file header is incorporated - in the file size. - """ - if hasattr(self.mgfile.info, 'bitrate') and self.mgfile.info.bitrate: - # Many formats provide it explicitly. - return self.mgfile.info.bitrate - else: - # Otherwise, we calculate bitrate from the file size. (This - # is the case for all of the lossless formats.) - if not self.length: - # Avoid division by zero if length is not available. - return 0 - size = os.path.getsize(self.path) - return int(size * 8 / self.length) - - @property - def format(self): - """A string describing the file format/codec.""" - return TYPES[self.type] diff --git a/lib/beets/ui/commands.py b/lib/beets/ui/commands.py deleted file mode 100644 index 7665e684..00000000 --- a/lib/beets/ui/commands.py +++ /dev/null @@ -1,1198 +0,0 @@ -# This file is part of beets. -# Copyright 2012, Adrian Sampson. -# -# 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. - -"""This module provides the default commands for beets' command-line -interface. -""" -from __future__ import print_function - -import logging -import os -import time -import itertools -import re - -import lib.beets -from lib.beets import ui -from lib.beets.ui import print_, input_, decargs -from lib.beets import autotag -from lib.beets import plugins -from lib.beets import importer -from lib.beets.util import syspath, normpath, ancestry, displayable_path -from lib.beets.util.functemplate import Template -from lib.beets import library - -# Global logger. -log = logging.getLogger('beets') - -# The list of default subcommands. This is populated with Subcommand -# objects that can be fed to a SubcommandsOptionParser. -default_commands = [] - -# Utility. - -def _do_query(lib, query, album, also_items=True): - """For commands that operate on matched items, performs a query - and returns a list of matching items and a list of matching - albums. (The latter is only nonempty when album is True.) Raises - a UserError if no items match. also_items controls whether, when - fetching albums, the associated items should be fetched also. - """ - if album: - albums = list(lib.albums(query)) - items = [] - if also_items: - for al in albums: - items += al.items() - - else: - albums = [] - items = list(lib.items(query)) - - if album and not albums: - raise ui.UserError('No matching albums found.') - elif not album and not items: - raise ui.UserError('No matching items found.') - - return items, albums - -FLOAT_EPSILON = 0.01 -def _showdiff(field, oldval, newval, color): - """Prints out a human-readable field difference line.""" - # Considering floats incomparable for perfect equality, introduce - # an epsilon tolerance. - if isinstance(oldval, float) and isinstance(newval, float) and \ - abs(oldval - newval) < FLOAT_EPSILON: - return - - if newval != oldval: - if color: - oldval, newval = ui.colordiff(oldval, newval) - else: - oldval, newval = unicode(oldval), unicode(newval) - print_(u' %s: %s -> %s' % (field, oldval, newval)) - - -# fields: Shows a list of available fields for queries and format strings. -fields_cmd = ui.Subcommand('fields', - help='show fields available for queries and format strings') -def fields_func(lib, config, opts, args): - print("Available item fields:") - print(" " + "\n ".join([key for key in library.ITEM_KEYS])) - print("\nAvailable album fields:") - print(" " + "\n ".join([key for key in library.ALBUM_KEYS])) - -fields_cmd.func = fields_func -default_commands.append(fields_cmd) - - -# import: Autotagger and importer. - -DEFAULT_IMPORT_COPY = True -DEFAULT_IMPORT_MOVE = False -DEFAULT_IMPORT_WRITE = True -DEFAULT_IMPORT_DELETE = False -DEFAULT_IMPORT_AUTOT = True -DEFAULT_IMPORT_TIMID = False -DEFAULT_IMPORT_QUIET = False -DEFAULT_IMPORT_QUIET_FALLBACK = 'skip' -DEFAULT_IMPORT_RESUME = None # "ask" -DEFAULT_IMPORT_INCREMENTAL = False -DEFAULT_THREADED = True -DEFAULT_COLOR = True -DEFAULT_IGNORE = [ - '.*', '*~', -] -DEFAULT_PER_DISC_NUMBERING = False - -VARIOUS_ARTISTS = u'Various Artists' - -PARTIAL_MATCH_MESSAGE = u'(partial match!)' - -# Importer utilities and support. - -def dist_string(dist, color): - """Formats a distance (a float) as a similarity percentage string. - The string is colorized if color is True. - """ - out = '%.1f%%' % ((1 - dist) * 100) - if color: - if dist <= autotag.STRONG_REC_THRESH: - out = ui.colorize('green', out) - elif dist <= autotag.MEDIUM_REC_THRESH: - out = ui.colorize('yellow', out) - else: - out = ui.colorize('red', out) - return out - -def show_change(cur_artist, cur_album, match, color=True, - per_disc_numbering=False): - """Print out a representation of the changes that will be made if an - album's tags are changed according to `match`, which must be an AlbumMatch - object. - """ - def show_album(artist, album, partial=False): - if artist: - album_description = u' %s - %s' % (artist, album) - elif album: - album_description = u' %s' % album - else: - album_description = u' (unknown album)' - - # Add a suffix if this is a partial match. - if partial: - warning = PARTIAL_MATCH_MESSAGE - else: - warning = None - if color and warning: - warning = ui.colorize('yellow', warning) - - out = album_description - if warning: - out += u' ' + warning - print_(out) - - def format_index(track_info): - """Return a string representing the track index of the given - TrackInfo object. - """ - if per_disc_numbering: - if match.info.mediums > 1: - return u'{0}-{1}'.format(track_info.medium, - track_info.medium_index) - else: - return unicode(track_info.medium_index) - else: - return unicode(track_info.index) - - # Identify the album in question. - if cur_artist != match.info.artist or \ - (cur_album != match.info.album and - match.info.album != VARIOUS_ARTISTS): - artist_l, artist_r = cur_artist or '', match.info.artist - album_l, album_r = cur_album or '', match.info.album - if artist_r == VARIOUS_ARTISTS: - # Hide artists for VA releases. - artist_l, artist_r = u'', u'' - - if color: - artist_l, artist_r = ui.colordiff(artist_l, artist_r) - album_l, album_r = ui.colordiff(album_l, album_r) - - print_("Correcting tags from:") - show_album(artist_l, album_l) - print_("To:") - show_album(artist_r, album_r) - else: - message = u"Tagging: %s - %s" % (match.info.artist, match.info.album) - if match.extra_items or match.extra_tracks: - warning = PARTIAL_MATCH_MESSAGE - if color: - warning = ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) - message += u' ' + warning - print_(message) - - # Distance/similarity. - print_('(Similarity: %s)' % dist_string(match.distance, color)) - - # Tracks. - pairs = match.mapping.items() - pairs.sort(key=lambda (_, track_info): track_info.index) - for item, track_info in pairs: - # Get displayable LHS and RHS values. - cur_track = unicode(item.track) - new_track = format_index(track_info) - tracks_differ = item.track not in (track_info.index, - track_info.medium_index) - cur_title = item.title - new_title = track_info.title - if item.length and track_info.length: - cur_length = ui.human_seconds_short(item.length) - new_length = ui.human_seconds_short(track_info.length) - if color: - cur_length = ui.colorize('red', cur_length) - new_length = ui.colorize('red', new_length) - - # Possibly colorize changes. - if color: - cur_title, new_title = ui.colordiff(cur_title, new_title) - cur_track = ui.colorize('red', cur_track) - new_track = ui.colorize('red', new_track) - - # Show filename (non-colorized) when title is not set. - if not item.title.strip(): - cur_title = displayable_path(os.path.basename(item.path)) - - if cur_title != new_title: - lhs, rhs = cur_title, new_title - if tracks_differ: - lhs += u' (%s)' % cur_track - rhs += u' (%s)' % new_track - print_(u" * %s -> %s" % (lhs, rhs)) - else: - line = u' * %s' % item.title - display = False - if tracks_differ: - display = True - line += u' (%s -> %s)' % (cur_track, new_track) - if item.length and track_info.length and \ - abs(item.length - track_info.length) > 2.0: - display = True - line += u' (%s vs. %s)' % (cur_length, new_length) - if display: - print_(line) - - # Missing and unmatched tracks. - for track_info in match.extra_tracks: - line = u' * Missing track: {0} ({1})'.format(track_info.title, - format_index(track_info)) - if color: - line = ui.colorize('yellow', line) - print_(line) - for item in match.extra_items: - line = u' * Unmatched track: {0} ({1})'.format(item.title, item.track) - if color: - line = ui.colorize('yellow', line) - print_(line) - -def show_item_change(item, match, color): - """Print out the change that would occur by tagging `item` with the - metadata from `match`, a TrackMatch object. - """ - cur_artist, new_artist = item.artist, match.info.artist - cur_title, new_title = item.title, match.info.title - - if cur_artist != new_artist or cur_title != new_title: - if color: - cur_artist, new_artist = ui.colordiff(cur_artist, new_artist) - cur_title, new_title = ui.colordiff(cur_title, new_title) - - print_("Correcting track tags from:") - print_(" %s - %s" % (cur_artist, cur_title)) - print_("To:") - print_(" %s - %s" % (new_artist, new_title)) - - else: - print_("Tagging track: %s - %s" % (cur_artist, cur_title)) - - print_('(Similarity: %s)' % dist_string(match.distance, color)) - -def should_resume(config, path): - return ui.input_yn("Import of the directory:\n%s" - "\nwas interrupted. Resume (Y/n)?" % path) - -def _quiet_fall_back(config): - """Show the user that the default action is being taken because - we're in quiet mode and the recommendation is not strong. - """ - if config.quiet_fallback == importer.action.SKIP: - print_('Skipping.') - elif config.quiet_fallback == importer.action.ASIS: - print_('Importing as-is.') - else: - assert(False) - return config.quiet_fallback - -def choose_candidate(candidates, singleton, rec, color, timid, - cur_artist=None, cur_album=None, item=None, - itemcount=None, per_disc_numbering=False): - """Given a sorted list of candidates, ask the user for a selection - of which candidate to use. Applies to both full albums and - singletons (tracks). Candidates are either AlbumMatch or TrackMatch - objects depending on `singleton`. for albums, `cur_artist`, - `cur_album`, and `itemcount` must be provided. For singletons, - `item` must be provided. - - Returns the result of the choice, which may SKIP, ASIS, TRACKS, or - MANUAL or a candidate (an AlbumMatch/TrackMatch object). - """ - # Sanity check. - if singleton: - assert item is not None - else: - assert cur_artist is not None - assert cur_album is not None - - # Zero candidates. - if not candidates: - if singleton: - print_("No matching recordings found.") - opts = ('Use as-is', 'Skip', 'Enter search', 'enter Id', - 'aBort') - else: - print_("No matching release found for {0} tracks." - .format(itemcount)) - print_('For help, see: ' - 'https://github.com/sampsyo/beets/wiki/FAQ#wiki-nomatch') - opts = ('Use as-is', 'as Tracks', 'Skip', 'Enter search', - 'enter Id', 'aBort') - sel = ui.input_options(opts, color=color) - if sel == 'u': - return importer.action.ASIS - elif sel == 't': - assert not singleton - return importer.action.TRACKS - elif sel == 'e': - return importer.action.MANUAL - elif sel == 's': - return importer.action.SKIP - elif sel == 'b': - raise importer.ImportAbort() - elif sel == 'i': - return importer.action.MANUAL_ID - else: - assert False - - # Is the change good enough? - bypass_candidates = False - if rec != autotag.RECOMMEND_NONE: - match = candidates[0] - bypass_candidates = True - - while True: - # Display and choose from candidates. - if not bypass_candidates: - # Display list of candidates. - if singleton: - print_('Finding tags for track "%s - %s".' % - (item.artist, item.title)) - print_('Candidates:') - for i, match in enumerate(candidates): - print_('%i. %s - %s (%s)' % - (i + 1, match.info.artist, match.info.title, - dist_string(match.distance, color))) - else: - print_('Finding tags for album "%s - %s".' % - (cur_artist, cur_album)) - print_('Candidates:') - for i, match in enumerate(candidates): - line = '%i. %s - %s' % (i + 1, match.info.artist, - match.info.album) - - # Label and year disambiguation, if available. - label, year = None, None - if match.info.label: - label = match.info.label - if match.info.year: - year = unicode(match.info.year) - if label and year: - line += u' [%s, %s]' % (label, year) - elif label: - line += u' [%s]' % label - elif year: - line += u' [%s]' % year - - line += ' (%s)' % dist_string(match.distance, color) - - # Point out the partial matches. - if match.extra_items or match.extra_tracks: - warning = PARTIAL_MATCH_MESSAGE - if color: - warning = ui.colorize('yellow', warning) - line += u' %s' % warning - - print_(line) - - # Ask the user for a choice. - if singleton: - opts = ('Skip', 'Use as-is', 'Enter search', 'enter Id', - 'aBort') - else: - opts = ('Skip', 'Use as-is', 'as Tracks', 'Enter search', - 'enter Id', 'aBort') - sel = ui.input_options(opts, numrange=(1, len(candidates)), - color=color) - if sel == 's': - return importer.action.SKIP - elif sel == 'u': - return importer.action.ASIS - elif sel == 'e': - return importer.action.MANUAL - elif sel == 't': - assert not singleton - return importer.action.TRACKS - elif sel == 'b': - raise importer.ImportAbort() - elif sel == 'i': - return importer.action.MANUAL_ID - else: # Numerical selection. - if singleton: - match = candidates[sel - 1] - else: - match = candidates[sel - 1] - bypass_candidates = False - - # Show what we're about to do. - if singleton: - show_item_change(item, match, color) - else: - show_change(cur_artist, cur_album, match, color, - per_disc_numbering) - - # Exact match => tag automatically if we're not in timid mode. - if rec == autotag.RECOMMEND_STRONG and not timid: - return match - - # Ask for confirmation. - if singleton: - opts = ('Apply', 'More candidates', 'Skip', 'Use as-is', - 'Enter search', 'enter Id', 'aBort') - else: - opts = ('Apply', 'More candidates', 'Skip', 'Use as-is', - 'as Tracks', 'Enter search', 'enter Id', 'aBort') - sel = ui.input_options(opts, color=color) - if sel == 'a': - return match - elif sel == 'm': - pass - elif sel == 's': - return importer.action.SKIP - elif sel == 'u': - return importer.action.ASIS - elif sel == 't': - assert not singleton - return importer.action.TRACKS - elif sel == 'e': - return importer.action.MANUAL - elif sel == 'b': - raise importer.ImportAbort() - elif sel == 'i': - return importer.action.MANUAL_ID - -def manual_search(singleton): - """Input either an artist and album (for full albums) or artist and - track name (for singletons) for manual search. - """ - artist = input_('Artist:') - name = input_('Track:' if singleton else 'Album:') - return artist.strip(), name.strip() - -def manual_id(singleton): - """Input a MusicBrainz ID, either for an album ("release") or a - track ("recording"). If no valid ID is entered, returns None. - """ - prompt = 'Enter MusicBrainz %s ID:' % \ - ('recording' if singleton else 'release') - entry = input_(prompt).strip() - - # Find the first thing that looks like a UUID/MBID. - match = re.search('[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}', entry) - if match: - return match.group() - else: - log.error('Invalid MBID.') - return None - -def choose_match(task, config): - """Given an initial autotagging of items, go through an interactive - dance with the user to ask for a choice of metadata. Returns an - AlbumMatch object, ASIS, or SKIP. - """ - # Show what we're tagging. - print_() - print_(task.path) - - if config.quiet: - # No input; just make a decision. - if task.rec == autotag.RECOMMEND_STRONG: - match = task.candidates[0] - show_change(task.cur_artist, task.cur_album, match, config.color) - return match - else: - return _quiet_fall_back(config) - - # Loop until we have a choice. - candidates, rec = task.candidates, task.rec - while True: - # Ask for a choice from the user. - choice = choose_candidate(candidates, False, rec, config.color, - config.timid, task.cur_artist, - task.cur_album, itemcount=len(task.items), - per_disc_numbering=config.per_disc_numbering) - - # Choose which tags to use. - if choice in (importer.action.SKIP, importer.action.ASIS, - importer.action.TRACKS): - # Pass selection to main control flow. - return choice - elif choice is importer.action.MANUAL: - # Try again with manual search terms. - search_artist, search_album = manual_search(False) - try: - _, _, candidates, rec = \ - autotag.tag_album(task.items, config.timid, search_artist, - search_album) - except autotag.AutotagError: - candidates, rec = None, None - elif choice is importer.action.MANUAL_ID: - # Try a manually-entered ID. - search_id = manual_id(False) - if search_id: - try: - _, _, candidates, rec = \ - autotag.tag_album(task.items, config.timid, - search_id=search_id) - except autotag.AutotagError: - candidates, rec = None, None - else: - # We have a candidate! Finish tagging. Here, choice is an - # AlbumMatch object. - assert isinstance(choice, autotag.AlbumMatch) - return choice - -def choose_item(task, config): - """Ask the user for a choice about tagging a single item. Returns - either an action constant or a TrackMatch object. - """ - print_() - print_(task.item.path) - candidates, rec = task.candidates, task.rec - - if config.quiet: - # Quiet mode; make a decision. - if rec == autotag.RECOMMEND_STRONG: - match = candidates[0] - show_item_change(task.item, match, config.color) - return match - else: - return _quiet_fall_back(config) - - while True: - # Ask for a choice. - choice = choose_candidate(candidates, True, rec, config.color, - config.timid, item=task.item) - - if choice in (importer.action.SKIP, importer.action.ASIS): - return choice - elif choice == importer.action.TRACKS: - assert False # TRACKS is only legal for albums. - elif choice == importer.action.MANUAL: - # Continue in the loop with a new set of candidates. - search_artist, search_title = manual_search(True) - candidates, rec = autotag.tag_item(task.item, config.timid, - search_artist, search_title) - elif choice == importer.action.MANUAL_ID: - # Ask for a track ID. - search_id = manual_id(True) - if search_id: - candidates, rec = autotag.tag_item(task.item, config.timid, - search_id=search_id) - else: - # Chose a candidate. - assert isinstance(choice, autotag.TrackMatch) - return choice - -def resolve_duplicate(task, config): - """Decide what to do when a new album or item seems similar to one - that's already in the library. - """ - log.warn("This %s is already in the library!" % - ("album" if task.is_album else "item")) - - if config.quiet: - # In quiet mode, don't prompt -- just skip. - log.info('Skipping.') - sel = 's' - else: - sel = ui.input_options( - ('Skip new', 'Keep both', 'Remove old'), - color=config.color - ) - - if sel == 's': - # Skip new. - task.set_choice(importer.action.SKIP) - elif sel == 'k': - # Keep both. Do nothing; leave the choice intact. - pass - elif sel == 'r': - # Remove old. - task.remove_duplicates = True - else: - assert False - -# The import command. - -def import_files(lib, paths, copy, move, write, autot, logpath, threaded, - color, delete, quiet, resume, quiet_fallback, singletons, - timid, query, incremental, ignore, per_disc_numbering): - """Import the files in the given list of paths, tagging each leaf - directory as an album. If copy, then the files are copied into the - library folder. If write, then new metadata is written to the files - themselves. If not autot, then just import the files without - attempting to tag. If logpath is provided, then untaggable albums - will be logged there. If threaded, then accelerate autotagging - imports by running them in multiple threads. If color, then - ANSI-colorize some terminal output. If delete, then old files are - deleted when they are copied. If quiet, then the user is never - prompted for input; instead, the tagger just skips anything it is - not confident about. resume indicates whether interrupted imports - can be resumed and is either a boolean or None. quiet_fallback - should be either ASIS or SKIP and indicates what should happen in - quiet mode when the recommendation is not strong. - """ - # Check the user-specified directories. - for path in paths: - fullpath = syspath(normpath(path)) - if not singletons and not os.path.isdir(fullpath): - raise ui.UserError('not a directory: ' + path) - elif singletons and not os.path.exists(fullpath): - raise ui.UserError('no such file: ' + path) - - # Check parameter consistency. - if quiet and timid: - raise ui.UserError("can't be both quiet and timid") - - # Open the log. - if logpath: - logpath = normpath(logpath) - try: - logfile = open(syspath(logpath), 'a') - except IOError: - raise ui.UserError(u"could not open log file for writing: %s" % - displayable_path(logpath)) - print('import started', time.asctime(), file=logfile) - else: - logfile = None - - # Never ask for input in quiet mode. - if resume is None and quiet: - resume = False - - try: - # Perform the import. - importer.run_import( - lib = lib, - paths = paths, - resume = resume, - logfile = logfile, - color = color, - quiet = quiet, - quiet_fallback = quiet_fallback, - copy = copy, - move = move, - write = write, - delete = delete, - threaded = threaded, - autot = autot, - choose_match_func = choose_match, - should_resume_func = should_resume, - singletons = singletons, - timid = timid, - choose_item_func = choose_item, - query = query, - incremental = incremental, - ignore = ignore, - resolve_duplicate_func = resolve_duplicate, - per_disc_numbering = per_disc_numbering, - ) - - finally: - # If we were logging, close the file. - if logfile: - print('', file=logfile) - logfile.close() - - # Emit event. - plugins.send('import', lib=lib, paths=paths) - -import_cmd = ui.Subcommand('import', help='import new music', - aliases=('imp', 'im')) -import_cmd.parser.add_option('-c', '--copy', action='store_true', - default=None, help="copy tracks into library directory (default)") -import_cmd.parser.add_option('-C', '--nocopy', action='store_false', - dest='copy', help="don't copy tracks (opposite of -c)") -import_cmd.parser.add_option('-w', '--write', action='store_true', - default=None, help="write new metadata to files' tags (default)") -import_cmd.parser.add_option('-W', '--nowrite', action='store_false', - dest='write', help="don't write metadata (opposite of -w)") -import_cmd.parser.add_option('-a', '--autotag', action='store_true', - dest='autotag', help="infer tags for imported files (default)") -import_cmd.parser.add_option('-A', '--noautotag', action='store_false', - dest='autotag', - help="don't infer tags for imported files (opposite of -a)") -import_cmd.parser.add_option('-p', '--resume', action='store_true', - default=None, help="resume importing if interrupted") -import_cmd.parser.add_option('-P', '--noresume', action='store_false', - dest='resume', help="do not try to resume importing") -import_cmd.parser.add_option('-q', '--quiet', action='store_true', - dest='quiet', help="never prompt for input: skip albums instead") -import_cmd.parser.add_option('-l', '--log', dest='logpath', - help='file to log untaggable albums for later review') -import_cmd.parser.add_option('-s', '--singletons', action='store_true', - help='import individual tracks instead of full albums') -import_cmd.parser.add_option('-t', '--timid', dest='timid', - action='store_true', help='always confirm all actions') -import_cmd.parser.add_option('-L', '--library', dest='library', - action='store_true', help='retag items matching a query') -import_cmd.parser.add_option('-i', '--incremental', dest='incremental', - action='store_true', help='skip already-imported directories') -import_cmd.parser.add_option('-I', '--noincremental', dest='incremental', - action='store_false', help='do not skip already-imported directories') -def import_func(lib, config, opts, args): - copy = opts.copy if opts.copy is not None else \ - ui.config_val(config, 'beets', 'import_copy', - DEFAULT_IMPORT_COPY, bool) - move = ui.config_val(config, 'beets', 'import_move', - DEFAULT_IMPORT_MOVE, bool) - write = opts.write if opts.write is not None else \ - ui.config_val(config, 'beets', 'import_write', - DEFAULT_IMPORT_WRITE, bool) - delete = ui.config_val(config, 'beets', 'import_delete', - DEFAULT_IMPORT_DELETE, bool) - autot = opts.autotag if opts.autotag is not None else DEFAULT_IMPORT_AUTOT - threaded = ui.config_val(config, 'beets', 'threaded', - DEFAULT_THREADED, bool) - color = ui.config_val(config, 'beets', 'color', DEFAULT_COLOR, bool) - quiet = opts.quiet if opts.quiet is not None else DEFAULT_IMPORT_QUIET - quiet_fallback_str = ui.config_val(config, 'beets', 'import_quiet_fallback', - DEFAULT_IMPORT_QUIET_FALLBACK) - singletons = opts.singletons - timid = opts.timid if opts.timid is not None else \ - ui.config_val(config, 'beets', 'import_timid', - DEFAULT_IMPORT_TIMID, bool) - logpath = opts.logpath if opts.logpath is not None else \ - ui.config_val(config, 'beets', 'import_log', None) - incremental = opts.incremental if opts.incremental is not None else \ - ui.config_val(config, 'beets', 'import_incremental', - DEFAULT_IMPORT_INCREMENTAL, bool) - ignore = ui.config_val(config, 'beets', 'ignore', DEFAULT_IGNORE, list) - per_disc_numbering = ui.config_val(config, 'beets', 'per_disc_numbering', - DEFAULT_PER_DISC_NUMBERING, bool) - - # Resume has three options: yes, no, and "ask" (None). - resume = opts.resume if opts.resume is not None else \ - ui.config_val(config, 'beets', 'import_resume', DEFAULT_IMPORT_RESUME) - if isinstance(resume, basestring): - if resume.lower() in ('yes', 'true', 't', 'y', '1'): - resume = True - elif resume.lower() in ('no', 'false', 'f', 'n', '0'): - resume = False - else: - resume = None - - # Special case: --copy flag suppresses import_move (which would - # otherwise take precedence). - if opts.copy: - move = False - - if quiet_fallback_str == 'asis': - quiet_fallback = importer.action.ASIS - else: - quiet_fallback = importer.action.SKIP - - if opts.library: - query = args - paths = [] - else: - query = None - paths = args - - import_files(lib, paths, copy, move, write, autot, logpath, threaded, - color, delete, quiet, resume, quiet_fallback, singletons, - timid, query, incremental, ignore, per_disc_numbering) -import_cmd.func = import_func -default_commands.append(import_cmd) - - -# list: Query and show library contents. - -DEFAULT_LIST_FORMAT_ITEM = '$artist - $album - $title' -DEFAULT_LIST_FORMAT_ALBUM = '$albumartist - $album' - -def list_items(lib, query, album, path, fmt): - """Print out items in lib matching query. If album, then search for - albums instead of single items. If path, print the matched objects' - paths instead of human-readable information about them. - """ - template = Template(fmt) - - if album: - for album in lib.albums(query): - if path: - print_(album.item_dir()) - elif fmt is not None: - print_(album.evaluate_template(template)) - else: - for item in lib.items(query): - if path: - print_(item.path) - elif fmt is not None: - print_(item.evaluate_template(template, lib)) - -list_cmd = ui.Subcommand('list', help='query the library', aliases=('ls',)) -list_cmd.parser.add_option('-a', '--album', action='store_true', - help='show matching albums instead of tracks') -list_cmd.parser.add_option('-p', '--path', action='store_true', - help='print paths for matched items or albums') -list_cmd.parser.add_option('-f', '--format', action='store', - help='print with custom format', default=None) -def list_func(lib, config, opts, args): - fmt = opts.format - if not fmt: - # If no format is specified, fall back to a default. - if opts.album: - fmt = ui.config_val(config, 'beets', 'list_format_album', - DEFAULT_LIST_FORMAT_ALBUM) - else: - fmt = ui.config_val(config, 'beets', 'list_format_item', - DEFAULT_LIST_FORMAT_ITEM) - list_items(lib, decargs(args), opts.album, opts.path, fmt) -list_cmd.func = list_func -default_commands.append(list_cmd) - - -# update: Update library contents according to on-disk tags. - -def update_items(lib, query, album, move, color, pretend): - """For all the items matched by the query, update the library to - reflect the item's embedded tags. - """ - with lib.transaction(): - items, _ = _do_query(lib, query, album) - - # Walk through the items and pick up their changes. - affected_albums = set() - for item in items: - # Item deleted? - if not os.path.exists(syspath(item.path)): - print_(u'X %s - %s' % (item.artist, item.title)) - if not pretend: - lib.remove(item, True) - affected_albums.add(item.album_id) - continue - - # Did the item change since last checked? - if item.current_mtime() <= item.mtime: - log.debug(u'skipping %s because mtime is up to date (%i)' % - (displayable_path(item.path), item.mtime)) - continue - - # Read new data. - old_data = dict(item.record) - item.read() - - # Special-case album artist when it matches track artist. (Hacky - # but necessary for preserving album-level metadata for non- - # autotagged imports.) - if not item.albumartist and \ - old_data['albumartist'] == old_data['artist'] == \ - item.artist: - item.albumartist = old_data['albumartist'] - item.dirty['albumartist'] = False - - # Get and save metadata changes. - changes = {} - for key in library.ITEM_KEYS_META: - if item.dirty[key]: - changes[key] = old_data[key], getattr(item, key) - if changes: - # Something changed. - print_(u'* %s - %s' % (item.artist, item.title)) - for key, (oldval, newval) in changes.iteritems(): - _showdiff(key, oldval, newval, color) - - # If we're just pretending, then don't move or save. - if pretend: - continue - - # Move the item if it's in the library. - if move and lib.directory in ancestry(item.path): - lib.move(item) - - lib.store(item) - affected_albums.add(item.album_id) - elif not pretend: - # The file's mtime was different, but there were no changes - # to the metadata. Store the new mtime, which is set in the - # call to read(), so we don't check this again in the - # future. - lib.store(item) - - # Skip album changes while pretending. - if pretend: - return - - # Modify affected albums to reflect changes in their items. - for album_id in affected_albums: - if album_id is None: # Singletons. - continue - album = lib.get_album(album_id) - if not album: # Empty albums have already been removed. - log.debug('emptied album %i' % album_id) - continue - al_items = list(album.items()) - - # Update album structure to reflect an item in it. - for key in library.ALBUM_KEYS_ITEM: - setattr(album, key, getattr(al_items[0], key)) - - # Move album art (and any inconsistent items). - if move and lib.directory in ancestry(al_items[0].path): - log.debug('moving album %i' % album_id) - album.move() - -update_cmd = ui.Subcommand('update', - help='update the library', aliases=('upd','up',)) -update_cmd.parser.add_option('-a', '--album', action='store_true', - help='show matching albums instead of tracks') -update_cmd.parser.add_option('-M', '--nomove', action='store_false', - default=True, dest='move', help="don't move files in library") -update_cmd.parser.add_option('-p', '--pretend', action='store_true', - help="show all changes but do nothing") -def update_func(lib, config, opts, args): - color = ui.config_val(config, 'beets', 'color', DEFAULT_COLOR, bool) - update_items(lib, decargs(args), opts.album, opts.move, color, opts.pretend) -update_cmd.func = update_func -default_commands.append(update_cmd) - - -# remove: Remove items from library, delete files. - -def remove_items(lib, query, album, delete=False): - """Remove items matching query from lib. If album, then match and - remove whole albums. If delete, also remove files from disk. - """ - # Get the matching items. - items, albums = _do_query(lib, query, album) - - # Show all the items. - for item in items: - print_(item.artist + ' - ' + item.album + ' - ' + item.title) - - # Confirm with user. - print_() - if delete: - prompt = 'Really DELETE %i files (y/n)?' % len(items) - else: - prompt = 'Really remove %i items from the library (y/n)?' % \ - len(items) - if not ui.input_yn(prompt, True): - return - - # Remove (and possibly delete) items. - with lib.transaction(): - if album: - for al in albums: - al.remove(delete) - else: - for item in items: - lib.remove(item, delete) - -remove_cmd = ui.Subcommand('remove', - help='remove matching items from the library', aliases=('rm',)) -remove_cmd.parser.add_option("-d", "--delete", action="store_true", - help="also remove files from disk") -remove_cmd.parser.add_option('-a', '--album', action='store_true', - help='match albums instead of tracks') -def remove_func(lib, config, opts, args): - remove_items(lib, decargs(args), opts.album, opts.delete) -remove_cmd.func = remove_func -default_commands.append(remove_cmd) - - -# stats: Show library/query statistics. - -def show_stats(lib, query): - """Shows some statistics about the matched items.""" - items = lib.items(query) - - total_size = 0 - total_time = 0.0 - total_items = 0 - artists = set() - albums = set() - - for item in items: - #fixme This is approximate, so people might complain that - # this total size doesn't match "du -sh". Could fix this - # by putting total file size in the database. - total_size += int(item.length * item.bitrate / 8) - total_time += item.length - total_items += 1 - artists.add(item.artist) - albums.add(item.album) - - print_("""Tracks: %i -Total time: %s -Total size: %s -Artists: %i -Albums: %i""" % ( - total_items, - ui.human_seconds(total_time), - ui.human_bytes(total_size), - len(artists), len(albums) - )) - -stats_cmd = ui.Subcommand('stats', - help='show statistics about the library or a query') -def stats_func(lib, config, opts, args): - show_stats(lib, decargs(args)) -stats_cmd.func = stats_func -default_commands.append(stats_cmd) - - -# version: Show current beets version. - -def show_version(lib, config, opts, args): - - print_('beets version %s' % lib.beets.__version__) - - # Show plugins. - names = [] - for plugin in plugins.find_plugins(): - modname = plugin.__module__ - names.append(modname.split('.')[-1]) - if names: - print_('plugins:', ', '.join(names)) - else: - print_('no plugins loaded') -version_cmd = ui.Subcommand('version', - help='output version information') -version_cmd.func = show_version -default_commands.append(version_cmd) - - -# modify: Declaratively change metadata. - -def modify_items(lib, mods, query, write, move, album, color, confirm): - """Modifies matching items according to key=value assignments.""" - # Parse key=value specifications into a dictionary. - allowed_keys = library.ALBUM_KEYS if album else library.ITEM_KEYS_WRITABLE - fsets = {} - for mod in mods: - key, value = mod.split('=', 1) - if key not in allowed_keys: - raise ui.UserError('"%s" is not a valid field' % key) - fsets[key] = value - - # Get the items to modify. - items, albums = _do_query(lib, query, album, False) - objs = albums if album else items - - # Preview change. - print_('Modifying %i %ss.' % (len(objs), 'album' if album else 'item')) - for obj in objs: - # Identify the changed object. - if album: - print_(u'* %s - %s' % (obj.albumartist, obj.album)) - else: - print_(u'* %s - %s' % (obj.artist, obj.title)) - - # Show each change. - for field, value in fsets.iteritems(): - curval = getattr(obj, field) - _showdiff(field, curval, value, color) - - # Confirm. - if confirm: - extra = ' and write tags' if write else '' - if not ui.input_yn('Really modify%s (Y/n)?' % extra): - return - - # Apply changes to database. - with lib.transaction(): - for obj in objs: - for field, value in fsets.iteritems(): - setattr(obj, field, value) - - if move: - cur_path = obj.item_dir() if album else obj.path - if lib.directory in ancestry(cur_path): # In library? - log.debug('moving object %s' % cur_path) - if album: - obj.move() - else: - lib.move(obj) - - # When modifying items, we have to store them to the database. - if not album: - lib.store(obj) - - # Apply tags if requested. - if write: - if album: - items = itertools.chain(*(a.items() for a in albums)) - for item in items: - item.write() - -modify_cmd = ui.Subcommand('modify', - help='change metadata fields', aliases=('mod',)) -modify_cmd.parser.add_option('-M', '--nomove', action='store_false', - default=True, dest='move', help="don't move files in library") -modify_cmd.parser.add_option('-w', '--write', action='store_true', - default=None, help="write new metadata to files' tags (default)") -modify_cmd.parser.add_option('-W', '--nowrite', action='store_false', - dest='write', help="don't write metadata (opposite of -w)") -modify_cmd.parser.add_option('-a', '--album', action='store_true', - help='modify whole albums instead of tracks') -modify_cmd.parser.add_option('-y', '--yes', action='store_true', - help='skip confirmation') -def modify_func(lib, config, opts, args): - args = decargs(args) - mods = [a for a in args if '=' in a] - query = [a for a in args if '=' not in a] - if not mods: - raise ui.UserError('no modifications specified') - write = opts.write if opts.write is not None else \ - ui.config_val(config, 'beets', 'import_write', - DEFAULT_IMPORT_WRITE, bool) - color = ui.config_val(config, 'beets', 'color', DEFAULT_COLOR, bool) - modify_items(lib, mods, query, write, opts.move, opts.album, color, - not opts.yes) -modify_cmd.func = modify_func -default_commands.append(modify_cmd) - - -# move: Move/copy files to the library or a new base directory. - -def move_items(lib, dest, query, copy, album): - """Moves or copies items to a new base directory, given by dest. If - dest is None, then the library's base directory is used, making the - command "consolidate" files. - """ - items, albums = _do_query(lib, query, album, False) - objs = albums if album else items - - action = 'Copying' if copy else 'Moving' - entity = 'album' if album else 'item' - logging.info('%s %i %ss.' % (action, len(objs), entity)) - for obj in objs: - old_path = obj.item_dir() if album else obj.path - logging.debug('moving: %s' % old_path) - - if album: - obj.move(copy, basedir=dest) - else: - lib.move(obj, copy, basedir=dest) - lib.store(obj) - -move_cmd = ui.Subcommand('move', - help='move or copy items', aliases=('mv',)) -move_cmd.parser.add_option('-d', '--dest', metavar='DIR', dest='dest', - help='destination directory') -move_cmd.parser.add_option('-c', '--copy', default=False, action='store_true', - help='copy instead of moving') -move_cmd.parser.add_option('-a', '--album', default=False, action='store_true', - help='match whole albums instead of tracks') -def move_func(lib, config, opts, args): - dest = opts.dest - if dest is not None: - dest = normpath(dest) - if not os.path.isdir(dest): - raise ui.UserError('no such directory: %s' % dest) - - move_items(lib, dest, decargs(args), opts.copy, opts.album) -move_cmd.func = move_func -default_commands.append(move_cmd) diff --git a/lib/munkres.py b/lib/munkres.py old mode 100755 new mode 100644 index a79ceef3..f5337223 --- a/lib/munkres.py +++ b/lib/munkres.py @@ -61,7 +61,7 @@ You could then use that index matrix to loop over the original cost matrix and calculate the smallest cost of the combinations:: n = len(matrix) - minval = sys.maxint + minval = sys.maxsize for row in range(n): cost = 0 for col in range(n): @@ -163,7 +163,7 @@ large value. For example:: for row in matrix: cost_row = [] for col in row: - cost_row += [sys.maxint - col] + cost_row += [sys.maxsize - col] cost_matrix += [cost_row] m = Munkres() @@ -197,7 +197,7 @@ creation of the cost matrix:: import munkres cost_matrix = munkres.make_cost_matrix(matrix, - lambda cost: sys.maxint - cost) + lambda cost: sys.maxsize - cost) So, the above profit-calculation program can be recast as:: @@ -206,7 +206,7 @@ So, the above profit-calculation program can be recast as:: matrix = [[5, 9, 1], [10, 3, 2], [8, 7, 4]] - cost_matrix = make_cost_matrix(matrix, lambda cost: sys.maxint - cost) + cost_matrix = make_cost_matrix(matrix, lambda cost: sys.maxsize - cost) m = Munkres() indexes = m.compute(cost_matrix) print_matrix(matrix, msg='Lowest cost through this matrix:') @@ -277,6 +277,7 @@ __docformat__ = 'restructuredtext' # --------------------------------------------------------------------------- import sys +import copy # --------------------------------------------------------------------------- # Exports @@ -289,7 +290,7 @@ __all__ = ['Munkres', 'make_cost_matrix'] # --------------------------------------------------------------------------- # Info about the module -__version__ = "1.0.5.4" +__version__ = "1.0.6" __author__ = "Brian Clapper, bmc@clapper.org" __url__ = "http://software.clapper.org/munkres/" __copyright__ = "(c) 2008 Brian M. Clapper" @@ -458,8 +459,8 @@ class Munkres: for i in range(n): for j in range(n): if (self.C[i][j] == 0) and \ - (not self.col_covered[j]) and \ - (not self.row_covered[i]): + (not self.col_covered[j]) and \ + (not self.row_covered[i]): self.marked[i][j] = 1 self.col_covered[j] = True self.row_covered[i] = True @@ -575,7 +576,7 @@ class Munkres: def __find_smallest(self): """Find the smallest uncovered value in the matrix.""" - minval = sys.maxint + minval = sys.maxsize for i in range(self.n): for j in range(self.n): if (not self.row_covered[i]) and (not self.col_covered[j]): @@ -595,8 +596,8 @@ class Munkres: j = 0 while True: if (self.C[i][j] == 0) and \ - (not self.row_covered[i]) and \ - (not self.col_covered[j]): + (not self.row_covered[i]) and \ + (not self.col_covered[j]): row = i col = j done = True @@ -690,7 +691,7 @@ def make_cost_matrix(profit_matrix, inversion_function): .. python:: - cost_matrix = Munkres.make_cost_matrix(matrix, lambda x : sys.maxint - x) + cost_matrix = Munkres.make_cost_matrix(matrix, lambda x : sys.maxsize - x) :Parameters: profit_matrix : list of lists @@ -721,7 +722,7 @@ def print_matrix(matrix, msg=None): import math if msg is not None: - print msg + print(msg) # Calculate the appropriate format width. width = 0 @@ -746,36 +747,31 @@ def print_matrix(matrix, msg=None): if __name__ == '__main__': - matrices = [ - # Square - ([[400, 150, 400], - [400, 450, 600], - [300, 225, 300]], - 850 # expected cost - ), + # Square + ([[400, 150, 400], + [400, 450, 600], + [300, 225, 300]], + 850), # expected cost - # Rectangular variant - ([[400, 150, 400, 1], - [400, 450, 600, 2], - [300, 225, 300, 3]], - 452 # expected cost - ), + # Rectangular variant + ([[400, 150, 400, 1], + [400, 450, 600, 2], + [300, 225, 300, 3]], + 452), # expected cost - # Square - ([[10, 10, 8], - [ 9, 8, 1], - [ 9, 7, 4]], - 18 - ), - # Rectangular variant - ([[10, 10, 8, 11], - [ 9, 8, 1, 1], - [ 9, 7, 4, 10]], - 15 - ), - ] + # Square + ([[10, 10, 8], + [9, 8, 1], + [9, 7, 4]], + 18), + + # Rectangular variant + ([[10, 10, 8, 11], + [9, 8, 1, 1], + [9, 7, 4, 10]], + 15)] m = Munkres() for cost_matrix, expected_total in matrices: @@ -785,7 +781,6 @@ if __name__ == '__main__': for r, c in indexes: x = cost_matrix[r][c] total_cost += x - print '(%d, %d) -> %d' % (r, c, x) - print 'lowest cost=%d' % total_cost + print('(%d, %d) -> %d' % (r, c, x)) + print('lowest cost=%d' % total_cost) assert expected_total == total_cost - diff --git a/lib/mutagen/id3.py b/lib/mutagen/id3.py deleted file mode 100644 index 989c2cfc..00000000 --- a/lib/mutagen/id3.py +++ /dev/null @@ -1,2005 +0,0 @@ -# id3 support for mutagen -# Copyright (C) 2005 Michael Urman -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of version 2 of the GNU General Public License as -# published by the Free Software Foundation. -# -# $Id: id3.py 4285 2008-09-06 08:01:31Z piman $ - -"""ID3v2 reading and writing. - -This is based off of the following references: - http://www.id3.org/id3v2.4.0-structure.txt - http://www.id3.org/id3v2.4.0-frames.txt - http://www.id3.org/id3v2.3.0.html - http://www.id3.org/id3v2-00.txt - http://www.id3.org/id3v1.html - -Its largest deviation from the above (versions 2.3 and 2.2) is that it -will not interpret the / characters as a separator, and will almost -always accept null separators to generate multi-valued text frames. - -Because ID3 frame structure differs between frame types, each frame is -implemented as a different class (e.g. TIT2 as mutagen.id3.TIT2). Each -frame's documentation contains a list of its attributes. - -Since this file's documentation is a little unwieldy, you are probably -interested in the 'ID3' class to start with. -""" - -__all__ = ['ID3', 'ID3FileType', 'Frames', 'Open', 'delete'] - -import struct; from struct import unpack, pack -from zlib import error as zlibError -from warnings import warn - -import lib.mutagen -from lib.mutagen._util import insert_bytes, delete_bytes, DictProxy - -class error(Exception): pass -class ID3NoHeaderError(error, ValueError): pass -class ID3BadUnsynchData(error, ValueError): pass -class ID3BadCompressedData(error, ValueError): pass -class ID3TagError(error, ValueError): pass -class ID3UnsupportedVersionError(error, NotImplementedError): pass -class ID3EncryptionUnsupportedError(error, NotImplementedError): pass -class ID3JunkFrameError(error, ValueError): pass - -class ID3Warning(error, UserWarning): pass - -def is_valid_frame_id(frame_id): - return frame_id.isalnum() and frame_id.isupper() - -class ID3(DictProxy, lib.mutagen.Metadata): - """A file with an ID3v2 tag. - - Attributes: - version -- ID3 tag version as a tuple - unknown_frames -- raw frame data of any unknown frames found - size -- the total size of the ID3 tag, including the header - """ - - PEDANTIC = True - version = (2, 4, 0) - - filename = None - size = 0 - __flags = 0 - __readbytes = 0 - __crc = None - - def __init__(self, *args, **kwargs): - self.unknown_frames = [] - super(ID3, self).__init__(*args, **kwargs) - - def __fullread(self, size): - try: - if size < 0: - raise ValueError('Requested bytes (%s) less than zero' % size) - if size > self.__filesize: - raise EOFError('Requested %#x of %#x (%s)' % - (long(size), long(self.__filesize), self.filename)) - except AttributeError: pass - data = self.__fileobj.read(size) - if len(data) != size: raise EOFError - self.__readbytes += size - return data - - def load(self, filename, known_frames=None, translate=True): - """Load tags from a filename. - - Keyword arguments: - filename -- filename to load tag data from - known_frames -- dict mapping frame IDs to Frame objects - translate -- Update all tags to ID3v2.4 internally. Mutagen is - only capable of writing ID3v2.4 tags, so if you - intend to save, this must be true. - - Example of loading a custom frame: - my_frames = dict(mutagen.id3.Frames) - class XMYF(Frame): ... - my_frames["XMYF"] = XMYF - mutagen.id3.ID3(filename, known_frames=my_frames) - """ - - from os.path import getsize - self.filename = filename - self.__known_frames = known_frames - self.__fileobj = file(filename, 'rb') - self.__filesize = getsize(filename) - try: - try: - self.__load_header() - except EOFError: - self.size = 0 - raise ID3NoHeaderError("%s: too small (%d bytes)" %( - filename, self.__filesize)) - except (ID3NoHeaderError, ID3UnsupportedVersionError), err: - self.size = 0 - import sys - stack = sys.exc_info()[2] - try: self.__fileobj.seek(-128, 2) - except EnvironmentError: raise err, None, stack - else: - frames = ParseID3v1(self.__fileobj.read(128)) - if frames is not None: - self.version = (1, 1) - map(self.add, frames.values()) - else: raise err, None, stack - else: - frames = self.__known_frames - if frames is None: - if (2,3,0) <= self.version: frames = Frames - elif (2,2,0) <= self.version: frames = Frames_2_2 - data = self.__fullread(self.size - 10) - for frame in self.__read_frames(data, frames=frames): - if isinstance(frame, Frame): self.add(frame) - else: self.unknown_frames.append(frame) - finally: - self.__fileobj.close() - del self.__fileobj - del self.__filesize - if translate: - self.update_to_v24() - - def getall(self, key): - """Return all frames with a given name (the list may be empty). - - This is best explained by examples: - id3.getall('TIT2') == [id3['TIT2']] - id3.getall('TTTT') == [] - id3.getall('TXXX') == [TXXX(desc='woo', text='bar'), - TXXX(desc='baz', text='quuuux'), ...] - - Since this is based on the frame's HashKey, which is - colon-separated, you can use it to do things like - getall('COMM:MusicMatch') or getall('TXXX:QuodLibet:'). - """ - if key in self: return [self[key]] - else: - key = key + ":" - return [v for s,v in self.items() if s.startswith(key)] - - def delall(self, key): - """Delete all tags of a given kind; see getall.""" - if key in self: del(self[key]) - else: - key = key + ":" - for k in filter(lambda s: s.startswith(key), self.keys()): - del(self[k]) - - def setall(self, key, values): - """Delete frames of the given type and add frames in 'values'.""" - self.delall(key) - for tag in values: - self[tag.HashKey] = tag - - def pprint(self): - """Return tags in a human-readable format. - - "Human-readable" is used loosely here. The format is intended - to mirror that used for Vorbis or APEv2 output, e.g. - TIT2=My Title - However, ID3 frames can have multiple keys: - POPM=user@example.org=3 128/255 - """ - return "\n".join(map(Frame.pprint, self.values())) - - def loaded_frame(self, tag): - """Deprecated; use the add method.""" - # turn 2.2 into 2.3/2.4 tags - if len(type(tag).__name__) == 3: tag = type(tag).__base__(tag) - self[tag.HashKey] = tag - - # add = loaded_frame (and vice versa) break applications that - # expect to be able to override loaded_frame (e.g. Quod Libet), - # as does making loaded_frame call add. - def add(self, frame): - """Add a frame to the tag.""" - return self.loaded_frame(frame) - - def __load_header(self): - fn = self.filename - data = self.__fullread(10) - id3, vmaj, vrev, flags, size = unpack('>3sBBB4s', data) - self.__flags = flags - self.size = BitPaddedInt(size) + 10 - self.version = (2, vmaj, vrev) - - if id3 != 'ID3': - raise ID3NoHeaderError("'%s' doesn't start with an ID3 tag" % fn) - if vmaj not in [2, 3, 4]: - raise ID3UnsupportedVersionError("'%s' ID3v2.%d not supported" - % (fn, vmaj)) - - if self.PEDANTIC: - if (2,4,0) <= self.version and (flags & 0x0f): - raise ValueError("'%s' has invalid flags %#02x" % (fn, flags)) - elif (2,3,0) <= self.version < (2,4,0) and (flags & 0x1f): - raise ValueError("'%s' has invalid flags %#02x" % (fn, flags)) - - if self.f_extended: - extsize = self.__fullread(4) - if extsize in Frames: - # Some tagger sets the extended header flag but - # doesn't write an extended header; in this case, the - # ID3 data follows immediately. Since no extended - # header is going to be long enough to actually match - # a frame, and if it's *not* a frame we're going to be - # completely lost anyway, this seems to be the most - # correct check. - # http://code.google.com/p/quodlibet/issues/detail?id=126 - self.__flags ^= 0x40 - self.__extsize = 0 - self.__fileobj.seek(-4, 1) - self.__readbytes -= 4 - elif self.version >= (2,4,0): - # "Where the 'Extended header size' is the size of the whole - # extended header, stored as a 32 bit synchsafe integer." - self.__extsize = BitPaddedInt(extsize) - 4 - else: - # "Where the 'Extended header size', currently 6 or 10 bytes, - # excludes itself." - self.__extsize = unpack('>L', extsize)[0] - if self.__extsize: - self.__extdata = self.__fullread(self.__extsize) - else: - self.__extdata = "" - - def __determine_bpi(self, data, frames, EMPTY="\x00" * 10): - if self.version < (2, 4, 0): - return int - # have to special case whether to use bitpaddedints here - # spec says to use them, but iTunes has it wrong - - # count number of tags found as BitPaddedInt and how far past - o = 0 - asbpi = 0 - while o < len(data) - 10: - part = data[o:o + 10] - if part == EMPTY: - bpioff = -((len(data) - o) % 10) - break - name, size, flags = unpack('>4sLH', part) - size = BitPaddedInt(size) - o += 10 + size - if name in frames: - asbpi += 1 - else: - bpioff = o - len(data) - - # count number of tags found as int and how far past - o = 0 - asint = 0 - while o < len(data) - 10: - part = data[o:o + 10] - if part == EMPTY: - intoff = -((len(data) - o) % 10) - break - name, size, flags = unpack('>4sLH', part) - o += 10 + size - if name in frames: - asint += 1 - else: - intoff = o - len(data) - - # if more tags as int, or equal and bpi is past and int is not - if asint > asbpi or (asint == asbpi and (bpioff >= 1 and intoff <= 1)): - return int - return BitPaddedInt - - def __read_frames(self, data, frames): - if self.version < (2,4,0) and self.f_unsynch: - try: data = unsynch.decode(data) - except ValueError: pass - - if (2,3,0) <= self.version: - bpi = self.__determine_bpi(data, frames) - while data: - header = data[:10] - try: name, size, flags = unpack('>4sLH', header) - except struct.error: return # not enough header - if name.strip('\x00') == '': return - size = bpi(size) - framedata = data[10:10+size] - data = data[10+size:] - if size == 0: continue # drop empty frames - try: tag = frames[name] - except KeyError: - if is_valid_frame_id(name): yield header + framedata - else: - try: yield self.__load_framedata(tag, flags, framedata) - except NotImplementedError: yield header + framedata - except ID3JunkFrameError: pass - - elif (2,2,0) <= self.version: - while data: - header = data[0:6] - try: name, size = unpack('>3s3s', header) - except struct.error: return # not enough header - size, = struct.unpack('>L', '\x00'+size) - if name.strip('\x00') == '': return - framedata = data[6:6+size] - data = data[6+size:] - if size == 0: continue # drop empty frames - try: tag = frames[name] - except KeyError: - if is_valid_frame_id(name): yield header + framedata - else: - try: yield self.__load_framedata(tag, 0, framedata) - except NotImplementedError: yield header + framedata - except ID3JunkFrameError: pass - - def __load_framedata(self, tag, flags, framedata): - return tag.fromData(self, flags, framedata) - - f_unsynch = property(lambda s: bool(s.__flags & 0x80)) - f_extended = property(lambda s: bool(s.__flags & 0x40)) - f_experimental = property(lambda s: bool(s.__flags & 0x20)) - f_footer = property(lambda s: bool(s.__flags & 0x10)) - - #f_crc = property(lambda s: bool(s.__extflags & 0x8000)) - - def save(self, filename=None, v1=1): - """Save changes to a file. - - If no filename is given, the one most recently loaded is used. - - Keyword arguments: - v1 -- if 0, ID3v1 tags will be removed - if 1, ID3v1 tags will be updated but not added - if 2, ID3v1 tags will be created and/or updated - - The lack of a way to update only an ID3v1 tag is intentional. - """ - - # Sort frames by 'importance' - order = ["TIT2", "TPE1", "TRCK", "TALB", "TPOS", "TDRC", "TCON"] - order = dict(zip(order, range(len(order)))) - last = len(order) - frames = self.items() - frames.sort(lambda a, b: cmp(order.get(a[0][:4], last), - order.get(b[0][:4], last))) - - framedata = [self.__save_frame(frame) for (key, frame) in frames] - framedata.extend([data for data in self.unknown_frames - if len(data) > 10]) - if not framedata: - try: - self.delete(filename) - except EnvironmentError, err: - from errno import ENOENT - if err.errno != ENOENT: raise - return - - framedata = ''.join(framedata) - framesize = len(framedata) - - if filename is None: filename = self.filename - try: f = open(filename, 'rb+') - except IOError, err: - from errno import ENOENT - if err.errno != ENOENT: raise - f = open(filename, 'ab') # create, then reopen - f = open(filename, 'rb+') - try: - idata = f.read(10) - try: id3, vmaj, vrev, flags, insize = unpack('>3sBBB4s', idata) - except struct.error: id3, insize = '', 0 - insize = BitPaddedInt(insize) - if id3 != 'ID3': insize = -10 - - if insize >= framesize: outsize = insize - else: outsize = (framesize + 1023) & ~0x3FF - framedata += '\x00' * (outsize - framesize) - - framesize = BitPaddedInt.to_str(outsize, width=4) - flags = 0 - header = pack('>3sBBB4s', 'ID3', 4, 0, flags, framesize) - data = header + framedata - - if (insize < outsize): - insert_bytes(f, outsize-insize, insize+10) - f.seek(0) - f.write(data) - - try: - f.seek(-128, 2) - except IOError, err: - from errno import EINVAL - if err.errno != EINVAL: raise - f.seek(0, 2) # ensure read won't get "TAG" - - if f.read(3) == "TAG": - f.seek(-128, 2) - if v1 > 0: f.write(MakeID3v1(self)) - else: f.truncate() - elif v1 == 2: - f.seek(0, 2) - f.write(MakeID3v1(self)) - - finally: - f.close() - - def delete(self, filename=None, delete_v1=True, delete_v2=True): - """Remove tags from a file. - - If no filename is given, the one most recently loaded is used. - - Keyword arguments: - delete_v1 -- delete any ID3v1 tag - delete_v2 -- delete any ID3v2 tag - """ - if filename is None: - filename = self.filename - delete(filename, delete_v1, delete_v2) - self.clear() - - def __save_frame(self, frame): - flags = 0 - if self.PEDANTIC and isinstance(frame, TextFrame): - if len(str(frame)) == 0: return '' - framedata = frame._writeData() - usize = len(framedata) - if usize > 2048: - # Disabled as this causes iTunes and other programs - # to fail to find these frames, which usually includes - # e.g. APIC. - #framedata = BitPaddedInt.to_str(usize) + framedata.encode('zlib') - #flags |= Frame.FLAG24_COMPRESS | Frame.FLAG24_DATALEN - pass - datasize = BitPaddedInt.to_str(len(framedata), width=4) - header = pack('>4s4sH', type(frame).__name__, datasize, flags) - return header + framedata - - def update_to_v24(self): - """Convert older tags into an ID3v2.4 tag. - - This updates old ID3v2 frames to ID3v2.4 ones (e.g. TYER to - TDRC). If you intend to save tags, you must call this function - at some point; it is called by default when loading the tag. - """ - - if self.version < (2,3,0): del self.unknown_frames[:] - # unsafe to write - - # TDAT, TYER, and TIME have been turned into TDRC. - try: - if str(self.get("TYER", "")).strip("\x00"): - date = str(self.pop("TYER")) - if str(self.get("TDAT", "")).strip("\x00"): - dat = str(self.pop("TDAT")) - date = "%s-%s-%s" % (date, dat[2:], dat[:2]) - if str(self.get("TIME", "")).strip("\x00"): - time = str(self.pop("TIME")) - date += "T%s:%s:00" % (time[:2], time[2:]) - if "TDRC" not in self: - self.add(TDRC(encoding=0, text=date)) - except UnicodeDecodeError: - # Old ID3 tags have *lots* of Unicode problems, so if TYER - # is bad, just chuck the frames. - pass - - # TORY can be the first part of a TDOR. - if "TORY" in self: - f = self.pop("TORY") - if "TDOR" not in self: - try: - self.add(TDOR(encoding=0, text=str(f))) - except UnicodeDecodeError: - pass - - # IPLS is now TIPL. - if "IPLS" in self: - f = self.pop("IPLS") - if "TIPL" not in self: - self.add(TIPL(encoding=f.encoding, people=f.people)) - - if "TCON" in self: - # Get rid of "(xx)Foobr" format. - self["TCON"].genres = self["TCON"].genres - - if self.version < (2, 3): - # ID3v2.2 PIC frames are slightly different. - pics = self.getall("APIC") - mimes = { "PNG": "image/png", "JPG": "image/jpeg" } - self.delall("APIC") - for pic in pics: - newpic = APIC( - encoding=pic.encoding, mime=mimes.get(pic.mime, pic.mime), - type=pic.type, desc=pic.desc, data=pic.data) - self.add(newpic) - - # ID3v2.2 LNK frames are just way too different to upgrade. - self.delall("LINK") - - # These can't be trivially translated to any ID3v2.4 tags, or - # should have been removed already. - for key in ["RVAD", "EQUA", "TRDA", "TSIZ", "TDAT", "TIME", "CRM"]: - if key in self: del(self[key]) - -def delete(filename, delete_v1=True, delete_v2=True): - """Remove tags from a file. - - Keyword arguments: - delete_v1 -- delete any ID3v1 tag - delete_v2 -- delete any ID3v2 tag - """ - - f = open(filename, 'rb+') - - if delete_v1: - try: - f.seek(-128, 2) - except IOError: pass - else: - if f.read(3) == "TAG": - f.seek(-128, 2) - f.truncate() - - # technically an insize=0 tag is invalid, but we delete it anyway - # (primarily because we used to write it) - if delete_v2: - f.seek(0, 0) - idata = f.read(10) - try: id3, vmaj, vrev, flags, insize = unpack('>3sBBB4s', idata) - except struct.error: id3, insize = '', -1 - insize = BitPaddedInt(insize) - if id3 == 'ID3' and insize >= 0: - delete_bytes(f, insize + 10, 0) - -class BitPaddedInt(int): - def __new__(cls, value, bits=7, bigendian=True): - "Strips 8-bits bits out of every byte" - mask = (1<<(bits))-1 - if isinstance(value, (int, long)): - bytes = [] - while value: - bytes.append(value & ((1<> 8 - if isinstance(value, str): - bytes = [ord(byte) & mask for byte in value] - if bigendian: bytes.reverse() - numeric_value = 0 - for shift, byte in zip(range(0, len(bytes)*bits, bits), bytes): - numeric_value += byte << shift - if isinstance(numeric_value, long): - self = long.__new__(BitPaddedLong, numeric_value) - else: - self = int.__new__(BitPaddedInt, numeric_value) - self.bits = bits - self.bigendian = bigendian - return self - - def as_str(value, bits=7, bigendian=True, width=4): - bits = getattr(value, 'bits', bits) - bigendian = getattr(value, 'bigendian', bigendian) - value = int(value) - mask = (1<> bits - # PCNT and POPM use growing integers of at least 4 bytes as counters. - if width == -1: width = max(4, len(bytes)) - if len(bytes) > width: - raise ValueError, 'Value too wide (%d bytes)' % len(bytes) - else: bytes.extend([0] * (width-len(bytes))) - if bigendian: bytes.reverse() - return ''.join(map(chr, bytes)) - to_str = staticmethod(as_str) - -class BitPaddedLong(long): - def as_str(value, bits=7, bigendian=True, width=4): - return BitPaddedInt.to_str(value, bits, bigendian, width) - to_str = staticmethod(as_str) - -class unsynch(object): - def decode(value): - output = [] - safe = True - append = output.append - for val in value: - if safe: - append(val) - safe = val != '\xFF' - else: - if val >= '\xE0': raise ValueError('invalid sync-safe string') - elif val != '\x00': append(val) - safe = True - if not safe: raise ValueError('string ended unsafe') - return ''.join(output) - decode = staticmethod(decode) - - def encode(value): - output = [] - safe = True - append = output.append - for val in value: - if safe: - append(val) - if val == '\xFF': safe = False - elif val == '\x00' or val >= '\xE0': - append('\x00') - append(val) - safe = val != '\xFF' - else: - append(val) - safe = True - if not safe: append('\x00') - return ''.join(output) - encode = staticmethod(encode) - -class Spec(object): - def __init__(self, name): self.name = name - def __hash__(self): raise TypeError("Spec objects are unhashable") - -class ByteSpec(Spec): - def read(self, frame, data): return ord(data[0]), data[1:] - def write(self, frame, value): return chr(value) - def validate(self, frame, value): return value - -class IntegerSpec(Spec): - def read(self, frame, data): - return int(BitPaddedInt(data, bits=8)), '' - def write(self, frame, value): - return BitPaddedInt.to_str(value, bits=8, width=-1) - def validate(self, frame, value): - return value - -class SizedIntegerSpec(Spec): - def __init__(self, name, size): - self.name, self.__sz = name, size - def read(self, frame, data): - return int(BitPaddedInt(data[:self.__sz], bits=8)), data[self.__sz:] - def write(self, frame, value): - return BitPaddedInt.to_str(value, bits=8, width=self.__sz) - def validate(self, frame, value): - return value - -class EncodingSpec(ByteSpec): - def read(self, frame, data): - enc, data = super(EncodingSpec, self).read(frame, data) - if enc < 16: return enc, data - else: return 0, chr(enc)+data - - def validate(self, frame, value): - if 0 <= value <= 3: return value - if value is None: return None - raise ValueError, 'Invalid Encoding: %r' % value - -class StringSpec(Spec): - def __init__(self, name, length): - super(StringSpec, self).__init__(name) - self.len = length - def read(s, frame, data): return data[:s.len], data[s.len:] - def write(s, frame, value): - if value is None: return '\x00' * s.len - else: return (str(value) + '\x00' * s.len)[:s.len] - def validate(s, frame, value): - if value is None: return None - if isinstance(value, basestring) and len(value) == s.len: return value - raise ValueError, 'Invalid StringSpec[%d] data: %r' % (s.len, value) - -class BinaryDataSpec(Spec): - def read(self, frame, data): return data, '' - def write(self, frame, value): return str(value) - def validate(self, frame, value): return str(value) - -class EncodedTextSpec(Spec): - # Okay, seriously. This is private and defined explicitly and - # completely by the ID3 specification. You can't just add - # encodings here however you want. - _encodings = ( ('latin1', '\x00'), ('utf16', '\x00\x00'), - ('utf_16_be', '\x00\x00'), ('utf8', '\x00') ) - - def read(self, frame, data): - enc, term = self._encodings[frame.encoding] - ret = '' - if len(term) == 1: - if term in data: - data, ret = data.split(term, 1) - else: - offset = -1 - try: - while True: - offset = data.index(term, offset+1) - if offset & 1: continue - data, ret = data[0:offset], data[offset+2:]; break - except ValueError: pass - - if len(data) < len(term): return u'', ret - return data.decode(enc), ret - - def write(self, frame, value): - enc, term = self._encodings[frame.encoding] - return value.encode(enc) + term - - def validate(self, frame, value): return unicode(value) - -class MultiSpec(Spec): - def __init__(self, name, *specs, **kw): - super(MultiSpec, self).__init__(name) - self.specs = specs - self.sep = kw.get('sep') - - def read(self, frame, data): - values = [] - while data: - record = [] - for spec in self.specs: - value, data = spec.read(frame, data) - record.append(value) - if len(self.specs) != 1: values.append(record) - else: values.append(record[0]) - return values, data - - def write(self, frame, value): - data = [] - if len(self.specs) == 1: - for v in value: - data.append(self.specs[0].write(frame, v)) - else: - for record in value: - for v, s in zip(record, self.specs): - data.append(s.write(frame, v)) - return ''.join(data) - - def validate(self, frame, value): - if value is None: return [] - if self.sep and isinstance(value, basestring): - value = value.split(self.sep) - if isinstance(value, list): - if len(self.specs) == 1: - return [self.specs[0].validate(frame, v) for v in value] - else: - return [ - [s.validate(frame, v) for (v,s) in zip(val, self.specs)] - for val in value ] - raise ValueError, 'Invalid MultiSpec data: %r' % value - -class EncodedNumericTextSpec(EncodedTextSpec): pass -class EncodedNumericPartTextSpec(EncodedTextSpec): pass - -class Latin1TextSpec(EncodedTextSpec): - def read(self, frame, data): - if '\x00' in data: data, ret = data.split('\x00',1) - else: ret = '' - return data.decode('latin1'), ret - - def write(self, data, value): - return value.encode('latin1') + '\x00' - - def validate(self, frame, value): return unicode(value) - -class ID3TimeStamp(object): - """A time stamp in ID3v2 format. - - This is a restricted form of the ISO 8601 standard; time stamps - take the form of: - YYYY-MM-DD HH:MM:SS - Or some partial form (YYYY-MM-DD HH, YYYY, etc.). - - The 'text' attribute contains the raw text data of the time stamp. - """ - - import re - def __init__(self, text): - if isinstance(text, ID3TimeStamp): text = text.text - self.text = text - - __formats = ['%04d'] + ['%02d'] * 5 - __seps = ['-', '-', ' ', ':', ':', 'x'] - def get_text(self): - parts = [self.year, self.month, self.day, - self.hour, self.minute, self.second] - pieces = [] - for i, part in enumerate(iter(iter(parts).next, None)): - pieces.append(self.__formats[i]%part + self.__seps[i]) - return u''.join(pieces)[:-1] - - def set_text(self, text, splitre=re.compile('[-T:/.]|\s+')): - year, month, day, hour, minute, second = \ - splitre.split(text + ':::::')[:6] - for a in 'year month day hour minute second'.split(): - try: v = int(locals()[a]) - except ValueError: v = None - setattr(self, a, v) - - text = property(get_text, set_text, doc="ID3v2.4 date and time.") - - def __str__(self): return self.text - def __repr__(self): return repr(self.text) - def __cmp__(self, other): return cmp(self.text, other.text) - def encode(self, *args): return self.text.encode(*args) - -class TimeStampSpec(EncodedTextSpec): - def read(self, frame, data): - value, data = super(TimeStampSpec, self).read(frame, data) - return self.validate(frame, value), data - - def write(self, frame, data): - return super(TimeStampSpec, self).write(frame, - data.text.replace(' ', 'T')) - - def validate(self, frame, value): - try: return ID3TimeStamp(value) - except TypeError: raise ValueError, "Invalid ID3TimeStamp: %r" % value - -class ChannelSpec(ByteSpec): - (OTHER, MASTER, FRONTRIGHT, FRONTLEFT, BACKRIGHT, BACKLEFT, FRONTCENTRE, - BACKCENTRE, SUBWOOFER) = range(9) - -class VolumeAdjustmentSpec(Spec): - def read(self, frame, data): - value, = unpack('>h', data[0:2]) - return value/512.0, data[2:] - - def write(self, frame, value): - return pack('>h', int(round(value * 512))) - - def validate(self, frame, value): return value - -class VolumePeakSpec(Spec): - def read(self, frame, data): - # http://bugs.xmms.org/attachment.cgi?id=113&action=view - peak = 0 - bits = ord(data[0]) - bytes = min(4, (bits + 7) >> 3) - # not enough frame data - if bytes + 1 > len(data): raise ID3JunkFrameError - shift = ((8 - (bits & 7)) & 7) + (4 - bytes) * 8 - for i in range(1, bytes+1): - peak *= 256 - peak += ord(data[i]) - peak *= 2**shift - return (float(peak) / (2**31-1)), data[1+bytes:] - - def write(self, frame, value): - # always write as 16 bits for sanity. - return "\x10" + pack('>H', int(round(value * 32768))) - - def validate(self, frame, value): return value - -class SynchronizedTextSpec(EncodedTextSpec): - def read(self, frame, data): - texts = [] - encoding, term = self._encodings[frame.encoding] - while data: - l = len(term) - try: - value_idx = data.index(term) - except ValueError: - raise ID3JunkFrameError - value = data[:value_idx].decode(encoding) - time, = struct.unpack(">I", data[value_idx+l:value_idx+l+4]) - texts.append((value, time)) - data = data[value_idx+l+4:] - return texts, "" - - def write(self, frame, value): - data = [] - encoding, term = self._encodings[frame.encoding] - for text, time in frame.text: - text = text.encode(encoding) + term - data.append(text + struct.pack(">I", time)) - return "".join(data) - - def validate(self, frame, value): - return value - -class KeyEventSpec(Spec): - def read(self, frame, data): - events = [] - while len(data) >= 5: - events.append(struct.unpack(">bI", data[:5])) - data = data[5:] - return events, data - - def write(self, frame, value): - return "".join([struct.pack(">bI", *event) for event in value]) - - def validate(self, frame, value): - return value - -class VolumeAdjustmentsSpec(Spec): - # Not to be confused with VolumeAdjustmentSpec. - def read(self, frame, data): - adjustments = {} - while len(data) >= 4: - freq, adj = struct.unpack(">Hh", data[:4]) - data = data[4:] - freq /= 2.0 - adj /= 512.0 - adjustments[freq] = adj - adjustments = adjustments.items() - adjustments.sort() - return adjustments, data - - def write(self, frame, value): - value.sort() - return "".join([struct.pack(">Hh", int(freq * 2), int(adj * 512)) - for (freq, adj) in value]) - - def validate(self, frame, value): - return value - -class ASPIIndexSpec(Spec): - def read(self, frame, data): - if frame.b == 16: - format = "H" - size = 2 - elif frame.b == 8: - format = "B" - size = 1 - else: - warn("invalid bit count in ASPI (%d)" % frame.b, ID3Warning) - return [], data - - indexes = data[:frame.N * size] - data = data[frame.N * size:] - return list(struct.unpack(">" + format * frame.N, indexes)), data - - def write(self, frame, values): - if frame.b == 16: format = "H" - elif frame.b == 8: format = "B" - else: raise ValueError("frame.b must be 8 or 16") - return struct.pack(">" + format * frame.N, *values) - - def validate(self, frame, values): - return values - -class Frame(object): - """Fundamental unit of ID3 data. - - ID3 tags are split into frames. Each frame has a potentially - different structure, and so this base class is not very featureful. - """ - - FLAG23_ALTERTAG = 0x8000 - FLAG23_ALTERFILE = 0x4000 - FLAG23_READONLY = 0x2000 - FLAG23_COMPRESS = 0x0080 - FLAG23_ENCRYPT = 0x0040 - FLAG23_GROUP = 0x0020 - - FLAG24_ALTERTAG = 0x4000 - FLAG24_ALTERFILE = 0x2000 - FLAG24_READONLY = 0x1000 - FLAG24_GROUPID = 0x0040 - FLAG24_COMPRESS = 0x0008 - FLAG24_ENCRYPT = 0x0004 - FLAG24_UNSYNCH = 0x0002 - FLAG24_DATALEN = 0x0001 - - _framespec = [] - def __init__(self, *args, **kwargs): - if len(args)==1 and len(kwargs)==0 and isinstance(args[0], type(self)): - other = args[0] - for checker in self._framespec: - val = checker.validate(self, getattr(other, checker.name)) - setattr(self, checker.name, val) - else: - for checker, val in zip(self._framespec, args): - setattr(self, checker.name, checker.validate(self, val)) - for checker in self._framespec[len(args):]: - validated = checker.validate( - self, kwargs.get(checker.name, None)) - setattr(self, checker.name, validated) - - HashKey = property( - lambda s: s.FrameID, - doc="an internal key used to ensure frame uniqueness in a tag") - FrameID = property( - lambda s: type(s).__name__, - doc="ID3v2 three or four character frame ID") - - def __repr__(self): - """Python representation of a frame. - - The string returned is a valid Python expression to construct - a copy of this frame. - """ - kw = [] - for attr in self._framespec: - kw.append('%s=%r' % (attr.name, getattr(self, attr.name))) - return '%s(%s)' % (type(self).__name__, ', '.join(kw)) - - def _readData(self, data): - odata = data - for reader in self._framespec: - if len(data): - try: value, data = reader.read(self, data) - except UnicodeDecodeError: - raise ID3JunkFrameError - else: raise ID3JunkFrameError - setattr(self, reader.name, value) - if data.strip('\x00'): - warn('Leftover data: %s: %r (from %r)' % ( - type(self).__name__, data, odata), - ID3Warning) - - def _writeData(self): - data = [] - for writer in self._framespec: - data.append(writer.write(self, getattr(self, writer.name))) - return ''.join(data) - - def pprint(self): - """Return a human-readable representation of the frame.""" - return "%s=%s" % (type(self).__name__, self._pprint()) - - def _pprint(self): - return "[unrepresentable data]" - - def fromData(cls, id3, tflags, data): - """Construct this ID3 frame from raw string data.""" - - if (2,4,0) <= id3.version: - if tflags & (Frame.FLAG24_COMPRESS | Frame.FLAG24_DATALEN): - # The data length int is syncsafe in 2.4 (but not 2.3). - # However, we don't actually need the data length int, - # except to work around a QL 0.12 bug, and in that case - # all we need are the raw bytes. - datalen_bytes = data[:4] - data = data[4:] - if tflags & Frame.FLAG24_UNSYNCH or id3.f_unsynch: - try: data = unsynch.decode(data) - except ValueError, err: - if id3.PEDANTIC: - raise ID3BadUnsynchData, '%s: %r' % (err, data) - if tflags & Frame.FLAG24_ENCRYPT: - raise ID3EncryptionUnsupportedError - if tflags & Frame.FLAG24_COMPRESS: - try: data = data.decode('zlib') - except zlibError, err: - # the initial mutagen that went out with QL 0.12 did not - # write the 4 bytes of uncompressed size. Compensate. - data = datalen_bytes + data - try: data = data.decode('zlib') - except zlibError, err: - if id3.PEDANTIC: - raise ID3BadCompressedData, '%s: %r' % (err, data) - - elif (2,3,0) <= id3.version: - if tflags & Frame.FLAG23_COMPRESS: - usize, = unpack('>L', data[:4]) - data = data[4:] - if tflags & Frame.FLAG23_ENCRYPT: - raise ID3EncryptionUnsupportedError - if tflags & Frame.FLAG23_COMPRESS: - try: data = data.decode('zlib') - except zlibError, err: - if id3.PEDANTIC: - raise ID3BadCompressedData, '%s: %r' % (err, data) - - frame = cls() - frame._rawdata = data - frame._flags = tflags - frame._readData(data) - return frame - fromData = classmethod(fromData) - - def __hash__(self): - raise TypeError("Frame objects are unhashable") - -class FrameOpt(Frame): - """A frame with optional parts. - - Some ID3 frames have optional data; this class extends Frame to - provide support for those parts. - """ - _optionalspec = [] - - def __init__(self, *args, **kwargs): - super(FrameOpt, self).__init__(*args, **kwargs) - for spec in self._optionalspec: - if spec.name in kwargs: - validated = spec.validate(self, kwargs[spec.name]) - setattr(self, spec.name, validated) - else: break - - def _readData(self, data): - odata = data - for reader in self._framespec: - if len(data): value, data = reader.read(self, data) - else: raise ID3JunkFrameError - setattr(self, reader.name, value) - if data: - for reader in self._optionalspec: - if len(data): value, data = reader.read(self, data) - else: break - setattr(self, reader.name, value) - if data.strip('\x00'): - warn('Leftover data: %s: %r (from %r)' % ( - type(self).__name__, data, odata), - ID3Warning) - - def _writeData(self): - data = [] - for writer in self._framespec: - data.append(writer.write(self, getattr(self, writer.name))) - for writer in self._optionalspec: - try: data.append(writer.write(self, getattr(self, writer.name))) - except AttributeError: break - return ''.join(data) - - def __repr__(self): - kw = [] - for attr in self._framespec: - kw.append('%s=%r' % (attr.name, getattr(self, attr.name))) - for attr in self._optionalspec: - if hasattr(self, attr.name): - kw.append('%s=%r' % (attr.name, getattr(self, attr.name))) - return '%s(%s)' % (type(self).__name__, ', '.join(kw)) - - -class TextFrame(Frame): - """Text strings. - - Text frames support casts to unicode or str objects, as well as - list-like indexing, extend, and append. - - Iterating over a TextFrame iterates over its strings, not its - characters. - - Text frames have a 'text' attribute which is the list of strings, - and an 'encoding' attribute; 0 for ISO-8859 1, 1 UTF-16, 2 for - UTF-16BE, and 3 for UTF-8. If you don't want to worry about - encodings, just set it to 3. - """ - - _framespec = [ EncodingSpec('encoding'), - MultiSpec('text', EncodedTextSpec('text'), sep=u'\u0000') ] - def __str__(self): return self.__unicode__().encode('utf-8') - def __unicode__(self): return u'\u0000'.join(self.text) - def __eq__(self, other): - if isinstance(other, str): return str(self) == other - elif isinstance(other, unicode): return unicode(self) == other - return self.text == other - def __getitem__(self, item): return self.text[item] - def __iter__(self): return iter(self.text) - def append(self, value): return self.text.append(value) - def extend(self, value): return self.text.extend(value) - def _pprint(self): return " / ".join(self.text) - -class NumericTextFrame(TextFrame): - """Numerical text strings. - - The numeric value of these frames can be gotten with unary plus, e.g. - frame = TLEN('12345') - length = +frame - """ - - _framespec = [ EncodingSpec('encoding'), - MultiSpec('text', EncodedNumericTextSpec('text'), sep=u'\u0000') ] - - def __pos__(self): - """Return the numerical value of the string.""" - return int(self.text[0]) - -class NumericPartTextFrame(TextFrame): - """Multivalue numerical text strings. - - These strings indicate 'part (e.g. track) X of Y', and unary plus - returns the first value: - frame = TRCK('4/15') - track = +frame # track == 4 - """ - - _framespec = [ EncodingSpec('encoding'), - MultiSpec('text', EncodedNumericPartTextSpec('text'), sep=u'\u0000') ] - def __pos__(self): - return int(self.text[0].split("/")[0]) - -class TimeStampTextFrame(TextFrame): - """A list of time stamps. - - The 'text' attribute in this frame is a list of ID3TimeStamp - objects, not a list of strings. - """ - - _framespec = [ EncodingSpec('encoding'), - MultiSpec('text', TimeStampSpec('stamp'), sep=u',') ] - def __str__(self): return self.__unicode__().encode('utf-8') - def __unicode__(self): return ','.join([stamp.text for stamp in self.text]) - def _pprint(self): - return " / ".join([stamp.text for stamp in self.text]) - -class UrlFrame(Frame): - """A frame containing a URL string. - - The ID3 specification is silent about IRIs and normalized URL - forms. Mutagen assumes all URLs in files are encoded as Latin 1, - but string conversion of this frame returns a UTF-8 representation - for compatibility with other string conversions. - - The only sane way to handle URLs in MP3s is to restrict them to - ASCII. - """ - - _framespec = [ Latin1TextSpec('url') ] - def __str__(self): return self.url.encode('utf-8') - def __unicode__(self): return self.url - def __eq__(self, other): return self.url == other - def _pprint(self): return self.url - -class UrlFrameU(UrlFrame): - HashKey = property(lambda s: '%s:%s' % (s.FrameID, s.url)) - -class TALB(TextFrame): "Album" -class TBPM(NumericTextFrame): "Beats per minute" -class TCOM(TextFrame): "Composer" - -class TCON(TextFrame): - """Content type (Genre) - - ID3 has several ways genres can be represented; for convenience, - use the 'genres' property rather than the 'text' attribute. - """ - - from lib.mutagen._constants import GENRES - - def __get_genres(self): - genres = [] - import re - genre_re = re.compile(r"((?:\((?P[0-9]+|RX|CR)\))*)(?P.+)?") - for value in self.text: - if value.isdigit(): - try: genres.append(self.GENRES[int(value)]) - except IndexError: genres.append(u"Unknown") - elif value == "CR": genres.append(u"Cover") - elif value == "RX": genres.append(u"Remix") - elif value: - newgenres = [] - genreid, dummy, genrename = genre_re.match(value).groups() - - if genreid: - for gid in genreid[1:-1].split(")("): - if gid.isdigit() and int(gid) < len(self.GENRES): - gid = unicode(self.GENRES[int(gid)]) - newgenres.append(gid) - elif gid == "CR": newgenres.append(u"Cover") - elif gid == "RX": newgenres.append(u"Remix") - else: newgenres.append(u"Unknown") - - if genrename: - # "Unescaping" the first parenthesis - if genrename.startswith("(("): genrename = genrename[1:] - if genrename not in newgenres: newgenres.append(genrename) - - genres.extend(newgenres) - - return genres - - def __set_genres(self, genres): - if isinstance(genres, basestring): genres = [genres] - self.text = map(self.__decode, genres) - - def __decode(self, value): - if isinstance(value, str): - enc = EncodedTextSpec._encodings[self.encoding][0] - return value.decode(enc) - else: return value - - genres = property(__get_genres, __set_genres, None, - "A list of genres parsed from the raw text data.") - - def _pprint(self): - return " / ".join(self.genres) - -class TCOP(TextFrame): "Copyright (c)" -class TCMP(NumericTextFrame): "iTunes Compilation Flag" -class TDAT(TextFrame): "Date of recording (DDMM)" -class TDEN(TimeStampTextFrame): "Encoding Time" -class TDOR(TimeStampTextFrame): "Original Release Time" -class TDLY(NumericTextFrame): "Audio Delay (ms)" -class TDRC(TimeStampTextFrame): "Recording Time" -class TDRL(TimeStampTextFrame): "Release Time" -class TDTG(TimeStampTextFrame): "Tagging Time" -class TENC(TextFrame): "Encoder" -class TEXT(TextFrame): "Lyricist" -class TFLT(TextFrame): "File type" -class TIME(TextFrame): "Time of recording (HHMM)" -class TIT1(TextFrame): "Content group description" -class TIT2(TextFrame): "Title" -class TIT3(TextFrame): "Subtitle/Description refinement" -class TKEY(TextFrame): "Starting Key" -class TLAN(TextFrame): "Audio Languages" -class TLEN(NumericTextFrame): "Audio Length (ms)" -class TMED(TextFrame): "Source Media Type" -class TMOO(TextFrame): "Mood" -class TOAL(TextFrame): "Original Album" -class TOFN(TextFrame): "Original Filename" -class TOLY(TextFrame): "Original Lyricist" -class TOPE(TextFrame): "Original Artist/Performer" -class TORY(NumericTextFrame): "Original Release Year" -class TOWN(TextFrame): "Owner/Licensee" -class TPE1(TextFrame): "Lead Artist/Performer/Soloist/Group" -class TPE2(TextFrame): "Band/Orchestra/Accompaniment" -class TPE3(TextFrame): "Conductor" -class TPE4(TextFrame): "Interpreter/Remixer/Modifier" -class TPOS(NumericPartTextFrame): "Part of set" -class TPRO(TextFrame): "Produced (P)" -class TPUB(TextFrame): "Publisher" -class TRCK(NumericPartTextFrame): "Track Number" -class TRDA(TextFrame): "Recording Dates" -class TRSN(TextFrame): "Internet Radio Station Name" -class TRSO(TextFrame): "Internet Radio Station Owner" -class TSIZ(NumericTextFrame): "Size of audio data (bytes)" -class TSO2(TextFrame): "iTunes Album Artist Sort" -class TSOA(TextFrame): "Album Sort Order key" -class TSOC(TextFrame): "iTunes Composer Sort" -class TSOP(TextFrame): "Perfomer Sort Order key" -class TSOT(TextFrame): "Title Sort Order key" -class TSRC(TextFrame): "International Standard Recording Code (ISRC)" -class TSSE(TextFrame): "Encoder settings" -class TSST(TextFrame): "Set Subtitle" -class TYER(NumericTextFrame): "Year of recording" - -class TXXX(TextFrame): - """User-defined text data. - - TXXX frames have a 'desc' attribute which is set to any Unicode - value (though the encoding of the text and the description must be - the same). Many taggers use this frame to store freeform keys. - """ - _framespec = [ EncodingSpec('encoding'), EncodedTextSpec('desc'), - MultiSpec('text', EncodedTextSpec('text'), sep=u'\u0000') ] - HashKey = property(lambda s: '%s:%s' % (s.FrameID, s.desc)) - def _pprint(self): return "%s=%s" % (self.desc, " / ".join(self.text)) - -class WCOM(UrlFrameU): "Commercial Information" -class WCOP(UrlFrame): "Copyright Information" -class WOAF(UrlFrame): "Official File Information" -class WOAR(UrlFrameU): "Official Artist/Performer Information" -class WOAS(UrlFrame): "Official Source Information" -class WORS(UrlFrame): "Official Internet Radio Information" -class WPAY(UrlFrame): "Payment Information" -class WPUB(UrlFrame): "Official Publisher Information" - -class WXXX(UrlFrame): - """User-defined URL data. - - Like TXXX, this has a freeform description associated with it. - """ - _framespec = [ EncodingSpec('encoding'), EncodedTextSpec('desc'), - Latin1TextSpec('url') ] - HashKey = property(lambda s: '%s:%s' % (s.FrameID, s.desc)) - -class PairedTextFrame(Frame): - """Paired text strings. - - Some ID3 frames pair text strings, to associate names with a more - specific involvement in the song. The 'people' attribute of these - frames contains a list of pairs: - [['trumpet', 'Miles Davis'], ['bass', 'Paul Chambers']] - - Like text frames, these frames also have an encoding attribute. - """ - - _framespec = [ EncodingSpec('encoding'), MultiSpec('people', - EncodedTextSpec('involvement'), EncodedTextSpec('person')) ] - def __eq__(self, other): - return self.people == other - -class TIPL(PairedTextFrame): "Involved People List" -class TMCL(PairedTextFrame): "Musicians Credits List" -class IPLS(TIPL): "Involved People List" - -class MCDI(Frame): - """Binary dump of CD's TOC. - - The 'data' attribute contains the raw byte string. - """ - _framespec = [ BinaryDataSpec('data') ] - def __eq__(self, other): return self.data == other - -class ETCO(Frame): - """Event timing codes.""" - _framespec = [ ByteSpec("format"), KeyEventSpec("events") ] - def __eq__(self, other): return self.events == other - -class MLLT(Frame): - """MPEG location lookup table. - - This frame's attributes may be changed in the future based on - feedback from real-world use. - """ - _framespec = [ SizedIntegerSpec('frames', 2), - SizedIntegerSpec('bytes', 3), - SizedIntegerSpec('milliseconds', 3), - ByteSpec('bits_for_bytes'), - ByteSpec('bits_for_milliseconds'), - BinaryDataSpec('data') ] - def __eq__(self, other): return self.data == other - -class SYTC(Frame): - """Synchronised tempo codes. - - This frame's attributes may be changed in the future based on - feedback from real-world use. - """ - _framespec = [ ByteSpec("format"), BinaryDataSpec("data") ] - def __eq__(self, other): return self.data == other - -class USLT(Frame): - """Unsynchronised lyrics/text transcription. - - Lyrics have a three letter ISO language code ('lang'), a - description ('desc'), and a block of plain text ('text'). - """ - - _framespec = [ EncodingSpec('encoding'), StringSpec('lang', 3), - EncodedTextSpec('desc'), EncodedTextSpec('text') ] - HashKey = property(lambda s: '%s:%s:%r' % (s.FrameID, s.desc, s.lang)) - - def __str__(self): return self.text.encode('utf-8') - def __unicode__(self): return self.text - def __eq__(self, other): return self.text == other - -class SYLT(Frame): - """Synchronised lyrics/text.""" - - _framespec = [ EncodingSpec('encoding'), StringSpec('lang', 3), - ByteSpec('format'), ByteSpec('type'), EncodedTextSpec('desc'), - SynchronizedTextSpec('text') ] - HashKey = property(lambda s: '%s:%s:%r' % (s.FrameID, s.desc, s.lang)) - - def __eq__(self, other): - return str(self) == other - - def __str__(self): - return "".join([text for (text, time) in self.text]).encode('utf-8') - -class COMM(TextFrame): - """User comment. - - User comment frames have a descrption, like TXXX, and also a three - letter ISO language code in the 'lang' attribute. - """ - _framespec = [ EncodingSpec('encoding'), StringSpec('lang', 3), - EncodedTextSpec('desc'), - MultiSpec('text', EncodedTextSpec('text'), sep=u'\u0000') ] - HashKey = property(lambda s: '%s:%s:%r' % (s.FrameID, s.desc, s.lang)) - def _pprint(self): return "%s=%r=%s" % ( - self.desc, self.lang, " / ".join(self.text)) - -class RVA2(Frame): - """Relative volume adjustment (2). - - This frame is used to implemented volume scaling, and in - particular, normalization using ReplayGain. - - Attributes: - desc -- description or context of this adjustment - channel -- audio channel to adjust (master is 1) - gain -- a + or - dB gain relative to some reference level - peak -- peak of the audio as a floating point number, [0, 1] - - When storing ReplayGain tags, use descriptions of 'album' and - 'track' on channel 1. - """ - - _framespec = [ Latin1TextSpec('desc'), ChannelSpec('channel'), - VolumeAdjustmentSpec('gain'), VolumePeakSpec('peak') ] - _channels = ["Other", "Master volume", "Front right", "Front left", - "Back right", "Back left", "Front centre", "Back centre", - "Subwoofer"] - HashKey = property(lambda s: '%s:%s' % (s.FrameID, s.desc)) - - def __eq__(self, other): - return ((str(self) == other) or - (self.desc == other.desc and - self.channel == other.channel and - self.gain == other.gain and - self.peak == other.peak)) - - def __str__(self): - return "%s: %+0.4f dB/%0.4f" % ( - self._channels[self.channel], self.gain, self.peak) - -class EQU2(Frame): - """Equalisation (2). - - Attributes: - method -- interpolation method (0 = band, 1 = linear) - desc -- identifying description - adjustments -- list of (frequency, vol_adjustment) pairs - """ - _framespec = [ ByteSpec("method"), Latin1TextSpec("desc"), - VolumeAdjustmentsSpec("adjustments") ] - def __eq__(self, other): return self.adjustments == other - HashKey = property(lambda s: '%s:%s' % (s.FrameID, s.desc)) - -# class RVAD: unsupported -# class EQUA: unsupported - -class RVRB(Frame): - """Reverb.""" - _framespec = [ SizedIntegerSpec('left', 2), SizedIntegerSpec('right', 2), - ByteSpec('bounce_left'), ByteSpec('bounce_right'), - ByteSpec('feedback_ltl'), ByteSpec('feedback_ltr'), - ByteSpec('feedback_rtr'), ByteSpec('feedback_rtl'), - ByteSpec('premix_ltr'), ByteSpec('premix_rtl') ] - - def __eq__(self, other): return (self.left, self.right) == other - -class APIC(Frame): - """Attached (or linked) Picture. - - Attributes: - encoding -- text encoding for the description - mime -- a MIME type (e.g. image/jpeg) or '-->' if the data is a URI - type -- the source of the image (3 is the album front cover) - desc -- a text description of the image - data -- raw image data, as a byte string - - Mutagen will automatically compress large images when saving tags. - """ - _framespec = [ EncodingSpec('encoding'), Latin1TextSpec('mime'), - ByteSpec('type'), EncodedTextSpec('desc'), BinaryDataSpec('data') ] - def __eq__(self, other): return self.data == other - HashKey = property(lambda s: '%s:%s' % (s.FrameID, s.desc)) - def _pprint(self): - return "%s (%s, %d bytes)" % ( - self.desc, self.mime, len(self.data)) - -class PCNT(Frame): - """Play counter. - - The 'count' attribute contains the (recorded) number of times this - file has been played. - - This frame is basically obsoleted by POPM. - """ - _framespec = [ IntegerSpec('count') ] - - def __eq__(self, other): return self.count == other - def __pos__(self): return self.count - def _pprint(self): return unicode(self.count) - -class POPM(FrameOpt): - """Popularimeter. - - This frame keys a rating (out of 255) and a play count to an email - address. - - Attributes: - email -- email this POPM frame is for - rating -- rating from 0 to 255 - count -- number of times the files has been played (optional) - """ - _framespec = [ Latin1TextSpec('email'), ByteSpec('rating') ] - _optionalspec = [ IntegerSpec('count') ] - - HashKey = property(lambda s: '%s:%s' % (s.FrameID, s.email)) - - def __eq__(self, other): return self.rating == other - def __pos__(self): return self.rating - def _pprint(self): return "%s=%r %r/255" % ( - self.email, getattr(self, 'count', None), self.rating) - -class GEOB(Frame): - """General Encapsulated Object. - - A blob of binary data, that is not a picture (those go in APIC). - - Attributes: - encoding -- encoding of the description - mime -- MIME type of the data or '-->' if the data is a URI - filename -- suggested filename if extracted - desc -- text description of the data - data -- raw data, as a byte string - """ - _framespec = [ EncodingSpec('encoding'), Latin1TextSpec('mime'), - EncodedTextSpec('filename'), EncodedTextSpec('desc'), - BinaryDataSpec('data') ] - HashKey = property(lambda s: '%s:%s' % (s.FrameID, s.desc)) - - def __eq__(self, other): return self.data == other - -class RBUF(FrameOpt): - """Recommended buffer size. - - Attributes: - size -- recommended buffer size in bytes - info -- if ID3 tags may be elsewhere in the file (optional) - offset -- the location of the next ID3 tag, if any - - Mutagen will not find the next tag itself. - """ - _framespec = [ SizedIntegerSpec('size', 3) ] - _optionalspec = [ ByteSpec('info'), SizedIntegerSpec('offset', 4) ] - - def __eq__(self, other): return self.size == other - def __pos__(self): return self.size - -class AENC(FrameOpt): - """Audio encryption. - - Attributes: - owner -- key identifying this encryption type - preview_start -- unencrypted data block offset - preview_length -- number of unencrypted blocks - data -- data required for decryption (optional) - - Mutagen cannot decrypt files. - """ - _framespec = [ Latin1TextSpec('owner'), - SizedIntegerSpec('preview_start', 2), - SizedIntegerSpec('preview_length', 2) ] - _optionalspec = [ BinaryDataSpec('data') ] - HashKey = property(lambda s: '%s:%s' % (s.FrameID, s.owner)) - - def __str__(self): return self.owner.encode('utf-8') - def __unicode__(self): return self.owner - def __eq__(self, other): return self.owner == other - -class LINK(FrameOpt): - """Linked information. - - Attributes: - frameid -- the ID of the linked frame - url -- the location of the linked frame - data -- further ID information for the frame - """ - - _framespec = [ StringSpec('frameid', 4), Latin1TextSpec('url') ] - _optionalspec = [ BinaryDataSpec('data') ] - def __HashKey(self): - try: - return "%s:%s:%s:%r" % ( - self.FrameID, self.frameid, self.url, self.data) - except AttributeError: - return "%s:%s:%s" % (self.FrameID, self.frameid, self.url) - HashKey = property(__HashKey) - def __eq__(self, other): - try: return (self.frameid, self.url, self.data) == other - except AttributeError: return (self.frameid, self.url) == other - -class POSS(Frame): - """Position synchronisation frame - - Attribute: - format -- format of the position attribute (frames or milliseconds) - position -- current position of the file - """ - _framespec = [ ByteSpec('format'), IntegerSpec('position') ] - - def __pos__(self): return self.position - def __eq__(self, other): return self.position == other - -class UFID(Frame): - """Unique file identifier. - - Attributes: - owner -- format/type of identifier - data -- identifier - """ - - _framespec = [ Latin1TextSpec('owner'), BinaryDataSpec('data') ] - HashKey = property(lambda s: '%s:%s' % (s.FrameID, s.owner)) - def __eq__(s, o): - if isinstance(o, UFI): return s.owner == o.owner and s.data == o.data - else: return s.data == o - def _pprint(self): - isascii = ord(max(self.data)) < 128 - if isascii: return "%s=%s" % (self.owner, self.data) - else: return "%s (%d bytes)" % (self.owner, len(self.data)) - -class USER(Frame): - """Terms of use. - - Attributes: - encoding -- text encoding - lang -- ISO three letter language code - text -- licensing terms for the audio - """ - _framespec = [ EncodingSpec('encoding'), StringSpec('lang', 3), - EncodedTextSpec('text') ] - HashKey = property(lambda s: '%s:%r' % (s.FrameID, s.lang)) - - def __str__(self): return self.text.encode('utf-8') - def __unicode__(self): return self.text - def __eq__(self, other): return self.text == other - def _pprint(self): return "%r=%s" % (self.lang, self.text) - -class OWNE(Frame): - """Ownership frame.""" - _framespec = [ EncodingSpec('encoding'), Latin1TextSpec('price'), - StringSpec('date', 8), EncodedTextSpec('seller') ] - - def __str__(self): return self.seller.encode('utf-8') - def __unicode__(self): return self.seller - def __eq__(self, other): return self.seller == other - -class COMR(FrameOpt): - """Commercial frame.""" - _framespec = [ EncodingSpec('encoding'), Latin1TextSpec('price'), - StringSpec('valid_until', 8), Latin1TextSpec('contact'), - ByteSpec('format'), EncodedTextSpec('seller'), - EncodedTextSpec('desc')] - _optionalspec = [ Latin1TextSpec('mime'), BinaryDataSpec('logo') ] - HashKey = property(lambda s: '%s:%s' % (s.FrameID, s._writeData())) - def __eq__(self, other): return self._writeData() == other._writeData() - -class ENCR(Frame): - """Encryption method registration. - - The standard does not allow multiple ENCR frames with the same owner - or the same method. Mutagen only verifies that the owner is unique. - """ - _framespec = [ Latin1TextSpec('owner'), ByteSpec('method'), - BinaryDataSpec('data') ] - HashKey = property(lambda s: "%s:%s" % (s.FrameID, s.owner)) - def __str__(self): return self.data - def __eq__(self, other): return self.data == other - -class GRID(FrameOpt): - """Group identification registration.""" - _framespec = [ Latin1TextSpec('owner'), ByteSpec('group') ] - _optionalspec = [ BinaryDataSpec('data') ] - HashKey = property(lambda s: '%s:%s' % (s.FrameID, s.group)) - def __pos__(self): return self.group - def __str__(self): return self.owner.encode('utf-8') - def __unicode__(self): return self.owner - def __eq__(self, other): return self.owner == other or self.group == other - - -class PRIV(Frame): - """Private frame.""" - _framespec = [ Latin1TextSpec('owner'), BinaryDataSpec('data') ] - HashKey = property(lambda s: '%s:%s:%s' % ( - s.FrameID, s.owner, s.data.decode('latin1'))) - def __str__(self): return self.data - def __eq__(self, other): return self.data == other - def _pprint(self): - isascii = ord(max(self.data)) < 128 - if isascii: return "%s=%s" % (self.owner, self.data) - else: return "%s (%d bytes)" % (self.owner, len(self.data)) - -class SIGN(Frame): - """Signature frame.""" - _framespec = [ ByteSpec('group'), BinaryDataSpec('sig') ] - HashKey = property(lambda s: '%s:%c:%s' % (s.FrameID, s.group, s.sig)) - def __str__(self): return self.sig - def __eq__(self, other): return self.sig == other - -class SEEK(Frame): - """Seek frame. - - Mutagen does not find tags at seek offsets. - """ - _framespec = [ IntegerSpec('offset') ] - def __pos__(self): return self.offset - def __eq__(self, other): return self.offset == other - -class ASPI(Frame): - """Audio seek point index. - - Attributes: S, L, N, b, and Fi. For the meaning of these, see - the ID3v2.4 specification. Fi is a list of integers. - """ - _framespec = [ SizedIntegerSpec("S", 4), SizedIntegerSpec("L", 4), - SizedIntegerSpec("N", 2), ByteSpec("b"), - ASPIIndexSpec("Fi") ] - def __eq__(self, other): return self.Fi == other - -Frames = dict([(k,v) for (k,v) in globals().items() - if len(k)==4 and isinstance(v, type) and issubclass(v, Frame)]) -"""All supported ID3v2 frames, keyed by frame name.""" -del(k); del(v) - -# ID3v2.2 frames -class UFI(UFID): "Unique File Identifier" - -class TT1(TIT1): "Content group description" -class TT2(TIT2): "Title" -class TT3(TIT3): "Subtitle/Description refinement" -class TP1(TPE1): "Lead Artist/Performer/Soloist/Group" -class TP2(TPE2): "Band/Orchestra/Accompaniment" -class TP3(TPE3): "Conductor" -class TP4(TPE4): "Interpreter/Remixer/Modifier" -class TCM(TCOM): "Composer" -class TXT(TEXT): "Lyricist" -class TLA(TLAN): "Audio Language(s)" -class TCO(TCON): "Content Type (Genre)" -class TAL(TALB): "Album" -class TPA(TPOS): "Part of set" -class TRK(TRCK): "Track Number" -class TRC(TSRC): "International Standard Recording Code (ISRC)" -class TYE(TYER): "Year of recording" -class TDA(TDAT): "Date of recording (DDMM)" -class TIM(TIME): "Time of recording (HHMM)" -class TRD(TRDA): "Recording Dates" -class TMT(TMED): "Source Media Type" -class TFT(TFLT): "File Type" -class TBP(TBPM): "Beats per minute" -class TCP(TCMP): "iTunes Compilation Flag" -class TCR(TCOP): "Copyright (C)" -class TPB(TPUB): "Publisher" -class TEN(TENC): "Encoder" -class TSS(TSSE): "Encoder settings" -class TOF(TOFN): "Original Filename" -class TLE(TLEN): "Audio Length (ms)" -class TSI(TSIZ): "Audio Data size (bytes)" -class TDY(TDLY): "Audio Delay (ms)" -class TKE(TKEY): "Starting Key" -class TOT(TOAL): "Original Album" -class TOA(TOPE): "Original Artist/Perfomer" -class TOL(TOLY): "Original Lyricist" -class TOR(TORY): "Original Release Year" - -class TXX(TXXX): "User-defined Text" - -class WAF(WOAF): "Official File Information" -class WAR(WOAR): "Official Artist/Performer Information" -class WAS(WOAS): "Official Source Information" -class WCM(WCOM): "Commercial Information" -class WCP(WCOP): "Copyright Information" -class WPB(WPUB): "Official Publisher Information" - -class WXX(WXXX): "User-defined URL" - -class IPL(IPLS): "Involved people list" -class MCI(MCDI): "Binary dump of CD's TOC" -class ETC(ETCO): "Event timing codes" -class MLL(MLLT): "MPEG location lookup table" -class STC(SYTC): "Synced tempo codes" -class ULT(USLT): "Unsychronised lyrics/text transcription" -class SLT(SYLT): "Synchronised lyrics/text" -class COM(COMM): "Comment" -#class RVA(RVAD) -#class EQU(EQUA) -class REV(RVRB): "Reverb" -class PIC(APIC): - """Attached Picture. - - The 'mime' attribute of an ID3v2.2 attached picture must be either - 'PNG' or 'JPG'. - """ - _framespec = [ EncodingSpec('encoding'), StringSpec('mime', 3), - ByteSpec('type'), EncodedTextSpec('desc'), BinaryDataSpec('data') ] -class GEO(GEOB): "General Encapsulated Object" -class CNT(PCNT): "Play counter" -class POP(POPM): "Popularimeter" -class BUF(RBUF): "Recommended buffer size" - -class CRM(Frame): - """Encrypted meta frame""" - _framespec = [ Latin1TextSpec('owner'), Latin1TextSpec('desc'), - BinaryDataSpec('data') ] - def __eq__(self, other): return self.data == other - -class CRA(AENC): "Audio encryption" - -class LNK(LINK): - """Linked information""" - _framespec = [ StringSpec('frameid', 3), Latin1TextSpec('url') ] - _optionalspec = [ BinaryDataSpec('data') ] - -Frames_2_2 = dict([(k,v) for (k,v) in globals().items() - if len(k)==3 and isinstance(v, type) and issubclass(v, Frame)]) - -# support open(filename) as interface -Open = ID3 - -# ID3v1.1 support. -def ParseID3v1(string): - """Parse an ID3v1 tag, returning a list of ID3v2.4 frames.""" - from struct import error as StructError - frames = {} - try: - tag, title, artist, album, year, comment, track, genre = unpack( - "3s30s30s30s4s29sBB", string) - except StructError: return None - - if tag != "TAG": return None - def fix(string): - return string.split("\x00")[0].strip().decode('latin1') - title, artist, album, year, comment = map( - fix, [title, artist, album, year, comment]) - - if title: frames["TIT2"] = TIT2(encoding=0, text=title) - if artist: frames["TPE1"] = TPE1(encoding=0, text=[artist]) - if album: frames["TALB"] = TALB(encoding=0, text=album) - if year: frames["TDRC"] = TDRC(encoding=0, text=year) - if comment: frames["COMM"] = COMM( - encoding=0, lang="eng", desc="ID3v1 Comment", text=comment) - # Don't read a track number if it looks like the comment was - # padded with spaces instead of nulls (thanks, WinAmp). - if track and (track != 32 or string[-3] == '\x00'): - frames["TRCK"] = TRCK(encoding=0, text=str(track)) - if genre != 255: frames["TCON"] = TCON(encoding=0, text=str(genre)) - return frames - -def MakeID3v1(id3): - """Return an ID3v1.1 tag string from a dict of ID3v2.4 frames.""" - - v1 = {} - - for v2id, name in {"TIT2": "title", "TPE1": "artist", - "TALB": "album"}.items(): - if v2id in id3: - text = id3[v2id].text[0].encode('latin1', 'replace')[:30] - else: - text = "" - v1[name] = text + ("\x00" * (30 - len(text))) - - if "COMM" in id3: - cmnt = id3["COMM"].text[0].encode('latin1', 'replace')[:28] - else: cmnt = "" - v1["comment"] = cmnt + ("\x00" * (29 - len(cmnt))) - - if "TRCK" in id3: - try: v1["track"] = chr(+id3["TRCK"]) - except ValueError: v1["track"] = "\x00" - else: v1["track"] = "\x00" - - if "TCON" in id3: - try: genre = id3["TCON"].genres[0] - except IndexError: pass - else: - if genre in TCON.GENRES: - v1["genre"] = chr(TCON.GENRES.index(genre)) - if "genre" not in v1: v1["genre"] = "\xff" - - if "TDRC" in id3: - v1["year"] = str(id3["TDRC"])[:4] - elif "TYER" in id3: - v1["year"] = str(id3["TYER"])[:4] - else: - v1["year"] = "\x00\x00\x00\x00" - - return ("TAG%(title)s%(artist)s%(album)s%(year)s%(comment)s" - "%(track)s%(genre)s") % v1 - -class ID3FileType(lib.mutagen.FileType): - """An unknown type of file with ID3 tags.""" - - ID3 = ID3 - - class _Info(object): - length = 0 - def __init__(self, fileobj, offset): pass - pprint = staticmethod(lambda: "Unknown format with ID3 tag") - - def score(filename, fileobj, header): - return header.startswith("ID3") - score = staticmethod(score) - - def add_tags(self, ID3=None): - """Add an empty ID3 tag to the file. - - A custom tag reader may be used in instead of the default - mutagen.id3.ID3 object, e.g. an EasyID3 reader. - """ - if ID3 is None: - ID3 = self.ID3 - if self.tags is None: - self.tags = ID3() - else: - raise error("an ID3 tag already exists") - - def load(self, filename, ID3=None, **kwargs): - """Load stream and tag information from a file. - - A custom tag reader may be used in instead of the default - mutagen.id3.ID3 object, e.g. an EasyID3 reader. - """ - if ID3 is None: - ID3 = self.ID3 - self.filename = filename - try: self.tags = ID3(filename, **kwargs) - except error: self.tags = None - if self.tags is not None: - try: offset = self.tags.size - except AttributeError: offset = None - else: offset = None - try: - fileobj = file(filename, "rb") - self.info = self._Info(fileobj, offset) - finally: - fileobj.close() diff --git a/lib/mutagen/musepack.py b/lib/mutagen/musepack.py deleted file mode 100644 index f5b347da..00000000 --- a/lib/mutagen/musepack.py +++ /dev/null @@ -1,118 +0,0 @@ -# A Musepack reader/tagger -# -# Copyright 2006 Lukas Lalinsky -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -# $Id: musepack.py 4013 2007-04-23 09:18:22Z luks $ - -"""Musepack audio streams with APEv2 tags. - -Musepack is an audio format originally based on the MPEG-1 Layer-2 -algorithms. Stream versions 4 through 7 are supported. - -For more information, see http://www.musepack.net/. -""" - -__all__ = ["Musepack", "Open", "delete"] - -import struct - -from lib.mutagen.apev2 import APEv2File, error, delete -from lib.mutagen.id3 import BitPaddedInt -from lib.mutagen._util import cdata - -class MusepackHeaderError(error): pass - -RATES = [44100, 48000, 37800, 32000] - -class MusepackInfo(object): - """Musepack stream information. - - Attributes: - channels -- number of audio channels - length -- file length in seconds, as a float - sample_rate -- audio sampling rate in Hz - bitrate -- audio bitrate, in bits per second - version -- Musepack stream version - - Optional Attributes: - title_gain, title_peak -- Replay Gain and peak data for this song - album_gain, album_peak -- Replay Gain and peak data for this album - - These attributes are only available in stream version 7. The - gains are a float, +/- some dB. The peaks are a percentage [0..1] of - the maximum amplitude. This means to get a number comparable to - VorbisGain, you must multiply the peak by 2. - """ - - def __init__(self, fileobj): - header = fileobj.read(32) - if len(header) != 32: - raise MusepackHeaderError("not a Musepack file") - # Skip ID3v2 tags - if header[:3] == "ID3": - size = 10 + BitPaddedInt(header[6:10]) - fileobj.seek(size) - header = fileobj.read(32) - if len(header) != 32: - raise MusepackHeaderError("not a Musepack file") - # SV7 - if header.startswith("MP+"): - self.version = ord(header[3]) & 0xF - if self.version < 7: - raise MusepackHeaderError("not a Musepack file") - frames = cdata.uint_le(header[4:8]) - flags = cdata.uint_le(header[8:12]) - - self.title_peak, self.title_gain = struct.unpack( - "> 16) & 0x0003] - self.bitrate = 0 - # SV4-SV6 - else: - header_dword = cdata.uint_le(header[0:4]) - self.version = (header_dword >> 11) & 0x03FF; - if self.version < 4 or self.version > 6: - raise MusepackHeaderError("not a Musepack file") - self.bitrate = (header_dword >> 23) & 0x01FF; - self.sample_rate = 44100 - if self.version >= 5: - frames = cdata.uint_le(header[4:8]) - else: - frames = cdata.ushort_le(header[6:8]) - if self.version < 6: - frames -= 1 - self.channels = 2 - self.length = float(frames * 1152 - 576) / self.sample_rate - if not self.bitrate and self.length != 0: - fileobj.seek(0, 2) - self.bitrate = int(fileobj.tell() * 8 / (self.length * 1000) + 0.5) - - def pprint(self): - if self.version >= 7: - rg_data = ", Gain: %+0.2f (title), %+0.2f (album)" %( - self.title_gain, self.album_gain) - else: - rg_data = "" - return "Musepack, %.2f seconds, %d Hz%s" % ( - self.length, self.sample_rate, rg_data) - -class Musepack(APEv2File): - _Info = MusepackInfo - _mimes = ["audio/x-musepack", "audio/x-mpc"] - - def score(filename, fileobj, header): - return header.startswith("MP+") + filename.endswith(".mpc") - score = staticmethod(score) - -Open = Musepack diff --git a/lib/unidecode/__init__.py b/lib/unidecode/__init__.py new file mode 100644 index 00000000..82eb5a3f --- /dev/null +++ b/lib/unidecode/__init__.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +"""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 unidecode(string): + """Transliterate an Unicode object into an ASCII string + + >>> unidecode(u"\u5317\u4EB0") + "Bei Jing " + """ + + 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) + + 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 + + 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), [], [], ['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/lib/unidecode/x000.py b/lib/unidecode/x000.py new file mode 100644 index 00000000..6821df47 --- /dev/null +++ b/lib/unidecode/x000.py @@ -0,0 +1,258 @@ +data = ( +'\x00', # 0x00 +'\x01', # 0x01 +'\x02', # 0x02 +'\x03', # 0x03 +'\x04', # 0x04 +'\x05', # 0x05 +'\x06', # 0x06 +'\x07', # 0x07 +'\x08', # 0x08 +'\x09', # 0x09 +'\x0a', # 0x0a +'\x0b', # 0x0b +'\x0c', # 0x0c +'\x0d', # 0x0d +'\x0e', # 0x0e +'\x0f', # 0x0f +'\x10', # 0x10 +'\x11', # 0x11 +'\x12', # 0x12 +'\x13', # 0x13 +'\x14', # 0x14 +'\x15', # 0x15 +'\x16', # 0x16 +'\x17', # 0x17 +'\x18', # 0x18 +'\x19', # 0x19 +'\x1a', # 0x1a +'\x1b', # 0x1b +'\x1c', # 0x1c +'\x1d', # 0x1d +'\x1e', # 0x1e +'\x1f', # 0x1f +' ', # 0x20 +'!', # 0x21 +'"', # 0x22 +'#', # 0x23 +'$', # 0x24 +'%', # 0x25 +'&', # 0x26 +'\'', # 0x27 +'(', # 0x28 +')', # 0x29 +'*', # 0x2a +'+', # 0x2b +',', # 0x2c +'-', # 0x2d +'.', # 0x2e +'/', # 0x2f +'0', # 0x30 +'1', # 0x31 +'2', # 0x32 +'3', # 0x33 +'4', # 0x34 +'5', # 0x35 +'6', # 0x36 +'7', # 0x37 +'8', # 0x38 +'9', # 0x39 +':', # 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 +'a', # 0x61 +'b', # 0x62 +'c', # 0x63 +'d', # 0x64 +'e', # 0x65 +'f', # 0x66 +'g', # 0x67 +'h', # 0x68 +'i', # 0x69 +'j', # 0x6a +'k', # 0x6b +'l', # 0x6c +'m', # 0x6d +'n', # 0x6e +'o', # 0x6f +'p', # 0x70 +'q', # 0x71 +'r', # 0x72 +'s', # 0x73 +'t', # 0x74 +'u', # 0x75 +'v', # 0x76 +'w', # 0x77 +'x', # 0x78 +'y', # 0x79 +'z', # 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 +'C/', # 0xa2 +'PS', # 0xa3 +'$?', # 0xa4 +'Y=', # 0xa5 +'|', # 0xa6 +'SS', # 0xa7 +'"', # 0xa8 +'(c)', # 0xa9 +'a', # 0xaa +'<<', # 0xab +'!', # 0xac +'', # 0xad +'(r)', # 0xae +'-', # 0xaf +'deg', # 0xb0 +'+-', # 0xb1 +'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 +'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 +'O', # 0xd6 +'x', # 0xd7 +'O', # 0xd8 +'U', # 0xd9 +'U', # 0xda +'U', # 0xdb +'U', # 0xdc +'Y', # 0xdd +'Th', # 0xde +'ss', # 0xdf +'a', # 0xe0 +'a', # 0xe1 +'a', # 0xe2 +'a', # 0xe3 +'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 +'o', # 0xf6 +'/', # 0xf7 +'o', # 0xf8 +'u', # 0xf9 +'u', # 0xfa +'u', # 0xfb +'u', # 0xfc +'y', # 0xfd +'th', # 0xfe +'y', # 0xff +) diff --git a/lib/unidecode/x001.py b/lib/unidecode/x001.py new file mode 100644 index 00000000..212c2d1a --- /dev/null +++ b/lib/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/lib/unidecode/x002.py b/lib/unidecode/x002.py new file mode 100644 index 00000000..ea45441e --- /dev/null +++ b/lib/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/lib/unidecode/x003.py b/lib/unidecode/x003.py new file mode 100644 index 00000000..4ba8d726 --- /dev/null +++ b/lib/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/lib/unidecode/x004.py b/lib/unidecode/x004.py new file mode 100644 index 00000000..1cc3dbc4 --- /dev/null +++ b/lib/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/lib/unidecode/x005.py b/lib/unidecode/x005.py new file mode 100644 index 00000000..2913ffff --- /dev/null +++ b/lib/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/lib/unidecode/x006.py b/lib/unidecode/x006.py new file mode 100644 index 00000000..09440b28 --- /dev/null +++ b/lib/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/lib/unidecode/x007.py b/lib/unidecode/x007.py new file mode 100644 index 00000000..d2c00213 --- /dev/null +++ b/lib/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/lib/unidecode/x009.py b/lib/unidecode/x009.py new file mode 100644 index 00000000..564ec784 --- /dev/null +++ b/lib/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/lib/unidecode/x00a.py b/lib/unidecode/x00a.py new file mode 100644 index 00000000..1ccd9df6 --- /dev/null +++ b/lib/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/lib/unidecode/x00b.py b/lib/unidecode/x00b.py new file mode 100644 index 00000000..19d18488 --- /dev/null +++ b/lib/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/lib/unidecode/x00c.py b/lib/unidecode/x00c.py new file mode 100644 index 00000000..56f3654f --- /dev/null +++ b/lib/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/lib/unidecode/x00d.py b/lib/unidecode/x00d.py new file mode 100644 index 00000000..d105c437 --- /dev/null +++ b/lib/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/lib/unidecode/x00e.py b/lib/unidecode/x00e.py new file mode 100644 index 00000000..775b5f4a --- /dev/null +++ b/lib/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/lib/unidecode/x00f.py b/lib/unidecode/x00f.py new file mode 100644 index 00000000..4c2410e0 --- /dev/null +++ b/lib/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/lib/unidecode/x010.py b/lib/unidecode/x010.py new file mode 100644 index 00000000..aaf820d9 --- /dev/null +++ b/lib/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/lib/unidecode/x011.py b/lib/unidecode/x011.py new file mode 100644 index 00000000..f0d8f929 --- /dev/null +++ b/lib/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/lib/unidecode/x012.py b/lib/unidecode/x012.py new file mode 100644 index 00000000..f2670650 --- /dev/null +++ b/lib/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/lib/unidecode/x013.py b/lib/unidecode/x013.py new file mode 100644 index 00000000..8a8c3f9c --- /dev/null +++ b/lib/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/lib/unidecode/x014.py b/lib/unidecode/x014.py new file mode 100644 index 00000000..e8c01809 --- /dev/null +++ b/lib/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/lib/unidecode/x015.py b/lib/unidecode/x015.py new file mode 100644 index 00000000..5ac22cbe --- /dev/null +++ b/lib/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/lib/unidecode/x016.py b/lib/unidecode/x016.py new file mode 100644 index 00000000..613d1e90 --- /dev/null +++ b/lib/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/lib/unidecode/x017.py b/lib/unidecode/x017.py new file mode 100644 index 00000000..e0a8f447 --- /dev/null +++ b/lib/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/lib/unidecode/x018.py b/lib/unidecode/x018.py new file mode 100644 index 00000000..3162a010 --- /dev/null +++ b/lib/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/lib/unidecode/x01d.py b/lib/unidecode/x01d.py new file mode 100644 index 00000000..5b659060 --- /dev/null +++ b/lib/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/lib/unidecode/x01e.py b/lib/unidecode/x01e.py new file mode 100644 index 00000000..606576b6 --- /dev/null +++ b/lib/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/lib/unidecode/x01f.py b/lib/unidecode/x01f.py new file mode 100644 index 00000000..bcd2dec5 --- /dev/null +++ b/lib/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/lib/unidecode/x020.py b/lib/unidecode/x020.py new file mode 100644 index 00000000..f67264c8 --- /dev/null +++ b/lib/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 +'EU', # 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/lib/unidecode/x021.py b/lib/unidecode/x021.py new file mode 100644 index 00000000..fcb651ba --- /dev/null +++ b/lib/unidecode/x021.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 +'(sm)', # 0x20 +'TEL', # 0x21 +'(tm)', # 0x22 +'', # 0x23 +'', # 0x24 +'', # 0x25 +'', # 0x26 +'', # 0x27 +'', # 0x28 +'', # 0x29 +'K', # 0x2a +'A', # 0x2b +'', # 0x2c +'', # 0x2d +'', # 0x2e +'', # 0x2f +'', # 0x30 +'', # 0x31 +'F', # 0x32 +'', # 0x33 +'', # 0x34 +'', # 0x35 +'', # 0x36 +'', # 0x37 +'', # 0x38 +'', # 0x39 +'', # 0x3a +'FAX', # 0x3b +'[?]', # 0x3c +'[?]', # 0x3d +'[?]', # 0x3e +'[?]', # 0x3f +'[?]', # 0x40 +'[?]', # 0x41 +'[?]', # 0x42 +'[?]', # 0x43 +'[?]', # 0x44 +'[?]', # 0x45 +'[?]', # 0x46 +'[?]', # 0x47 +'[?]', # 0x48 +'[?]', # 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/lib/unidecode/x022.py b/lib/unidecode/x022.py new file mode 100644 index 00000000..e38fb5cc --- /dev/null +++ b/lib/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/lib/unidecode/x023.py b/lib/unidecode/x023.py new file mode 100644 index 00000000..3c4462e2 --- /dev/null +++ b/lib/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/lib/unidecode/x024.py b/lib/unidecode/x024.py new file mode 100644 index 00000000..20b3c8f1 --- /dev/null +++ b/lib/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/lib/unidecode/x025.py b/lib/unidecode/x025.py new file mode 100644 index 00000000..5a62b10d --- /dev/null +++ b/lib/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/lib/unidecode/x026.py b/lib/unidecode/x026.py new file mode 100644 index 00000000..c575472c --- /dev/null +++ b/lib/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/lib/unidecode/x027.py b/lib/unidecode/x027.py new file mode 100644 index 00000000..3c74c073 --- /dev/null +++ b/lib/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/lib/unidecode/x028.py b/lib/unidecode/x028.py new file mode 100644 index 00000000..dc2f3f05 --- /dev/null +++ b/lib/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/lib/unidecode/x029.py b/lib/unidecode/x029.py new file mode 100644 index 00000000..c2df2548 --- /dev/null +++ b/lib/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/lib/unidecode/x02a.py b/lib/unidecode/x02a.py new file mode 100644 index 00000000..b832ef35 --- /dev/null +++ b/lib/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/lib/unidecode/x02c.py b/lib/unidecode/x02c.py new file mode 100644 index 00000000..0d05d069 --- /dev/null +++ b/lib/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/lib/unidecode/x02e.py b/lib/unidecode/x02e.py new file mode 100644 index 00000000..feaad8d3 --- /dev/null +++ b/lib/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/lib/unidecode/x02f.py b/lib/unidecode/x02f.py new file mode 100644 index 00000000..01f8b15b --- /dev/null +++ b/lib/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/lib/unidecode/x030.py b/lib/unidecode/x030.py new file mode 100644 index 00000000..d65ed4c5 --- /dev/null +++ b/lib/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/lib/unidecode/x031.py b/lib/unidecode/x031.py new file mode 100644 index 00000000..f5576080 --- /dev/null +++ b/lib/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/lib/unidecode/x032.py b/lib/unidecode/x032.py new file mode 100644 index 00000000..30282d4a --- /dev/null +++ b/lib/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/lib/unidecode/x033.py b/lib/unidecode/x033.py new file mode 100644 index 00000000..64eb651a --- /dev/null +++ b/lib/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/lib/unidecode/x04d.py b/lib/unidecode/x04d.py new file mode 100644 index 00000000..b025461a --- /dev/null +++ b/lib/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/lib/unidecode/x04e.py b/lib/unidecode/x04e.py new file mode 100644 index 00000000..e346f67b --- /dev/null +++ b/lib/unidecode/x04e.py @@ -0,0 +1,258 @@ +data = ( +'[?] ', # 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/lib/unidecode/x04f.py b/lib/unidecode/x04f.py new file mode 100644 index 00000000..98c22910 --- /dev/null +++ b/lib/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/lib/unidecode/x050.py b/lib/unidecode/x050.py new file mode 100644 index 00000000..184b87fd --- /dev/null +++ b/lib/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/lib/unidecode/x051.py b/lib/unidecode/x051.py new file mode 100644 index 00000000..c1928354 --- /dev/null +++ b/lib/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/lib/unidecode/x052.py b/lib/unidecode/x052.py new file mode 100644 index 00000000..088f221f --- /dev/null +++ b/lib/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/lib/unidecode/x053.py b/lib/unidecode/x053.py new file mode 100644 index 00000000..fa08b6ef --- /dev/null +++ b/lib/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/lib/unidecode/x054.py b/lib/unidecode/x054.py new file mode 100644 index 00000000..c014e0fe --- /dev/null +++ b/lib/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/lib/unidecode/x055.py b/lib/unidecode/x055.py new file mode 100644 index 00000000..26aea747 --- /dev/null +++ b/lib/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/lib/unidecode/x056.py b/lib/unidecode/x056.py new file mode 100644 index 00000000..30b7fa54 --- /dev/null +++ b/lib/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/lib/unidecode/x057.py b/lib/unidecode/x057.py new file mode 100644 index 00000000..9392fb86 --- /dev/null +++ b/lib/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/lib/unidecode/x058.py b/lib/unidecode/x058.py new file mode 100644 index 00000000..88057182 --- /dev/null +++ b/lib/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/lib/unidecode/x059.py b/lib/unidecode/x059.py new file mode 100644 index 00000000..45966661 --- /dev/null +++ b/lib/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/lib/unidecode/x05a.py b/lib/unidecode/x05a.py new file mode 100644 index 00000000..be56e652 --- /dev/null +++ b/lib/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/lib/unidecode/x05b.py b/lib/unidecode/x05b.py new file mode 100644 index 00000000..1b167b3e --- /dev/null +++ b/lib/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/lib/unidecode/x05c.py b/lib/unidecode/x05c.py new file mode 100644 index 00000000..62957e87 --- /dev/null +++ b/lib/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/lib/unidecode/x05d.py b/lib/unidecode/x05d.py new file mode 100644 index 00000000..c85032aa --- /dev/null +++ b/lib/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/lib/unidecode/x05e.py b/lib/unidecode/x05e.py new file mode 100644 index 00000000..af879280 --- /dev/null +++ b/lib/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/lib/unidecode/x05f.py b/lib/unidecode/x05f.py new file mode 100644 index 00000000..032eab89 --- /dev/null +++ b/lib/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/lib/unidecode/x060.py b/lib/unidecode/x060.py new file mode 100644 index 00000000..ad3728f8 --- /dev/null +++ b/lib/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/lib/unidecode/x061.py b/lib/unidecode/x061.py new file mode 100644 index 00000000..6e8ab80d --- /dev/null +++ b/lib/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/lib/unidecode/x062.py b/lib/unidecode/x062.py new file mode 100644 index 00000000..97979203 --- /dev/null +++ b/lib/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/lib/unidecode/x063.py b/lib/unidecode/x063.py new file mode 100644 index 00000000..896cea25 --- /dev/null +++ b/lib/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/lib/unidecode/x064.py b/lib/unidecode/x064.py new file mode 100644 index 00000000..dc1514b6 --- /dev/null +++ b/lib/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/lib/unidecode/x065.py b/lib/unidecode/x065.py new file mode 100644 index 00000000..ede51764 --- /dev/null +++ b/lib/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/lib/unidecode/x066.py b/lib/unidecode/x066.py new file mode 100644 index 00000000..01898d55 --- /dev/null +++ b/lib/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/lib/unidecode/x067.py b/lib/unidecode/x067.py new file mode 100644 index 00000000..2e863ae0 --- /dev/null +++ b/lib/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/lib/unidecode/x068.py b/lib/unidecode/x068.py new file mode 100644 index 00000000..c562311c --- /dev/null +++ b/lib/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/lib/unidecode/x069.py b/lib/unidecode/x069.py new file mode 100644 index 00000000..7fa8c7de --- /dev/null +++ b/lib/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/lib/unidecode/x06a.py b/lib/unidecode/x06a.py new file mode 100644 index 00000000..12fcabd5 --- /dev/null +++ b/lib/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/lib/unidecode/x06b.py b/lib/unidecode/x06b.py new file mode 100644 index 00000000..56aa7c65 --- /dev/null +++ b/lib/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/lib/unidecode/x06c.py b/lib/unidecode/x06c.py new file mode 100644 index 00000000..a1534e74 --- /dev/null +++ b/lib/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/lib/unidecode/x06d.py b/lib/unidecode/x06d.py new file mode 100644 index 00000000..a9113465 --- /dev/null +++ b/lib/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/lib/unidecode/x06e.py b/lib/unidecode/x06e.py new file mode 100644 index 00000000..d4698fd4 --- /dev/null +++ b/lib/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/lib/unidecode/x06f.py b/lib/unidecode/x06f.py new file mode 100644 index 00000000..36bf2a26 --- /dev/null +++ b/lib/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/lib/unidecode/x070.py b/lib/unidecode/x070.py new file mode 100644 index 00000000..b12567ff --- /dev/null +++ b/lib/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/lib/unidecode/x071.py b/lib/unidecode/x071.py new file mode 100644 index 00000000..bad8f7ea --- /dev/null +++ b/lib/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/lib/unidecode/x072.py b/lib/unidecode/x072.py new file mode 100644 index 00000000..c91c93cb --- /dev/null +++ b/lib/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/lib/unidecode/x073.py b/lib/unidecode/x073.py new file mode 100644 index 00000000..4cf0176d --- /dev/null +++ b/lib/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/lib/unidecode/x074.py b/lib/unidecode/x074.py new file mode 100644 index 00000000..312fc646 --- /dev/null +++ b/lib/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/lib/unidecode/x075.py b/lib/unidecode/x075.py new file mode 100644 index 00000000..a356ac41 --- /dev/null +++ b/lib/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/lib/unidecode/x076.py b/lib/unidecode/x076.py new file mode 100644 index 00000000..fc8b1672 --- /dev/null +++ b/lib/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/lib/unidecode/x077.py b/lib/unidecode/x077.py new file mode 100644 index 00000000..3ed6a36b --- /dev/null +++ b/lib/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/lib/unidecode/x078.py b/lib/unidecode/x078.py new file mode 100644 index 00000000..23d677de --- /dev/null +++ b/lib/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/lib/unidecode/x079.py b/lib/unidecode/x079.py new file mode 100644 index 00000000..ed1c5143 --- /dev/null +++ b/lib/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/lib/unidecode/x07a.py b/lib/unidecode/x07a.py new file mode 100644 index 00000000..b6d512cd --- /dev/null +++ b/lib/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/lib/unidecode/x07b.py b/lib/unidecode/x07b.py new file mode 100644 index 00000000..c904395c --- /dev/null +++ b/lib/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/lib/unidecode/x07c.py b/lib/unidecode/x07c.py new file mode 100644 index 00000000..3379947a --- /dev/null +++ b/lib/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/lib/unidecode/x07d.py b/lib/unidecode/x07d.py new file mode 100644 index 00000000..241db29c --- /dev/null +++ b/lib/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/lib/unidecode/x07e.py b/lib/unidecode/x07e.py new file mode 100644 index 00000000..131ef35c --- /dev/null +++ b/lib/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/lib/unidecode/x07f.py b/lib/unidecode/x07f.py new file mode 100644 index 00000000..0a708d6d --- /dev/null +++ b/lib/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/lib/unidecode/x080.py b/lib/unidecode/x080.py new file mode 100644 index 00000000..11f324b4 --- /dev/null +++ b/lib/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/lib/unidecode/x081.py b/lib/unidecode/x081.py new file mode 100644 index 00000000..01ca95d3 --- /dev/null +++ b/lib/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/lib/unidecode/x082.py b/lib/unidecode/x082.py new file mode 100644 index 00000000..daea2e23 --- /dev/null +++ b/lib/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/lib/unidecode/x083.py b/lib/unidecode/x083.py new file mode 100644 index 00000000..672cd5d8 --- /dev/null +++ b/lib/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/lib/unidecode/x084.py b/lib/unidecode/x084.py new file mode 100644 index 00000000..571a3607 --- /dev/null +++ b/lib/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/lib/unidecode/x085.py b/lib/unidecode/x085.py new file mode 100644 index 00000000..c11c513b --- /dev/null +++ b/lib/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/lib/unidecode/x086.py b/lib/unidecode/x086.py new file mode 100644 index 00000000..38784a61 --- /dev/null +++ b/lib/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/lib/unidecode/x087.py b/lib/unidecode/x087.py new file mode 100644 index 00000000..2a2b79aa --- /dev/null +++ b/lib/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/lib/unidecode/x088.py b/lib/unidecode/x088.py new file mode 100644 index 00000000..f907ce92 --- /dev/null +++ b/lib/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/lib/unidecode/x089.py b/lib/unidecode/x089.py new file mode 100644 index 00000000..d23abc3c --- /dev/null +++ b/lib/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/lib/unidecode/x08a.py b/lib/unidecode/x08a.py new file mode 100644 index 00000000..0b0fa0a6 --- /dev/null +++ b/lib/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/lib/unidecode/x08b.py b/lib/unidecode/x08b.py new file mode 100644 index 00000000..b89c37a2 --- /dev/null +++ b/lib/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/lib/unidecode/x08c.py b/lib/unidecode/x08c.py new file mode 100644 index 00000000..514c446b --- /dev/null +++ b/lib/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/lib/unidecode/x08d.py b/lib/unidecode/x08d.py new file mode 100644 index 00000000..ae63f226 --- /dev/null +++ b/lib/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/lib/unidecode/x08e.py b/lib/unidecode/x08e.py new file mode 100644 index 00000000..015ed1ea --- /dev/null +++ b/lib/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/lib/unidecode/x08f.py b/lib/unidecode/x08f.py new file mode 100644 index 00000000..39d04a9c --- /dev/null +++ b/lib/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/lib/unidecode/x090.py b/lib/unidecode/x090.py new file mode 100644 index 00000000..ade65069 --- /dev/null +++ b/lib/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/lib/unidecode/x091.py b/lib/unidecode/x091.py new file mode 100644 index 00000000..fa3dd766 --- /dev/null +++ b/lib/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/lib/unidecode/x092.py b/lib/unidecode/x092.py new file mode 100644 index 00000000..e752f4fe --- /dev/null +++ b/lib/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/lib/unidecode/x093.py b/lib/unidecode/x093.py new file mode 100644 index 00000000..82857e9a --- /dev/null +++ b/lib/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/lib/unidecode/x094.py b/lib/unidecode/x094.py new file mode 100644 index 00000000..17eb9ddb --- /dev/null +++ b/lib/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/lib/unidecode/x095.py b/lib/unidecode/x095.py new file mode 100644 index 00000000..4b363942 --- /dev/null +++ b/lib/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/lib/unidecode/x096.py b/lib/unidecode/x096.py new file mode 100644 index 00000000..738a4ea3 --- /dev/null +++ b/lib/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/lib/unidecode/x097.py b/lib/unidecode/x097.py new file mode 100644 index 00000000..7255f0f8 --- /dev/null +++ b/lib/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/lib/unidecode/x098.py b/lib/unidecode/x098.py new file mode 100644 index 00000000..98160e77 --- /dev/null +++ b/lib/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/lib/unidecode/x099.py b/lib/unidecode/x099.py new file mode 100644 index 00000000..2adf3de8 --- /dev/null +++ b/lib/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/lib/unidecode/x09a.py b/lib/unidecode/x09a.py new file mode 100644 index 00000000..ed9cd937 --- /dev/null +++ b/lib/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/lib/unidecode/x09b.py b/lib/unidecode/x09b.py new file mode 100644 index 00000000..7fd0a2db --- /dev/null +++ b/lib/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/lib/unidecode/x09c.py b/lib/unidecode/x09c.py new file mode 100644 index 00000000..e7f7937f --- /dev/null +++ b/lib/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/lib/unidecode/x09d.py b/lib/unidecode/x09d.py new file mode 100644 index 00000000..99d5859c --- /dev/null +++ b/lib/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/lib/unidecode/x09e.py b/lib/unidecode/x09e.py new file mode 100644 index 00000000..8a392a23 --- /dev/null +++ b/lib/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/lib/unidecode/x09f.py b/lib/unidecode/x09f.py new file mode 100644 index 00000000..acd59a69 --- /dev/null +++ b/lib/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/lib/unidecode/x0a0.py b/lib/unidecode/x0a0.py new file mode 100644 index 00000000..c25f17bc --- /dev/null +++ b/lib/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/lib/unidecode/x0a1.py b/lib/unidecode/x0a1.py new file mode 100644 index 00000000..185dc8ba --- /dev/null +++ b/lib/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/lib/unidecode/x0a2.py b/lib/unidecode/x0a2.py new file mode 100644 index 00000000..8ea89913 --- /dev/null +++ b/lib/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/lib/unidecode/x0a3.py b/lib/unidecode/x0a3.py new file mode 100644 index 00000000..5e77aec0 --- /dev/null +++ b/lib/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/lib/unidecode/x0a4.py b/lib/unidecode/x0a4.py new file mode 100644 index 00000000..4fb6b264 --- /dev/null +++ b/lib/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/lib/unidecode/x0ac.py b/lib/unidecode/x0ac.py new file mode 100644 index 00000000..e627fab7 --- /dev/null +++ b/lib/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/lib/unidecode/x0ad.py b/lib/unidecode/x0ad.py new file mode 100644 index 00000000..ac2cf2a5 --- /dev/null +++ b/lib/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/lib/unidecode/x0ae.py b/lib/unidecode/x0ae.py new file mode 100644 index 00000000..37a7abca --- /dev/null +++ b/lib/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/lib/unidecode/x0af.py b/lib/unidecode/x0af.py new file mode 100644 index 00000000..448d26bf --- /dev/null +++ b/lib/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/lib/unidecode/x0b0.py b/lib/unidecode/x0b0.py new file mode 100644 index 00000000..20f41b3e --- /dev/null +++ b/lib/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/lib/unidecode/x0b1.py b/lib/unidecode/x0b1.py new file mode 100644 index 00000000..5aabeae2 --- /dev/null +++ b/lib/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/lib/unidecode/x0b2.py b/lib/unidecode/x0b2.py new file mode 100644 index 00000000..8b8aee41 --- /dev/null +++ b/lib/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/lib/unidecode/x0b3.py b/lib/unidecode/x0b3.py new file mode 100644 index 00000000..830915aa --- /dev/null +++ b/lib/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/lib/unidecode/x0b4.py b/lib/unidecode/x0b4.py new file mode 100644 index 00000000..7a6a5aaa --- /dev/null +++ b/lib/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/lib/unidecode/x0b5.py b/lib/unidecode/x0b5.py new file mode 100644 index 00000000..9d4de3df --- /dev/null +++ b/lib/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/lib/unidecode/x0b6.py b/lib/unidecode/x0b6.py new file mode 100644 index 00000000..2800e3bc --- /dev/null +++ b/lib/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/lib/unidecode/x0b7.py b/lib/unidecode/x0b7.py new file mode 100644 index 00000000..483dddeb --- /dev/null +++ b/lib/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/lib/unidecode/x0b8.py b/lib/unidecode/x0b8.py new file mode 100644 index 00000000..5c845ebc --- /dev/null +++ b/lib/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/lib/unidecode/x0b9.py b/lib/unidecode/x0b9.py new file mode 100644 index 00000000..35340dc7 --- /dev/null +++ b/lib/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/lib/unidecode/x0ba.py b/lib/unidecode/x0ba.py new file mode 100644 index 00000000..9ef82940 --- /dev/null +++ b/lib/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/lib/unidecode/x0bb.py b/lib/unidecode/x0bb.py new file mode 100644 index 00000000..b92031be --- /dev/null +++ b/lib/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/lib/unidecode/x0bc.py b/lib/unidecode/x0bc.py new file mode 100644 index 00000000..c0b3f320 --- /dev/null +++ b/lib/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/lib/unidecode/x0bd.py b/lib/unidecode/x0bd.py new file mode 100644 index 00000000..6473883f --- /dev/null +++ b/lib/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/lib/unidecode/x0be.py b/lib/unidecode/x0be.py new file mode 100644 index 00000000..85c184e7 --- /dev/null +++ b/lib/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/lib/unidecode/x0bf.py b/lib/unidecode/x0bf.py new file mode 100644 index 00000000..a7b3a718 --- /dev/null +++ b/lib/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/lib/unidecode/x0c0.py b/lib/unidecode/x0c0.py new file mode 100644 index 00000000..35e50391 --- /dev/null +++ b/lib/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/lib/unidecode/x0c1.py b/lib/unidecode/x0c1.py new file mode 100644 index 00000000..776847f4 --- /dev/null +++ b/lib/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/lib/unidecode/x0c2.py b/lib/unidecode/x0c2.py new file mode 100644 index 00000000..5b799cb6 --- /dev/null +++ b/lib/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/lib/unidecode/x0c3.py b/lib/unidecode/x0c3.py new file mode 100644 index 00000000..bc81d642 --- /dev/null +++ b/lib/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/lib/unidecode/x0c4.py b/lib/unidecode/x0c4.py new file mode 100644 index 00000000..6288ca63 --- /dev/null +++ b/lib/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/lib/unidecode/x0c5.py b/lib/unidecode/x0c5.py new file mode 100644 index 00000000..3f4778e7 --- /dev/null +++ b/lib/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/lib/unidecode/x0c6.py b/lib/unidecode/x0c6.py new file mode 100644 index 00000000..c6eeaeba --- /dev/null +++ b/lib/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/lib/unidecode/x0c7.py b/lib/unidecode/x0c7.py new file mode 100644 index 00000000..4c1a9e13 --- /dev/null +++ b/lib/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/lib/unidecode/x0c8.py b/lib/unidecode/x0c8.py new file mode 100644 index 00000000..2dc75649 --- /dev/null +++ b/lib/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/lib/unidecode/x0c9.py b/lib/unidecode/x0c9.py new file mode 100644 index 00000000..7e098327 --- /dev/null +++ b/lib/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/lib/unidecode/x0ca.py b/lib/unidecode/x0ca.py new file mode 100644 index 00000000..20239b71 --- /dev/null +++ b/lib/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/lib/unidecode/x0cb.py b/lib/unidecode/x0cb.py new file mode 100644 index 00000000..96d9c18b --- /dev/null +++ b/lib/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/lib/unidecode/x0cc.py b/lib/unidecode/x0cc.py new file mode 100644 index 00000000..58f819a0 --- /dev/null +++ b/lib/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/lib/unidecode/x0cd.py b/lib/unidecode/x0cd.py new file mode 100644 index 00000000..dd6909a1 --- /dev/null +++ b/lib/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/lib/unidecode/x0ce.py b/lib/unidecode/x0ce.py new file mode 100644 index 00000000..4b993e89 --- /dev/null +++ b/lib/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/lib/unidecode/x0cf.py b/lib/unidecode/x0cf.py new file mode 100644 index 00000000..e825983e --- /dev/null +++ b/lib/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/lib/unidecode/x0d0.py b/lib/unidecode/x0d0.py new file mode 100644 index 00000000..d6b38294 --- /dev/null +++ b/lib/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/lib/unidecode/x0d1.py b/lib/unidecode/x0d1.py new file mode 100644 index 00000000..c2bbd16d --- /dev/null +++ b/lib/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/lib/unidecode/x0d2.py b/lib/unidecode/x0d2.py new file mode 100644 index 00000000..052d462a --- /dev/null +++ b/lib/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/lib/unidecode/x0d3.py b/lib/unidecode/x0d3.py new file mode 100644 index 00000000..70a4701e --- /dev/null +++ b/lib/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/lib/unidecode/x0d4.py b/lib/unidecode/x0d4.py new file mode 100644 index 00000000..87caad48 --- /dev/null +++ b/lib/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/lib/unidecode/x0d5.py b/lib/unidecode/x0d5.py new file mode 100644 index 00000000..4dc55f8e --- /dev/null +++ b/lib/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/lib/unidecode/x0d6.py b/lib/unidecode/x0d6.py new file mode 100644 index 00000000..042ce2bd --- /dev/null +++ b/lib/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/lib/unidecode/x0d7.py b/lib/unidecode/x0d7.py new file mode 100644 index 00000000..1dfb7296 --- /dev/null +++ b/lib/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/lib/unidecode/x0f9.py b/lib/unidecode/x0f9.py new file mode 100644 index 00000000..6cc9e4cb --- /dev/null +++ b/lib/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/lib/unidecode/x0fa.py b/lib/unidecode/x0fa.py new file mode 100644 index 00000000..3d4e705c --- /dev/null +++ b/lib/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/lib/unidecode/x0fb.py b/lib/unidecode/x0fb.py new file mode 100644 index 00000000..bf69dbb9 --- /dev/null +++ b/lib/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/lib/unidecode/x0fc.py b/lib/unidecode/x0fc.py new file mode 100644 index 00000000..298b1dc3 --- /dev/null +++ b/lib/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/lib/unidecode/x0fd.py b/lib/unidecode/x0fd.py new file mode 100644 index 00000000..892bcb05 --- /dev/null +++ b/lib/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/lib/unidecode/x0fe.py b/lib/unidecode/x0fe.py new file mode 100644 index 00000000..60e86179 --- /dev/null +++ b/lib/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/lib/unidecode/x0ff.py b/lib/unidecode/x0ff.py new file mode 100644 index 00000000..04410151 --- /dev/null +++ b/lib/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/lib/unidecode/x1d4.py b/lib/unidecode/x1d4.py new file mode 100644 index 00000000..53795931 --- /dev/null +++ b/lib/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/lib/unidecode/x1d5.py b/lib/unidecode/x1d5.py new file mode 100644 index 00000000..6ec605ba --- /dev/null +++ b/lib/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/lib/unidecode/x1d6.py b/lib/unidecode/x1d6.py new file mode 100644 index 00000000..c06a855d --- /dev/null +++ b/lib/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/lib/unidecode/x1d7.py b/lib/unidecode/x1d7.py new file mode 100644 index 00000000..6943bf45 --- /dev/null +++ b/lib/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/lib/mutagen/__init__.py b/mutagen/__init__.py similarity index 66% rename from lib/mutagen/__init__.py rename to mutagen/__init__.py index 8eedf2d8..28febab3 100644 --- a/lib/mutagen/__init__.py +++ b/mutagen/__init__.py @@ -1,32 +1,35 @@ -#! /usr/bin/env python -# # mutagen aims to be an all purpose media tagging library # Copyright (C) 2005 Michael Urman # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License as # published by the Free Software Foundation. -# -# $Id: __init__.py 4348 2008-12-02 02:41:15Z piman $ -# + """Mutagen aims to be an all purpose tagging library. +:: + import mutagen.[format] metadata = mutagen.[format].Open(filename) -metadata acts like a dictionary of tags in the file. Tags are generally a +`metadata` acts like a dictionary of tags in the file. Tags are generally a list of string-like values, but may have additional methods available depending on tag or format. They may also be entirely different objects for certain keys, again depending on format. """ -version = (1, 20) +version = (1, 22) +"""Version tuple.""" + version_string = ".".join(map(str, version)) +"""Version string.""" + import warnings -from lib.mutagen import _util +import mutagen._util + class Metadata(object): """An abstract dict-like object. @@ -42,17 +45,23 @@ class Metadata(object): raise NotImplementedError def save(self, filename=None): + """Save changes to a file.""" + raise NotImplementedError def delete(self, filename=None): + """Remove tags from a file.""" + raise NotImplementedError -class FileType(_util.DictMixin): + +class FileType(mutagen._util.DictMixin): """An abstract object wrapping tags and audio stream information. Attributes: - info -- stream information (length, bitrate, sample rate) - tags -- metadata tags, if any + + * info -- stream information (length, bitrate, sample rate) + * tags -- metadata tags, if any Each file format has different potential tags and stream information. @@ -82,8 +91,11 @@ class FileType(_util.DictMixin): If the file has no tags at all, a KeyError is raised. """ - if self.tags is None: raise KeyError, key - else: return self.tags[key] + + if self.tags is None: + raise KeyError(key) + else: + return self.tags[key] def __setitem__(self, key, value): """Set a metadata tag. @@ -91,6 +103,7 @@ class FileType(_util.DictMixin): If the file has no tags, an appropriate format is added (but not written until save is called). """ + if self.tags is None: self.add_tags() self.tags[key] = value @@ -100,19 +113,26 @@ class FileType(_util.DictMixin): If the file has no tags at all, a KeyError is raised. """ - if self.tags is None: raise KeyError, key - else: del(self.tags[key]) + + if self.tags is None: + raise KeyError(key) + else: + del(self.tags[key]) def keys(self): """Return a list of keys in the metadata tag. If the file has no tags at all, an empty list is returned. """ - if self.tags is None: return [] - else: return self.tags.keys() + + if self.tags is None: + return [] + else: + return self.tags.keys() def delete(self, filename=None): """Remove tags from a file.""" + if self.tags is not None: if filename is None: filename = self.filename @@ -124,6 +144,7 @@ class FileType(_util.DictMixin): def save(self, filename=None, **kwargs): """Save metadata tags.""" + if filename is None: filename = self.filename else: @@ -132,20 +153,32 @@ class FileType(_util.DictMixin): DeprecationWarning) if self.tags is not None: return self.tags.save(filename, **kwargs) - else: raise ValueError("no tags in file") + else: + raise ValueError("no tags in file") def pprint(self): """Print stream information and comment key=value pairs.""" + stream = "%s (%s)" % (self.info.pprint(), self.mime[0]) - try: tags = self.tags.pprint() + try: + tags = self.tags.pprint() except AttributeError: return stream - else: return stream + ((tags and "\n" + tags) or "") + else: + return stream + ((tags and "\n" + tags) or "") def add_tags(self): + """Adds new tags to the file. + + Raises if tags already exist. + """ + raise NotImplementedError - def __get_mime(self): + @property + def mime(self): + """A list of mime types""" + mimes = [] for Kind in type(self).__mro__: for mime in getattr(Kind, '_mimes', []): @@ -153,7 +186,10 @@ class FileType(_util.DictMixin): mimes.append(mime) return mimes - mime = property(__get_mime) + @staticmethod + def score(filename, fileobj, header): + raise NotImplementedError + def File(filename, options=None, easy=False): """Guess the type of the file and try to open it. @@ -163,44 +199,52 @@ def File(filename, options=None, easy=False): filename extension, and the presence of existing tags. If no appropriate type could be found, None is returned. + + :param options: Sequence of :class:`FileType` implementations, defaults to + all included ones. + + :param easy: If the easy wrappers should be returnd if available. + For example :class:`EasyMP3 ` instead + of :class:`MP3 `. """ if options is None: - from lib.mutagen.asf import ASF - from lib.mutagen.apev2 import APEv2File - from lib.mutagen.flac import FLAC + from mutagen.asf import ASF + from mutagen.apev2 import APEv2File + from mutagen.flac import FLAC if easy: - from lib.mutagen.easyid3 import EasyID3FileType as ID3FileType + from mutagen.easyid3 import EasyID3FileType as ID3FileType else: - from lib.mutagen.id3 import ID3FileType + from mutagen.id3 import ID3FileType if easy: - from lib.mutagen.mp3 import EasyMP3 as MP3 + from mutagen.mp3 import EasyMP3 as MP3 else: - from lib.mutagen.mp3 import MP3 - from lib.mutagen.oggflac import OggFLAC - from lib.mutagen.oggspeex import OggSpeex - from lib.mutagen.oggtheora import OggTheora - from lib.mutagen.oggvorbis import OggVorbis + from mutagen.mp3 import MP3 + from mutagen.oggflac import OggFLAC + from mutagen.oggspeex import OggSpeex + from mutagen.oggtheora import OggTheora + from mutagen.oggvorbis import OggVorbis + from mutagen.oggopus import OggOpus if easy: - from lib.mutagen.trueaudio import EasyTrueAudio as TrueAudio + from mutagen.trueaudio import EasyTrueAudio as TrueAudio else: - from lib.mutagen.trueaudio import TrueAudio - from lib.mutagen.wavpack import WavPack + from mutagen.trueaudio import TrueAudio + from mutagen.wavpack import WavPack if easy: - from lib.mutagen.easymp4 import EasyMP4 as MP4 + from mutagen.easymp4 import EasyMP4 as MP4 else: - from lib.mutagen.mp4 import MP4 - from lib.mutagen.musepack import Musepack - from lib.mutagen.monkeysaudio import MonkeysAudio - from lib.mutagen.optimfrog import OptimFROG + from mutagen.mp4 import MP4 + from mutagen.musepack import Musepack + from mutagen.monkeysaudio import MonkeysAudio + from mutagen.optimfrog import OptimFROG options = [MP3, TrueAudio, OggTheora, OggSpeex, OggVorbis, OggFLAC, FLAC, APEv2File, MP4, ID3FileType, WavPack, Musepack, - MonkeysAudio, OptimFROG, ASF] + MonkeysAudio, OptimFROG, ASF, OggOpus] if not options: return None - fileobj = file(filename, "rb") + fileobj = open(filename, "rb") try: header = fileobj.read(128) # Sort by name after score. Otherwise import order affects @@ -213,5 +257,7 @@ def File(filename, options=None, easy=False): results = zip(results, options) results.sort() (score, name), Kind = results[-1] - if score > 0: return Kind(filename) - else: return None + if score > 0: + return Kind(filename) + else: + return None diff --git a/lib/mutagen/_constants.py b/mutagen/_constants.py similarity index 71% rename from lib/mutagen/_constants.py rename to mutagen/_constants.py index 2381e979..f5ecd90c 100644 --- a/lib/mutagen/_constants.py +++ b/mutagen/_constants.py @@ -60,7 +60,7 @@ GENRES = [ u"Southern Rock", u"Comedy", u"Cult", - u"Gangsta", + u"Gangsta Rap", u"Top 40", u"Christian Rap", u"Pop/Funk", @@ -68,7 +68,7 @@ GENRES = [ u"Native American", u"Cabaret", u"New Wave", - u"Psychadelic", + u"Psychedelic", u"Rave", u"Showtunes", u"Trailer", @@ -82,11 +82,11 @@ GENRES = [ u"Rock & Roll", u"Hard Rock", u"Folk", - u"Folk/Rock", + u"Folk-Rock", u"National Folk", u"Swing", - u"Fusion", - u"Bebob", + u"Fast-Fusion", + u"Bebop", u"Latin", u"Revival", u"Celtic", @@ -94,7 +94,7 @@ GENRES = [ u"Avantgarde", u"Gothic Rock", u"Progressive Rock", - u"Psychadelic Rock", + u"Psychedelic Rock", u"Symphonic Rock", u"Slow Rock", u"Big Band", @@ -124,7 +124,7 @@ GENRES = [ u"Duet", u"Punk Rock", u"Drum Solo", - u"A Capella", + u"A Cappella", u"Euro-House", u"Dance Hall", u"Goa", @@ -134,7 +134,7 @@ GENRES = [ u"Terror", u"Indie", u"BritPop", - u"Negerpunk", + u"Afro-Punk", u"Polsk Punk", u"Beat", u"Christian Gangsta Rap", @@ -147,7 +147,51 @@ GENRES = [ u"Salsa", u"Thrash Metal", u"Anime", - u"Jpop", - u"Synthpop" - ] + u"JPop", + u"Synthpop", + u"Abstract", + u"Art Rock", + u"Baroque", + u"Bhangra", + u"Big Beat", + u"Breakbeat", + u"Chillout", + u"Downtempo", + u"Dub", + u"EBM", + u"Eclectic", + u"Electro", + u"Electroclash", + u"Emo", + u"Experimental", + u"Garage", + u"Global", + u"IDM", + u"Illbient", + u"Industro-Goth", + u"Jam Band", + u"Krautrock", + u"Leftfield", + u"Lounge", + u"Math Rock", + u"New Romantic", + u"Nu-Breakz", + u"Post-Punk", + u"Post-Rock", + u"Psytrance", + u"Shoegaze", + u"Space Rock", + u"Trop Rock", + u"World Music", + u"Neoclassical", + u"Audiobook", + u"Audio Theatre", + u"Neue Deutsche Welle", + u"Podcast", + u"Indie Rock", + u"G-Funk", + u"Dubstep", + u"Garage Rock", + u"Psybient", +] """The ID3v1 genre list.""" diff --git a/mutagen/_id3frames.py b/mutagen/_id3frames.py new file mode 100644 index 00000000..c6130f6b --- /dev/null +++ b/mutagen/_id3frames.py @@ -0,0 +1,1842 @@ +# Copyright (C) 2005 Michael Urman +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. + +from zlib import error as zlibError +from warnings import warn +from struct import unpack + +from mutagen._id3util import ( + ID3Warning, ID3JunkFrameError, ID3BadCompressedData, + ID3EncryptionUnsupportedError, ID3BadUnsynchData, unsynch) +from mutagen._id3specs import ( + BinaryDataSpec, StringSpec, Latin1TextSpec, EncodedTextSpec, ByteSpec, + EncodingSpec, ASPIIndexSpec, SizedIntegerSpec, IntegerSpec, + VolumeAdjustmentsSpec, VolumePeakSpec, VolumeAdjustmentSpec, + ChannelSpec, MultiSpec, SynchronizedTextSpec, KeyEventSpec, TimeStampSpec, + EncodedNumericPartTextSpec, EncodedNumericTextSpec) + + +def is_valid_frame_id(frame_id): + return frame_id.isalnum() and frame_id.isupper() + + +class Frame(object): + """Fundamental unit of ID3 data. + + ID3 tags are split into frames. Each frame has a potentially + different structure, and so this base class is not very featureful. + """ + + FLAG23_ALTERTAG = 0x8000 + FLAG23_ALTERFILE = 0x4000 + FLAG23_READONLY = 0x2000 + FLAG23_COMPRESS = 0x0080 + FLAG23_ENCRYPT = 0x0040 + FLAG23_GROUP = 0x0020 + + FLAG24_ALTERTAG = 0x4000 + FLAG24_ALTERFILE = 0x2000 + FLAG24_READONLY = 0x1000 + FLAG24_GROUPID = 0x0040 + FLAG24_COMPRESS = 0x0008 + FLAG24_ENCRYPT = 0x0004 + FLAG24_UNSYNCH = 0x0002 + FLAG24_DATALEN = 0x0001 + + _framespec = [] + + def __init__(self, *args, **kwargs): + if len(args) == 1 and len(kwargs) == 0 and \ + isinstance(args[0], type(self)): + other = args[0] + for checker in self._framespec: + try: + val = checker.validate(self, getattr(other, checker.name)) + except ValueError as e: + e.message = "%s: %s" % (checker.name, e.message) + raise + setattr(self, checker.name, val) + else: + for checker, val in zip(self._framespec, args): + setattr(self, checker.name, checker.validate(self, val)) + for checker in self._framespec[len(args):]: + try: + validated = checker.validate( + self, kwargs.get(checker.name, None)) + except ValueError as e: + e.message = "%s: %s" % (checker.name, e.message) + raise + setattr(self, checker.name, validated) + + def _get_v23_frame(self, **kwargs): + """Returns a frame copy which is suitable for writing into a v2.3 tag. + + kwargs get passed to the specs. + """ + + new_kwargs = {} + for checker in self._framespec: + name = checker.name + value = getattr(self, name) + new_kwargs[name] = checker._validate23(self, value, **kwargs) + return type(self)(**new_kwargs) + + @property + def HashKey(self): + """An internal key used to ensure frame uniqueness in a tag""" + + return self.FrameID + + @property + def FrameID(self): + """ID3v2 three or four character frame ID""" + + return type(self).__name__ + + def __repr__(self): + """Python representation of a frame. + + The string returned is a valid Python expression to construct + a copy of this frame. + """ + kw = [] + for attr in self._framespec: + kw.append('%s=%r' % (attr.name, getattr(self, attr.name))) + return '%s(%s)' % (type(self).__name__, ', '.join(kw)) + + def _readData(self, data): + odata = data + for reader in self._framespec: + if len(data): + try: + value, data = reader.read(self, data) + except UnicodeDecodeError: + raise ID3JunkFrameError + else: + raise ID3JunkFrameError + setattr(self, reader.name, value) + if data.strip('\x00'): + warn('Leftover data: %s: %r (from %r)' % ( + type(self).__name__, data, odata), + ID3Warning) + + def _writeData(self): + data = [] + for writer in self._framespec: + data.append(writer.write(self, getattr(self, writer.name))) + return ''.join(data) + + def pprint(self): + """Return a human-readable representation of the frame.""" + return "%s=%s" % (type(self).__name__, self._pprint()) + + def _pprint(self): + return "[unrepresentable data]" + + @classmethod + def fromData(cls, id3, tflags, data): + """Construct this ID3 frame from raw string data.""" + + if id3._V24 <= id3.version: + if tflags & (Frame.FLAG24_COMPRESS | Frame.FLAG24_DATALEN): + # The data length int is syncsafe in 2.4 (but not 2.3). + # However, we don't actually need the data length int, + # except to work around a QL 0.12 bug, and in that case + # all we need are the raw bytes. + datalen_bytes = data[:4] + data = data[4:] + if tflags & Frame.FLAG24_UNSYNCH or id3.f_unsynch: + try: + data = unsynch.decode(data) + except ValueError, err: + if id3.PEDANTIC: + raise ID3BadUnsynchData('%s: %r' % (err, data)) + if tflags & Frame.FLAG24_ENCRYPT: + raise ID3EncryptionUnsupportedError + if tflags & Frame.FLAG24_COMPRESS: + try: + data = data.decode('zlib') + except zlibError, err: + # the initial mutagen that went out with QL 0.12 did not + # write the 4 bytes of uncompressed size. Compensate. + data = datalen_bytes + data + try: + data = data.decode('zlib') + except zlibError, err: + if id3.PEDANTIC: + raise ID3BadCompressedData('%s: %r' % (err, data)) + + elif id3._V23 <= id3.version: + if tflags & Frame.FLAG23_COMPRESS: + usize, = unpack('>L', data[:4]) + data = data[4:] + if tflags & Frame.FLAG23_ENCRYPT: + raise ID3EncryptionUnsupportedError + if tflags & Frame.FLAG23_COMPRESS: + try: + data = data.decode('zlib') + except zlibError, err: + if id3.PEDANTIC: + raise ID3BadCompressedData('%s: %r' % (err, data)) + + frame = cls() + frame._rawdata = data + frame._flags = tflags + frame._readData(data) + return frame + + def __hash__(self): + raise TypeError("Frame objects are unhashable") + + +class FrameOpt(Frame): + """A frame with optional parts. + + Some ID3 frames have optional data; this class extends Frame to + provide support for those parts. + """ + + _optionalspec = [] + + def __init__(self, *args, **kwargs): + super(FrameOpt, self).__init__(*args, **kwargs) + for spec in self._optionalspec: + if spec.name in kwargs: + validated = spec.validate(self, kwargs[spec.name]) + setattr(self, spec.name, validated) + else: + break + + def _readData(self, data): + odata = data + for reader in self._framespec: + if len(data): + value, data = reader.read(self, data) + else: + raise ID3JunkFrameError + setattr(self, reader.name, value) + if data: + for reader in self._optionalspec: + if len(data): + value, data = reader.read(self, data) + else: + break + setattr(self, reader.name, value) + if data.strip('\x00'): + warn('Leftover data: %s: %r (from %r)' % ( + type(self).__name__, data, odata), + ID3Warning) + + def _writeData(self): + data = [] + for writer in self._framespec: + data.append(writer.write(self, getattr(self, writer.name))) + for writer in self._optionalspec: + try: + data.append(writer.write(self, getattr(self, writer.name))) + except AttributeError: + break + return ''.join(data) + + def __repr__(self): + kw = [] + for attr in self._framespec: + kw.append('%s=%r' % (attr.name, getattr(self, attr.name))) + for attr in self._optionalspec: + if hasattr(self, attr.name): + kw.append('%s=%r' % (attr.name, getattr(self, attr.name))) + return '%s(%s)' % (type(self).__name__, ', '.join(kw)) + + +class TextFrame(Frame): + """Text strings. + + Text frames support casts to unicode or str objects, as well as + list-like indexing, extend, and append. + + Iterating over a TextFrame iterates over its strings, not its + characters. + + Text frames have a 'text' attribute which is the list of strings, + and an 'encoding' attribute; 0 for ISO-8859 1, 1 UTF-16, 2 for + UTF-16BE, and 3 for UTF-8. If you don't want to worry about + encodings, just set it to 3. + """ + + _framespec = [ + EncodingSpec('encoding'), + MultiSpec('text', EncodedTextSpec('text'), sep=u'\u0000'), + ] + + def __str__(self): + return self.__unicode__().encode('utf-8') + + def __unicode__(self): + return u'\u0000'.join(self.text) + + def __eq__(self, other): + if isinstance(other, str): + return str(self) == other + elif isinstance(other, unicode): + return unicode(self) == other + return self.text == other + + __hash__ = Frame.__hash__ + + def __getitem__(self, item): + return self.text[item] + + def __iter__(self): + return iter(self.text) + + def append(self, value): + """Append a string.""" + + return self.text.append(value) + + def extend(self, value): + """Extend the list by appending all strings from the given list.""" + + return self.text.extend(value) + + def _pprint(self): + return " / ".join(self.text) + + +class NumericTextFrame(TextFrame): + """Numerical text strings. + + The numeric value of these frames can be gotten with unary plus, e.g.:: + + frame = TLEN('12345') + length = +frame + """ + + _framespec = [ + EncodingSpec('encoding'), + MultiSpec('text', EncodedNumericTextSpec('text'), sep=u'\u0000'), + ] + + def __pos__(self): + """Return the numerical value of the string.""" + return int(self.text[0]) + + +class NumericPartTextFrame(TextFrame): + """Multivalue numerical text strings. + + These strings indicate 'part (e.g. track) X of Y', and unary plus + returns the first value:: + + frame = TRCK('4/15') + track = +frame # track == 4 + """ + + _framespec = [ + EncodingSpec('encoding'), + MultiSpec('text', EncodedNumericPartTextSpec('text'), sep=u'\u0000'), + ] + + def __pos__(self): + return int(self.text[0].split("/")[0]) + + +class TimeStampTextFrame(TextFrame): + """A list of time stamps. + + The 'text' attribute in this frame is a list of ID3TimeStamp + objects, not a list of strings. + """ + + _framespec = [ + EncodingSpec('encoding'), + MultiSpec('text', TimeStampSpec('stamp'), sep=u','), + ] + + def __str__(self): + return self.__unicode__().encode('utf-8') + + def __unicode__(self): + return ','.join([stamp.text for stamp in self.text]) + + def _pprint(self): + return " / ".join([stamp.text for stamp in self.text]) + + +class UrlFrame(Frame): + """A frame containing a URL string. + + The ID3 specification is silent about IRIs and normalized URL + forms. Mutagen assumes all URLs in files are encoded as Latin 1, + but string conversion of this frame returns a UTF-8 representation + for compatibility with other string conversions. + + The only sane way to handle URLs in MP3s is to restrict them to + ASCII. + """ + + _framespec = [Latin1TextSpec('url')] + + def __str__(self): + return self.url.encode('utf-8') + + def __unicode__(self): + return self.url + + def __eq__(self, other): + return self.url == other + + __hash__ = Frame.__hash__ + + def _pprint(self): + return self.url + + +class UrlFrameU(UrlFrame): + + @property + def HashKey(self): + return '%s:%s' % (self.FrameID, self.url) + + +class TALB(TextFrame): + "Album" + + +class TBPM(NumericTextFrame): + "Beats per minute" + + +class TCOM(TextFrame): + "Composer" + + +class TCON(TextFrame): + """Content type (Genre) + + ID3 has several ways genres can be represented; for convenience, + use the 'genres' property rather than the 'text' attribute. + """ + + from mutagen._constants import GENRES + GENRES = GENRES + + def __get_genres(self): + genres = [] + import re + genre_re = re.compile(r"((?:\((?P[0-9]+|RX|CR)\))*)(?P.+)?") + for value in self.text: + # 255 possible entries in id3v1 + if value.isdigit() and int(value) < 256: + try: + genres.append(self.GENRES[int(value)]) + except IndexError: + genres.append(u"Unknown") + elif value == "CR": + genres.append(u"Cover") + elif value == "RX": + genres.append(u"Remix") + elif value: + newgenres = [] + genreid, dummy, genrename = genre_re.match(value).groups() + + if genreid: + for gid in genreid[1:-1].split(")("): + if gid.isdigit() and int(gid) < len(self.GENRES): + gid = unicode(self.GENRES[int(gid)]) + newgenres.append(gid) + elif gid == "CR": + newgenres.append(u"Cover") + elif gid == "RX": + newgenres.append(u"Remix") + else: + newgenres.append(u"Unknown") + + if genrename: + # "Unescaping" the first parenthesis + if genrename.startswith("(("): + genrename = genrename[1:] + if genrename not in newgenres: + newgenres.append(genrename) + + genres.extend(newgenres) + + return genres + + def __set_genres(self, genres): + if isinstance(genres, basestring): + genres = [genres] + self.text = map(self.__decode, genres) + + def __decode(self, value): + if isinstance(value, str): + enc = EncodedTextSpec._encodings[self.encoding][0] + return value.decode(enc) + else: + return value + + genres = property(__get_genres, __set_genres, None, + "A list of genres parsed from the raw text data.") + + def _pprint(self): + return " / ".join(self.genres) + + +class TCOP(TextFrame): + "Copyright (c)" + + +class TCMP(NumericTextFrame): + "iTunes Compilation Flag" + + +class TDAT(TextFrame): + "Date of recording (DDMM)" + + +class TDEN(TimeStampTextFrame): + "Encoding Time" + + +class TDES(TextFrame): + "iTunes Podcast Description" + + +class TDOR(TimeStampTextFrame): + "Original Release Time" + + +class TDLY(NumericTextFrame): + "Audio Delay (ms)" + + +class TDRC(TimeStampTextFrame): + "Recording Time" + + +class TDRL(TimeStampTextFrame): + "Release Time" + + +class TDTG(TimeStampTextFrame): + "Tagging Time" + + +class TENC(TextFrame): + "Encoder" + + +class TEXT(TextFrame): + "Lyricist" + + +class TFLT(TextFrame): + "File type" + + +class TGID(TextFrame): + "iTunes Podcast Identifier" + + +class TIME(TextFrame): + "Time of recording (HHMM)" + + +class TIT1(TextFrame): + "Content group description" + + +class TIT2(TextFrame): + "Title" + + +class TIT3(TextFrame): + "Subtitle/Description refinement" + + +class TKEY(TextFrame): + "Starting Key" + + +class TLAN(TextFrame): + "Audio Languages" + + +class TLEN(NumericTextFrame): + "Audio Length (ms)" + + +class TMED(TextFrame): + "Source Media Type" + + +class TMOO(TextFrame): + "Mood" + + +class TOAL(TextFrame): + "Original Album" + + +class TOFN(TextFrame): + "Original Filename" + + +class TOLY(TextFrame): + "Original Lyricist" + + +class TOPE(TextFrame): + "Original Artist/Performer" + + +class TORY(NumericTextFrame): + "Original Release Year" + + +class TOWN(TextFrame): + "Owner/Licensee" + + +class TPE1(TextFrame): + "Lead Artist/Performer/Soloist/Group" + + +class TPE2(TextFrame): + "Band/Orchestra/Accompaniment" + + +class TPE3(TextFrame): + "Conductor" + + +class TPE4(TextFrame): + "Interpreter/Remixer/Modifier" + + +class TPOS(NumericPartTextFrame): + "Part of set" + + +class TPRO(TextFrame): + "Produced (P)" + + +class TPUB(TextFrame): + "Publisher" + + +class TRCK(NumericPartTextFrame): + "Track Number" + + +class TRDA(TextFrame): + "Recording Dates" + + +class TRSN(TextFrame): + "Internet Radio Station Name" + + +class TRSO(TextFrame): + "Internet Radio Station Owner" + + +class TSIZ(NumericTextFrame): + "Size of audio data (bytes)" + + +class TSO2(TextFrame): + "iTunes Album Artist Sort" + + +class TSOA(TextFrame): + "Album Sort Order key" + + +class TSOC(TextFrame): + "iTunes Composer Sort" + + +class TSOP(TextFrame): + "Perfomer Sort Order key" + + +class TSOT(TextFrame): + "Title Sort Order key" + + +class TSRC(TextFrame): + "International Standard Recording Code (ISRC)" + + +class TSSE(TextFrame): + "Encoder settings" + + +class TSST(TextFrame): + "Set Subtitle" + + +class TYER(NumericTextFrame): + "Year of recording" + + +class TXXX(TextFrame): + """User-defined text data. + + TXXX frames have a 'desc' attribute which is set to any Unicode + value (though the encoding of the text and the description must be + the same). Many taggers use this frame to store freeform keys. + """ + + _framespec = [ + EncodingSpec('encoding'), + EncodedTextSpec('desc'), + MultiSpec('text', EncodedTextSpec('text'), sep=u'\u0000'), + ] + + @property + def HashKey(self): + return '%s:%s' % (self.FrameID, self.desc) + + def _pprint(self): + return "%s=%s" % (self.desc, " / ".join(self.text)) + + +class WCOM(UrlFrameU): + "Commercial Information" + + +class WCOP(UrlFrame): + "Copyright Information" + + +class WFED(UrlFrame): + "iTunes Podcast Feed" + + +class WOAF(UrlFrame): + "Official File Information" + + +class WOAR(UrlFrameU): + "Official Artist/Performer Information" + + +class WOAS(UrlFrame): + "Official Source Information" + + +class WORS(UrlFrame): + "Official Internet Radio Information" + + +class WPAY(UrlFrame): + "Payment Information" + + +class WPUB(UrlFrame): + "Official Publisher Information" + + +class WXXX(UrlFrame): + """User-defined URL data. + + Like TXXX, this has a freeform description associated with it. + """ + + _framespec = [ + EncodingSpec('encoding'), + EncodedTextSpec('desc'), + Latin1TextSpec('url'), + ] + + @property + def HashKey(self): + return '%s:%s' % (self.FrameID, self.desc) + + +class PairedTextFrame(Frame): + """Paired text strings. + + Some ID3 frames pair text strings, to associate names with a more + specific involvement in the song. The 'people' attribute of these + frames contains a list of pairs:: + + [['trumpet', 'Miles Davis'], ['bass', 'Paul Chambers']] + + Like text frames, these frames also have an encoding attribute. + """ + + _framespec = [ + EncodingSpec('encoding'), + MultiSpec('people', + EncodedTextSpec('involvement'), + EncodedTextSpec('person')) + ] + + def __eq__(self, other): + return self.people == other + + __hash__ = Frame.__hash__ + + +class TIPL(PairedTextFrame): + "Involved People List" + + +class TMCL(PairedTextFrame): + "Musicians Credits List" + + +class IPLS(TIPL): + "Involved People List" + + +class BinaryFrame(Frame): + """Binary data + + The 'data' attribute contains the raw byte string. + """ + + _framespec = [BinaryDataSpec('data')] + + def __eq__(self, other): + return self.data == other + + __hash__ = Frame.__hash__ + + +class MCDI(BinaryFrame): + "Binary dump of CD's TOC" + + +class ETCO(Frame): + """Event timing codes.""" + + _framespec = [ + ByteSpec("format"), + KeyEventSpec("events"), + ] + + def __eq__(self, other): + return self.events == other + + __hash__ = Frame.__hash__ + + +class MLLT(Frame): + """MPEG location lookup table. + + This frame's attributes may be changed in the future based on + feedback from real-world use. + """ + + _framespec = [ + SizedIntegerSpec('frames', 2), + SizedIntegerSpec('bytes', 3), + SizedIntegerSpec('milliseconds', 3), + ByteSpec('bits_for_bytes'), + ByteSpec('bits_for_milliseconds'), + BinaryDataSpec('data'), + ] + + def __eq__(self, other): + return self.data == other + + __hash__ = Frame.__hash__ + + +class SYTC(Frame): + """Synchronised tempo codes. + + This frame's attributes may be changed in the future based on + feedback from real-world use. + """ + + _framespec = [ + ByteSpec("format"), + BinaryDataSpec("data"), + ] + + def __eq__(self, other): + return self.data == other + + __hash__ = Frame.__hash__ + + +class USLT(Frame): + """Unsynchronised lyrics/text transcription. + + Lyrics have a three letter ISO language code ('lang'), a + description ('desc'), and a block of plain text ('text'). + """ + + _framespec = [ + EncodingSpec('encoding'), + StringSpec('lang', 3), + EncodedTextSpec('desc'), + EncodedTextSpec('text'), + ] + + @property + def HashKey(self): + return '%s:%s:%r' % (self.FrameID, self.desc, self.lang) + + def __str__(self): + return self.text.encode('utf-8') + + def __unicode__(self): + return self.text + + def __eq__(self, other): + return self.text == other + + __hash__ = Frame.__hash__ + + +class SYLT(Frame): + """Synchronised lyrics/text.""" + + _framespec = [ + EncodingSpec('encoding'), + StringSpec('lang', 3), + ByteSpec('format'), + ByteSpec('type'), + EncodedTextSpec('desc'), + SynchronizedTextSpec('text'), + ] + + @property + def HashKey(self): + return '%s:%s:%r' % (self.FrameID, self.desc, self.lang) + + def __eq__(self, other): + return str(self) == other + + __hash__ = Frame.__hash__ + + def __str__(self): + return "".join([text for (text, time) in self.text]).encode('utf-8') + + +class COMM(TextFrame): + """User comment. + + User comment frames have a descrption, like TXXX, and also a three + letter ISO language code in the 'lang' attribute. + """ + + _framespec = [ + EncodingSpec('encoding'), + StringSpec('lang', 3), + EncodedTextSpec('desc'), + MultiSpec('text', EncodedTextSpec('text'), sep=u'\u0000'), + ] + + @property + def HashKey(self): + return '%s:%s:%r' % (self.FrameID, self.desc, self.lang) + + def _pprint(self): + return "%s=%r=%s" % (self.desc, self.lang, " / ".join(self.text)) + + +class RVA2(Frame): + """Relative volume adjustment (2). + + This frame is used to implemented volume scaling, and in + particular, normalization using ReplayGain. + + Attributes: + + * desc -- description or context of this adjustment + * channel -- audio channel to adjust (master is 1) + * gain -- a + or - dB gain relative to some reference level + * peak -- peak of the audio as a floating point number, [0, 1] + + When storing ReplayGain tags, use descriptions of 'album' and + 'track' on channel 1. + """ + + _framespec = [ + Latin1TextSpec('desc'), + ChannelSpec('channel'), + VolumeAdjustmentSpec('gain'), + VolumePeakSpec('peak'), + ] + + _channels = ["Other", "Master volume", "Front right", "Front left", + "Back right", "Back left", "Front centre", "Back centre", + "Subwoofer"] + + @property + def HashKey(self): + return '%s:%s' % (self.FrameID, self.desc) + + def __eq__(self, other): + try: + return ((str(self) == other) or + (self.desc == other.desc and + self.channel == other.channel and + self.gain == other.gain and + self.peak == other.peak)) + except AttributeError: + return False + + __hash__ = Frame.__hash__ + + def __str__(self): + return "%s: %+0.4f dB/%0.4f" % ( + self._channels[self.channel], self.gain, self.peak) + + +class EQU2(Frame): + """Equalisation (2). + + Attributes: + method -- interpolation method (0 = band, 1 = linear) + desc -- identifying description + adjustments -- list of (frequency, vol_adjustment) pairs + """ + + _framespec = [ + ByteSpec("method"), + Latin1TextSpec("desc"), + VolumeAdjustmentsSpec("adjustments"), + ] + + def __eq__(self, other): + return self.adjustments == other + + __hash__ = Frame.__hash__ + + @property + def HashKey(self): + return '%s:%s' % (self.FrameID, self.desc) + + +# class RVAD: unsupported +# class EQUA: unsupported + + +class RVRB(Frame): + """Reverb.""" + + _framespec = [ + SizedIntegerSpec('left', 2), + SizedIntegerSpec('right', 2), + ByteSpec('bounce_left'), + ByteSpec('bounce_right'), + ByteSpec('feedback_ltl'), + ByteSpec('feedback_ltr'), + ByteSpec('feedback_rtr'), + ByteSpec('feedback_rtl'), + ByteSpec('premix_ltr'), + ByteSpec('premix_rtl'), + ] + + def __eq__(self, other): + return (self.left, self.right) == other + + __hash__ = Frame.__hash__ + + +class APIC(Frame): + """Attached (or linked) Picture. + + Attributes: + + * encoding -- text encoding for the description + * mime -- a MIME type (e.g. image/jpeg) or '-->' if the data is a URI + * type -- the source of the image (3 is the album front cover) + * desc -- a text description of the image + * data -- raw image data, as a byte string + + Mutagen will automatically compress large images when saving tags. + """ + + _framespec = [ + EncodingSpec('encoding'), + Latin1TextSpec('mime'), + ByteSpec('type'), + EncodedTextSpec('desc'), + BinaryDataSpec('data'), + ] + + def __eq__(self, other): + return self.data == other + + __hash__ = Frame.__hash__ + + @property + def HashKey(self): + return '%s:%s' % (self.FrameID, self.desc) + + def _pprint(self): + return "%s (%s, %d bytes)" % ( + self.desc, self.mime, len(self.data)) + + +class PCNT(Frame): + """Play counter. + + The 'count' attribute contains the (recorded) number of times this + file has been played. + + This frame is basically obsoleted by POPM. + """ + + _framespec = [IntegerSpec('count')] + + def __eq__(self, other): + return self.count == other + + __hash__ = Frame.__hash__ + + def __pos__(self): + return self.count + + def _pprint(self): + return unicode(self.count) + + +class POPM(FrameOpt): + """Popularimeter. + + This frame keys a rating (out of 255) and a play count to an email + address. + + Attributes: + + * email -- email this POPM frame is for + * rating -- rating from 0 to 255 + * count -- number of times the files has been played (optional) + """ + + _framespec = [ + Latin1TextSpec('email'), + ByteSpec('rating'), + ] + + _optionalspec = [IntegerSpec('count')] + + @property + def HashKey(self): + return '%s:%s' % (self.FrameID, self.email) + + def __eq__(self, other): + return self.rating == other + + __hash__ = FrameOpt.__hash__ + + def __pos__(self): + return self.rating + + def _pprint(self): + return "%s=%r %r/255" % ( + self.email, getattr(self, 'count', None), self.rating) + + +class GEOB(Frame): + """General Encapsulated Object. + + A blob of binary data, that is not a picture (those go in APIC). + + Attributes: + + * encoding -- encoding of the description + * mime -- MIME type of the data or '-->' if the data is a URI + * filename -- suggested filename if extracted + * desc -- text description of the data + * data -- raw data, as a byte string + """ + + _framespec = [ + EncodingSpec('encoding'), + Latin1TextSpec('mime'), + EncodedTextSpec('filename'), + EncodedTextSpec('desc'), + BinaryDataSpec('data'), + ] + + @property + def HashKey(self): + return '%s:%s' % (self.FrameID, self.desc) + + def __eq__(self, other): + return self.data == other + + __hash__ = Frame.__hash__ + + +class RBUF(FrameOpt): + """Recommended buffer size. + + Attributes: + + * size -- recommended buffer size in bytes + * info -- if ID3 tags may be elsewhere in the file (optional) + * offset -- the location of the next ID3 tag, if any + + Mutagen will not find the next tag itself. + """ + + _framespec = [SizedIntegerSpec('size', 3)] + + _optionalspec = [ + ByteSpec('info'), + SizedIntegerSpec('offset', 4), + ] + + def __eq__(self, other): + return self.size == other + + __hash__ = FrameOpt.__hash__ + + def __pos__(self): + return self.size + + +class AENC(FrameOpt): + """Audio encryption. + + Attributes: + + * owner -- key identifying this encryption type + * preview_start -- unencrypted data block offset + * preview_length -- number of unencrypted blocks + * data -- data required for decryption (optional) + + Mutagen cannot decrypt files. + """ + + _framespec = [ + Latin1TextSpec('owner'), + SizedIntegerSpec('preview_start', 2), + SizedIntegerSpec('preview_length', 2), + ] + + _optionalspec = [BinaryDataSpec('data')] + + @property + def HashKey(self): + return '%s:%s' % (self.FrameID, self.owner) + + def __str__(self): + return self.owner.encode('utf-8') + + def __unicode__(self): + return self.owner + + def __eq__(self, other): + return self.owner == other + + __hash__ = FrameOpt.__hash__ + + +class LINK(FrameOpt): + """Linked information. + + Attributes: + + * frameid -- the ID of the linked frame + * url -- the location of the linked frame + * data -- further ID information for the frame + """ + + _framespec = [ + StringSpec('frameid', 4), + Latin1TextSpec('url'), + ] + + _optionalspec = [BinaryDataSpec('data')] + + @property + def HashKey(self): + try: + return "%s:%s:%s:%r" % ( + self.FrameID, self.frameid, self.url, self.data) + except AttributeError: + return "%s:%s:%s" % (self.FrameID, self.frameid, self.url) + + def __eq__(self, other): + try: + return (self.frameid, self.url, self.data) == other + except AttributeError: + return (self.frameid, self.url) == other + + __hash__ = FrameOpt.__hash__ + + +class POSS(Frame): + """Position synchronisation frame + + Attribute: + + * format -- format of the position attribute (frames or milliseconds) + * position -- current position of the file + """ + + _framespec = [ + ByteSpec('format'), + IntegerSpec('position'), + ] + + def __pos__(self): + return self.position + + def __eq__(self, other): + return self.position == other + + __hash__ = Frame.__hash__ + + +class UFID(Frame): + """Unique file identifier. + + Attributes: + + * owner -- format/type of identifier + * data -- identifier + """ + + _framespec = [ + Latin1TextSpec('owner'), + BinaryDataSpec('data'), + ] + + @property + def HashKey(self): + return '%s:%s' % (self.FrameID, self.owner) + + def __eq__(s, o): + if isinstance(o, UFI): + return s.owner == o.owner and s.data == o.data + else: + return s.data == o + + __hash__ = Frame.__hash__ + + def _pprint(self): + isascii = ord(max(self.data)) < 128 + if isascii: + return "%s=%s" % (self.owner, self.data) + else: + return "%s (%d bytes)" % (self.owner, len(self.data)) + + +class USER(Frame): + """Terms of use. + + Attributes: + + * encoding -- text encoding + * lang -- ISO three letter language code + * text -- licensing terms for the audio + """ + + _framespec = [ + EncodingSpec('encoding'), + StringSpec('lang', 3), + EncodedTextSpec('text'), + ] + + @property + def HashKey(self): + return '%s:%r' % (self.FrameID, self.lang) + + def __str__(self): + return self.text.encode('utf-8') + + def __unicode__(self): + return self.text + + def __eq__(self, other): + return self.text == other + + __hash__ = Frame.__hash__ + + def _pprint(self): + return "%r=%s" % (self.lang, self.text) + + +class OWNE(Frame): + """Ownership frame.""" + + _framespec = [ + EncodingSpec('encoding'), + Latin1TextSpec('price'), + StringSpec('date', 8), + EncodedTextSpec('seller'), + ] + + def __str__(self): + return self.seller.encode('utf-8') + + def __unicode__(self): + return self.seller + + def __eq__(self, other): + return self.seller == other + + __hash__ = Frame.__hash__ + + +class COMR(FrameOpt): + """Commercial frame.""" + + _framespec = [ + EncodingSpec('encoding'), + Latin1TextSpec('price'), + StringSpec('valid_until', 8), + Latin1TextSpec('contact'), + ByteSpec('format'), + EncodedTextSpec('seller'), + EncodedTextSpec('desc'), + ] + + _optionalspec = [ + Latin1TextSpec('mime'), + BinaryDataSpec('logo'), + ] + + @property + def HashKey(self): + return '%s:%s' % (self.FrameID, self._writeData()) + + def __eq__(self, other): + return self._writeData() == other._writeData() + + __hash__ = FrameOpt.__hash__ + + +class ENCR(Frame): + """Encryption method registration. + + The standard does not allow multiple ENCR frames with the same owner + or the same method. Mutagen only verifies that the owner is unique. + """ + + _framespec = [ + Latin1TextSpec('owner'), + ByteSpec('method'), + BinaryDataSpec('data'), + ] + + @property + def HashKey(self): + return "%s:%s" % (self.FrameID, self.owner) + + def __str__(self): + return self.data + + def __eq__(self, other): + return self.data == other + + __hash__ = Frame.__hash__ + + +class GRID(FrameOpt): + """Group identification registration.""" + + _framespec = [ + Latin1TextSpec('owner'), + ByteSpec('group'), + ] + + _optionalspec = [BinaryDataSpec('data')] + + @property + def HashKey(self): + return '%s:%s' % (self.FrameID, self.group) + + def __pos__(self): + return self.group + + def __str__(self): + return self.owner.encode('utf-8') + + def __unicode__(self): + return self.owner + + def __eq__(self, other): + return self.owner == other or self.group == other + + __hash__ = FrameOpt.__hash__ + + +class PRIV(Frame): + """Private frame.""" + + _framespec = [ + Latin1TextSpec('owner'), + BinaryDataSpec('data'), + ] + + @property + def HashKey(self): + return '%s:%s:%s' % ( + self.FrameID, self.owner, self.data.decode('latin1')) + + def __str__(self): + return self.data + + def __eq__(self, other): + return self.data == other + + def _pprint(self): + isascii = ord(max(self.data)) < 128 + if isascii: + return "%s=%s" % (self.owner, self.data) + else: + return "%s (%d bytes)" % (self.owner, len(self.data)) + + __hash__ = Frame.__hash__ + + +class SIGN(Frame): + """Signature frame.""" + + _framespec = [ + ByteSpec('group'), + BinaryDataSpec('sig'), + ] + + @property + def HashKey(self): + return '%s:%c:%s' % (self.FrameID, self.group, self.sig) + + def __str__(self): + return self.sig + + def __eq__(self, other): + return self.sig == other + + __hash__ = Frame.__hash__ + + +class SEEK(Frame): + """Seek frame. + + Mutagen does not find tags at seek offsets. + """ + + _framespec = [IntegerSpec('offset')] + + def __pos__(self): + return self.offset + + def __eq__(self, other): + return self.offset == other + + __hash__ = Frame.__hash__ + + +class ASPI(Frame): + """Audio seek point index. + + Attributes: S, L, N, b, and Fi. For the meaning of these, see + the ID3v2.4 specification. Fi is a list of integers. + """ + _framespec = [ + SizedIntegerSpec("S", 4), + SizedIntegerSpec("L", 4), + SizedIntegerSpec("N", 2), + ByteSpec("b"), + ASPIIndexSpec("Fi"), + ] + + def __eq__(self, other): + return self.Fi == other + + __hash__ = Frame.__hash__ + + +Frames = dict([(k, v) for (k, v) in globals().items() + if len(k) == 4 and isinstance(v, type) and + issubclass(v, Frame)]) +"""All supported ID3v2 frames, keyed by frame name.""" + +del(k) +del(v) + + +# ID3v2.2 frames +class UFI(UFID): + "Unique File Identifier" + + +class TT1(TIT1): + "Content group description" + + +class TT2(TIT2): + "Title" + + +class TT3(TIT3): + "Subtitle/Description refinement" + + +class TP1(TPE1): + "Lead Artist/Performer/Soloist/Group" + + +class TP2(TPE2): + "Band/Orchestra/Accompaniment" + + +class TP3(TPE3): + "Conductor" + + +class TP4(TPE4): + "Interpreter/Remixer/Modifier" + + +class TCM(TCOM): + "Composer" + + +class TXT(TEXT): + "Lyricist" + + +class TLA(TLAN): + "Audio Language(s)" + + +class TCO(TCON): + "Content Type (Genre)" + + +class TAL(TALB): + "Album" + + +class TPA(TPOS): + "Part of set" + + +class TRK(TRCK): + "Track Number" + + +class TRC(TSRC): + "International Standard Recording Code (ISRC)" + + +class TYE(TYER): + "Year of recording" + + +class TDA(TDAT): + "Date of recording (DDMM)" + + +class TIM(TIME): + "Time of recording (HHMM)" + + +class TRD(TRDA): + "Recording Dates" + + +class TMT(TMED): + "Source Media Type" + + +class TFT(TFLT): + "File Type" + + +class TBP(TBPM): + "Beats per minute" + + +class TCP(TCMP): + "iTunes Compilation Flag" + + +class TCR(TCOP): + "Copyright (C)" + + +class TPB(TPUB): + "Publisher" + + +class TEN(TENC): + "Encoder" + + +class TSS(TSSE): + "Encoder settings" + + +class TOF(TOFN): + "Original Filename" + + +class TLE(TLEN): + "Audio Length (ms)" + + +class TSI(TSIZ): + "Audio Data size (bytes)" + + +class TDY(TDLY): + "Audio Delay (ms)" + + +class TKE(TKEY): + "Starting Key" + + +class TOT(TOAL): + "Original Album" + + +class TOA(TOPE): + "Original Artist/Perfomer" + + +class TOL(TOLY): + "Original Lyricist" + + +class TOR(TORY): + "Original Release Year" + + +class TXX(TXXX): + "User-defined Text" + + +class WAF(WOAF): + "Official File Information" + + +class WAR(WOAR): + "Official Artist/Performer Information" + + +class WAS(WOAS): + "Official Source Information" + + +class WCM(WCOM): + "Commercial Information" + + +class WCP(WCOP): + "Copyright Information" + + +class WPB(WPUB): + "Official Publisher Information" + + +class WXX(WXXX): + "User-defined URL" + + +class IPL(IPLS): + "Involved people list" + + +class MCI(MCDI): + "Binary dump of CD's TOC" + + +class ETC(ETCO): + "Event timing codes" + + +class MLL(MLLT): + "MPEG location lookup table" + + +class STC(SYTC): + "Synced tempo codes" + + +class ULT(USLT): + "Unsychronised lyrics/text transcription" + + +class SLT(SYLT): + "Synchronised lyrics/text" + + +class COM(COMM): + "Comment" + + +#class RVA(RVAD) +#class EQU(EQUA) + + +class REV(RVRB): + "Reverb" + + +class PIC(APIC): + """Attached Picture. + + The 'mime' attribute of an ID3v2.2 attached picture must be either + 'PNG' or 'JPG'. + """ + _framespec = [EncodingSpec('encoding'), StringSpec('mime', 3), + ByteSpec('type'), EncodedTextSpec('desc'), + BinaryDataSpec('data')] + + +class GEO(GEOB): + "General Encapsulated Object" + + +class CNT(PCNT): + "Play counter" + + +class POP(POPM): + "Popularimeter" + + +class BUF(RBUF): + "Recommended buffer size" + + +class CRM(Frame): + """Encrypted meta frame""" + _framespec = [Latin1TextSpec('owner'), Latin1TextSpec('desc'), + BinaryDataSpec('data')] + + def __eq__(self, other): + return self.data == other + __hash__ = Frame.__hash__ + + +class CRA(AENC): + "Audio encryption" + + +class LNK(LINK): + """Linked information""" + _framespec = [StringSpec('frameid', 3), Latin1TextSpec('url')] + _optionalspec = [BinaryDataSpec('data')] + + +Frames_2_2 = dict([(k, v) for (k, v) in globals().items() + if len(k) == 3 and isinstance(v, type) and + issubclass(v, Frame)]) + +del k +del v diff --git a/mutagen/_id3specs.py b/mutagen/_id3specs.py new file mode 100644 index 00000000..32ef3afe --- /dev/null +++ b/mutagen/_id3specs.py @@ -0,0 +1,465 @@ +# Copyright (C) 2005 Michael Urman +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. + +import struct +from struct import unpack, pack +from warnings import warn + +from mutagen._id3util import ID3JunkFrameError, ID3Warning, BitPaddedInt + + +class Spec(object): + def __init__(self, name): + self.name = name + + def __hash__(self): + raise TypeError("Spec objects are unhashable") + + def _validate23(self, frame, value, **kwargs): + """Return a possibly modified value which, if written, + results in valid id3v2.3 data. + """ + + return value + + +class ByteSpec(Spec): + def read(self, frame, data): + return ord(data[0]), data[1:] + + def write(self, frame, value): + return chr(value) + + def validate(self, frame, value): + if value is not None: + chr(value) + return value + + +class IntegerSpec(Spec): + def read(self, frame, data): + return int(BitPaddedInt(data, bits=8)), '' + + def write(self, frame, value): + return BitPaddedInt.to_str(value, bits=8, width=-1) + + def validate(self, frame, value): + return value + + +class SizedIntegerSpec(Spec): + def __init__(self, name, size): + self.name, self.__sz = name, size + + def read(self, frame, data): + return int(BitPaddedInt(data[:self.__sz], bits=8)), data[self.__sz:] + + def write(self, frame, value): + return BitPaddedInt.to_str(value, bits=8, width=self.__sz) + + def validate(self, frame, value): + return value + + +class EncodingSpec(ByteSpec): + def read(self, frame, data): + enc, data = super(EncodingSpec, self).read(frame, data) + if enc < 16: + return enc, data + else: + return 0, chr(enc)+data + + def validate(self, frame, value): + if 0 <= value <= 3: + return value + if value is None: + return None + raise ValueError('Invalid Encoding: %r' % value) + + def _validate23(self, frame, value, **kwargs): + # only 0, 1 are valid in v2.3, default to utf-16 + return min(1, value) + + +class StringSpec(Spec): + def __init__(self, name, length): + super(StringSpec, self).__init__(name) + self.len = length + + def read(s, frame, data): + return data[:s.len], data[s.len:] + + def write(s, frame, value): + if value is None: + return '\x00' * s.len + else: + return (str(value) + '\x00' * s.len)[:s.len] + + def validate(s, frame, value): + if value is None: + return None + if isinstance(value, basestring) and len(value) == s.len: + return value + raise ValueError('Invalid StringSpec[%d] data: %r' % (s.len, value)) + + +class BinaryDataSpec(Spec): + def read(self, frame, data): + return data, '' + + def write(self, frame, value): + return str(value) + + def validate(self, frame, value): + return str(value) + + +class EncodedTextSpec(Spec): + # Okay, seriously. This is private and defined explicitly and + # completely by the ID3 specification. You can't just add + # encodings here however you want. + _encodings = ( + ('latin1', '\x00'), + ('utf16', '\x00\x00'), + ('utf_16_be', '\x00\x00'), + ('utf8', '\x00') + ) + + def read(self, frame, data): + enc, term = self._encodings[frame.encoding] + ret = '' + if len(term) == 1: + if term in data: + data, ret = data.split(term, 1) + else: + offset = -1 + try: + while True: + offset = data.index(term, offset+1) + if offset & 1: + continue + data, ret = data[0:offset], data[offset+2:] + break + except ValueError: + pass + + if len(data) < len(term): + return u'', ret + return data.decode(enc), ret + + def write(self, frame, value): + enc, term = self._encodings[frame.encoding] + return value.encode(enc) + term + + def validate(self, frame, value): + return unicode(value) + + +class MultiSpec(Spec): + def __init__(self, name, *specs, **kw): + super(MultiSpec, self).__init__(name) + self.specs = specs + self.sep = kw.get('sep') + + def read(self, frame, data): + values = [] + while data: + record = [] + for spec in self.specs: + value, data = spec.read(frame, data) + record.append(value) + if len(self.specs) != 1: + values.append(record) + else: + values.append(record[0]) + return values, data + + def write(self, frame, value): + data = [] + if len(self.specs) == 1: + for v in value: + data.append(self.specs[0].write(frame, v)) + else: + for record in value: + for v, s in zip(record, self.specs): + data.append(s.write(frame, v)) + return ''.join(data) + + def validate(self, frame, value): + if value is None: + return [] + if self.sep and isinstance(value, basestring): + value = value.split(self.sep) + if isinstance(value, list): + if len(self.specs) == 1: + return [self.specs[0].validate(frame, v) for v in value] + else: + return [ + [s.validate(frame, v) for (v, s) in zip(val, self.specs)] + for val in value] + raise ValueError('Invalid MultiSpec data: %r' % value) + + def _validate23(self, frame, value, **kwargs): + if len(self.specs) != 1: + return [[s._validate23(frame, v, **kwargs) + for (v, s) in zip(val, self.specs)] + for val in value] + + spec = self.specs[0] + + # Merge single text spec multispecs only. + # (TimeStampSpec beeing the exception, but it's not a valid v2.3 frame) + if not isinstance(spec, EncodedTextSpec) or \ + isinstance(spec, TimeStampSpec): + return value + + value = [spec._validate23(frame, v, **kwargs) for v in value] + if kwargs.get("sep") is not None: + return [spec.validate(frame, kwargs["sep"].join(value))] + return value + + +class EncodedNumericTextSpec(EncodedTextSpec): + pass + + +class EncodedNumericPartTextSpec(EncodedTextSpec): + pass + + +class Latin1TextSpec(EncodedTextSpec): + def read(self, frame, data): + if '\x00' in data: + data, ret = data.split('\x00', 1) + else: + ret = '' + return data.decode('latin1'), ret + + def write(self, data, value): + return value.encode('latin1') + '\x00' + + def validate(self, frame, value): + return unicode(value) + + +class ID3TimeStamp(object): + """A time stamp in ID3v2 format. + + This is a restricted form of the ISO 8601 standard; time stamps + take the form of: + YYYY-MM-DD HH:MM:SS + Or some partial form (YYYY-MM-DD HH, YYYY, etc.). + + The 'text' attribute contains the raw text data of the time stamp. + """ + + import re + + def __init__(self, text): + if isinstance(text, ID3TimeStamp): + text = text.text + self.text = text + + __formats = ['%04d'] + ['%02d'] * 5 + __seps = ['-', '-', ' ', ':', ':', 'x'] + + def get_text(self): + parts = [self.year, self.month, self.day, + self.hour, self.minute, self.second] + pieces = [] + for i, part in enumerate(iter(iter(parts).next, None)): + pieces.append(self.__formats[i] % part + self.__seps[i]) + return u''.join(pieces)[:-1] + + def set_text(self, text, splitre=re.compile('[-T:/.]|\s+')): + year, month, day, hour, minute, second = \ + splitre.split(text + ':::::')[:6] + for a in 'year month day hour minute second'.split(): + try: + v = int(locals()[a]) + except ValueError: + v = None + setattr(self, a, v) + + text = property(get_text, set_text, doc="ID3v2.4 date and time.") + + def __str__(self): + return self.text + + def __repr__(self): + return repr(self.text) + + def __cmp__(self, other): + return cmp(self.text, other.text) + + __hash__ = object.__hash__ + + def encode(self, *args): + return self.text.encode(*args) + + +class TimeStampSpec(EncodedTextSpec): + def read(self, frame, data): + value, data = super(TimeStampSpec, self).read(frame, data) + return self.validate(frame, value), data + + def write(self, frame, data): + return super(TimeStampSpec, self).write(frame, + data.text.replace(' ', 'T')) + + def validate(self, frame, value): + try: + return ID3TimeStamp(value) + except TypeError: + raise ValueError("Invalid ID3TimeStamp: %r" % value) + + +class ChannelSpec(ByteSpec): + (OTHER, MASTER, FRONTRIGHT, FRONTLEFT, BACKRIGHT, BACKLEFT, FRONTCENTRE, + BACKCENTRE, SUBWOOFER) = range(9) + + +class VolumeAdjustmentSpec(Spec): + def read(self, frame, data): + value, = unpack('>h', data[0:2]) + return value/512.0, data[2:] + + def write(self, frame, value): + return pack('>h', int(round(value * 512))) + + def validate(self, frame, value): + if value is not None: + try: + self.write(frame, value) + except struct.error: + raise ValueError("out of range") + return value + + +class VolumePeakSpec(Spec): + def read(self, frame, data): + # http://bugs.xmms.org/attachment.cgi?id=113&action=view + peak = 0 + bits = ord(data[0]) + bytes = min(4, (bits + 7) >> 3) + # not enough frame data + if bytes + 1 > len(data): + raise ID3JunkFrameError + shift = ((8 - (bits & 7)) & 7) + (4 - bytes) * 8 + for i in range(1, bytes+1): + peak *= 256 + peak += ord(data[i]) + peak *= 2 ** shift + return (float(peak) / (2**31-1)), data[1+bytes:] + + def write(self, frame, value): + # always write as 16 bits for sanity. + return "\x10" + pack('>H', int(round(value * 32768))) + + def validate(self, frame, value): + if value is not None: + try: + self.write(frame, value) + except struct.error: + raise ValueError("out of range") + return value + + +class SynchronizedTextSpec(EncodedTextSpec): + def read(self, frame, data): + texts = [] + encoding, term = self._encodings[frame.encoding] + while data: + l = len(term) + try: + value_idx = data.index(term) + except ValueError: + raise ID3JunkFrameError + value = data[:value_idx].decode(encoding) + if len(data) < value_idx + l + 4: + raise ID3JunkFrameError + time, = struct.unpack(">I", data[value_idx+l:value_idx+l+4]) + texts.append((value, time)) + data = data[value_idx+l+4:] + return texts, "" + + def write(self, frame, value): + data = [] + encoding, term = self._encodings[frame.encoding] + for text, time in frame.text: + text = text.encode(encoding) + term + data.append(text + struct.pack(">I", time)) + return "".join(data) + + def validate(self, frame, value): + return value + + +class KeyEventSpec(Spec): + def read(self, frame, data): + events = [] + while len(data) >= 5: + events.append(struct.unpack(">bI", data[:5])) + data = data[5:] + return events, data + + def write(self, frame, value): + return "".join([struct.pack(">bI", *event) for event in value]) + + def validate(self, frame, value): + return value + + +class VolumeAdjustmentsSpec(Spec): + # Not to be confused with VolumeAdjustmentSpec. + def read(self, frame, data): + adjustments = {} + while len(data) >= 4: + freq, adj = struct.unpack(">Hh", data[:4]) + data = data[4:] + freq /= 2.0 + adj /= 512.0 + adjustments[freq] = adj + adjustments = adjustments.items() + adjustments.sort() + return adjustments, data + + def write(self, frame, value): + value.sort() + return "".join([struct.pack(">Hh", int(freq * 2), int(adj * 512)) + for (freq, adj) in value]) + + def validate(self, frame, value): + return value + + +class ASPIIndexSpec(Spec): + def read(self, frame, data): + if frame.b == 16: + format = "H" + size = 2 + elif frame.b == 8: + format = "B" + size = 1 + else: + warn("invalid bit count in ASPI (%d)" % frame.b, ID3Warning) + return [], data + + indexes = data[:frame.N * size] + data = data[frame.N * size:] + return list(struct.unpack(">" + format * frame.N, indexes)), data + + def write(self, frame, values): + if frame.b == 16: + format = "H" + elif frame.b == 8: + format = "B" + else: + raise ValueError("frame.b must be 8 or 16") + return struct.pack(">" + format * frame.N, *values) + + def validate(self, frame, values): + return values diff --git a/mutagen/_id3util.py b/mutagen/_id3util.py new file mode 100644 index 00000000..de82e36a --- /dev/null +++ b/mutagen/_id3util.py @@ -0,0 +1,176 @@ +# Copyright (C) 2005 Michael Urman +# 2013 Christoph Reiter +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. + + +class error(Exception): + pass + + +class ID3NoHeaderError(error, ValueError): + pass + + +class ID3BadUnsynchData(error, ValueError): + pass + + +class ID3BadCompressedData(error, ValueError): + pass + + +class ID3TagError(error, ValueError): + pass + + +class ID3UnsupportedVersionError(error, NotImplementedError): + pass + + +class ID3EncryptionUnsupportedError(error, NotImplementedError): + pass + + +class ID3JunkFrameError(error, ValueError): + pass + + +class ID3Warning(error, UserWarning): + pass + + +class unsynch(object): + @staticmethod + def decode(value): + output = [] + safe = True + append = output.append + for val in value: + if safe: + append(val) + safe = val != '\xFF' + else: + if val >= '\xE0': + raise ValueError('invalid sync-safe string') + elif val != '\x00': + append(val) + safe = True + if not safe: + raise ValueError('string ended unsafe') + return ''.join(output) + + @staticmethod + def encode(value): + output = [] + safe = True + append = output.append + for val in value: + if safe: + append(val) + if val == '\xFF': + safe = False + elif val == '\x00' or val >= '\xE0': + append('\x00') + append(val) + safe = val != '\xFF' + else: + append(val) + safe = True + if not safe: + append('\x00') + return ''.join(output) + + +class _BitPaddedMixin(object): + + def as_str(self, width=4, minwidth=4): + return self.to_str(self, self.bits, self.bigendian, width, minwidth) + + @staticmethod + def to_str(value, bits=7, bigendian=True, width=4, minwidth=4): + mask = (1 << bits) - 1 + + if width != -1: + index = 0 + bytes_ = bytearray(width) + try: + while value: + bytes_[index] = value & mask + value >>= bits + index += 1 + except IndexError: + raise ValueError('Value too wide (>%d bytes)' % width) + else: + # PCNT and POPM use growing integers + # of at least 4 bytes (=minwidth) as counters. + bytes_ = bytearray() + append = bytes_.append + while value: + append(value & mask) + value >>= bits + bytes_ = bytes_.ljust(minwidth, "\x00") + + if bigendian: + bytes_.reverse() + return str(bytes_) + + @staticmethod + def has_valid_padding(value, bits=7): + """Whether the padding bits are all zero""" + + assert bits <= 8 + + mask = (((1 << (8 - bits)) - 1) << bits) + + if isinstance(value, (int, long)): + while value: + if value & mask: + return False + value >>= 8 + elif isinstance(value, str): + for byte in value: + if ord(byte) & mask: + return False + else: + raise TypeError + + return True + + +class BitPaddedInt(int, _BitPaddedMixin): + + def __new__(cls, value, bits=7, bigendian=True): + + mask = (1 << (bits)) - 1 + numeric_value = 0 + shift = 0 + + if isinstance(value, (int, long)): + while value: + numeric_value += (value & mask) << shift + value >>= 8 + shift += bits + elif isinstance(value, str): + if bigendian: + value = reversed(value) + for byte in value: + numeric_value += (ord(byte) & mask) << shift + shift += bits + else: + raise TypeError + + if isinstance(numeric_value, long): + self = long.__new__(BitPaddedLong, numeric_value) + else: + self = int.__new__(BitPaddedInt, numeric_value) + + self.bits = bits + self.bigendian = bigendian + return self + + +class BitPaddedLong(long, _BitPaddedMixin): + pass diff --git a/lib/mutagen/_util.py b/mutagen/_util.py similarity index 88% rename from lib/mutagen/_util.py rename to mutagen/_util.py index 79f8f846..2c8e1a56 100644 --- a/lib/mutagen/_util.py +++ b/mutagen/_util.py @@ -3,8 +3,6 @@ # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. -# -# $Id: _util.py 4218 2007-12-02 06:11:20Z piman $ """Utility classes for Mutagen. @@ -16,6 +14,7 @@ import struct from fnmatch import fnmatchcase + class DictMixin(object): """Implement the dict API using keys() and __*item__ methods. @@ -35,9 +34,12 @@ class DictMixin(object): return iter(self.keys()) def has_key(self, key): - try: self[key] - except KeyError: return False - else: return True + try: + self[key] + except KeyError: + return False + else: + return True __contains__ = has_key iterkeys = lambda self: iter(self.keys()) @@ -56,10 +58,13 @@ class DictMixin(object): def pop(self, key, *args): if len(args) > 1: raise TypeError("pop takes at most two arguments") - try: value = self[key] + try: + value = self[key] except KeyError: - if args: return args[0] - else: raise + if args: + return args[0] + else: + raise del(self[key]) return value @@ -67,38 +72,48 @@ class DictMixin(object): try: key = self.keys()[0] return key, self.pop(key) - except IndexError: raise KeyError("dictionary is empty") + except IndexError: + raise KeyError("dictionary is empty") def update(self, other=None, **kwargs): if other is None: self.update(kwargs) other = {} - try: map(self.__setitem__, other.keys(), other.values()) + try: + map(self.__setitem__, other.keys(), other.values()) except AttributeError: for key, value in other: self[key] = value def setdefault(self, key, default=None): - try: return self[key] + try: + return self[key] except KeyError: self[key] = default return default def get(self, key, default=None): - try: return self[key] - except KeyError: return default + try: + return self[key] + except KeyError: + return default def __repr__(self): return repr(dict(self.items())) def __cmp__(self, other): - if other is None: return 1 - else: return cmp(dict(self.items()), other) + if other is None: + return 1 + else: + return cmp(dict(self.items()), other) + + __hash__ = object.__hash__ def __len__(self): return len(self.keys()) + class DictProxy(DictMixin): def __init__(self, *args, **kwargs): self.__dict = {} @@ -116,10 +131,12 @@ class DictProxy(DictMixin): def keys(self): return self.__dict.keys() + class cdata(object): """C character buffer to Python numeric type conversions.""" from struct import error + error = error short_le = staticmethod(lambda data: struct.unpack('> n) & 1)) + def lock(fileobj): """Lock a file object 'safely'. @@ -175,11 +193,14 @@ def lock(fileobj): raises an exception in more extreme circumstances (full lock table, invalid file). """ - try: import fcntl + + try: + import fcntl except ImportError: return False else: - try: fcntl.lockf(fileobj, fcntl.LOCK_EX) + try: + fcntl.lockf(fileobj, fcntl.LOCK_EX) except IOError: # FIXME: There's possibly a lot of complicated # logic that needs to go here in case the IOError @@ -188,17 +209,20 @@ def lock(fileobj): else: return True + def unlock(fileobj): """Unlock a file object. Don't call this on a file object unless a call to lock() returned true. """ + # If this fails there's a mismatched lock/unlock pair, # so we definitely don't want to ignore errors. import fcntl fcntl.lockf(fileobj, fcntl.LOCK_UN) + def insert_bytes(fobj, size, offset, BUFFER_SIZE=2**16): """Insert size bytes of empty space starting at offset. @@ -206,6 +230,7 @@ def insert_bytes(fobj, size, offset, BUFFER_SIZE=2**16): equivalent. Mutagen tries to use mmap to resize the file, but falls back to a significantly slower method if mmap fails. """ + assert 0 < size assert 0 <= offset locked = False @@ -218,8 +243,10 @@ def insert_bytes(fobj, size, offset, BUFFER_SIZE=2**16): try: import mmap map = mmap.mmap(fobj.fileno(), filesize + size) - try: map.move(offset + size, offset, movesize) - finally: map.close() + try: + map.move(offset + size, offset, movesize) + finally: + map.close() except (ValueError, EnvironmentError, ImportError): # handle broken mmap scenarios locked = lock(fobj) @@ -257,6 +284,7 @@ def insert_bytes(fobj, size, offset, BUFFER_SIZE=2**16): if locked: unlock(fobj) + def delete_bytes(fobj, size, offset, BUFFER_SIZE=2**16): """Delete size bytes of empty space starting at offset. @@ -264,6 +292,7 @@ def delete_bytes(fobj, size, offset, BUFFER_SIZE=2**16): equivalent. Mutagen tries to use mmap to resize the file, but falls back to a significantly slower method if mmap fails. """ + locked = False assert 0 < size assert 0 <= offset @@ -277,8 +306,10 @@ def delete_bytes(fobj, size, offset, BUFFER_SIZE=2**16): try: import mmap map = mmap.mmap(fobj.fileno(), filesize) - try: map.move(offset, offset + size, movesize) - finally: map.close() + try: + map.move(offset, offset + size, movesize) + finally: + map.close() except (ValueError, EnvironmentError, ImportError): # handle broken mmap scenarios locked = lock(fobj) @@ -296,13 +327,17 @@ def delete_bytes(fobj, size, offset, BUFFER_SIZE=2**16): if locked: unlock(fobj) + def utf8(data): """Convert a basestring to a valid UTF-8 str.""" + if isinstance(data, str): return data.decode("utf-8", "replace").encode("utf-8") elif isinstance(data, unicode): return data.encode("utf-8") - else: raise TypeError("only unicode/str types can be converted to UTF-8") + else: + raise TypeError("only unicode/str types can be converted to UTF-8") + def dict_match(d, key, default=None): try: diff --git a/lib/mutagen/_vorbis.py b/mutagen/_vorbis.py similarity index 76% rename from lib/mutagen/_vorbis.py rename to mutagen/_vorbis.py index 1d88860c..4ee8da4a 100644 --- a/lib/mutagen/_vorbis.py +++ b/mutagen/_vorbis.py @@ -18,12 +18,9 @@ import sys from cStringIO import StringIO -import lib.mutagen -from lib.mutagen._util import DictMixin, cdata +import mutagen +from mutagen._util import DictMixin, cdata -try: set -except NameError: - from sets import Set as set def is_valid_key(key): """Return true if a string is a valid Vorbis comment key. @@ -32,15 +29,27 @@ def is_valid_key(key): and 0x7D ('}'), excluding '='. """ for c in key: - if c < " " or c > "}" or c == "=": return False - else: return bool(key) + if c < " " or c > "}" or c == "=": + return False + else: + return bool(key) + istag = is_valid_key -class error(IOError): pass -class VorbisUnsetFrameError(error): pass -class VorbisEncodingError(error): pass -class VComment(lib.mutagen.Metadata, list): +class error(IOError): + pass + + +class VorbisUnsetFrameError(error): + pass + + +class VorbisEncodingError(error): + pass + + +class VComment(mutagen.Metadata, list): """A Vorbis comment parser, accessor, and renderer. All comment ordering is preserved. A VComment is a list of @@ -54,7 +63,7 @@ class VComment(lib.mutagen.Metadata, list): vendor -- the stream 'vendor' (i.e. writer); default 'Mutagen' """ - vendor = u"Mutagen " + lib.mutagen.version_string + vendor = u"Mutagen " + mutagen.version_string def __init__(self, data=None, *args, **kwargs): # Collect the args to pass to load, this lets child classes @@ -84,24 +93,28 @@ class VComment(lib.mutagen.Metadata, list): vendor_length = cdata.uint_le(fileobj.read(4)) self.vendor = fileobj.read(vendor_length).decode('utf-8', errors) count = cdata.uint_le(fileobj.read(4)) - for i in range(count): + for i in xrange(count): length = cdata.uint_le(fileobj.read(4)) - try: string = fileobj.read(length).decode('utf-8', errors) + try: + string = fileobj.read(length).decode('utf-8', errors) except (OverflowError, MemoryError): raise error("cannot read %d bytes, too large" % length) - try: tag, value = string.split('=', 1) + try: + tag, value = string.split('=', 1) except ValueError, err: if errors == "ignore": continue elif errors == "replace": tag, value = u"unknown%d" % i, string else: - raise VorbisEncodingError, str(err), sys.exc_info()[2] - try: tag = tag.encode('ascii', errors) + raise VorbisEncodingError, err, sys.exc_info()[2] + try: + tag = tag.encode('ascii', errors) except UnicodeEncodeError: - raise VorbisEncodingError, "invalid tag name %r" % tag + raise VorbisEncodingError("invalid tag name %r" % tag) else: - if is_valid_key(tag): self.append((tag, value)) + if is_valid_key(tag): + self.append((tag, value)) if framing and not ord(fileobj.read(1)) & 0x01: raise VorbisUnsetFrameError("framing bit was unset") except (cdata.error, TypeError): @@ -116,17 +129,24 @@ class VComment(lib.mutagen.Metadata, list): """ if not isinstance(self.vendor, unicode): - try: self.vendor.decode('utf-8') - except UnicodeDecodeError: raise ValueError + try: + self.vendor.decode('utf-8') + except UnicodeDecodeError: + raise ValueError for key, value in self: try: - if not is_valid_key(key): raise ValueError - except: raise ValueError("%r is not a valid key" % key) + if not is_valid_key(key): + raise ValueError + except: + raise ValueError("%r is not a valid key" % key) if not isinstance(value, unicode): - try: value.encode("utf-8") - except: raise ValueError("%r is not a valid value" % value) - else: return True + try: + value.encode("utf-8") + except: + raise ValueError("%r is not a valid value" % value) + else: + return True def clear(self): """Clear all keys from the comment.""" @@ -152,12 +172,14 @@ class VComment(lib.mutagen.Metadata, list): comment = "%s=%s" % (tag, value.encode('utf-8')) f.write(cdata.to_uint_le(len(comment))) f.write(comment) - if framing: f.write("\x01") + if framing: + f.write("\x01") return f.getvalue() def pprint(self): return "\n".join(["%s=%s" % (k.lower(), v) for k, v in self]) + class VCommentDict(VComment, DictMixin): """A VComment that looks like a dictionary. @@ -181,22 +203,28 @@ class VCommentDict(VComment, DictMixin): """ key = key.lower().encode('ascii') values = [value for (k, value) in self if k.lower() == key] - if not values: raise KeyError, key - else: return values + if not values: + raise KeyError(key) + else: + return values def __delitem__(self, key): """Delete all values associated with the key.""" key = key.lower().encode('ascii') to_delete = filter(lambda x: x[0].lower() == key, self) - if not to_delete:raise KeyError, key - else: map(self.remove, to_delete) + if not to_delete: + raise KeyError(key) + else: + map(self.remove, to_delete) def __contains__(self, key): """Return true if the key has any values.""" key = key.lower().encode('ascii') for k, value in self: - if k.lower() == key: return True - else: return False + if k.lower() == key: + return True + else: + return False def __setitem__(self, key, values): """Set a key's value or values. @@ -206,11 +234,14 @@ class VCommentDict(VComment, DictMixin): string. """ - key = key.lower().encode('ascii') + + key = key.encode('ascii') if not isinstance(values, list): values = [values] - try: del(self[key]) - except KeyError: pass + try: + del(self[key]) + except KeyError: + pass for value in values: self.append((key, value)) @@ -220,4 +251,4 @@ class VCommentDict(VComment, DictMixin): def as_dict(self): """Return a copy of the comment data in a real dict.""" - return dict((key, self[key]) for key in self.keys()) + return dict([(key, self[key]) for key in self.keys()]) diff --git a/lib/mutagen/apev2.py b/mutagen/apev2.py similarity index 84% rename from lib/mutagen/apev2.py rename to mutagen/apev2.py index d7e67010..aa1e00e6 100644 --- a/lib/mutagen/apev2.py +++ b/mutagen/apev2.py @@ -5,8 +5,6 @@ # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. -# -# $Id: apev2.py 4008 2007-04-21 04:02:07Z piman $ """APEv2 reading and writing. @@ -35,6 +33,10 @@ __all__ = ["APEv2", "APEv2File", "Open", "delete"] import struct from cStringIO import StringIO +from mutagen import Metadata, FileType +from mutagen._util import DictMixin, cdata, utf8, delete_bytes + + def is_valid_apev2_key(key): return (2 <= len(key) <= 255 and min(key) >= ' ' and max(key) <= '~' and key not in ["OggS", "TAG", "ID3", "MP+"]) @@ -48,15 +50,24 @@ TEXT, BINARY, EXTERNAL = range(3) HAS_HEADER = 1L << 31 HAS_NO_FOOTER = 1L << 30 -IS_HEADER = 1L << 29 +IS_HEADER = 1L << 29 -class error(IOError): pass -class APENoHeaderError(error, ValueError): pass -class APEUnsupportedVersionError(error, ValueError): pass -class APEBadItemError(error, ValueError): pass -from lib.mutagen import Metadata, FileType -from lib.mutagen._util import DictMixin, cdata, utf8, delete_bytes +class error(IOError): + pass + + +class APENoHeaderError(error, ValueError): + pass + + +class APEUnsupportedVersionError(error, ValueError): + pass + + +class APEBadItemError(error, ValueError): + pass + class _APEv2Data(object): # Store offsets of the important parts of the file. @@ -79,7 +90,8 @@ class _APEv2Data(object): def __init__(self, fileobj): self.__find_metadata(fileobj) self.metadata = max(self.header, self.footer) - if self.metadata is None: return + if self.metadata is None: + return self.__fill_missing(fileobj) self.__fix_brokenness(fileobj) if self.data is not None: @@ -90,7 +102,8 @@ class _APEv2Data(object): # Try to find a header or footer. # Check for a simple footer. - try: fileobj.seek(-32, 2) + try: + fileobj.seek(-32, 2) except IOError: fileobj.seek(0, 2) return @@ -104,7 +117,7 @@ class _APEv2Data(object): fileobj.seek(-128, 2) if fileobj.read(3) == "TAG": - fileobj.seek(-35, 1) # "TAG" + header length + fileobj.seek(-35, 1) # "TAG" + header length if fileobj.read(8) == "APETAGEX": fileobj.seek(-8, 1) self.footer = fileobj.tell() @@ -115,8 +128,9 @@ class _APEv2Data(object): # (header length - "APETAGEX") - "LYRICS200" fileobj.seek(15, 1) if fileobj.read(9) == 'LYRICS200': - fileobj.seek(-15, 1) # "LYRICS200" + size tag - try: offset = int(fileobj.read(6)) + fileobj.seek(-15, 1) # "LYRICS200" + size tag + try: + offset = int(fileobj.read(6)) except ValueError: raise IOError @@ -157,27 +171,37 @@ class _APEv2Data(object): self.header = self.data - 32 else: self.header = self.data - else: raise APENoHeaderError("No APE tag found") + else: + raise APENoHeaderError("No APE tag found") + + # exclude the footer from size + if self.footer is not None: + self.size -= 32 def __fix_brokenness(self, fileobj): # Fix broken tags written with PyMusepack. - if self.header is not None: start = self.header - else: start = self.data + if self.header is not None: + start = self.header + else: + start = self.data fileobj.seek(start) while start > 0: # Clean up broken writing from pre-Mutagen PyMusepack. # It didn't remove the first 24 bytes of header. - try: fileobj.seek(-24, 1) + try: + fileobj.seek(-24, 1) except IOError: break else: if fileobj.read(8) == "APETAGEX": fileobj.seek(-8, 1) start = fileobj.tell() - else: break + else: + break self.start = start + class APEv2(DictMixin, Metadata): """A file with an APEv2 tag. @@ -206,7 +230,7 @@ class APEv2(DictMixin, Metadata): def load(self, filename): """Load tags from a filename.""" self.filename = filename - fileobj = file(filename, "rb") + fileobj = open(filename, "rb") try: data = _APEv2Data(fileobj) finally: @@ -222,7 +246,11 @@ class APEv2(DictMixin, Metadata): fileobj = StringIO(tag) for i in range(count): - size = cdata.uint_le(fileobj.read(4)) + size_data = fileobj.read(4) + # someone writes wrong item counts + if not size_data: + break + size = cdata.uint_le(size_data) flags = cdata.uint_le(fileobj.read(4)) # Bits 1 and 2 bits are flags, 0-3 @@ -242,11 +270,13 @@ class APEv2(DictMixin, Metadata): def __getitem__(self, key): if not is_valid_apev2_key(key): raise KeyError("%r is not a valid APEv2 key" % key) + key = key.encode('ascii') return self.__dict[key.lower()] def __delitem__(self, key): if not is_valid_apev2_key(key): raise KeyError("%r is not a valid APEv2 key" % key) + key = key.encode('ascii') del(self.__dict[key.lower()]) def __setitem__(self, key, value): @@ -261,13 +291,15 @@ class APEv2(DictMixin, Metadata): If you need to force a specific type of value (e.g. binary data that also happens to be valid UTF-8, or an external reference), use the APEValue factory and set the value to the - result of that: - from lib.mutagen.apev2 import APEValue, EXTERNAL + result of that:: + + from mutagen.apev2 import APEValue, EXTERNAL tag['Website'] = APEValue('http://example.org', EXTERNAL) """ if not is_valid_apev2_key(key): raise KeyError("%r is not a valid APEv2 key" % key) + key = key.encode('ascii') if not isinstance(value, _APEValue): # let's guess at the content if we're not already a value... @@ -278,7 +310,8 @@ class APEv2(DictMixin, Metadata): # list? text. value = APEValue("\0".join(map(utf8, value)), TEXT) else: - try: dummy = value.decode("utf-8") + try: + value.decode("utf-8") except UnicodeError: # invalid UTF8 text, probably binary value = APEValue(value, BINARY) @@ -302,9 +335,9 @@ class APEv2(DictMixin, Metadata): filename = filename or self.filename try: - fileobj = file(filename, "r+b") + fileobj = open(filename, "r+b") except IOError: - fileobj = file(filename, "w+b") + fileobj = open(filename, "w+b") data = _APEv2Data(fileobj) if data.is_at_start: @@ -323,7 +356,7 @@ class APEv2(DictMixin, Metadata): num_tags = len(tags) tags = "".join(tags) - header = "APETAGEX%s%s" %( + header = "APETAGEX%s%s" % ( # version, tag size, item count, flags struct.pack("<4I", 2000, len(tags) + 32, num_tags, HAS_HEADER | IS_HEADER), @@ -332,7 +365,7 @@ class APEv2(DictMixin, Metadata): fileobj.write(tags) - footer = "APETAGEX%s%s" %( + footer = "APETAGEX%s%s" % ( # version, tag size, item count, flags struct.pack("<4I", 2000, len(tags) + 32, num_tags, HAS_HEADER), @@ -343,7 +376,7 @@ class APEv2(DictMixin, Metadata): def delete(self, filename=None): """Remove tags from a file.""" filename = filename or self.filename - fileobj = file(filename, "r+b") + fileobj = open(filename, "r+b") try: data = _APEv2Data(fileobj) if data.start is not None and data.size is not None: @@ -352,12 +385,17 @@ class APEv2(DictMixin, Metadata): fileobj.close() self.clear() + Open = APEv2 + def delete(filename): """Remove tags from a file.""" - try: APEv2(filename).delete() - except APENoHeaderError: pass + try: + APEv2(filename).delete() + except APENoHeaderError: + pass + def APEValue(value, kind): """APEv2 tag value factory. @@ -365,10 +403,15 @@ def APEValue(value, kind): Use this if you need to specify the value's type manually. Binary and text data are automatically detected by APEv2.__setitem__. """ - if kind == TEXT: return APETextValue(value, kind) - elif kind == BINARY: return APEBinaryValue(value, kind) - elif kind == EXTERNAL: return APEExtValue(value, kind) - else: raise ValueError("kind must be TEXT, BINARY, or EXTERNAL") + if kind == TEXT: + return APETextValue(value, kind) + elif kind == BINARY: + return APEBinaryValue(value, kind) + elif kind == EXTERNAL: + return APEExtValue(value, kind) + else: + raise ValueError("kind must be TEXT, BINARY, or EXTERNAL") + class _APEValue(object): def __init__(self, value, kind): @@ -377,6 +420,7 @@ class _APEValue(object): def __len__(self): return len(self.value) + def __str__(self): return self.value @@ -387,13 +431,14 @@ class _APEValue(object): # 1B: Null # Key value def _internal(self, key): - return "%s%s\0%s" %( + return "%s%s\0%s" % ( struct.pack("<2I", len(self.value), self.kind << 1), key, self.value) def __repr__(self): return "%s(%r, %d)" % (type(self).__name__, self.value, self.kind) + class APETextValue(_APEValue): """An APEv2 text value. @@ -416,6 +461,8 @@ class APETextValue(_APEValue): def __cmp__(self, other): return cmp(unicode(self), other) + __hash__ = _APEValue.__hash__ + def __setitem__(self, index, value): values = list(self) values[index] = value.encode("utf-8") @@ -424,30 +471,42 @@ class APETextValue(_APEValue): def pprint(self): return " / ".join(self) + class APEBinaryValue(_APEValue): """An APEv2 binary value.""" - def pprint(self): return "[%d bytes]" % len(self) + def pprint(self): + return "[%d bytes]" % len(self) + class APEExtValue(_APEValue): """An APEv2 external value. External values are usually URI or IRI strings. """ - def pprint(self): return "[External] %s" % unicode(self) + def pprint(self): + return "[External] %s" % unicode(self) + class APEv2File(FileType): class _Info(object): length = 0 bitrate = 0 - def __init__(self, fileobj): pass - pprint = staticmethod(lambda: "Unknown format with APEv2 tag.") + + def __init__(self, fileobj): + pass + + @staticmethod + def pprint(): + return "Unknown format with APEv2 tag." def load(self, filename): self.filename = filename - self.info = self._Info(file(filename, "rb")) - try: self.tags = APEv2(filename) - except error: self.tags = None + self.info = self._Info(open(filename, "rb")) + try: + self.tags = APEv2(filename) + except error: + self.tags = None def add_tags(self): if self.tags is None: @@ -455,11 +514,12 @@ class APEv2File(FileType): else: raise ValueError("%r already has tags: %r" % (self, self.tags)) + @staticmethod def score(filename, fileobj, header): - try: fileobj.seek(-160, 2) + try: + fileobj.seek(-160, 2) except IOError: fileobj.seek(0) footer = fileobj.read() filename = filename.lower() return (("APETAGEX" in footer) - header.startswith("ID3")) - score = staticmethod(score) diff --git a/lib/mutagen/asf.py b/mutagen/asf.py similarity index 92% rename from lib/mutagen/asf.py rename to mutagen/asf.py index d7adfeb2..fab5559b 100644 --- a/lib/mutagen/asf.py +++ b/mutagen/asf.py @@ -4,20 +4,26 @@ # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. -# -# $Id: asf.py 4224 2007-12-03 09:01:49Z luks $ """Read and write ASF (Window Media Audio) files.""" __all__ = ["ASF", "Open"] import struct -from lib.mutagen import FileType, Metadata -from lib.mutagen._util import insert_bytes, delete_bytes, DictMixin +from mutagen import FileType, Metadata +from mutagen._util import insert_bytes, delete_bytes, DictMixin -class error(IOError): pass -class ASFError(error): pass -class ASFHeaderError(error): pass + +class error(IOError): + pass + + +class ASFError(error): + pass + + +class ASFHeaderError(error): + pass class ASFInfo(object): @@ -49,20 +55,26 @@ class ASFTags(list, DictMixin, Metadata): """ values = [value for (k, value) in self if k == key] - if not values: raise KeyError, key - else: return values + if not values: + raise KeyError(key) + else: + return values def __delitem__(self, key): """Delete all values associated with the key.""" to_delete = filter(lambda x: x[0] == key, self) - if not to_delete: raise KeyError, key - else: map(self.remove, to_delete) + if not to_delete: + raise KeyError(key) + else: + map(self.remove, to_delete) def __contains__(self, key): """Return true if the key has any values.""" for k, value in self: - if k == key: return True - else: return False + if k == key: + return True + else: + return False def __setitem__(self, key, values): """Set a key's value or values. @@ -74,8 +86,10 @@ class ASFTags(list, DictMixin, Metadata): """ if not isinstance(values, list): values = [values] - try: del(self[key]) - except KeyError: pass + try: + del(self[key]) + except KeyError: + pass for value in values: if key in _standard_attribute_names: value = unicode(value) @@ -151,6 +165,7 @@ class ASFBaseAttribute(object): return (struct.pack(" 0xFFFF + library_only = (value.data_size() > 0xFFFF or value.TYPE == GUID) if (value.language is None and value.stream is None and - name not in self.to_extended_content_description and - not large_value): + name not in self.to_extended_content_description and + not library_only): self.to_extended_content_description[name] = value elif (value.language is None and value.stream is not None and - name not in self.to_metadata and not large_value): + name not in self.to_metadata and not library_only): self.to_metadata[name] = value else: self.to_metadata_library.append((name, value)) @@ -625,7 +656,7 @@ class ASF(FileType): struct.pack(" self.size: @@ -637,10 +668,13 @@ class ASF(FileType): finally: fileobj.close() + self.size = size + self.num_objects = len(self.objects) + def __read_file(self, fileobj): header = fileobj.read(30) if len(header) != 30 or header[:16] != HeaderObject.GUID: - raise ASFHeaderError, "Not an ASF file." + raise ASFHeaderError("Not an ASF file.") self.extended_content_description_obj = None self.content_description_obj = None @@ -663,8 +697,8 @@ class ASF(FileType): obj.parse(self, data, fileobj, size) self.objects.append(obj) + @staticmethod def score(filename, fileobj, header): return header.startswith(HeaderObject.GUID) * 2 - score = staticmethod(score) Open = ASF diff --git a/lib/mutagen/easyid3.py b/mutagen/easyid3.py similarity index 86% rename from lib/mutagen/easyid3.py rename to mutagen/easyid3.py index 8158fb39..e69a5453 100644 --- a/lib/mutagen/easyid3.py +++ b/mutagen/easyid3.py @@ -4,8 +4,6 @@ # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License as # published by the Free Software Foundation. -# -# $Id: id3.py 3086 2006-04-04 02:13:21Z piman $ """Easier access to ID3 tags. @@ -13,16 +11,16 @@ EasyID3 is a wrapper around mutagen.id3.ID3 to make ID3 tags appear more like Vorbis or APEv2 tags. """ -from fnmatch import fnmatchcase +import mutagen.id3 -import lib.mutagen.id3 +from mutagen import Metadata +from mutagen._util import DictMixin, dict_match +from mutagen.id3 import ID3, error, delete, ID3FileType -from lib.mutagen import Metadata -from lib.mutagen._util import DictMixin, dict_match -from lib.mutagen.id3 import ID3, error, delete, ID3FileType __all__ = ['EasyID3', 'Open', 'delete'] + class EasyID3KeyError(KeyError, ValueError, error): """Raised when trying to get/set an invalid key. @@ -30,6 +28,7 @@ class EasyID3KeyError(KeyError, ValueError, error): catching KeyError is preferred. """ + class EasyID3(DictMixin, Metadata): """A file with an ID3 tag. @@ -44,19 +43,22 @@ class EasyID3(DictMixin, Metadata): keys. These can be set on EasyID3 or on individual instances after creation. - To use an EasyID3 class with mutagen.mp3.MP3: + To use an EasyID3 class with mutagen.mp3.MP3:: + from mutagen.mp3 import EasyMP3 as MP3 MP3(filename) Because many of the attributes are constructed on the fly, things - like the following will not work: + like the following will not work:: + ezid3["performer"].append("Joe") - Instead, you must do: + + Instead, you must do:: + values = ezid3["performer"] values.append("Joe") ezid3["performer"] = values - """ Set = {} @@ -71,7 +73,8 @@ class EasyID3(DictMixin, Metadata): SetFallback = None DeleteFallback = None ListFallback = None - + + @classmethod def RegisterKey(cls, key, getter=None, setter=None, deleter=None, lister=None): """Register a new key mapping. @@ -99,14 +102,15 @@ class EasyID3(DictMixin, Metadata): cls.Delete[key] = deleter if lister is not None: cls.List[key] = lister - RegisterKey = classmethod(RegisterKey) + @classmethod def RegisterTextKey(cls, key, frameid): """Register a text key. If the key you need to register is a simple one-to-one mapping of ID3 frame name to EasyID3 key, then you can use this - function: + function:: + EasyID3.RegisterTextKey("title", "TIT2") """ def getter(id3, key): @@ -116,7 +120,7 @@ class EasyID3(DictMixin, Metadata): try: frame = id3[frameid] except KeyError: - id3.add(lib.mutagen.id3.Frames[frameid](encoding=3, text=value)) + id3.add(mutagen.id3.Frames[frameid](encoding=3, text=value)) else: frame.encoding = 3 frame.text = value @@ -125,17 +129,19 @@ class EasyID3(DictMixin, Metadata): del(id3[frameid]) cls.RegisterKey(key, getter, setter, deleter) - RegisterTextKey = classmethod(RegisterTextKey) + @classmethod def RegisterTXXXKey(cls, key, desc): """Register a user-defined text frame key. Some ID3 tags are stored in TXXX frames, which allow a freeform 'description' which acts as a subkey, - e.g. TXXX:BARCODE. - EasyID3.RegisterTXXXKey('barcode', 'BARCODE'). + e.g. TXXX:BARCODE.:: + + EasyID3.RegisterTXXXKey('barcode', 'BARCODE'). """ frameid = "TXXX:" + desc + def getter(id3, key): return list(id3[frameid]) @@ -146,9 +152,9 @@ class EasyID3(DictMixin, Metadata): enc = 0 # Store 8859-1 if we can, per MusicBrainz spec. for v in value: - if max(v) > u'\x7f': + if v and max(v) > u'\x7f': enc = 3 - id3.add(lib.mutagen.id3.TXXX(encoding=enc, text=value, desc=desc)) + id3.add(mutagen.id3.TXXX(encoding=enc, text=value, desc=desc)) else: frame.text = value @@ -156,21 +162,26 @@ class EasyID3(DictMixin, Metadata): del(id3[frameid]) cls.RegisterKey(key, getter, setter, deleter) - RegisterTXXXKey = classmethod(RegisterTXXXKey) def __init__(self, filename=None): self.__id3 = ID3() - self.load = self.__id3.load - self.save = self.__id3.save - self.delete = self.__id3.delete if filename is not None: self.load(filename) + load = property(lambda s: s.__id3.load, + lambda s, v: setattr(s.__id3, 'load', v)) + + save = property(lambda s: s.__id3.save, + lambda s, v: setattr(s.__id3, 'save', v)) + + delete = property(lambda s: s.__id3.delete, + lambda s, v: setattr(s.__id3, 'delete', v)) + filename = property(lambda s: s.__id3.filename, lambda s, fn: setattr(s.__id3, 'filename', fn)) - _size = property(lambda s: s._id3.size, - lambda s, fn: setattr(s.__id3, '_size', fn)) + size = property(lambda s: s.__id3.size, + lambda s, fn: setattr(s.__id3, 'size', s)) def __getitem__(self, key): key = key.lower() @@ -218,32 +229,40 @@ class EasyID3(DictMixin, Metadata): strings.append("%s=%s" % (key, value)) return "\n".join(strings) + Open = EasyID3 + def genre_get(id3, key): return id3["TCON"].genres + def genre_set(id3, key, value): try: frame = id3["TCON"] except KeyError: - id3.add(lib.mutagen.id3.TCON(encoding=3, text=value)) + id3.add(mutagen.id3.TCON(encoding=3, text=value)) else: frame.encoding = 3 frame.genres = value + def genre_delete(id3, key): del(id3["TCON"]) + def date_get(id3, key): return [stamp.text for stamp in id3["TDRC"].text] + def date_set(id3, key, value): - id3.add(lib.mutagen.id3.TDRC(encoding=3, text=value)) + id3.add(mutagen.id3.TDRC(encoding=3, text=value)) + def date_delete(id3, key): del(id3["TDRC"]) + def performer_get(id3, key): people = [] wanted_role = key.split(":", 1)[1] @@ -258,13 +277,14 @@ def performer_get(id3, key): return people else: raise KeyError(key) - + + def performer_set(id3, key, value): wanted_role = key.split(":", 1)[1] try: mcl = id3["TMCL"] except KeyError: - mcl = lib.mutagen.id3.TMCL(encoding=3, people=[]) + mcl = mutagen.id3.TMCL(encoding=3, people=[]) id3.add(mcl) mcl.encoding = 3 people = [p for p in mcl.people if p[0] != wanted_role] @@ -272,6 +292,7 @@ def performer_set(id3, key, value): people.append((wanted_role, v)) mcl.people = people + def performer_delete(id3, key): wanted_role = key.split(":", 1)[1] try: @@ -285,17 +306,21 @@ def performer_delete(id3, key): mcl.people = people else: del(id3["TMCL"]) - + + def performer_list(id3, key): - try: mcl = id3["TMCL"] + try: + mcl = id3["TMCL"] except KeyError: return [] else: return list(set("performer:" + p[0] for p in mcl.people)) + def musicbrainz_trackid_get(id3, key): return [id3["UFID:http://musicbrainz.org"].data.decode('ascii')] + def musicbrainz_trackid_set(id3, key, value): if len(value) != 1: raise ValueError("only one track ID may be set per song") @@ -303,14 +328,16 @@ def musicbrainz_trackid_set(id3, key, value): try: frame = id3["UFID:http://musicbrainz.org"] except KeyError: - frame = lib.mutagen.id3.UFID(owner="http://musicbrainz.org", data=value) + frame = mutagen.id3.UFID(owner="http://musicbrainz.org", data=value) id3.add(frame) else: frame.data = value + def musicbrainz_trackid_delete(id3, key): del(id3["UFID:http://musicbrainz.org"]) + def website_get(id3, key): urls = [frame.url for frame in id3.getall("WOAR")] if urls: @@ -318,14 +345,17 @@ def website_get(id3, key): else: raise EasyID3KeyError(key) + def website_set(id3, key, value): id3.delall("WOAR") for v in value: - id3.add(lib.mutagen.id3.WOAR(url=v)) + id3.add(mutagen.id3.WOAR(url=v)) + def website_delete(id3, key): id3.delall("WOAR") + def gain_get(id3, key): try: frame = id3["RVA2:" + key[11:-5]] @@ -334,17 +364,20 @@ def gain_get(id3, key): else: return [u"%+f dB" % frame.gain] + def gain_set(id3, key, value): if len(value) != 1: - raise ValueError("there must be exactly one gain value, not %r.", value) + raise ValueError( + "there must be exactly one gain value, not %r.", value) gain = float(value[0].split()[0]) try: frame = id3["RVA2:" + key[11:-5]] except KeyError: - frame = lib.mutagen.id3.RVA2(desc=key[11:-5], gain=0, peak=0, channel=1) + frame = mutagen.id3.RVA2(desc=key[11:-5], gain=0, peak=0, channel=1) id3.add(frame) frame.gain = gain + def gain_delete(id3, key): try: frame = id3["RVA2:" + key[11:-5]] @@ -356,6 +389,7 @@ def gain_delete(id3, key): else: del(id3["RVA2:" + key[11:-5]]) + def peak_get(id3, key): try: frame = id3["RVA2:" + key[11:-5]] @@ -364,19 +398,22 @@ def peak_get(id3, key): else: return [u"%f" % frame.peak] + def peak_set(id3, key, value): if len(value) != 1: - raise ValueError("there must be exactly one peak value, not %r.", value) + raise ValueError( + "there must be exactly one peak value, not %r.", value) peak = float(value[0]) if peak >= 2 or peak < 0: raise ValueError("peak must be => 0 and < 2.") try: frame = id3["RVA2:" + key[11:-5]] except KeyError: - frame = lib.mutagen.id3.RVA2(desc=key[11:-5], gain=0, peak=0, channel=1) + frame = mutagen.id3.RVA2(desc=key[11:-5], gain=0, peak=0, channel=1) id3.add(frame) frame.peak = peak + def peak_delete(id3, key): try: frame = id3["RVA2:" + key[11:-5]] @@ -388,6 +425,7 @@ def peak_delete(id3, key): else: del(id3["RVA2:" + key[11:-5]]) + def peakgain_list(id3, key): keys = [] for frame in id3.getall("RVA2"): @@ -398,7 +436,7 @@ def peakgain_list(id3, key): for frameid, key in { "TALB": "album", "TBPM": "bpm", - "TCMP": "compilation", # iTunes extension + "TCMP": "compilation", # iTunes extension "TCOM": "composer", "TCOP": "copyright", "TENC": "encodedby", @@ -409,21 +447,21 @@ for frameid, key in { "TIT2": "title", "TIT3": "version", "TPE1": "artist", - "TPE2": "performer", + "TPE2": "performer", "TPE3": "conductor", "TPE4": "arranger", "TPOS": "discnumber", "TPUB": "organization", "TRCK": "tracknumber", "TOLY": "author", - "TSO2": "albumartistsort", # iTunes extension + "TSO2": "albumartistsort", # iTunes extension "TSOA": "albumsort", - "TSOC": "composersort", # iTunes extension + "TSOC": "composersort", # iTunes extension "TSOP": "artistsort", "TSOT": "titlesort", "TSRC": "isrc", "TSST": "discsubtitle", - }.iteritems(): +}.iteritems(): EasyID3.RegisterTextKey(key, frameid) EasyID3.RegisterKey("genre", genre_get, genre_set, genre_delete) @@ -457,9 +495,10 @@ for desc, key in { u"ASIN": "asin", u"ALBUMARTISTSORT": "albumartistsort", u"BARCODE": "barcode", - }.iteritems(): +}.iteritems(): EasyID3.RegisterTXXXKey(key, desc) + class EasyID3FileType(ID3FileType): """Like ID3FileType, but uses EasyID3 for tags.""" ID3 = EasyID3 diff --git a/lib/mutagen/easymp4.py b/mutagen/easymp4.py similarity index 89% rename from lib/mutagen/easymp4.py rename to mutagen/easymp4.py index bcec19a9..3abacccc 100644 --- a/lib/mutagen/easymp4.py +++ b/mutagen/easymp4.py @@ -1,21 +1,29 @@ -import lib.mutagen.mp4 +# Copyright 2009 Joe Wreschnig +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. -from lib.mutagen import Metadata -from lib.mutagen._util import DictMixin, dict_match, utf8 -from libmutagen.mp4 import MP4, MP4Tags, error, delete +from mutagen import Metadata +from mutagen._util import DictMixin, dict_match, utf8 +from mutagen.mp4 import MP4, MP4Tags, error, delete __all__ = ["EasyMP4Tags", "EasyMP4", "delete", "error"] + class EasyMP4KeyError(error, KeyError, ValueError): pass + class EasyMP4Tags(DictMixin, Metadata): """A file with MPEG-4 iTunes metadata. Like Vorbis comments, EasyMP4Tags keys are case-insensitive ASCII strings, and values are a list of Unicode strings (and these lists - are always of length 0 or 1). If you need access to the full MP4 - metadata feature set, you should use MP4, not EasyMP4. + are always of length 0 or 1). + + If you need access to the full MP4 metadata feature set, you should use + MP4, not EasyMP4. """ Set = {} @@ -32,6 +40,7 @@ class EasyMP4Tags(DictMixin, Metadata): filename = property(lambda s: s.__mp4.filename, lambda s, fn: setattr(s.__mp4, 'filename', fn)) + @classmethod def RegisterKey(cls, key, getter=None, setter=None, deleter=None, lister=None): """Register a new key mapping. @@ -59,14 +68,15 @@ class EasyMP4Tags(DictMixin, Metadata): cls.Delete[key] = deleter if lister is not None: cls.List[key] = lister - RegisterKey = classmethod(RegisterKey) + @classmethod def RegisterTextKey(cls, key, atomid): """Register a text key. If the key you need to register is a simple one-to-one mapping of MP4 atom name to EasyMP4Tags key, then you can use this - function: + function:: + EasyMP4Tags.RegisterTextKey("artist", "\xa9ART") """ def getter(tags, key): @@ -79,8 +89,8 @@ class EasyMP4Tags(DictMixin, Metadata): del(tags[atomid]) cls.RegisterKey(key, getter, setter, deleter) - RegisterTextKey = classmethod(RegisterTextKey) + @classmethod def RegisterIntKey(cls, key, atomid, min_value=0, max_value=2**16-1): """Register a scalar integer key. """ @@ -96,8 +106,8 @@ class EasyMP4Tags(DictMixin, Metadata): del(tags[atomid]) cls.RegisterKey(key, getter, setter, deleter) - RegisterIntKey = classmethod(RegisterIntKey) + @classmethod def RegisterIntPairKey(cls, key, atomid, min_value=0, max_value=2**16-1): def getter(tags, key): ret = [] @@ -126,14 +136,15 @@ class EasyMP4Tags(DictMixin, Metadata): del(tags[atomid]) cls.RegisterKey(key, getter, setter, deleter) - RegisterIntPairKey = classmethod(RegisterIntPairKey) + @classmethod def RegisterFreeformKey(cls, key, name, mean="com.apple.iTunes"): """Register a text key. If the key you need to register is a simple one-to-one mapping of MP4 freeform atom (----) and name to EasyMP4Tags key, then - you can use this function: + you can use this function:: + EasyMP4Tags.RegisterFreeformKey( "musicbrainz_artistid", "MusicBrainz Artist Id") """ @@ -149,7 +160,6 @@ class EasyMP4Tags(DictMixin, Metadata): del(tags[atomid]) cls.RegisterKey(key, getter, setter, deleter) - RegisterFreeformKey = classmethod(RegisterFreeformKey) def __getitem__(self, key): key = key.lower() @@ -211,7 +221,7 @@ for atomid, key in { 'soar': 'artistsort', 'sonm': 'titlesort', 'soco': 'composersort', - }.items(): +}.items(): EasyMP4Tags.RegisterTextKey(key, atomid) for name, key in { @@ -223,22 +233,29 @@ for name, key in { 'MusicBrainz Album Status': 'musicbrainz_albumstatus', 'MusicBrainz Album Type': 'musicbrainz_albumtype', 'MusicBrainz Release Country': 'releasecountry', - }.items(): +}.items(): EasyMP4Tags.RegisterFreeformKey(key, name) for name, key in { "tmpo": "bpm", - }.items(): +}.items(): EasyMP4Tags.RegisterIntKey(key, name) for name, key in { "trkn": "tracknumber", "disk": "discnumber", - }.items(): +}.items(): EasyMP4Tags.RegisterIntPairKey(key, name) + class EasyMP4(MP4): - """Like MP4, but uses EasyMP4Tags for tags.""" + """Like :class:`MP4 `, + but uses :class:`EasyMP4Tags` for tags. + + :ivar info: :class:`MP4Info ` + :ivar tags: :class:`EasyMP4Tags` + """ + MP4Tags = EasyMP4Tags Get = EasyMP4Tags.Get diff --git a/lib/mutagen/flac.py b/mutagen/flac.py similarity index 61% rename from lib/mutagen/flac.py rename to mutagen/flac.py index 00bce539..f8e014bc 100644 --- a/lib/mutagen/flac.py +++ b/mutagen/flac.py @@ -24,19 +24,53 @@ __all__ = ["FLAC", "Open", "delete"] import struct from cStringIO import StringIO from _vorbis import VCommentDict -from lib.mutagen import FileType -from lib.mutagen._util import insert_bytes -from lib.mutagen.id3 import BitPaddedInt +from mutagen import FileType +from mutagen._util import insert_bytes +from mutagen.id3 import BitPaddedInt +import sys +if sys.version_info >= (2, 6): + from functools import reduce + + +class error(IOError): + pass + + +class FLACNoHeaderError(error): + pass + + +class FLACVorbisError(ValueError, error): + pass -class error(IOError): pass -class FLACNoHeaderError(error): pass -class FLACVorbisError(ValueError, error): pass def to_int_be(string): """Convert an arbitrarily-long string to a long using big-endian byte order.""" return reduce(lambda a, b: (a << 8) + ord(b), string, 0L) + +class StrictFileObject(object): + """Wraps a file-like object and raises an exception if the requested + amount of data to read isn't returned.""" + + def __init__(self, fileobj): + self._fileobj = fileobj + for m in ["close", "tell", "seek", "write", "name"]: + if hasattr(fileobj, m): + setattr(self, m, getattr(fileobj, m)) + + def read(self, size=-1): + data = self._fileobj.read(size) + if size >= 0 and len(data) != size: + raise error("file said %d bytes, read %d bytes" % ( + size, len(data))) + return data + + def tryread(self, *args): + return self._fileobj.read(*args) + + class MetadataBlock(object): """A generic block of FLAC metadata. @@ -44,22 +78,32 @@ class MetadataBlock(object): blocks, and also as a container for data blobs of unknown blocks. Attributes: - data -- raw binary data for this block + + * data -- raw binary data for this block """ + _distrust_size = False + def __init__(self, data): """Parse the given data string or file-like as a metadata block. The metadata header should not be included.""" if data is not None: - if isinstance(data, str): data = StringIO(data) - elif not hasattr(data, 'read'): - raise TypeError( - "StreamInfo requires string data or a file-like") + if not isinstance(data, StrictFileObject): + if isinstance(data, str): + data = StringIO(data) + elif not hasattr(data, 'read'): + raise TypeError( + "StreamInfo requires string data or a file-like") + data = StrictFileObject(data) self.load(data) - def load(self, data): self.data = data.read() - def write(self): return self.data + def load(self, data): + self.data = data.read() + def write(self): + return self.data + + @staticmethod def writeblocks(blocks): """Render metadata block as a byte string.""" data = [] @@ -72,8 +116,8 @@ class MetadataBlock(object): length = struct.pack(">I", len(datum))[-3:] data.append(byte + length + datum) return "".join(data) - writeblocks = staticmethod(writeblocks) + @staticmethod def group_padding(blocks): """Consolidate FLAC padding metadata blocks. @@ -81,13 +125,13 @@ class MetadataBlock(object): this adds several bytes of padding for each merged block.""" paddings = filter(lambda x: isinstance(x, Padding), blocks) map(blocks.remove, paddings) - padding = Padding() # total padding size is the sum of padding sizes plus 4 bytes # per removed header. size = sum([padding.length for padding in paddings]) + padding = Padding() padding.length = size + 4 * (len(paddings) - 1) blocks.append(padding) - group_padding = staticmethod(group_padding) + class StreamInfo(MetadataBlock): """FLAC stream information. @@ -99,25 +143,30 @@ class StreamInfo(MetadataBlock): attributes of this block. Attributes: - min_blocksize -- minimum audio block size - max_blocksize -- maximum audio block size - sample_rate -- audio sample rate in Hz - channels -- audio channels (1 for mono, 2 for stereo) - bits_per_sample -- bits per sample - total_samples -- total samples in file - length -- audio length in seconds + + * min_blocksize -- minimum audio block size + * max_blocksize -- maximum audio block size + * sample_rate -- audio sample rate in Hz + * channels -- audio channels (1 for mono, 2 for stereo) + * bits_per_sample -- bits per sample + * total_samples -- total samples in file + * length -- audio length in seconds """ code = 0 def __eq__(self, other): - try: return (self.min_blocksize == other.min_blocksize and - self.max_blocksize == other.max_blocksize and - self.sample_rate == other.sample_rate and - self.channels == other.channels and - self.bits_per_sample == other.bits_per_sample and - self.total_samples == other.total_samples) - except: return False + try: + return (self.min_blocksize == other.min_blocksize and + self.max_blocksize == other.max_blocksize and + self.sample_rate == other.sample_rate and + self.channels == other.channels and + self.bits_per_sample == other.bits_per_sample and + self.total_samples == other.total_samples) + except: + return False + + __hash__ = MetadataBlock.__hash__ def load(self, data): self.min_blocksize = int(to_int_be(data.read(2))) @@ -133,6 +182,8 @@ class StreamInfo(MetadataBlock): sample_tail = sample_channels_bps >> 4 self.sample_rate = int((sample_first << 4) + sample_tail) + if not self.sample_rate: + raise error("A sample rate value of 0 is invalid") self.channels = int(((sample_channels_bps >> 1) & 7) + 1) bps_tail = bps_total >> 36 bps_head = (sample_channels_bps & 1) << 4 @@ -157,7 +208,7 @@ class StreamInfo(MetadataBlock): byte += ((self.bits_per_sample - 1) >> 4) & 1 f.write(chr(byte)) # 4 bits of bps, 4 of sample count - byte = ((self.bits_per_sample - 1) & 0xF) << 4 + byte = ((self.bits_per_sample - 1) & 0xF) << 4 byte += (self.total_samples >> 32) & 0xF f.write(chr(byte)) # last 32 of sample count @@ -172,6 +223,7 @@ class StreamInfo(MetadataBlock): def pprint(self): return "FLAC, %.2f seconds, %d Hz" % (self.length, self.sample_rate) + class SeekPoint(tuple): """A single seek point in a FLAC file. @@ -183,23 +235,27 @@ class SeekPoint(tuple): may be any number of them. Attributes: - first_sample -- sample number of first sample in the target frame - byte_offset -- offset from first frame to target frame - num_samples -- number of samples in target frame + + * first_sample -- sample number of first sample in the target frame + * byte_offset -- offset from first frame to target frame + * num_samples -- number of samples in target frame """ def __new__(cls, first_sample, byte_offset, num_samples): - return super(cls, SeekPoint).__new__(cls, (first_sample, - byte_offset, num_samples)) + return super(cls, SeekPoint).__new__( + cls, (first_sample, byte_offset, num_samples)) + first_sample = property(lambda self: self[0]) byte_offset = property(lambda self: self[1]) num_samples = property(lambda self: self[2]) + class SeekTable(MetadataBlock): """Read and write FLAC seek tables. Attributes: - seekpoints -- list of SeekPoint objects + + * seekpoints -- list of SeekPoint objects """ __SEEKPOINT_FORMAT = '>QQH' @@ -212,21 +268,26 @@ class SeekTable(MetadataBlock): super(SeekTable, self).__init__(data) def __eq__(self, other): - try: return (self.seekpoints == other.seekpoints) - except (AttributeError, TypeError): return False + try: + return (self.seekpoints == other.seekpoints) + except (AttributeError, TypeError): + return False + + __hash__ = MetadataBlock.__hash__ def load(self, data): self.seekpoints = [] - sp = data.read(self.__SEEKPOINT_SIZE) + sp = data.tryread(self.__SEEKPOINT_SIZE) while len(sp) == self.__SEEKPOINT_SIZE: self.seekpoints.append(SeekPoint( *struct.unpack(self.__SEEKPOINT_FORMAT, sp))) - sp = data.read(self.__SEEKPOINT_SIZE) + sp = data.tryread(self.__SEEKPOINT_SIZE) def write(self): f = StringIO() for seekpoint in self.seekpoints: - packed = struct.pack(self.__SEEKPOINT_FORMAT, + packed = struct.pack( + self.__SEEKPOINT_FORMAT, seekpoint.first_sample, seekpoint.byte_offset, seekpoint.num_samples) f.write(packed) @@ -235,6 +296,7 @@ class SeekTable(MetadataBlock): def __repr__(self): return "<%s seekpoints=%r>" % (type(self).__name__, self.seekpoints) + class VCFLACDict(VCommentDict): """Read and write FLAC Vorbis comments. @@ -243,6 +305,7 @@ class VCFLACDict(VCommentDict): """ code = 4 + _distrust_size = True def load(self, data, errors='replace', framing=False): super(VCFLACDict, self).load(data, errors=errors, framing=framing) @@ -250,6 +313,7 @@ class VCFLACDict(VCommentDict): def write(self, framing=False): return super(VCFLACDict, self).write(framing=framing) + class CueSheetTrackIndex(tuple): """Index for a track in a cuesheet. @@ -260,16 +324,19 @@ class CueSheetTrackIndex(tuple): divisible by 588 samples. Attributes: - index_number -- index point number - index_offset -- offset in samples from track start + + * index_number -- index point number + * index_offset -- offset in samples from track start """ - + def __new__(cls, index_number, index_offset): - return super(cls, CueSheetTrackIndex).__new__(cls, - (index_number, index_offset)) + return super(cls, CueSheetTrackIndex).__new__( + cls, (index_number, index_offset)) + index_number = property(lambda self: self[0]) index_offset = property(lambda self: self[1]) + class CueSheetTrack(object): """A track in a cuesheet. @@ -279,12 +346,13 @@ class CueSheetTrack(object): which must have none. Attributes: - track_number -- track number - start_offset -- track offset in samples from start of FLAC stream - isrc -- ISRC code - type -- 0 for audio, 1 for digital data - pre_emphasis -- true if the track is recorded with pre-emphasis - indexes -- list of CueSheetTrackIndex objects + + * track_number -- track number + * start_offset -- track offset in samples from start of FLAC stream + * isrc -- ISRC code + * type -- 0 for audio, 1 for digital data + * pre_emphasis -- true if the track is recorded with pre-emphasis + * indexes -- list of CueSheetTrackIndex objects """ def __init__(self, track_number, start_offset, isrc='', type_=0, @@ -297,19 +365,24 @@ class CueSheetTrack(object): self.indexes = [] def __eq__(self, other): - try: return (self.track_number == other.track_number and - self.start_offset == other.start_offset and - self.isrc == other.isrc and - self.type == other.type and - self.pre_emphasis == other.pre_emphasis and - self.indexes == other.indexes) - except (AttributeError, TypeError): return False + try: + return (self.track_number == other.track_number and + self.start_offset == other.start_offset and + self.isrc == other.isrc and + self.type == other.type and + self.pre_emphasis == other.pre_emphasis and + self.indexes == other.indexes) + except (AttributeError, TypeError): + return False + + __hash__ = object.__hash__ def __repr__(self): return ("<%s number=%r, offset=%d, isrc=%r, type=%r, " "pre_emphasis=%r, indexes=%r)>") % ( - type(self).__name__, self.track_number, self.start_offset, - self.isrc, self.type, self.pre_emphasis, self.indexes) + type(self).__name__, self.track_number, self.start_offset, + self.isrc, self.type, self.pre_emphasis, self.indexes) + class CueSheet(MetadataBlock): """Read and write FLAC embedded cue sheets. @@ -319,11 +392,12 @@ class CueSheet(MetadataBlock): in the cue sheet. Attributes: - media_catalog_number -- media catalog number in ASCII - lead_in_samples -- number of lead-in samples - compact_disc -- true if the cuesheet corresponds to a compact disc - tracks -- list of CueSheetTrack objects - lead_out -- lead-out as CueSheetTrack or None if lead-out was not found + + * media_catalog_number -- media catalog number in ASCII + * lead_in_samples -- number of lead-in samples + * compact_disc -- true if the cuesheet corresponds to a compact disc + * tracks -- list of CueSheetTrack objects + * lead_out -- lead-out as CueSheetTrack or None if lead-out was not found """ __CUESHEET_FORMAT = '>128sQB258xB' @@ -346,10 +420,13 @@ class CueSheet(MetadataBlock): def __eq__(self, other): try: return (self.media_catalog_number == other.media_catalog_number and - self.lead_in_samples == other.lead_in_samples and - self.compact_disc == other.compact_disc and - self.tracks == other.tracks) - except (AttributeError, TypeError): return False + self.lead_in_samples == other.lead_in_samples and + self.compact_disc == other.compact_disc and + self.tracks == other.tracks) + except (AttributeError, TypeError): + return False + + __hash__ = MetadataBlock.__hash__ def load(self, data): header = data.read(self.__CUESHEET_SIZE) @@ -359,7 +436,7 @@ class CueSheet(MetadataBlock): self.lead_in_samples = lead_in_samples self.compact_disc = bool(flags & 0x80) self.tracks = [] - for i in range(num_tracks): + for i in range(num_tracks): track = data.read(self.__CUESHEET_TRACK_SIZE) start_offset, track_number, isrc_padded, flags, num_indexes = \ struct.unpack(self.__CUESHEET_TRACK_FORMAT, track) @@ -375,11 +452,12 @@ class CueSheet(MetadataBlock): val.indexes.append( CueSheetTrackIndex(index_number, index_offset)) self.tracks.append(val) - + def write(self): f = StringIO() flags = 0 - if self.compact_disc: flags |= 0x80 + if self.compact_disc: + flags |= 0x80 packed = struct.pack( self.__CUESHEET_FORMAT, self.media_catalog_number, self.lead_in_samples, flags, len(self.tracks)) @@ -387,7 +465,8 @@ class CueSheet(MetadataBlock): for track in self.tracks: track_flags = 0 track_flags |= (track.type & 1) << 7 - if track.pre_emphasis: track_flags |= 0x40 + if track.pre_emphasis: + track_flags |= 0x40 track_packed = struct.pack( self.__CUESHEET_TRACK_FORMAT, track.start_offset, track.track_number, track.isrc, track_flags, @@ -403,25 +482,28 @@ class CueSheet(MetadataBlock): def __repr__(self): return ("<%s media_catalog_number=%r, lead_in=%r, compact_disc=%r, " "tracks=%r>") % ( - type(self).__name__, self.media_catalog_number, - self.lead_in_samples, self.compact_disc, self.tracks) + type(self).__name__, self.media_catalog_number, + self.lead_in_samples, self.compact_disc, self.tracks) + class Picture(MetadataBlock): """Read and write FLAC embed pictures. Attributes: - type -- picture type (same as types for ID3 APIC frames) - mime -- MIME type of the picture - desc -- picture's description - width -- width in pixels - height -- height in pixels - depth -- color depth in bits-per-pixel - colors -- number of colors for indexed palettes (like GIF), - 0 for non-indexed - data -- picture data + + * type -- picture type (same as types for ID3 APIC frames) + * mime -- MIME type of the picture + * desc -- picture's description + * width -- width in pixels + * height -- height in pixels + * depth -- color depth in bits-per-pixel + * colors -- number of colors for indexed palettes (like GIF), + 0 for non-indexed + * data -- picture data """ code = 6 + _distrust_size = True def __init__(self, data=None): self.type = 0 @@ -435,15 +517,19 @@ class Picture(MetadataBlock): super(Picture, self).__init__(data) def __eq__(self, other): - try: return (self.type == other.type and - self.mime == other.mime and - self.desc == other.desc and - self.width == other.width and - self.height == other.height and - self.depth == other.depth and - self.colors == other.colors and - self.data == other.data) - except (AttributeError, TypeError): return False + try: + return (self.type == other.type and + self.mime == other.mime and + self.desc == other.desc and + self.width == other.width and + self.height == other.height and + self.depth == other.depth and + self.colors == other.colors and + self.data == other.data) + except (AttributeError, TypeError): + return False + + __hash__ = MetadataBlock.__hash__ def load(self, data): self.type, length = struct.unpack('>2I', data.read(8)) @@ -471,6 +557,7 @@ class Picture(MetadataBlock): return "<%s '%s' (%d bytes)>" % (type(self).__name__, self.mime, len(self.data)) + class Padding(MetadataBlock): """Empty padding space for metadata blocks. @@ -482,10 +569,15 @@ class Padding(MetadataBlock): code = 1 - def __init__(self, data=""): super(Padding, self).__init__(data) - def load(self, data): self.length = len(data.read()) + def __init__(self, data=""): + super(Padding, self).__init__(data) + + def load(self, data): + self.length = len(data.read()) + def write(self): - try: return "\x00" * self.length + try: + return "\x00" * self.length # On some 64 bit platforms this won't generate a MemoryError # or OverflowError since you might have enough RAM, but it # still generates a ValueError. On other 64 bit platforms, @@ -494,65 +586,92 @@ class Padding(MetadataBlock): # do, writeblocks will catch it. except (OverflowError, ValueError, MemoryError): raise error("cannot write %d bytes" % self.length) + def __eq__(self, other): return isinstance(other, Padding) and self.length == other.length + + __hash__ = MetadataBlock.__hash__ + def __repr__(self): return "<%s (%d bytes)>" % (type(self).__name__, self.length) + class FLAC(FileType): """A FLAC audio file. - + Attributes: - info -- stream information (length, bitrate, sample rate) - tags -- metadata tags, if any - cuesheet -- CueSheet object, if any - seektable -- SeekTable object, if any - pictures -- list of embedded pictures + + * info -- stream information (length, bitrate, sample rate) + * tags -- metadata tags, if any + * cuesheet -- CueSheet object, if any + * seektable -- SeekTable object, if any + * pictures -- list of embedded pictures """ _mimes = ["audio/x-flac", "application/x-flac"] METADATA_BLOCKS = [StreamInfo, Padding, None, SeekTable, VCFLACDict, - CueSheet, Picture] + CueSheet, Picture] """Known metadata block types, indexed by ID.""" + @staticmethod def score(filename, fileobj, header): return (header.startswith("fLaC") + filename.lower().endswith(".flac") * 3) - score = staticmethod(score) - def __read_metadata_block(self, file): - byte = ord(file.read(1)) - size = to_int_be(file.read(3)) + def __read_metadata_block(self, fileobj): + byte = ord(fileobj.read(1)) + size = to_int_be(fileobj.read(3)) + code = byte & 0x7F + last_block = bool(byte & 0x80) + try: - data = file.read(size) - if len(data) != size: - raise error( - "file said %d bytes, read %d bytes" % (size, len(data))) - block = self.METADATA_BLOCKS[byte & 0x7F](data) - except (IndexError, TypeError): - block = MetadataBlock(data) - block.code = byte & 0x7F - self.metadata_blocks.append(block) + block_type = self.METADATA_BLOCKS[code] or MetadataBlock + except IndexError: + block_type = MetadataBlock + + if block_type._distrust_size: + # Some jackass is writing broken Metadata block length + # for Vorbis comment blocks, and the FLAC reference + # implementaton can parse them (mostly by accident), + # so we have to too. Instead of parsing the size + # given, parse an actual Vorbis comment, leaving + # fileobj in the right position. + # http://code.google.com/p/mutagen/issues/detail?id=52 + # ..same for the Picture block: + # http://code.google.com/p/mutagen/issues/detail?id=106 + block = block_type(fileobj) else: - self.metadata_blocks.append(block) - if block.code == VCFLACDict.code: - if self.tags is None: self.tags = block - else: raise FLACVorbisError("> 1 Vorbis comment block found") - elif block.code == CueSheet.code: - if self.cuesheet is None: self.cuesheet = block - else: raise error("> 1 CueSheet block found") - elif block.code == SeekTable.code: - if self.seektable is None: self.seektable = block - else: raise error("> 1 SeekTable block found") - return (byte >> 7) ^ 1 + data = fileobj.read(size) + block = block_type(data) + block.code = code + + if block.code == VCFLACDict.code: + if self.tags is None: + self.tags = block + else: + raise FLACVorbisError("> 1 Vorbis comment block found") + elif block.code == CueSheet.code: + if self.cuesheet is None: + self.cuesheet = block + else: + raise error("> 1 CueSheet block found") + elif block.code == SeekTable.code: + if self.seektable is None: + self.seektable = block + else: + raise error("> 1 SeekTable block found") + self.metadata_blocks.append(block) + return not last_block def add_tags(self): """Add a Vorbis comment block to the file.""" if self.tags is None: self.tags = VCFLACDict() self.metadata_blocks.append(self.tags) - else: raise FLACVorbisError("a Vorbis comment already exists") + else: + raise FLACVorbisError("a Vorbis comment already exists") + add_vorbiscomment = add_tags def delete(self, filename=None): @@ -560,7 +679,8 @@ class FLAC(FileType): If no filename is given, the one most recently loaded is used. """ - if filename is None: filename = self.filename + if filename is None: + filename = self.filename for s in list(self.metadata_blocks): if isinstance(s, VCFLACDict): self.metadata_blocks.remove(s) @@ -578,13 +698,11 @@ class FLAC(FileType): self.cuesheet = None self.seektable = None self.filename = filename - fileobj = file(filename, "rb") + fileobj = StrictFileObject(open(filename, "rb")) try: self.__check_header(fileobj) while self.__read_metadata_block(fileobj): pass - if fileobj.read(2) not in ["\xff\xf8", "\xff\xf9"]: - raise FLACNoHeaderError("End of metadata did not start audio") finally: fileobj.close() @@ -593,7 +711,9 @@ class FLAC(FileType): except (AttributeError, IndexError): raise FLACNoHeaderError("Stream info block not found") - info = property(lambda s: s.metadata_blocks[0]) + @property + def info(self): + return self.metadata_blocks[0] def add_picture(self, picture): """Add a new picture to the file.""" @@ -604,9 +724,10 @@ class FLAC(FileType): self.metadata_blocks = filter(lambda b: b.code != Picture.code, self.metadata_blocks) - def __get_pictures(self): + @property + def pictures(self): + """List of embedded pictures""" return filter(lambda b: b.code == Picture.code, self.metadata_blocks) - pictures = property(__get_pictures, doc="List of embedded pictures") def save(self, filename=None, deleteid3=False): """Save metadata blocks to a file. @@ -614,61 +735,78 @@ class FLAC(FileType): If no filename is given, the one most recently loaded is used. """ - if filename is None: filename = self.filename + if filename is None: + filename = self.filename f = open(filename, 'rb+') - # Ensure we've got padding at the end, and only at the end. - # If adding makes it too large, we'll scale it down later. - self.metadata_blocks.append(Padding('\x00' * 1020)) - MetadataBlock.group_padding(self.metadata_blocks) + try: + # Ensure we've got padding at the end, and only at the end. + # If adding makes it too large, we'll scale it down later. + self.metadata_blocks.append(Padding('\x00' * 1020)) + MetadataBlock.group_padding(self.metadata_blocks) - header = self.__check_header(f) - available = self.__find_audio_offset(f) - header # "fLaC" and maybe ID3 - data = MetadataBlock.writeblocks(self.metadata_blocks) + header = self.__check_header(f) + # "fLaC" and maybe ID3 + available = self.__find_audio_offset(f) - header + data = MetadataBlock.writeblocks(self.metadata_blocks) - # Delete ID3v2 - if deleteid3 and header > 4: - available += header - 4 - header = 4 + # Delete ID3v2 + if deleteid3 and header > 4: + available += header - 4 + header = 4 - if len(data) > available: - # If we have too much data, see if we can reduce padding. - padding = self.metadata_blocks[-1] - newlength = padding.length - (len(data) - available) - if newlength > 0: - padding.length = newlength + if len(data) > available: + # If we have too much data, see if we can reduce padding. + padding = self.metadata_blocks[-1] + newlength = padding.length - (len(data) - available) + if newlength > 0: + padding.length = newlength + data = MetadataBlock.writeblocks(self.metadata_blocks) + assert len(data) == available + + elif len(data) < available: + # If we have too little data, increase padding. + self.metadata_blocks[-1].length += (available - len(data)) data = MetadataBlock.writeblocks(self.metadata_blocks) assert len(data) == available - elif len(data) < available: - # If we have too little data, increase padding. - self.metadata_blocks[-1].length += (available - len(data)) - data = MetadataBlock.writeblocks(self.metadata_blocks) - assert len(data) == available + if len(data) != available: + # We couldn't reduce the padding enough. + diff = (len(data) - available) + insert_bytes(f, diff, header) - if len(data) != available: - # We couldn't reduce the padding enough. - diff = (len(data) - available) - insert_bytes(f, diff, header) + f.seek(header - 4) + f.write("fLaC" + data) - f.seek(header - 4) - f.write("fLaC" + data) - - # Delete ID3v1 - if deleteid3: - try: f.seek(-128, 2) - except IOError: pass - else: - if f.read(3) == "TAG": + # Delete ID3v1 + if deleteid3: + try: f.seek(-128, 2) - f.truncate() + except IOError: + pass + else: + if f.read(3) == "TAG": + f.seek(-128, 2) + f.truncate() + finally: + f.close() def __find_audio_offset(self, fileobj): byte = 0x00 - while not (byte >> 7) & 1: + while not (byte & 0x80): byte = ord(fileobj.read(1)) size = to_int_be(fileobj.read(3)) - fileobj.read(size) + try: + block_type = self.METADATA_BLOCKS[byte & 0x7F] + except IndexError: + block_type = None + + if block_type and block_type._distrust_size: + # See comments in read_metadata_block; the size can't + # be trusted for Vorbis comment blocks and Picture block + block_type(fileobj) + else: + fileobj.read(size) return fileobj.tell() def __check_header(self, fileobj): @@ -679,14 +817,17 @@ class FLAC(FileType): if header[:3] == "ID3": size = 14 + BitPaddedInt(fileobj.read(6)[2:]) fileobj.seek(size - 4) - if fileobj.read(4) != "fLaC": size = None + if fileobj.read(4) != "fLaC": + size = None if size is None: raise FLACNoHeaderError( "%r is not a valid FLAC file" % fileobj.name) return size + Open = FLAC + def delete(filename): """Remove tags from a file.""" FLAC(filename).delete() diff --git a/mutagen/id3.py b/mutagen/id3.py new file mode 100644 index 00000000..27d30e90 --- /dev/null +++ b/mutagen/id3.py @@ -0,0 +1,919 @@ +# id3 support for mutagen +# Copyright (C) 2005 Michael Urman +# 2006 Lukas Lalinsky +# 2013 Christoph Reiter +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. + +"""ID3v2 reading and writing. + +This is based off of the following references: + +* http://id3.org/id3v2.4.0-structure +* http://id3.org/id3v2.4.0-frames +* http://id3.org/id3v2.3.0 +* http://id3.org/id3v2-00 +* http://id3.org/ID3v1 + +Its largest deviation from the above (versions 2.3 and 2.2) is that it +will not interpret the / characters as a separator, and will almost +always accept null separators to generate multi-valued text frames. + +Because ID3 frame structure differs between frame types, each frame is +implemented as a different class (e.g. TIT2 as mutagen.id3.TIT2). Each +frame's documentation contains a list of its attributes. + +Since this file's documentation is a little unwieldy, you are probably +interested in the :class:`ID3` class to start with. +""" + +__all__ = ['ID3', 'ID3FileType', 'Frames', 'Open', 'delete'] + +import struct + +from struct import unpack, pack, error as StructError + +import mutagen +from mutagen._util import insert_bytes, delete_bytes, DictProxy + +from mutagen._id3util import * +from mutagen._id3frames import * +from mutagen._id3specs import * + + +class ID3(DictProxy, mutagen.Metadata): + """A file with an ID3v2 tag. + + Attributes: + + * version -- ID3 tag version as a tuple + * unknown_frames -- raw frame data of any unknown frames found + * size -- the total size of the ID3 tag, including the header + """ + + PEDANTIC = True + version = (2, 4, 0) + + filename = None + size = 0 + __flags = 0 + __readbytes = 0 + __crc = None + __unknown_version = None + + _V24 = (2, 4, 0) + _V23 = (2, 3, 0) + _V22 = (2, 2, 0) + _V11 = (1, 1) + + def __init__(self, *args, **kwargs): + self.unknown_frames = [] + super(ID3, self).__init__(*args, **kwargs) + + def __fullread(self, size): + try: + if size < 0: + raise ValueError('Requested bytes (%s) less than zero' % size) + if size > self.__filesize: + raise EOFError('Requested %#x of %#x (%s)' % ( + long(size), long(self.__filesize), self.filename)) + except AttributeError: + pass + data = self.__fileobj.read(size) + if len(data) != size: + raise EOFError + self.__readbytes += size + return data + + def load(self, filename, known_frames=None, translate=True, v2_version=4): + """Load tags from a filename. + + Keyword arguments: + + * filename -- filename to load tag data from + * known_frames -- dict mapping frame IDs to Frame objects + * translate -- Update all tags to ID3v2.3/4 internally. If you + intend to save, this must be true or you have to + call update_to_v23() / update_to_v24() manually. + * v2_version -- if update_to_v23 or update_to_v24 get called (3 or 4) + + Example of loading a custom frame:: + + my_frames = dict(mutagen.id3.Frames) + class XMYF(Frame): ... + my_frames["XMYF"] = XMYF + mutagen.id3.ID3(filename, known_frames=my_frames) + """ + + if not v2_version in (3, 4): + raise ValueError("Only 3 and 4 possible for v2_version") + + from os.path import getsize + + self.filename = filename + self.__known_frames = known_frames + self.__fileobj = open(filename, 'rb') + self.__filesize = getsize(filename) + try: + try: + self.__load_header() + except EOFError: + self.size = 0 + raise ID3NoHeaderError("%s: too small (%d bytes)" % ( + filename, self.__filesize)) + except (ID3NoHeaderError, ID3UnsupportedVersionError), err: + self.size = 0 + import sys + stack = sys.exc_info()[2] + try: + self.__fileobj.seek(-128, 2) + except EnvironmentError: + raise err, None, stack + else: + frames = ParseID3v1(self.__fileobj.read(128)) + if frames is not None: + self.version = self._V11 + map(self.add, frames.values()) + else: + raise err, None, stack + else: + frames = self.__known_frames + if frames is None: + if self._V23 <= self.version: + frames = Frames + elif self._V22 <= self.version: + frames = Frames_2_2 + data = self.__fullread(self.size - 10) + for frame in self.__read_frames(data, frames=frames): + if isinstance(frame, Frame): + self.add(frame) + else: + self.unknown_frames.append(frame) + self.__unknown_version = self.version + finally: + self.__fileobj.close() + del self.__fileobj + del self.__filesize + if translate: + if v2_version == 3: + self.update_to_v23() + else: + self.update_to_v24() + + def getall(self, key): + """Return all frames with a given name (the list may be empty). + + This is best explained by examples:: + + id3.getall('TIT2') == [id3['TIT2']] + id3.getall('TTTT') == [] + id3.getall('TXXX') == [TXXX(desc='woo', text='bar'), + TXXX(desc='baz', text='quuuux'), ...] + + Since this is based on the frame's HashKey, which is + colon-separated, you can use it to do things like + ``getall('COMM:MusicMatch')`` or ``getall('TXXX:QuodLibet:')``. + """ + if key in self: + return [self[key]] + else: + key = key + ":" + return [v for s, v in self.items() if s.startswith(key)] + + def delall(self, key): + """Delete all tags of a given kind; see getall.""" + if key in self: + del(self[key]) + else: + key = key + ":" + for k in filter(lambda s: s.startswith(key), self.keys()): + del(self[k]) + + def setall(self, key, values): + """Delete frames of the given type and add frames in 'values'.""" + self.delall(key) + for tag in values: + self[tag.HashKey] = tag + + def pprint(self): + """Return tags in a human-readable format. + + "Human-readable" is used loosely here. The format is intended + to mirror that used for Vorbis or APEv2 output, e.g. + + ``TIT2=My Title`` + + However, ID3 frames can have multiple keys: + + ``POPM=user@example.org=3 128/255`` + """ + frames = list(map(Frame.pprint, self.values())) + frames.sort() + return "\n".join(frames) + + def loaded_frame(self, tag): + """Deprecated; use the add method.""" + # turn 2.2 into 2.3/2.4 tags + if len(type(tag).__name__) == 3: + tag = type(tag).__base__(tag) + self[tag.HashKey] = tag + + # add = loaded_frame (and vice versa) break applications that + # expect to be able to override loaded_frame (e.g. Quod Libet), + # as does making loaded_frame call add. + def add(self, frame): + """Add a frame to the tag.""" + return self.loaded_frame(frame) + + def __load_header(self): + fn = self.filename + data = self.__fullread(10) + id3, vmaj, vrev, flags, size = unpack('>3sBBB4s', data) + self.__flags = flags + self.size = BitPaddedInt(size) + 10 + self.version = (2, vmaj, vrev) + + if id3 != 'ID3': + raise ID3NoHeaderError("'%s' doesn't start with an ID3 tag" % fn) + if vmaj not in [2, 3, 4]: + raise ID3UnsupportedVersionError("'%s' ID3v2.%d not supported" + % (fn, vmaj)) + + if self.PEDANTIC: + if not BitPaddedInt.has_valid_padding(size): + raise ValueError("Header size not synchsafe") + + if self._V24 <= self.version and (flags & 0x0f): + raise ValueError("'%s' has invalid flags %#02x" % (fn, flags)) + elif self._V23 <= self.version < self._V24 and (flags & 0x1f): + raise ValueError("'%s' has invalid flags %#02x" % (fn, flags)) + + if self.f_extended: + extsize = self.__fullread(4) + if extsize in Frames: + # Some tagger sets the extended header flag but + # doesn't write an extended header; in this case, the + # ID3 data follows immediately. Since no extended + # header is going to be long enough to actually match + # a frame, and if it's *not* a frame we're going to be + # completely lost anyway, this seems to be the most + # correct check. + # http://code.google.com/p/quodlibet/issues/detail?id=126 + self.__flags ^= 0x40 + self.__extsize = 0 + self.__fileobj.seek(-4, 1) + self.__readbytes -= 4 + elif self.version >= self._V24: + # "Where the 'Extended header size' is the size of the whole + # extended header, stored as a 32 bit synchsafe integer." + self.__extsize = BitPaddedInt(extsize) - 4 + if self.PEDANTIC: + if not BitPaddedInt.has_valid_padding(extsize): + raise ValueError("Extended header size not synchsafe") + else: + # "Where the 'Extended header size', currently 6 or 10 bytes, + # excludes itself." + self.__extsize = unpack('>L', extsize)[0] + if self.__extsize: + self.__extdata = self.__fullread(self.__extsize) + else: + self.__extdata = "" + + def __determine_bpi(self, data, frames, EMPTY="\x00" * 10): + if self.version < self._V24: + return int + # have to special case whether to use bitpaddedints here + # spec says to use them, but iTunes has it wrong + + # count number of tags found as BitPaddedInt and how far past + o = 0 + asbpi = 0 + while o < len(data) - 10: + part = data[o:o + 10] + if part == EMPTY: + bpioff = -((len(data) - o) % 10) + break + name, size, flags = unpack('>4sLH', part) + size = BitPaddedInt(size) + o += 10 + size + if name in frames: + asbpi += 1 + else: + bpioff = o - len(data) + + # count number of tags found as int and how far past + o = 0 + asint = 0 + while o < len(data) - 10: + part = data[o:o + 10] + if part == EMPTY: + intoff = -((len(data) - o) % 10) + break + name, size, flags = unpack('>4sLH', part) + o += 10 + size + if name in frames: + asint += 1 + else: + intoff = o - len(data) + + # if more tags as int, or equal and bpi is past and int is not + if asint > asbpi or (asint == asbpi and (bpioff >= 1 and intoff <= 1)): + return int + return BitPaddedInt + + def __read_frames(self, data, frames): + if self.version < self._V24 and self.f_unsynch: + try: + data = unsynch.decode(data) + except ValueError: + pass + + if self._V23 <= self.version: + bpi = self.__determine_bpi(data, frames) + while data: + header = data[:10] + try: + name, size, flags = unpack('>4sLH', header) + except struct.error: + return # not enough header + if name.strip('\x00') == '': + return + size = bpi(size) + framedata = data[10:10+size] + data = data[10+size:] + if size == 0: + continue # drop empty frames + try: + tag = frames[name] + except KeyError: + if is_valid_frame_id(name): + yield header + framedata + else: + try: + yield self.__load_framedata(tag, flags, framedata) + except NotImplementedError: + yield header + framedata + except ID3JunkFrameError: + pass + + elif self._V22 <= self.version: + while data: + header = data[0:6] + try: + name, size = unpack('>3s3s', header) + except struct.error: + return # not enough header + size, = struct.unpack('>L', '\x00'+size) + if name.strip('\x00') == '': + return + framedata = data[6:6+size] + data = data[6+size:] + if size == 0: + continue # drop empty frames + try: + tag = frames[name] + except KeyError: + if is_valid_frame_id(name): + yield header + framedata + else: + try: + yield self.__load_framedata(tag, 0, framedata) + except NotImplementedError: + yield header + framedata + except ID3JunkFrameError: + pass + + def __load_framedata(self, tag, flags, framedata): + return tag.fromData(self, flags, framedata) + + f_unsynch = property(lambda s: bool(s.__flags & 0x80)) + f_extended = property(lambda s: bool(s.__flags & 0x40)) + f_experimental = property(lambda s: bool(s.__flags & 0x20)) + f_footer = property(lambda s: bool(s.__flags & 0x10)) + + #f_crc = property(lambda s: bool(s.__extflags & 0x8000)) + + def save(self, filename=None, v1=1, v2_version=4, v23_sep='/'): + """Save changes to a file. + + If no filename is given, the one most recently loaded is used. + + Keyword arguments: + v1 -- if 0, ID3v1 tags will be removed + if 1, ID3v1 tags will be updated but not added + if 2, ID3v1 tags will be created and/or updated + v2 -- version of ID3v2 tags (3 or 4). + + By default Mutagen saves ID3v2.4 tags. If you want to save ID3v2.3 + tags, you must call method update_to_v23 before saving the file. + + v23_sep -- the separator used to join multiple text values + if v2_version == 3. Defaults to '/' but if it's None + will be the ID3v2v2.4 null separator. + + The lack of a way to update only an ID3v1 tag is intentional. + """ + + if v2_version == 3: + version = self._V23 + elif v2_version == 4: + version = self._V24 + else: + raise ValueError("Only 3 or 4 allowed for v2_version") + + # Sort frames by 'importance' + order = ["TIT2", "TPE1", "TRCK", "TALB", "TPOS", "TDRC", "TCON"] + order = dict(zip(order, range(len(order)))) + last = len(order) + frames = self.items() + frames.sort(lambda a, b: cmp(order.get(a[0][:4], last), + order.get(b[0][:4], last))) + + framedata = [self.__save_frame(frame, version=version, v23_sep=v23_sep) + for (key, frame) in frames] + + # only write unknown frames if they were loaded from the version + # we are saving with or upgraded to it + if self.__unknown_version == version: + framedata.extend([data for data in self.unknown_frames + if len(data) > 10]) + + if not framedata: + try: + self.delete(filename) + except EnvironmentError, err: + from errno import ENOENT + if err.errno != ENOENT: + raise + return + + framedata = ''.join(framedata) + framesize = len(framedata) + + if filename is None: + filename = self.filename + try: + f = open(filename, 'rb+') + except IOError, err: + from errno import ENOENT + if err.errno != ENOENT: + raise + f = open(filename, 'ab') # create, then reopen + f = open(filename, 'rb+') + try: + idata = f.read(10) + try: + id3, vmaj, vrev, flags, insize = unpack('>3sBBB4s', idata) + except struct.error: + id3, insize = '', 0 + insize = BitPaddedInt(insize) + if id3 != 'ID3': + insize = -10 + + if insize >= framesize: + outsize = insize + else: + outsize = (framesize + 1023) & ~0x3FF + framedata += '\x00' * (outsize - framesize) + + framesize = BitPaddedInt.to_str(outsize, width=4) + flags = 0 + header = pack('>3sBBB4s', 'ID3', v2_version, 0, flags, framesize) + data = header + framedata + + if (insize < outsize): + insert_bytes(f, outsize-insize, insize+10) + f.seek(0) + f.write(data) + + try: + f.seek(-128, 2) + except IOError, err: + # If the file is too small, that's OK - it just means + # we're certain it doesn't have a v1 tag. + from errno import EINVAL + if err.errno != EINVAL: + # If we failed to see for some other reason, bail out. + raise + # Since we're sure this isn't a v1 tag, don't read it. + f.seek(0, 2) + + data = f.read(128) + try: + idx = data.index("TAG") + except ValueError: + offset = 0 + has_v1 = False + else: + offset = idx - len(data) + has_v1 = True + + f.seek(offset, 2) + if v1 == 1 and has_v1 or v1 == 2: + f.write(MakeID3v1(self)) + else: + f.truncate() + + finally: + f.close() + + def delete(self, filename=None, delete_v1=True, delete_v2=True): + """Remove tags from a file. + + If no filename is given, the one most recently loaded is used. + + Keyword arguments: + + * delete_v1 -- delete any ID3v1 tag + * delete_v2 -- delete any ID3v2 tag + """ + if filename is None: + filename = self.filename + delete(filename, delete_v1, delete_v2) + self.clear() + + def __save_frame(self, frame, name=None, version=_V24, v23_sep=None): + flags = 0 + if self.PEDANTIC and isinstance(frame, TextFrame): + if len(str(frame)) == 0: + return '' + + if version == self._V23: + framev23 = frame._get_v23_frame(sep=v23_sep) + framedata = framev23._writeData() + else: + framedata = frame._writeData() + + usize = len(framedata) + if usize > 2048: + # Disabled as this causes iTunes and other programs + # to fail to find these frames, which usually includes + # e.g. APIC. + #framedata = BitPaddedInt.to_str(usize) + framedata.encode('zlib') + #flags |= Frame.FLAG24_COMPRESS | Frame.FLAG24_DATALEN + pass + + if version == self._V24: + bits = 7 + elif version == self._V23: + bits = 8 + else: + raise ValueError + + datasize = BitPaddedInt.to_str(len(framedata), width=4, bits=bits) + header = pack('>4s4sH', name or type(frame).__name__, datasize, flags) + return header + framedata + + def __update_common(self): + """Updates done by both v23 and v24 update""" + + if "TCON" in self: + # Get rid of "(xx)Foobr" format. + self["TCON"].genres = self["TCON"].genres + + if self.version < self._V23: + # ID3v2.2 PIC frames are slightly different. + pics = self.getall("APIC") + mimes = {"PNG": "image/png", "JPG": "image/jpeg"} + self.delall("APIC") + for pic in pics: + newpic = APIC( + encoding=pic.encoding, mime=mimes.get(pic.mime, pic.mime), + type=pic.type, desc=pic.desc, data=pic.data) + self.add(newpic) + + # ID3v2.2 LNK frames are just way too different to upgrade. + self.delall("LINK") + + def update_to_v24(self): + """Convert older tags into an ID3v2.4 tag. + + This updates old ID3v2 frames to ID3v2.4 ones (e.g. TYER to + TDRC). If you intend to save tags, you must call this function + at some point; it is called by default when loading the tag. + """ + + self.__update_common() + + if self.__unknown_version == (2, 3, 0): + # convert unknown 2.3 frames (flags/size) to 2.4 + converted = [] + for frame in self.unknown_frames: + try: + name, size, flags = unpack('>4sLH', frame[:10]) + frame = BinaryFrame.fromData(self, flags, frame[10:]) + except (struct.error, error): + continue + converted.append(self.__save_frame(frame, name=name)) + self.unknown_frames[:] = converted + self.__unknown_version = (2, 4, 0) + + # TDAT, TYER, and TIME have been turned into TDRC. + try: + if str(self.get("TYER", "")).strip("\x00"): + date = str(self.pop("TYER")) + if str(self.get("TDAT", "")).strip("\x00"): + dat = str(self.pop("TDAT")) + date = "%s-%s-%s" % (date, dat[2:], dat[:2]) + if str(self.get("TIME", "")).strip("\x00"): + time = str(self.pop("TIME")) + date += "T%s:%s:00" % (time[:2], time[2:]) + if "TDRC" not in self: + self.add(TDRC(encoding=0, text=date)) + except UnicodeDecodeError: + # Old ID3 tags have *lots* of Unicode problems, so if TYER + # is bad, just chuck the frames. + pass + + # TORY can be the first part of a TDOR. + if "TORY" in self: + f = self.pop("TORY") + if "TDOR" not in self: + try: + self.add(TDOR(encoding=0, text=str(f))) + except UnicodeDecodeError: + pass + + # IPLS is now TIPL. + if "IPLS" in self: + f = self.pop("IPLS") + if "TIPL" not in self: + self.add(TIPL(encoding=f.encoding, people=f.people)) + + # These can't be trivially translated to any ID3v2.4 tags, or + # should have been removed already. + for key in ["RVAD", "EQUA", "TRDA", "TSIZ", "TDAT", "TIME", "CRM"]: + if key in self: + del(self[key]) + + def update_to_v23(self): + """Convert older (and newer) tags into an ID3v2.3 tag. + + This updates incompatible ID3v2 frames to ID3v2.3 ones. If you + intend to save tags as ID3v2.3, you must call this function + at some point. + + If you want to to go off spec and include some v2.4 frames + in v2.3, remove them before calling this and add them back afterwards. + """ + + self.__update_common() + + # we could downgrade unknown v2.4 frames here, but given that + # the main reason to save v2.3 is compatibility and this + # might increase the chance of some parser breaking.. better not + + # TMCL, TIPL -> TIPL + if "TIPL" in self or "TMCL" in self: + people = [] + if "TIPL" in self: + f = self.pop("TIPL") + people.extend(f.people) + if "TMCL" in self: + f = self.pop("TMCL") + people.extend(f.people) + if "IPLS" not in self: + self.add(IPLS(encoding=f.encoding, people=people)) + + # TDOR -> TORY + if "TDOR" in self: + f = self.pop("TDOR") + if f.text: + d = f.text[0] + if d.year and "TORY" not in self: + self.add(TORY(encoding=f.encoding, text="%04d" % d.year)) + + # TDRC -> TYER, TDAT, TIME + if "TDRC" in self: + f = self.pop("TDRC") + if f.text: + d = f.text[0] + if d.year and "TYER" not in self: + self.add(TYER(encoding=f.encoding, text="%04d" % d.year)) + if d.month and d.day and "TDAT" not in self: + self.add(TDAT(encoding=f.encoding, + text="%02d%02d" % (d.day, d.month))) + if d.hour and d.minute and "TIME" not in self: + self.add(TIME(encoding=f.encoding, + text="%02d%02d" % (d.hour, d.minute))) + + # New frames added in v2.4 + v24_frames = [ + 'ASPI', 'EQU2', 'RVA2', 'SEEK', 'SIGN', 'TDEN', 'TDOR', + 'TDRC', 'TDRL', 'TDTG', 'TIPL', 'TMCL', 'TMOO', 'TPRO', + 'TSOA', 'TSOP', 'TSOT', 'TSST', + ] + + for key in v24_frames: + if key in self: + del(self[key]) + + +def delete(filename, delete_v1=True, delete_v2=True): + """Remove tags from a file. + + Keyword arguments: + + * delete_v1 -- delete any ID3v1 tag + * delete_v2 -- delete any ID3v2 tag + """ + + f = open(filename, 'rb+') + + if delete_v1: + try: + f.seek(-128, 2) + except IOError: + pass + else: + if f.read(3) == "TAG": + f.seek(-128, 2) + f.truncate() + + # technically an insize=0 tag is invalid, but we delete it anyway + # (primarily because we used to write it) + if delete_v2: + f.seek(0, 0) + idata = f.read(10) + try: + id3, vmaj, vrev, flags, insize = unpack('>3sBBB4s', idata) + except struct.error: + id3, insize = '', -1 + insize = BitPaddedInt(insize) + if id3 == 'ID3' and insize >= 0: + delete_bytes(f, insize + 10, 0) + + +# support open(filename) as interface +Open = ID3 + + +# ID3v1.1 support. +def ParseID3v1(string): + """Parse an ID3v1 tag, returning a list of ID3v2.4 frames.""" + + try: + string = string[string.index("TAG"):] + except ValueError: + return None + if 128 < len(string) or len(string) < 124: + return None + + # Issue #69 - Previous versions of Mutagen, when encountering + # out-of-spec TDRC and TYER frames of less than four characters, + # wrote only the characters available - e.g. "1" or "" - into the + # year field. To parse those, reduce the size of the year field. + # Amazingly, "0s" works as a struct format string. + unpack_fmt = "3s30s30s30s%ds29sBB" % (len(string) - 124) + + try: + tag, title, artist, album, year, comment, track, genre = unpack( + unpack_fmt, string) + except StructError: + return None + + if tag != "TAG": + return None + + def fix(string): + return string.split("\x00")[0].strip().decode('latin1') + + title, artist, album, year, comment = map( + fix, [title, artist, album, year, comment]) + + frames = {} + if title: + frames["TIT2"] = TIT2(encoding=0, text=title) + if artist: + frames["TPE1"] = TPE1(encoding=0, text=[artist]) + if album: + frames["TALB"] = TALB(encoding=0, text=album) + if year: + frames["TDRC"] = TDRC(encoding=0, text=year) + if comment: + frames["COMM"] = COMM( + encoding=0, lang="eng", desc="ID3v1 Comment", text=comment) + # Don't read a track number if it looks like the comment was + # padded with spaces instead of nulls (thanks, WinAmp). + if track and (track != 32 or string[-3] == '\x00'): + frames["TRCK"] = TRCK(encoding=0, text=str(track)) + if genre != 255: + frames["TCON"] = TCON(encoding=0, text=str(genre)) + return frames + + +def MakeID3v1(id3): + """Return an ID3v1.1 tag string from a dict of ID3v2.4 frames.""" + + v1 = {} + + for v2id, name in {"TIT2": "title", "TPE1": "artist", + "TALB": "album"}.items(): + if v2id in id3: + text = id3[v2id].text[0].encode('latin1', 'replace')[:30] + else: + text = "" + v1[name] = text + ("\x00" * (30 - len(text))) + + if "COMM" in id3: + cmnt = id3["COMM"].text[0].encode('latin1', 'replace')[:28] + else: + cmnt = "" + v1["comment"] = cmnt + ("\x00" * (29 - len(cmnt))) + + if "TRCK" in id3: + try: + v1["track"] = chr(+id3["TRCK"]) + except ValueError: + v1["track"] = "\x00" + else: + v1["track"] = "\x00" + + if "TCON" in id3: + try: + genre = id3["TCON"].genres[0] + except IndexError: + pass + else: + if genre in TCON.GENRES: + v1["genre"] = chr(TCON.GENRES.index(genre)) + if "genre" not in v1: + v1["genre"] = "\xff" + + if "TDRC" in id3: + year = str(id3["TDRC"]) + elif "TYER" in id3: + year = str(id3["TYER"]) + else: + year = "" + v1["year"] = (year + "\x00\x00\x00\x00")[:4] + + return ("TAG%(title)s%(artist)s%(album)s%(year)s%(comment)s" + "%(track)s%(genre)s") % v1 + + +class ID3FileType(mutagen.FileType): + """An unknown type of file with ID3 tags.""" + + ID3 = ID3 + + class _Info(object): + length = 0 + + def __init__(self, fileobj, offset): + pass + + @staticmethod + def pprint(): + return "Unknown format with ID3 tag" + + @staticmethod + def score(filename, fileobj, header): + return header.startswith("ID3") + + def add_tags(self, ID3=None): + """Add an empty ID3 tag to the file. + + A custom tag reader may be used in instead of the default + mutagen.id3.ID3 object, e.g. an EasyID3 reader. + """ + if ID3 is None: + ID3 = self.ID3 + if self.tags is None: + self.ID3 = ID3 + self.tags = ID3() + else: + raise error("an ID3 tag already exists") + + def load(self, filename, ID3=None, **kwargs): + """Load stream and tag information from a file. + + A custom tag reader may be used in instead of the default + mutagen.id3.ID3 object, e.g. an EasyID3 reader. + """ + + if ID3 is None: + ID3 = self.ID3 + else: + # If this was initialized with EasyID3, remember that for + # when tags are auto-instantiated in add_tags. + self.ID3 = ID3 + self.filename = filename + try: + self.tags = ID3(filename, **kwargs) + except error: + self.tags = None + if self.tags is not None: + try: + offset = self.tags.size + except AttributeError: + offset = None + else: + offset = None + try: + fileobj = open(filename, "rb") + self.info = self._Info(fileobj, offset) + finally: + fileobj.close() diff --git a/lib/mutagen/m4a.py b/mutagen/m4a.py similarity index 91% rename from lib/mutagen/m4a.py rename to mutagen/m4a.py index e6cbdb6a..64b89679 100644 --- a/lib/mutagen/m4a.py +++ b/mutagen/m4a.py @@ -3,8 +3,6 @@ # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. -# -# $Id: m4a.py 4231 2007-12-15 08:13:53Z luks $ """Read and write MPEG-4 audio files with iTunes metadata. @@ -27,30 +25,44 @@ import sys from cStringIO import StringIO -from lib.mutagen import FileType, Metadata -from lib.mutagen._constants import GENRES -from lib.mutagen._util import cdata, insert_bytes, delete_bytes, DictProxy +from mutagen import FileType, Metadata +from mutagen._constants import GENRES +from mutagen._util import cdata, insert_bytes, delete_bytes, DictProxy + + +class error(IOError): + pass + + +class M4AMetadataError(error): + pass + + +class M4AStreamInfoError(error): + pass + + +class M4AMetadataValueError(ValueError, M4AMetadataError): + pass -class error(IOError): pass -class M4AMetadataError(error): pass -class M4AStreamInfoError(error): pass -class M4AMetadataValueError(ValueError, M4AMetadataError): pass import warnings warnings.warn( "mutagen.m4a is deprecated; use mutagen.mp4 instead.", DeprecationWarning) + # This is not an exhaustive list of container atoms, but just the # ones this module needs to peek inside. _CONTAINERS = ["moov", "udta", "trak", "mdia", "meta", "ilst", "stbl", "minf", "stsd"] -_SKIP_SIZE = { "meta": 4 } +_SKIP_SIZE = {"meta": 4} __all__ = ['M4A', 'Open', 'delete', 'M4ACover'] + class M4ACover(str): """A cover artwork. - + Attributes: imageformat -- format of the image (either FORMAT_JPEG or FORMAT_PNG) """ @@ -59,13 +71,16 @@ class M4ACover(str): def __new__(cls, data, imageformat=None): self = str.__new__(cls, data) - if imageformat is None: imageformat = M4ACover.FORMAT_JPEG + if imageformat is None: + imageformat = M4ACover.FORMAT_JPEG self.imageformat = imageformat - try: self.format + try: + self.format except AttributeError: self.format = imageformat return self + class Atom(object): """An individual atom. @@ -96,6 +111,7 @@ class Atom(object): else: fileobj.seek(self.offset + self.length, 0) + @staticmethod def render(name, data): """Render raw atom data.""" # this raises OverflowError if Py_ssize_t can't handle the atom data @@ -104,7 +120,6 @@ class Atom(object): return struct.pack(">I4s", size, name) + data else: return struct.pack(">I4sQ", 1, name, size + 8) + data - render = staticmethod(render) def __getitem__(self, remaining): """Look up a child atom, potentially recursively. @@ -119,7 +134,7 @@ class Atom(object): if child.name == remaining[0]: return child[remaining[1:]] else: - raise KeyError, "%r not found" % remaining[0] + raise KeyError("%r not found" % remaining[0]) def __repr__(self): klass = self.__class__.__name__ @@ -132,6 +147,7 @@ class Atom(object): return "<%s name=%r length=%r offset=%r\n%s>" % ( klass, self.name, self.length, self.offset, children) + class Atoms(object): """Root atoms in a given file. @@ -157,7 +173,7 @@ class Atoms(object): """ path = [self] for name in names: - path.append(path[-1][name,]) + path.append(path[-1][name, ]) return path[1:] def __getitem__(self, names): @@ -172,11 +188,12 @@ class Atoms(object): if child.name == names[0]: return child[names[1:]] else: - raise KeyError, "%s not found" % names[0] + raise KeyError("%s not found" % names[0]) def __repr__(self): return "\n".join([repr(child) for child in self.atoms]) + class M4ATags(DictProxy, Metadata): """Dictionary containing Apple iTunes metadata list key/values. @@ -201,7 +218,8 @@ class M4ATags(DictProxy, Metadata): """ def load(self, atoms, fileobj): - try: ilst = atoms["moov.udta.meta.ilst"] + try: + ilst = atoms["moov.udta.meta.ilst"] except KeyError, key: raise M4AMetadataError(key) for atom in ilst.children: @@ -210,7 +228,10 @@ class M4ATags(DictProxy, Metadata): parse = self.__atoms.get(atom.name, (M4ATags.__parse_text,))[0] parse(self, atom, data) - def __key_sort((key1, v1), (key2, v2)): + @staticmethod + def __key_sort(item1, item2): + (key1, v1) = item1 + (key2, v2) = item2 # iTunes always writes the tags in order of "relevance", try # to copy it as closely as possible. order = ["\xa9nam", "\xa9ART", "\xa9wrt", "\xa9alb", @@ -224,7 +245,6 @@ class M4ATags(DictProxy, Metadata): # values, so we at least have something determinstic. return (cmp(order.get(key1[:4], last), order.get(key2[:4], last)) or cmp(len(v1), len(v2)) or cmp(v1, v2)) - __key_sort = staticmethod(__key_sort) def save(self, filename): """Save the metadata to the given filename.""" @@ -238,7 +258,7 @@ class M4ATags(DictProxy, Metadata): data = Atom.render("ilst", "".join(values)) # Find the old atoms. - fileobj = file(filename, "rb+") + fileobj = open(filename, "rb+") try: atoms = Atoms(fileobj) @@ -326,16 +346,18 @@ class M4ATags(DictProxy, Metadata): pass else: self["%s:%s:%s" % (atom.name, mean, name)] = value + def __render_freeform(self, key, value): dummy, mean, name = key.split(":", 2) mean = struct.pack(">I4sI", len(mean) + 12, "mean", 0) + mean name = struct.pack(">I4sI", len(name) + 12, "name", 0) + name value = struct.pack(">I4s2I", len(value) + 16, "data", 0x1, 0) + value final = mean + name + value - return Atom.render("----", mean + name + value) + return Atom.render("----", final) def __parse_pair(self, atom, data): self[atom.name] = struct.unpack(">2H", data[18:22]) + def __render_pair(self, key, value): track, total = value if 0 <= track < 1 << 16 and 0 <= total < 1 << 16: @@ -356,11 +378,14 @@ class M4ATags(DictProxy, Metadata): # Translate to a freeform genre. genre = cdata.short_be(data[16:18]) if "\xa9gen" not in self: - try: self["\xa9gen"] = GENRES[genre - 1] - except IndexError: pass + try: + self["\xa9gen"] = GENRES[genre - 1] + except IndexError: + pass def __parse_tempo(self, atom, data): self[atom.name] = cdata.short_be(data[16:18]) + def __render_tempo(self, key, value): if 0 <= value < 1 << 16: return self.__render_data(key, 0x15, cdata.to_ushort_be(value)) @@ -368,8 +393,10 @@ class M4ATags(DictProxy, Metadata): raise M4AMetadataValueError("invalid short integer %r" % value) def __parse_compilation(self, atom, data): - try: self[atom.name] = bool(ord(data[16:17])) - except TypeError: self[atom.name] = False + try: + self[atom.name] = bool(ord(data[16:17])) + except TypeError: + self[atom.name] = False def __render_compilation(self, key, value): return self.__render_data(key, 0x15, chr(bool(value))) @@ -381,10 +408,13 @@ class M4ATags(DictProxy, Metadata): "unexpected atom %r inside 'covr'" % name) if imageformat not in (M4ACover.FORMAT_JPEG, M4ACover.FORMAT_PNG): imageformat = M4ACover.FORMAT_JPEG - self[atom.name]= M4ACover(data[16:length], imageformat) + self[atom.name] = M4ACover(data[16:length], imageformat) + def __render_cover(self, key, value): - try: imageformat = value.imageformat - except AttributeError: imageformat = M4ACover.FORMAT_JPEG + try: + imageformat = value.imageformat + except AttributeError: + imageformat = M4ACover.FORMAT_JPEG data = Atom.render("data", struct.pack(">2I", imageformat, 0) + value) return Atom.render(key, data) @@ -392,6 +422,7 @@ class M4ATags(DictProxy, Metadata): flags = cdata.uint_be(data[8:12]) if flags == 1: self[atom.name] = data[16:].decode('utf-8', 'replace') + def __render_text(self, key, value): return self.__render_data(key, 0x1, value.encode('utf-8')) @@ -407,17 +438,19 @@ class M4ATags(DictProxy, Metadata): "tmpo": (__parse_tempo, __render_tempo), "cpil": (__parse_compilation, __render_compilation), "covr": (__parse_cover, __render_cover), - } + } def pprint(self): values = [] for key, value in self.iteritems(): key = key.decode('latin1') - try: values.append("%s=%s" % (key, value)) + try: + values.append("%s=%s" % (key, value)) except UnicodeDecodeError: values.append("%s=[%d bytes of data]" % (key, len(value))) return "\n".join(values) + class M4AInfo(object): """MPEG-4 stream information. @@ -460,6 +493,7 @@ class M4AInfo(object): return "MPEG-4 audio, %.2f seconds, %d bps" % ( self.length, self.bitrate) + class M4A(FileType): """An MPEG-4 audio file, probably containing AAC. @@ -471,13 +505,15 @@ class M4A(FileType): def load(self, filename): self.filename = filename - fileobj = file(filename, "rb") + fileobj = open(filename, "rb") try: atoms = Atoms(fileobj) - try: self.info = M4AInfo(atoms, fileobj) + try: + self.info = M4AInfo(atoms, fileobj) except StandardError, err: raise M4AStreamInfoError, err, sys.exc_info()[2] - try: self.tags = M4ATags(atoms, fileobj) + try: + self.tags = M4ATags(atoms, fileobj) except M4AMetadataError: self.tags = None except StandardError, err: @@ -488,12 +524,15 @@ class M4A(FileType): def add_tags(self): self.tags = M4ATags() + @staticmethod def score(filename, fileobj, header): return ("ftyp" in header) + ("mp4" in header) - score = staticmethod(score) + Open = M4A + def delete(filename): """Remove tags from a file.""" + M4A(filename).delete() diff --git a/lib/mutagen/monkeysaudio.py b/mutagen/monkeysaudio.py similarity index 83% rename from lib/mutagen/monkeysaudio.py rename to mutagen/monkeysaudio.py index 6fa9ba8c..355749b9 100644 --- a/lib/mutagen/monkeysaudio.py +++ b/mutagen/monkeysaudio.py @@ -5,8 +5,6 @@ # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. -# -# $Id: monkeysaudio.py 3976 2007-01-13 22:00:14Z piman $ """Monkey's Audio streams with APEv2 tags. @@ -20,20 +18,24 @@ __all__ = ["MonkeysAudio", "Open", "delete"] import struct -from lib.mutagen.apev2 import APEv2File, error, delete -from lib.mutagen._util import cdata +from mutagen.apev2 import APEv2File, error, delete +from mutagen._util import cdata + + +class MonkeysAudioHeaderError(error): + pass -class MonkeysAudioHeaderError(error): pass class MonkeysAudioInfo(object): """Monkey's Audio stream information. Attributes: - channels -- number of audio channels - length -- file length in seconds, as a float - sample_rate -- audio sampling rate in Hz - bits_per_sample -- bits per sample - version -- Monkey's Audio stream version, as a float (eg: 3.99) + + * channels -- number of audio channels + * length -- file length in seconds, as a float + * sample_rate -- audio sampling rate in Hz + * bits_per_sample -- bits per sample + * version -- Monkey's Audio stream version, as a float (eg: 3.99) """ def __init__(self, fileobj): @@ -69,12 +71,14 @@ class MonkeysAudioInfo(object): return "Monkey's Audio %.2f, %.2f seconds, %d Hz" % ( self.version, self.length, self.sample_rate) + class MonkeysAudio(APEv2File): _Info = MonkeysAudioInfo _mimes = ["audio/ape", "audio/x-ape"] + @staticmethod def score(filename, fileobj, header): return header.startswith("MAC ") + filename.lower().endswith(".ape") - score = staticmethod(score) + Open = MonkeysAudio diff --git a/lib/mutagen/mp3.py b/mutagen/mp3.py similarity index 71% rename from lib/mutagen/mp3.py rename to mutagen/mp3.py index b173b70b..2426610b 100644 --- a/lib/mutagen/mp3.py +++ b/mutagen/mp3.py @@ -10,17 +10,27 @@ import os import struct -from lib.mutagen.id3 import ID3FileType, BitPaddedInt, delete +from mutagen.id3 import ID3FileType, BitPaddedInt, delete __all__ = ["MP3", "Open", "delete", "MP3"] -class error(RuntimeError): pass -class HeaderNotFoundError(error, IOError): pass -class InvalidMPEGHeader(error, IOError): pass + +class error(RuntimeError): + pass + + +class HeaderNotFoundError(error, IOError): + pass + + +class InvalidMPEGHeader(error, IOError): + pass + # Mode values. STEREO, JOINTSTEREO, DUALCHANNEL, MONO = range(4) + class MPEGInfo(object): """MPEG audio stream information @@ -28,40 +38,47 @@ class MPEGInfo(object): Xing VBR header format. This code was implemented based on the format documentation at - http://www.dv.co.yu/mpgscript/mpeghdr.htm. + http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm. Useful attributes: - length -- audio length, in seconds - bitrate -- audio bitrate, in bits per second - sketchy -- if true, the file may not be valid MPEG audio + + * length -- audio length, in seconds + * bitrate -- audio bitrate, in bits per second + * sketchy -- if true, the file may not be valid MPEG audio Useless attributes: - version -- MPEG version (1, 2, 2.5) - layer -- 1, 2, or 3 - mode -- One of STEREO, JOINTSTEREO, DUALCHANNEL, or MONO (0-3) - protected -- whether or not the file is "protected" - padding -- whether or not audio frames are padded - sample_rate -- audio sample rate, in Hz + + * version -- MPEG version (1, 2, 2.5) + * layer -- 1, 2, or 3 + * mode -- One of STEREO, JOINTSTEREO, DUALCHANNEL, or MONO (0-3) + * protected -- whether or not the file is "protected" + * padding -- whether or not audio frames are padded + * sample_rate -- audio sample rate, in Hz """ # Map (version, layer) tuples to bitrates. __BITRATE = { (1, 1): range(0, 480, 32), - (1, 2): [0, 32, 48, 56, 64, 80, 96, 112,128,160,192,224,256,320,384], - (1, 3): [0, 32, 40, 48, 56, 64, 80, 96, 112,128,160,192,224,256,320], - (2, 1): [0, 32, 48, 56, 64, 80, 96, 112,128,144,160,176,192,224,256], - (2, 2): [0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160], - } - + (1, 2): [0, 32, 48, 56, 64, 80, 96, 112, 128, + 160, 192, 224, 256, 320, 384], + (1, 3): [0, 32, 40, 48, 56, 64, 80, 96, 112, + 128, 160, 192, 224, 256, 320], + (2, 1): [0, 32, 48, 56, 64, 80, 96, 112, 128, + 144, 160, 176, 192, 224, 256], + (2, 2): [0, 8, 16, 24, 32, 40, 48, 56, 64, + 80, 96, 112, 128, 144, 160], + } + __BITRATE[(2, 3)] = __BITRATE[(2, 2)] - for i in range(1, 4): __BITRATE[(2.5, i)] = __BITRATE[(2, i)] + for i in range(1, 4): + __BITRATE[(2.5, i)] = __BITRATE[(2, i)] # Map version to sample rates. __RATES = { 1: [44100, 48000, 32000], 2: [22050, 24000, 16000], 2.5: [11025, 12000, 8000] - } + } sketchy = False @@ -74,7 +91,8 @@ class MPEGInfo(object): loading files significantly faster. """ - try: size = os.path.getsize(fileobj.name) + try: + size = os.path.getsize(fileobj.name) except (IOError, OSError, AttributeError): fileobj.seek(0, 2) size = fileobj.tell() @@ -83,20 +101,26 @@ class MPEGInfo(object): if offset is None: fileobj.seek(0, 0) idata = fileobj.read(10) - try: id3, insize = struct.unpack('>3sxxx4s', idata) - except struct.error: id3, insize = '', 0 + try: + id3, insize = struct.unpack('>3sxxx4s', idata) + except struct.error: + id3, insize = '', 0 insize = BitPaddedInt(insize) if id3 == 'ID3' and insize > 0: - offset = insize - else: offset = 0 + offset = insize + 10 + else: + offset = 0 # Try to find two valid headers (meaning, very likely MPEG data) # at the given offset, 30% through the file, 60% through the file, # and 90% through the file. for i in [offset, 0.3 * size, 0.6 * size, 0.9 * size]: - try: self.__try(fileobj, int(i), size - offset) - except error, e: pass - else: break + try: + self.__try(fileobj, int(i), size - offset) + except error: + pass + else: + break # If we can't find any two consecutive frames, try to find just # one frame back at the original offset given. else: @@ -126,16 +150,17 @@ class MPEGInfo(object): bitrate = (frame_data >> 12) & 0xF sample_rate = (frame_data >> 10) & 0x3 padding = (frame_data >> 9) & 0x1 - private = (frame_data >> 8) & 0x1 + #private = (frame_data >> 8) & 0x1 self.mode = (frame_data >> 6) & 0x3 - mode_extension = (frame_data >> 4) & 0x3 - copyright = (frame_data >> 3) & 0x1 - original = (frame_data >> 2) & 0x1 - emphasis = (frame_data >> 0) & 0x3 + #mode_extension = (frame_data >> 4) & 0x3 + #copyright = (frame_data >> 3) & 0x1 + #original = (frame_data >> 2) & 0x1 + #emphasis = (frame_data >> 0) & 0x3 if (version == 1 or layer == 0 or sample_rate == 0x3 or - bitrate == 0 or bitrate == 0xF): + bitrate == 0 or bitrate == 0xF): frame_1 = data.find("\xff", frame_1 + 2) - else: break + else: + break else: raise HeaderNotFoundError("can't sync to an MPEG frame") @@ -164,13 +189,15 @@ class MPEGInfo(object): possible = frame_1 + frame_length if possible > len(data) + 4: raise HeaderNotFoundError("can't sync to second MPEG frame") - frame_data = struct.unpack(">H", data[possible:possible + 2])[0] + try: + frame_data = struct.unpack( + ">H", data[possible:possible + 2])[0] + except struct.error: + raise HeaderNotFoundError("can't sync to second MPEG frame") if frame_data & 0xFFE0 != 0xFFE0: raise HeaderNotFoundError("can't sync to second MPEG frame") - frame_count = real_size / float(frame_length) - samples = frame_size * frame_count - self.length = samples / self.sample_rate + self.length = 8 * real_size / float(self.bitrate) # Try to find/parse the Xing header, which trumps the above length # and bitrate calculation. @@ -183,7 +210,8 @@ class MPEGInfo(object): # calculation. try: vbri = data[:-24].index("VBRI") - except ValueError: pass + except ValueError: + pass else: # If a VBRI header was found, this is definitely MPEG audio. self.sketchy = False @@ -205,39 +233,43 @@ class MPEGInfo(object): bytes = struct.unpack('>I', data[xing + 12:xing + 16])[0] self.bitrate = int((bytes * 8) // self.length) - # If the bitrate * the length is nowhere near the file - # length, recalculate using the bitrate and file length. - # Don't do this for very small files. - fileobj.seek(2, 0) - size = fileobj.tell() - expected = (self.bitrate / 8) * self.length - if not (size / 2 < expected < size * 2) and size > 2**16: - self.length = size / float(self.bitrate * 8) - def pprint(self): s = "MPEG %s layer %d, %d bps, %s Hz, %.2f seconds" % ( self.version, self.layer, self.bitrate, self.sample_rate, self.length) - if self.sketchy: s += " (sketchy)" + if self.sketchy: + s += " (sketchy)" return s + class MP3(ID3FileType): - """An MPEG audio (usually MPEG-1 Layer 3) file.""" + """An MPEG audio (usually MPEG-1 Layer 3) file. + + :ivar info: :class:`MPEGInfo` + :ivar tags: :class:`ID3 ` + """ _Info = MPEGInfo _mimes = ["audio/mp3", "audio/x-mp3", "audio/mpeg", "audio/mpg", "audio/x-mpeg"] + @staticmethod def score(filename, fileobj, header): filename = filename.lower() return (header.startswith("ID3") * 2 + filename.endswith(".mp3") + filename.endswith(".mp2") + filename.endswith(".mpg") + filename.endswith(".mpeg")) - score = staticmethod(score) + Open = MP3 -class EasyMP3(MP3): - """Like MP3, but uses EasyID3 for tags.""" - from lib.mutagen.easyid3 import EasyID3 as ID3 +class EasyMP3(MP3): + """Like MP3, but uses EasyID3 for tags. + + :ivar info: :class:`MPEGInfo` + :ivar tags: :class:`EasyID3 ` + """ + + from mutagen.easyid3 import EasyID3 as ID3 + ID3 = ID3 diff --git a/lib/mutagen/mp4.py b/mutagen/mp4.py similarity index 72% rename from lib/mutagen/mp4.py rename to mutagen/mp4.py index 7d0b64eb..984a38c4 100644 --- a/lib/mutagen/mp4.py +++ b/mutagen/mp4.py @@ -3,8 +3,6 @@ # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. -# -# $Id: mp4.py 4233 2007-12-28 07:24:59Z luks $ """Read and write MPEG-4 audio files with iTunes metadata. @@ -13,50 +11,87 @@ as found in Apple's MP4 (aka M4A, M4B, M4P) files. There is no official specification for this format. The source code for TagLib, FAAD, and various MPEG specifications at -http://developer.apple.com/documentation/QuickTime/QTFF/, -http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt, -http://standards.iso.org/ittf/PubliclyAvailableStandards/c041828_ISO_IEC_14496-12_2005(E).zip, -and http://wiki.multimedia.cx/index.php?title=Apple_QuickTime were all -consulted. + +* http://developer.apple.com/documentation/QuickTime/QTFF/ +* http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt +* http://standards.iso.org/ittf/PubliclyAvailableStandards/\ +c041828_ISO_IEC_14496-12_2005(E).zip +* http://wiki.multimedia.cx/index.php?title=Apple_QuickTime + +were all consulted. """ import struct import sys -from lib.mutagen import FileType, Metadata -from lib.mutagen._constants import GENRES -from lib.mutagen._util import cdata, insert_bytes, delete_bytes, DictProxy, utf8 +from mutagen import FileType, Metadata +from mutagen._constants import GENRES +from mutagen._util import cdata, insert_bytes, DictProxy, utf8 + + +class error(IOError): + pass + + +class MP4MetadataError(error): + pass + + +class MP4StreamInfoError(error): + pass + + +class MP4MetadataValueError(ValueError, MP4MetadataError): + pass -class error(IOError): pass -class MP4MetadataError(error): pass -class MP4StreamInfoError(error): pass -class MP4MetadataValueError(ValueError, MP4MetadataError): pass # This is not an exhaustive list of container atoms, but just the # ones this module needs to peek inside. _CONTAINERS = ["moov", "udta", "trak", "mdia", "meta", "ilst", "stbl", "minf", "moof", "traf"] -_SKIP_SIZE = { "meta": 4 } +_SKIP_SIZE = {"meta": 4} + +__all__ = ['MP4', 'Open', 'delete', 'MP4Cover', 'MP4FreeForm'] -__all__ = ['MP4', 'Open', 'delete', 'MP4Cover'] class MP4Cover(str): """A cover artwork. - + Attributes: - imageformat -- format of the image (either FORMAT_JPEG or FORMAT_PNG) + + * imageformat -- format of the image (either FORMAT_JPEG or FORMAT_PNG) """ FORMAT_JPEG = 0x0D FORMAT_PNG = 0x0E - def __new__(cls, data, imageformat=None): - self = str.__new__(cls, data) - if imageformat is None: imageformat = MP4Cover.FORMAT_JPEG + def __new__(cls, data, *args, **kwargs): + return str.__new__(cls, data) + + def __init__(self, data, imageformat=FORMAT_JPEG): self.imageformat = imageformat - try: self.format + try: + self.format except AttributeError: self.format = imageformat - return self + + +class MP4FreeForm(str): + """A freeform value. + + Attributes: + + * dataformat -- format of the data (either FORMAT_TEXT or FORMAT_DATA) + """ + + FORMAT_DATA = 0x0 + FORMAT_TEXT = 0x1 + + def __new__(cls, data, *args, **kwargs): + return str.__new__(cls, data) + + def __init__(self, data, dataformat=FORMAT_TEXT): + self.dataformat = dataformat + class Atom(object): """An individual atom. @@ -72,22 +107,36 @@ class Atom(object): children = None - def __init__(self, fileobj): + def __init__(self, fileobj, level=0): self.offset = fileobj.tell() self.length, self.name = struct.unpack(">I4s", fileobj.read(8)) if self.length == 1: self.length, = struct.unpack(">Q", fileobj.read(8)) + if self.length < 16: + raise MP4MetadataError( + "64 bit atom length can only be 16 and higher") + elif self.length == 0: + if level != 0: + raise MP4MetadataError( + "only a top-level atom can have zero length") + # Only the last atom is supposed to have a zero-length, meaning it + # extends to the end of file. + fileobj.seek(0, 2) + self.length = fileobj.tell() - self.offset + fileobj.seek(self.offset + 8, 0) elif self.length < 8: - return + raise MP4MetadataError( + "atom length can only be 0, 1 or 8 and higher") if self.name in _CONTAINERS: self.children = [] fileobj.seek(_SKIP_SIZE.get(self.name, 0), 1) while fileobj.tell() < self.offset + self.length: - self.children.append(Atom(fileobj)) + self.children.append(Atom(fileobj, level + 1)) else: fileobj.seek(self.offset + self.length, 0) + @staticmethod def render(name, data): """Render raw atom data.""" # this raises OverflowError if Py_ssize_t can't handle the atom data @@ -96,7 +145,6 @@ class Atom(object): return struct.pack(">I4s", size, name) + data else: return struct.pack(">I4sQ", 1, name, size + 8) + data - render = staticmethod(render) def findall(self, name, recursive=False): """Recursively find all child atoms by specified name.""" @@ -121,7 +169,7 @@ class Atom(object): if child.name == remaining[0]: return child[remaining[1:]] else: - raise KeyError, "%r not found" % remaining[0] + raise KeyError("%r not found" % remaining[0]) def __repr__(self): klass = self.__class__.__name__ @@ -134,6 +182,7 @@ class Atom(object): return "<%s name=%r length=%r offset=%r\n%s>" % ( klass, self.name, self.length, self.offset, children) + class Atoms(object): """Root atoms in a given file. @@ -142,6 +191,7 @@ class Atoms(object): This structure should only be used internally by Mutagen. """ + def __init__(self, fileobj): self.atoms = [] fileobj.seek(0, 2) @@ -157,76 +207,90 @@ class Atoms(object): list of three atoms, corresponding to the moov, udta, and meta atoms. """ + path = [self] for name in names: - path.append(path[-1][name,]) + path.append(path[-1][name, ]) return path[1:] + def __contains__(self, names): + try: + self[names] + except KeyError: + return False + return True + def __getitem__(self, names): """Look up a child atom. 'names' may be a list of atoms (['moov', 'udta']) or a string specifying the complete path ('moov.udta'). """ + if isinstance(names, basestring): names = names.split(".") for child in self.atoms: if child.name == names[0]: return child[names[1:]] else: - raise KeyError, "%s not found" % names[0] + raise KeyError("%s not found" % names[0]) def __repr__(self): return "\n".join([repr(child) for child in self.atoms]) + class MP4Tags(DictProxy, Metadata): - """Dictionary containing Apple iTunes metadata list key/values. + r"""Dictionary containing Apple iTunes metadata list key/values. Keys are four byte identifiers, except for freeform ('----') keys. Values are usually unicode strings, but some atoms have a special structure: Text values (multiple values per key are supported): - '\xa9nam' -- track title - '\xa9alb' -- album - '\xa9ART' -- artist - 'aART' -- album artist - '\xa9wrt' -- composer - '\xa9day' -- year - '\xa9cmt' -- comment - 'desc' -- description (usually used in podcasts) - 'purd' -- purchase date - '\xa9grp' -- grouping - '\xa9gen' -- genre - '\xa9lyr' -- lyrics - 'purl' -- podcast URL - 'egid' -- podcast episode GUID - 'catg' -- podcast category - 'keyw' -- podcast keywords - '\xa9too' -- encoded by - 'cprt' -- copyright - 'soal' -- album sort order - 'soaa' -- album artist sort order - 'soar' -- artist sort order - 'sonm' -- title sort order - 'soco' -- composer sort order - 'sosn' -- show sort order - 'tvsh' -- show name + + * '\\xa9nam' -- track title + * '\\xa9alb' -- album + * '\\xa9ART' -- artist + * 'aART' -- album artist + * '\\xa9wrt' -- composer + * '\\xa9day' -- year + * '\\xa9cmt' -- comment + * 'desc' -- description (usually used in podcasts) + * 'purd' -- purchase date + * '\\xa9grp' -- grouping + * '\\xa9gen' -- genre + * '\\xa9lyr' -- lyrics + * 'purl' -- podcast URL + * 'egid' -- podcast episode GUID + * 'catg' -- podcast category + * 'keyw' -- podcast keywords + * '\\xa9too' -- encoded by + * 'cprt' -- copyright + * 'soal' -- album sort order + * 'soaa' -- album artist sort order + * 'soar' -- artist sort order + * 'sonm' -- title sort order + * 'soco' -- composer sort order + * 'sosn' -- show sort order + * 'tvsh' -- show name Boolean values: - 'cpil' -- part of a compilation - 'pgap' -- part of a gapless album - 'pcst' -- podcast (iTunes reads this only on import) + + * 'cpil' -- part of a compilation + * 'pgap' -- part of a gapless album + * 'pcst' -- podcast (iTunes reads this only on import) Tuples of ints (multiple values per key are supported): - 'trkn' -- track number, total tracks - 'disk' -- disc number, total discs + + * 'trkn' -- track number, total tracks + * 'disk' -- disc number, total discs Others: - 'tmpo' -- tempo/BPM, 16 bit int - 'covr' -- cover artwork, list of MP4Cover objects (which are - tagged strs) - 'gnre' -- ID3v1 genre. Not supported, use '\xa9gen' instead. + + * 'tmpo' -- tempo/BPM, 16 bit int + * 'covr' -- cover artwork, list of MP4Cover objects (which are + tagged strs) + * 'gnre' -- ID3v1 genre. Not supported, use '\\xa9gen' instead. The freeform '----' frames use a key in the format '----:mean:name' where 'mean' is usually 'com.apple.iTunes' and 'name' is a unique @@ -241,16 +305,35 @@ class MP4Tags(DictProxy, Metadata): """ def load(self, atoms, fileobj): - try: ilst = atoms["moov.udta.meta.ilst"] + try: + ilst = atoms["moov.udta.meta.ilst"] except KeyError, key: raise MP4MetadataError(key) for atom in ilst.children: fileobj.seek(atom.offset + 8) data = fileobj.read(atom.length - 8) - info = self.__atoms.get(atom.name, (type(self).__parse_text, None)) - info[0](self, atom, data, *info[2:]) + if len(data) != atom.length - 8: + raise MP4MetadataError("Not enough data") - def __key_sort((key1, v1), (key2, v2)): + if atom.name in self.__atoms: + info = self.__atoms[atom.name] + info[0](self, atom, data, *info[2:]) + else: + # unknown atom, try as text and skip if it fails + # FIXME: keep them somehow + try: + self.__parse_text(atom, data) + except MP4MetadataError: + continue + + @classmethod + def _can_load(cls, atoms): + return "moov.udta.meta.ilst" in atoms + + @staticmethod + def __key_sort(item1, item2): + (key1, v1) = item1 + (key2, v2) = item2 # iTunes always writes the tags in order of "relevance", try # to copy it as closely as possible. order = ["\xa9nam", "\xa9ART", "\xa9wrt", "\xa9alb", @@ -264,7 +347,6 @@ class MP4Tags(DictProxy, Metadata): # values, so we at least have something determinstic. return (cmp(order.get(key1[:4], last), order.get(key2[:4], last)) or cmp(len(v1), len(v2)) or cmp(v1, v2)) - __key_sort = staticmethod(__key_sort) def save(self, filename): """Save the metadata to the given filename.""" @@ -280,7 +362,7 @@ class MP4Tags(DictProxy, Metadata): data = Atom.render("ilst", "".join(values)) # Find the old atoms. - fileobj = file(filename, "rb+") + fileobj = open(filename, "rb+") try: atoms = Atoms(fileobj) try: @@ -356,12 +438,12 @@ class MP4Tags(DictProxy, Metadata): for atom in path: fileobj.seek(atom.offset) size = cdata.uint_be(fileobj.read(4)) - if size == 1: # 64bit + if size == 1: # 64bit # skip name (4B) and read size (8B) size = cdata.ulonglong_be(fileobj.read(12)[4:]) fileobj.seek(atom.offset + 8) fileobj.write(cdata.to_ulonglong_be(size + delta)) - else: # 32bit + else: # 32bit fileobj.seek(atom.offset) fileobj.write(cdata.to_uint_be(size + delta)) @@ -414,6 +496,7 @@ class MP4Tags(DictProxy, Metadata): "unexpected atom %r inside %r" % (name, atom.name)) yield flags, data[pos+16:pos+length] pos += length + def __render_data(self, key, flags, value): return Atom.render(key, "".join([ Atom.render("data", struct.pack(">2I", flags, 0) + data) @@ -432,23 +515,37 @@ class MP4Tags(DictProxy, Metadata): if atom_name != "data": raise MP4MetadataError( "unexpected atom %r inside %r" % (atom_name, atom.name)) - value.append(data[pos+16:pos+length]) + + version = ord(data[pos+8]) + if version != 0: + raise MP4MetadataError("Unsupported version: %r" % version) + + flags = struct.unpack(">I", "\x00" + data[pos+9:pos+12])[0] + value.append(MP4FreeForm(data[pos+16:pos+length], + dataformat=flags)) pos += length if value: self["%s:%s:%s" % (atom.name, mean, name)] = value + def __render_freeform(self, key, value): dummy, mean, name = key.split(":", 2) mean = struct.pack(">I4sI", len(mean) + 12, "mean", 0) + mean name = struct.pack(">I4sI", len(name) + 12, "name", 0) + name if isinstance(value, basestring): value = [value] - return Atom.render("----", mean + name + "".join([ - struct.pack(">I4s2I", len(data) + 16, "data", 1, 0) + data - for data in value])) + data = "" + for v in value: + flags = MP4FreeForm.FORMAT_TEXT + if isinstance(v, MP4FreeForm): + flags = v.dataformat + data += struct.pack(">I4s2I", len(v) + 16, "data", flags, 0) + data += v + return Atom.render("----", mean + name + data) def __parse_pair(self, atom, data): - self[atom.name] = [struct.unpack(">2H", data[2:6]) for - flags, data in self.__parse_data(atom, data)] + self[atom.name] = [struct.unpack(">2H", d[2:6]) for + flags, d in self.__parse_data(atom, data)] + def __render_pair(self, key, value): data = [] for (track, total) in value: @@ -473,8 +570,10 @@ class MP4Tags(DictProxy, Metadata): # Translate to a freeform genre. genre = cdata.short_be(data[16:18]) if "\xa9gen" not in self: - try: self["\xa9gen"] = [GENRES[genre - 1]] - except IndexError: pass + try: + self["\xa9gen"] = [GENRES[genre - 1]] + except IndexError: + pass def __parse_tempo(self, atom, data): self[atom.name] = [cdata.ushort_be(value[1]) for @@ -496,8 +595,11 @@ class MP4Tags(DictProxy, Metadata): return self.__render_data(key, 0x15, values) def __parse_bool(self, atom, data): - try: self[atom.name] = bool(ord(data[16:17])) - except TypeError: self[atom.name] = False + try: + self[atom.name] = bool(ord(data[16:17])) + except TypeError: + self[atom.name] = False + def __render_bool(self, key, value): return self.__render_data(key, 0x15, [chr(bool(value))]) @@ -505,23 +607,29 @@ class MP4Tags(DictProxy, Metadata): self[atom.name] = [] pos = 0 while pos < atom.length - 8: - length, name, imageformat = struct.unpack(">I4sI", data[pos:pos+12]) + length, name, imageformat = struct.unpack(">I4sI", + data[pos:pos+12]) if name != "data": + if name == "name": + pos += length + continue raise MP4MetadataError( "unexpected atom %r inside 'covr'" % name) if imageformat not in (MP4Cover.FORMAT_JPEG, MP4Cover.FORMAT_PNG): imageformat = MP4Cover.FORMAT_JPEG cover = MP4Cover(data[pos+16:pos+length], imageformat) - self[atom.name].append( - MP4Cover(data[pos+16:pos+length], imageformat)) + self[atom.name].append(cover) pos += length + def __render_cover(self, key, value): atom_data = [] for cover in value: - try: imageformat = cover.imageformat - except AttributeError: imageformat = MP4Cover.FORMAT_JPEG - atom_data.append( - Atom.render("data", struct.pack(">2I", imageformat, 0) + cover)) + try: + imageformat = cover.imageformat + except AttributeError: + imageformat = MP4Cover.FORMAT_JPEG + atom_data.append(Atom.render( + "data", struct.pack(">2I", imageformat, 0) + cover)) return Atom.render(key, "".join(atom_data)) def __parse_text(self, atom, data, expected_flags=1): @@ -530,6 +638,7 @@ class MP4Tags(DictProxy, Metadata): if flags == expected_flags] if value: self[atom.name] = value + def __render_text(self, key, value, flags=1): if isinstance(value, basestring): value = [value] @@ -537,6 +646,8 @@ class MP4Tags(DictProxy, Metadata): key, flags, map(utf8, value)) def delete(self, filename): + """Remove the metadata from the given filename.""" + self.clear() self.save(filename) @@ -552,7 +663,15 @@ class MP4Tags(DictProxy, Metadata): "covr": (__parse_cover, __render_cover), "purl": (__parse_text, __render_text, 0), "egid": (__parse_text, __render_text, 0), - } + } + + # the text atoms we know about which should make loading fail if parsing + # any of them fails + for name in ["\xa9nam", "\xa9alb", "\xa9ART", "aART", "\xa9wrt", "\xa9day", + "\xa9cmt", "desc", "purd", "\xa9grp", "\xa9gen", "\xa9lyr", + "catg", "keyw", "\xa9too", "cprt", "soal", "soaa", "soar", + "sonm", "soco", "sosn", "tvsh"]: + __atoms[name] = (__parse_text, __render_text) def pprint(self): values = [] @@ -567,15 +686,17 @@ class MP4Tags(DictProxy, Metadata): values.append("%s=%s" % (key, value)) return "\n".join(values) + class MP4Info(object): """MPEG-4 stream information. Attributes: - bitrate -- bitrate in bits per second, as an int - length -- file length in seconds, as a float - channels -- number of audio channels - sample_rate -- audio sampling rate in Hz - bits_per_sample -- bits per sample + + * bitrate -- bitrate in bits per second, as an int + * length -- file length in seconds, as a float + * channels -- number of audio channels + * sample_rate -- audio sampling rate in Hz + * bits_per_sample -- bits per sample """ bitrate = 0 @@ -641,42 +762,61 @@ class MP4Info(object): return "MPEG-4 audio, %.2f seconds, %d bps" % ( self.length, self.bitrate) + class MP4(FileType): """An MPEG-4 audio file, probably containing AAC. If more than one track is present in the file, the first is used. Only audio ('soun') tracks will be read. + + :ivar info: :class:`MP4Info` + :ivar tags: :class:`MP4Tags` """ MP4Tags = MP4Tags - + _mimes = ["audio/mp4", "audio/x-m4a", "audio/mpeg4", "audio/aac"] def load(self, filename): self.filename = filename - fileobj = file(filename, "rb") + fileobj = open(filename, "rb") try: atoms = Atoms(fileobj) - try: self.info = MP4Info(atoms, fileobj) + + # ftyp is always the first atom in a valid MP4 file + if not atoms.atoms or atoms.atoms[0].name != "ftyp": + raise error("Not a MP4 file") + + try: + self.info = MP4Info(atoms, fileobj) except StandardError, err: raise MP4StreamInfoError, err, sys.exc_info()[2] - try: self.tags = self.MP4Tags(atoms, fileobj) - except MP4MetadataError: + + if not MP4Tags._can_load(atoms): self.tags = None - except StandardError, err: - raise MP4MetadataError, err, sys.exc_info()[2] + else: + try: + self.tags = self.MP4Tags(atoms, fileobj) + except StandardError, err: + raise MP4MetadataError, err, sys.exc_info()[2] finally: fileobj.close() def add_tags(self): - self.tags = self.MP4Tags() + if self.tags is None: + self.tags = self.MP4Tags() + else: + raise error("an MP4 tag already exists") + @staticmethod def score(filename, fileobj, header): return ("ftyp" in header) + ("mp4" in header) - score = staticmethod(score) + Open = MP4 + def delete(filename): """Remove tags from a file.""" + MP4(filename).delete() diff --git a/mutagen/musepack.py b/mutagen/musepack.py new file mode 100644 index 00000000..9804deb3 --- /dev/null +++ b/mutagen/musepack.py @@ -0,0 +1,257 @@ +# A Musepack reader/tagger +# +# Copyright 2006 Lukas Lalinsky +# Copyright 2012 Christoph Reiter +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. + +"""Musepack audio streams with APEv2 tags. + +Musepack is an audio format originally based on the MPEG-1 Layer-2 +algorithms. Stream versions 4 through 7 are supported. + +For more information, see http://www.musepack.net/. +""" + +__all__ = ["Musepack", "Open", "delete"] + +import struct + +from mutagen.apev2 import APEv2File, error, delete +from mutagen.id3 import BitPaddedInt +from mutagen._util import cdata + + +class MusepackHeaderError(error): + pass + + +RATES = [44100, 48000, 37800, 32000] + + +def _parse_sv8_int(fileobj, limit=9): + """Reads (max limit) bytes from fileobj until the MSB is zero. + All 7 LSB will be merged to a big endian uint. + + Raises ValueError in case not MSB is zero, or EOFError in + case the file ended before limit is reached. + + Returns (parsed number, number of bytes read) + """ + + num = 0 + for i in xrange(limit): + c = fileobj.read(1) + if len(c) != 1: + raise EOFError + num = (num << 7) | (ord(c) & 0x7F) + if not ord(c) & 0x80: + return num, i + 1 + if limit > 0: + raise ValueError + return 0, 0 + + +def _calc_sv8_gain(gain): + # 64.82 taken from mpcdec + return 64.82 - gain / 256.0 + + +def _calc_sv8_peak(peak): + return (10 ** (peak / (256.0 * 20.0)) / 65535.0) + + +class MusepackInfo(object): + """Musepack stream information. + + Attributes: + + * channels -- number of audio channels + * length -- file length in seconds, as a float + * sample_rate -- audio sampling rate in Hz + * bitrate -- audio bitrate, in bits per second + * version -- Musepack stream version + + Optional Attributes: + + * title_gain, title_peak -- Replay Gain and peak data for this song + * album_gain, album_peak -- Replay Gain and peak data for this album + + These attributes are only available in stream version 7/8. The + gains are a float, +/- some dB. The peaks are a percentage [0..1] of + the maximum amplitude. This means to get a number comparable to + VorbisGain, you must multiply the peak by 2. + """ + + def __init__(self, fileobj): + header = fileobj.read(4) + if len(header) != 4: + raise MusepackHeaderError("not a Musepack file") + + # Skip ID3v2 tags + if header[:3] == "ID3": + header = fileobj.read(6) + if len(header) != 6: + raise MusepackHeaderError("not a Musepack file") + size = 10 + BitPaddedInt(header[2:6]) + fileobj.seek(size) + header = fileobj.read(4) + if len(header) != 4: + raise MusepackHeaderError("not a Musepack file") + + if header.startswith("MPCK"): + self.__parse_sv8(fileobj) + else: + self.__parse_sv467(fileobj) + + if not self.bitrate and self.length != 0: + fileobj.seek(0, 2) + self.bitrate = int(round(fileobj.tell() * 8 / self.length)) + + def __parse_sv8(self, fileobj): + #SV8 http://trac.musepack.net/trac/wiki/SV8Specification + + key_size = 2 + mandatory_packets = ["SH", "RG"] + + def check_frame_key(key): + if len(frame_type) != key_size or not 'AA' <= frame_type <= 'ZZ': + raise MusepackHeaderError("Invalid frame key.") + + frame_type = fileobj.read(key_size) + check_frame_key(frame_type) + + while frame_type not in ("AP", "SE") and mandatory_packets: + try: + frame_size, slen = _parse_sv8_int(fileobj) + except (EOFError, ValueError): + raise MusepackHeaderError("Invalid packet size.") + data_size = frame_size - key_size - slen + + if frame_type == "SH": + mandatory_packets.remove(frame_type) + self.__parse_stream_header(fileobj, data_size) + elif frame_type == "RG": + mandatory_packets.remove(frame_type) + self.__parse_replaygain_packet(fileobj, data_size) + else: + fileobj.seek(data_size, 1) + + frame_type = fileobj.read(key_size) + check_frame_key(frame_type) + + if mandatory_packets: + raise MusepackHeaderError("Missing mandatory packets: %s." + % ", ".join(mandatory_packets)) + + self.length = float(self.samples) / self.sample_rate + self.bitrate = 0 + + def __parse_stream_header(self, fileobj, data_size): + fileobj.seek(4, 1) + try: + self.version = ord(fileobj.read(1)) + except TypeError: + raise MusepackHeaderError("SH packet ended unexpectedly.") + try: + samples, l1 = _parse_sv8_int(fileobj) + samples_skip, l2 = _parse_sv8_int(fileobj) + except (EOFError, ValueError): + raise MusepackHeaderError( + "SH packet: Invalid sample counts.") + left_size = data_size - 5 - l1 - l2 + if left_size != 2: + raise MusepackHeaderError("Invalid SH packet size.") + data = fileobj.read(left_size) + if len(data) != left_size: + raise MusepackHeaderError("SH packet ended unexpectedly.") + self.sample_rate = RATES[ord(data[-2]) >> 5] + self.channels = (ord(data[-1]) >> 4) + 1 + self.samples = samples - samples_skip + + def __parse_replaygain_packet(self, fileobj, data_size): + data = fileobj.read(data_size) + if data_size != 9: + raise MusepackHeaderError("Invalid RG packet size.") + if len(data) != data_size: + raise MusepackHeaderError("RG packet ended unexpectedly.") + title_gain = cdata.short_be(data[1:3]) + title_peak = cdata.short_be(data[3:5]) + album_gain = cdata.short_be(data[5:7]) + album_peak = cdata.short_be(data[7:9]) + if title_gain: + self.title_gain = _calc_sv8_gain(title_gain) + if title_peak: + self.title_peak = _calc_sv8_peak(title_peak) + if album_gain: + self.album_gain = _calc_sv8_gain(album_gain) + if album_peak: + self.album_peak = _calc_sv8_peak(album_peak) + + def __parse_sv467(self, fileobj): + fileobj.seek(-4, 1) + header = fileobj.read(32) + if len(header) != 32: + raise MusepackHeaderError("not a Musepack file") + + # SV7 + if header.startswith("MP+"): + self.version = ord(header[3]) & 0xF + if self.version < 7: + raise MusepackHeaderError("not a Musepack file") + frames = cdata.uint_le(header[4:8]) + flags = cdata.uint_le(header[8:12]) + + self.title_peak, self.title_gain = struct.unpack( + "> 16) & 0x0003] + self.bitrate = 0 + # SV4-SV6 + else: + header_dword = cdata.uint_le(header[0:4]) + self.version = (header_dword >> 11) & 0x03FF + if self.version < 4 or self.version > 6: + raise MusepackHeaderError("not a Musepack file") + self.bitrate = (header_dword >> 23) & 0x01FF + self.sample_rate = 44100 + if self.version >= 5: + frames = cdata.uint_le(header[4:8]) + else: + frames = cdata.ushort_le(header[6:8]) + if self.version < 6: + frames -= 1 + self.channels = 2 + self.length = float(frames * 1152 - 576) / self.sample_rate + + def pprint(self): + rg_data = [] + if hasattr(self, "title_gain"): + rg_data.append("%+0.2f (title)" % self.title_gain) + if hasattr(self, "album_gain"): + rg_data.append("%+0.2f (album)" % self.album_gain) + rg_data = (rg_data and ", Gain: " + ", ".join(rg_data)) or "" + + return "Musepack SV%d, %.2f seconds, %d Hz, %d bps%s" % ( + self.version, self.length, self.sample_rate, self.bitrate, rg_data) + + +class Musepack(APEv2File): + _Info = MusepackInfo + _mimes = ["audio/x-musepack", "audio/x-mpc"] + + @staticmethod + def score(filename, fileobj, header): + return (header.startswith("MP+") + header.startswith("MPCK") + + filename.lower().endswith(".mpc")) + + +Open = Musepack diff --git a/lib/mutagen/ogg.py b/mutagen/ogg.py similarity index 86% rename from lib/mutagen/ogg.py rename to mutagen/ogg.py index 38dfdc7f..657eb7f7 100644 --- a/lib/mutagen/ogg.py +++ b/mutagen/ogg.py @@ -3,8 +3,6 @@ # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. -# -# $Id: ogg.py 3975 2007-01-13 21:51:17Z piman $ """Read and write Ogg bitstreams and pages. @@ -22,13 +20,16 @@ import zlib from cStringIO import StringIO -from lib.mutagen import FileType -from lib.mutagen._util import cdata, insert_bytes, delete_bytes +from mutagen import FileType +from mutagen._util import cdata, insert_bytes, delete_bytes + class error(IOError): """Ogg stream parsing errors.""" + pass + class OggPage(object): """A single Ogg page (not necessarily a single encoded packet). @@ -40,13 +41,14 @@ class OggPage(object): to the start of the next page. Attributes: - version -- stream structure version (currently always 0) - position -- absolute stream position (default -1) - serial -- logical stream serial number (default 0) - sequence -- page sequence number within logical stream (default 0) - offset -- offset this page was read from (default None) - complete -- if the last packet on this page is complete (default True) - packets -- list of raw packet data (default []) + + * version -- stream structure version (currently always 0) + * position -- absolute stream position (default -1) + * serial -- logical stream serial number (default 0) + * sequence -- page sequence number within logical stream (default 0) + * offset -- offset this page was read from (default None) + * complete -- if the last packet on this page is complete (default True) + * packets -- list of raw packet data (default []) Note that if 'complete' is false, the next page's 'continued' property must be true (so set both when constructing pages). @@ -78,7 +80,7 @@ class OggPage(object): try: (oggs, self.version, self.__type_flags, self.position, self.serial, self.sequence, crc, segments) = struct.unpack( - "<4sBBqIIiB", header) + "<4sBBqIIiB", header) except struct.error: raise error("unable to read full header; got %r" % header) @@ -114,6 +116,8 @@ class OggPage(object): except AttributeError: return False + __hash__ = object.__hash__ + def __repr__(self): attrs = ['version', 'position', 'serial', 'sequence', 'offset', 'complete', 'continued', 'first', 'last'] @@ -132,7 +136,7 @@ class OggPage(object): data = [ struct.pack("<4sBBqIIi", "OggS", self.version, self.__type_flags, self.position, self.serial, self.sequence, 0) - ] + ] lacing_data = [] for datum in self.packets: @@ -147,15 +151,19 @@ class OggPage(object): data = "".join(data) # Python's CRC is swapped relative to Ogg's needs. - crc = ~zlib.crc32(data.translate(cdata.bitswap), -1) - # Although we're using to_int_be, this actually makes the CRC + # crc32 returns uint prior to py2.6 on some platforms, so force uint + crc = (~zlib.crc32(data.translate(cdata.bitswap), -1)) & 0xffffffff + # Although we're using to_uint_be, this actually makes the CRC # a proper le integer, since Python's CRC is byteswapped. - crc = cdata.to_int_be(crc).translate(cdata.bitswap) + crc = cdata.to_uint_be(crc).translate(cdata.bitswap) data = data[:22] + crc + data[26:] return data - def __size(self): - size = 27 # Initial header size + @property + def size(self): + """Total frame size.""" + + size = 27 # Initial header size for datum in self.packets: quot, rem = divmod(len(datum), 255) size += quot + 1 @@ -166,12 +174,12 @@ class OggPage(object): size += sum(map(len, self.packets)) return size - size = property(__size, doc="Total frame size.") - def __set_flag(self, bit, val): mask = 1 << bit - if val: self.__type_flags |= mask - else: self.__type_flags &= ~mask + if val: + self.__type_flags |= mask + else: + self.__type_flags &= ~mask continued = property( lambda self: cdata.test_bit(self.__type_flags, 0), @@ -188,6 +196,7 @@ class OggPage(object): lambda self, v: self.__set_flag(2, v), doc="This is the last page of a logical bitstream.") + @classmethod def renumber(klass, fileobj, serial, start): """Renumber pages belonging to a specified logical stream. @@ -210,7 +219,8 @@ class OggPage(object): number = start while True: - try: page = OggPage(fileobj) + try: + page = OggPage(fileobj) except EOFError: break else: @@ -224,8 +234,8 @@ class OggPage(object): fileobj.write(page.write()) fileobj.seek(page.offset + page.size, 0) number += 1 - renumber = classmethod(renumber) + @classmethod def to_packets(klass, pages, strict=False): """Construct a list of packet data from a list of Ogg pages. @@ -243,22 +253,25 @@ class OggPage(object): if not pages[-1].complete: raise ValueError("last packet does not complete") elif pages and pages[0].continued: - packets.append("") + packets.append([""]) for page in pages: if serial != page.serial: raise ValueError("invalid serial number in %r" % page) elif sequence != page.sequence: raise ValueError("bad sequence number in %r" % page) - else: sequence += 1 + else: + sequence += 1 - if page.continued: packets[-1] += page.packets[0] - else: packets.append(page.packets[0]) - packets.extend(page.packets[1:]) + if page.continued: + packets[-1].append(page.packets[0]) + else: + packets.append([page.packets[0]]) + packets.extend([[p] for p in page.packets[1:]]) - return packets - to_packets = classmethod(to_packets) + return ["".join(p) for p in packets] + @classmethod def from_packets(klass, packets, sequence=0, default_size=4096, wiggle_room=2048): """Construct a list of Ogg pages from a list of packet data. @@ -318,8 +331,8 @@ class OggPage(object): pages.append(page) return pages - from_packets = classmethod(from_packets) + @classmethod def replace(klass, fileobj, old_pages, new_pages): """Replace old_pages with new_pages within fileobj. @@ -374,8 +387,8 @@ class OggPage(object): serial = new_pages[-1].serial sequence = new_pages[-1].sequence + 1 klass.renumber(fileobj, serial, sequence) - replace = classmethod(replace) + @classmethod def find_last(klass, fileobj, serial): """Find the last page of the stream 'serial'. @@ -387,12 +400,14 @@ class OggPage(object): """ # For non-muxed streams, look at the last page. - try: fileobj.seek(-256*256, 2) + try: + fileobj.seek(-256*256, 2) except IOError: # The file is less than 64k in length. fileobj.seek(0) data = fileobj.read() - try: index = data.rindex("OggS") + try: + index = data.rindex("OggS") except ValueError: raise error("unable to find final Ogg header") stringobj = StringIO(data[index:]) @@ -403,9 +418,12 @@ class OggPage(object): pass else: if page.serial == serial: - if page.last: return page - else: best_page = page - else: best_page = None + if page.last: + return page + else: + best_page = page + else: + best_page = None # The stream is muxed, so use the slow way. fileobj.seek(0) @@ -421,7 +439,7 @@ class OggPage(object): return best_page except EOFError: return best_page - find_last = classmethod(find_last) + class OggFileType(FileType): """An generic Ogg file.""" @@ -435,25 +453,12 @@ class OggFileType(FileType): """Load file information from a filename.""" self.filename = filename - fileobj = file(filename, "rb") + fileobj = open(filename, "rb") try: try: self.info = self._Info(fileobj) self.tags = self._Tags(fileobj, self.info) - - if self.info.length: - # The streaminfo gave us real length information, - # don't waste time scanning the Ogg. - return - - last_page = OggPage.find_last(fileobj, self.info.serial) - samples = last_page.position - try: - denom = self.info.sample_rate - except AttributeError: - denom = self.info.fps - self.info.length = samples / float(denom) - + self.info._post_tags(fileobj) except error, e: raise self._Error, e, sys.exc_info()[2] except EOFError: @@ -466,13 +471,15 @@ class OggFileType(FileType): If no filename is given, the one most recently loaded is used. """ + if filename is None: filename = self.filename self.tags.clear() - fileobj = file(filename, "rb+") + fileobj = open(filename, "rb+") try: - try: self.tags._inject(fileobj) + try: + self.tags._inject(fileobj) except error, e: raise self._Error, e, sys.exc_info()[2] except EOFError: @@ -485,11 +492,13 @@ class OggFileType(FileType): If no filename is given, the one most recently loaded is used. """ + if filename is None: filename = self.filename - fileobj = file(filename, "rb+") + fileobj = open(filename, "rb+") try: - try: self.tags._inject(fileobj) + try: + self.tags._inject(fileobj) except error, e: raise self._Error, e, sys.exc_info()[2] except EOFError: diff --git a/lib/mutagen/oggflac.py b/mutagen/oggflac.py similarity index 82% rename from lib/mutagen/oggflac.py rename to mutagen/oggflac.py index c5ea0786..14ecec00 100644 --- a/lib/mutagen/oggflac.py +++ b/mutagen/oggflac.py @@ -5,8 +5,6 @@ # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. -# -# $Id: oggflac.py 3976 2007-01-13 22:00:14Z piman $ """Read and write Ogg FLAC comments. @@ -23,11 +21,17 @@ import struct from cStringIO import StringIO -from lib.mutagen.flac import StreamInfo, VCFLACDict -from lib.mutagen.ogg import OggPage, OggFileType, error as OggError +from mutagen.flac import StreamInfo, VCFLACDict, StrictFileObject +from mutagen.ogg import OggPage, OggFileType, error as OggError + + +class error(OggError): + pass + + +class OggFLACHeaderError(error): + pass -class error(OggError): pass -class OggFLACHeaderError(error): pass class OggFLACStreamInfo(StreamInfo): """Ogg FLAC general header and stream info. @@ -36,14 +40,19 @@ class OggFLACStreamInfo(StreamInfo): block, as well as the Ogg codec setup that precedes it. Attributes (in addition to StreamInfo's): - packets -- number of metadata packets - serial -- Ogg logical stream serial number + + * packets -- number of metadata packets + * serial -- Ogg logical stream serial number """ packets = 0 serial = 0 def load(self, data): + # Ogg expects file objects that don't raise on read + if isinstance(data, StrictFileObject): + data = data._fileobj + page = OggPage(data) while not page.packets[0].startswith("\x7FFLAC"): page = OggPage(data) @@ -57,12 +66,19 @@ class OggFLACStreamInfo(StreamInfo): self.serial = page.serial # Skip over the block header. - stringobj = StringIO(page.packets[0][17:]) - super(OggFLACStreamInfo, self).load(StringIO(page.packets[0][17:])) + stringobj = StrictFileObject(StringIO(page.packets[0][17:])) + super(OggFLACStreamInfo, self).load(stringobj) + + def _post_tags(self, fileobj): + if self.length: + return + page = OggPage.find_last(fileobj, self.serial) + self.length = page.position / float(self.sample_rate) def pprint(self): return "Ogg " + super(OggFLACStreamInfo, self).pprint() + class OggFLACVComment(VCFLACDict): def load(self, data, info, errors='replace'): # data should be pointing at the start of an Ogg page, after @@ -107,6 +123,7 @@ class OggFLACVComment(VCFLACDict): new_pages = OggPage.from_packets(packets, old_pages[0].sequence) OggPage.replace(fileobj, old_pages, new_pages) + class OggFLAC(OggFileType): """An Ogg FLAC file.""" @@ -115,13 +132,16 @@ class OggFLAC(OggFileType): _Error = OggFLACHeaderError _mimes = ["audio/x-oggflac"] + @staticmethod def score(filename, fileobj, header): return (header.startswith("OggS") * ( ("FLAC" in header) + ("fLaC" in header))) - score = staticmethod(score) + Open = OggFLAC + def delete(filename): """Remove tags from a file.""" + OggFLAC(filename).delete() diff --git a/mutagen/oggopus.py b/mutagen/oggopus.py new file mode 100644 index 00000000..6de44391 --- /dev/null +++ b/mutagen/oggopus.py @@ -0,0 +1,125 @@ +# Copyright 2012 Christoph Reiter +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. + +"""Read and write Ogg Opus comments. + +This module handles Opus files wrapped in an Ogg bitstream. The +first Opus stream found is used. + +Based on http://tools.ietf.org/html/draft-terriberry-oggopus-01 +""" + +__all__ = ["OggOpus", "Open", "delete"] + +import struct + +from mutagen._vorbis import VCommentDict +from mutagen.ogg import OggPage, OggFileType, error as OggError + + +class error(OggError): + pass + + +class OggOpusHeaderError(error): + pass + + +class OggOpusInfo(object): + """Ogg Opus stream information. + + Attributes: + + * length - file length in seconds, as a float + * channels - number of channels + """ + + length = 0 + + def __init__(self, fileobj): + page = OggPage(fileobj) + while not page.packets[0].startswith("OpusHead"): + page = OggPage(fileobj) + + self.serial = page.serial + + if not page.first: + raise OggOpusHeaderError( + "page has ID header, but doesn't start a stream") + + (version, self.channels, pre_skip, orig_sample_rate, output_gain, + channel_map) = struct.unpack("> 4, version & 0xF + if major != 0: + raise OggOpusHeaderError("version %r unsupported" % major) + + def _post_tags(self, fileobj): + page = OggPage.find_last(fileobj, self.serial) + self.length = (page.position - self.__pre_skip) / float(48000) + + def pprint(self): + return "Ogg Opus, %.2f seconds" % (self.length) + + +class OggOpusVComment(VCommentDict): + """Opus comments embedded in an Ogg bitstream.""" + + def __get_comment_pages(self, fileobj, info): + # find the first tags page with the right serial + page = OggPage(fileobj) + while info.serial != page.serial or \ + not page.packets[0].startswith("OpusTags"): + page = OggPage(fileobj) + + # get all comment pages + pages = [page] + while not (pages[-1].complete or len(pages[-1].packets) > 1): + page = OggPage(fileobj) + if page.serial == pages[0].serial: + pages.append(page) + + return pages + + def __init__(self, fileobj, info): + pages = self.__get_comment_pages(fileobj, info) + data = OggPage.to_packets(pages)[0][8:] # Strip OpusTags + super(OggOpusVComment, self).__init__(data, framing=False) + + def _inject(self, fileobj): + fileobj.seek(0) + info = OggOpusInfo(fileobj) + old_pages = self.__get_comment_pages(fileobj, info) + + packets = OggPage.to_packets(old_pages) + packets[0] = "OpusTags" + self.write(framing=False) + new_pages = OggPage.from_packets(packets, old_pages[0].sequence) + OggPage.replace(fileobj, old_pages, new_pages) + + +class OggOpus(OggFileType): + """An Ogg Opus file.""" + + _Info = OggOpusInfo + _Tags = OggOpusVComment + _Error = OggOpusHeaderError + _mimes = ["audio/ogg", "audio/ogg; codecs=opus"] + + @staticmethod + def score(filename, fileobj, header): + return (header.startswith("OggS") * ("OpusHead" in header)) + + +Open = OggOpus + + +def delete(filename): + """Remove tags from a file.""" + + OggOpus(filename).delete() diff --git a/lib/mutagen/oggspeex.py b/mutagen/oggspeex.py similarity index 87% rename from lib/mutagen/oggspeex.py rename to mutagen/oggspeex.py index 4984925c..4f208521 100644 --- a/lib/mutagen/oggspeex.py +++ b/mutagen/oggspeex.py @@ -5,8 +5,6 @@ # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. -# -# $Id: oggspeex.py 3976 2007-01-13 22:00:14Z piman $ """Read and write Ogg Speex comments. @@ -21,20 +19,27 @@ http://lists.xiph.org/pipermail/speex-dev/2006-July/004676.html. __all__ = ["OggSpeex", "Open", "delete"] -from lib.mutagen._vorbis import VCommentDict -from lib.mutagen.ogg import OggPage, OggFileType, error as OggError -from lib.mutagen._util import cdata +from mutagen._vorbis import VCommentDict +from mutagen.ogg import OggPage, OggFileType, error as OggError +from mutagen._util import cdata + + +class error(OggError): + pass + + +class OggSpeexHeaderError(error): + pass -class error(OggError): pass -class OggSpeexHeaderError(error): pass class OggSpeexInfo(object): """Ogg Speex stream information. Attributes: - bitrate - nominal bitrate in bits per second - channels - number of channels - length - file length in seconds, as a float + + * bitrate - nominal bitrate in bits per second + * channels - number of channels + * length - file length in seconds, as a float The reference encoder does not set the bitrate; in this case, the bitrate will be 0. @@ -54,9 +59,14 @@ class OggSpeexInfo(object): self.bitrate = max(0, cdata.int_le(page.packets[0][52:56])) self.serial = page.serial + def _post_tags(self, fileobj): + page = OggPage.find_last(fileobj, self.serial) + self.length = page.position / float(self.sample_rate) + def pprint(self): return "Ogg Speex, %.2f seconds" % self.length + class OggSpeexVComment(VCommentDict): """Speex comments embedded in an Ogg bitstream.""" @@ -104,6 +114,7 @@ class OggSpeexVComment(VCommentDict): new_pages = OggPage.from_packets(packets, old_pages[0].sequence) OggPage.replace(fileobj, old_pages, new_pages) + class OggSpeex(OggFileType): """An Ogg Speex file.""" @@ -112,12 +123,15 @@ class OggSpeex(OggFileType): _Error = OggSpeexHeaderError _mimes = ["audio/x-speex"] + @staticmethod def score(filename, fileobj, header): return (header.startswith("OggS") * ("Speex " in header)) - score = staticmethod(score) + Open = OggSpeex + def delete(filename): """Remove tags from a file.""" + OggSpeex(filename).delete() diff --git a/lib/mutagen/oggtheora.py b/mutagen/oggtheora.py similarity index 80% rename from lib/mutagen/oggtheora.py rename to mutagen/oggtheora.py index b0a52985..edf221a7 100644 --- a/lib/mutagen/oggtheora.py +++ b/mutagen/oggtheora.py @@ -5,8 +5,6 @@ # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. -# -# $Id: oggtheora.py 3976 2007-01-13 22:00:14Z piman $ """Read and write Ogg Theora comments. @@ -20,18 +18,26 @@ __all__ = ["OggTheora", "Open", "delete"] import struct -from lib.mutagen._vorbis import VCommentDict -from lib.mutagen.ogg import OggPage, OggFileType, error as OggError +from mutagen._vorbis import VCommentDict +from mutagen._util import cdata +from mutagen.ogg import OggPage, OggFileType, error as OggError + + +class error(OggError): + pass + + +class OggTheoraHeaderError(error): + pass -class error(OggError): pass -class OggTheoraHeaderError(error): pass class OggTheoraInfo(object): """Ogg Theora stream information. Attributes: - length - file length in seconds, as a float - fps - video frames per second, as a float + + * length - file length in seconds, as a float + * fps - video frames per second, as a float """ length = 0 @@ -50,12 +56,21 @@ class OggTheoraInfo(object): "found Theora version %d.%d != 3.2" % (vmaj, vmin)) fps_num, fps_den = struct.unpack(">2I", data[22:30]) self.fps = fps_num / float(fps_den) - self.bitrate = struct.unpack(">I", data[37:40] + "\x00")[0] + self.bitrate = cdata.uint_be("\x00" + data[37:40]) + self.granule_shift = (cdata.ushort_be(data[40:42]) >> 5) & 0x1F self.serial = page.serial + def _post_tags(self, fileobj): + page = OggPage.find_last(fileobj, self.serial) + position = page.position + mask = (1 << self.granule_shift) - 1 + frames = (position >> self.granule_shift) + (position & mask) + self.length = frames / float(self.fps) + def pprint(self): return "Ogg Theora, %.2f seconds, %d bps" % (self.length, self.bitrate) + class OggTheoraCommentDict(VCommentDict): """Theora comments embedded in an Ogg bitstream.""" @@ -91,6 +106,7 @@ class OggTheoraCommentDict(VCommentDict): new_pages = OggPage.from_packets(packets, old_pages[0].sequence) OggPage.replace(fileobj, old_pages, new_pages) + class OggTheora(OggFileType): """An Ogg Theora file.""" @@ -99,13 +115,16 @@ class OggTheora(OggFileType): _Error = OggTheoraHeaderError _mimes = ["video/x-theora"] + @staticmethod def score(filename, fileobj, header): return (header.startswith("OggS") * (("\x80theora" in header) + ("\x81theora" in header))) - score = staticmethod(score) + Open = OggTheora + def delete(filename): """Remove tags from a file.""" + OggTheora(filename).delete() diff --git a/lib/mutagen/oggvorbis.py b/mutagen/oggvorbis.py similarity index 85% rename from lib/mutagen/oggvorbis.py rename to mutagen/oggvorbis.py index dbed6831..509fd966 100644 --- a/lib/mutagen/oggvorbis.py +++ b/mutagen/oggvorbis.py @@ -5,8 +5,6 @@ # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. -# -# $Id: oggvorbis.py 3976 2007-01-13 22:00:14Z piman $ """Read and write Ogg Vorbis comments. @@ -21,18 +19,25 @@ __all__ = ["OggVorbis", "Open", "delete"] import struct -from lib.mutagen._vorbis import VCommentDict -from lib.mutagen.ogg import OggPage, OggFileType, error as OggError +from mutagen._vorbis import VCommentDict +from mutagen.ogg import OggPage, OggFileType, error as OggError + + +class error(OggError): + pass + + +class OggVorbisHeaderError(error): + pass -class error(OggError): pass -class OggVorbisHeaderError(error): pass class OggVorbisInfo(object): """Ogg Vorbis stream information. Attributes: - length - file length in seconds, as a float - bitrate - nominal ('average') bitrate in bits per second, as an int + + * length - file length in seconds, as a float + * bitrate - nominal ('average') bitrate in bits per second, as an int """ length = 0 @@ -63,14 +68,14 @@ class OggVorbisInfo(object): else: self.bitrate = nominal_bitrate - if self.bitrate == 0 and self.length > 0: - fileobj.seek(0, 2) - self.bitrate = int((fileobj.tell() * 8) / self.length) - + def _post_tags(self, fileobj): + page = OggPage.find_last(fileobj, self.serial) + self.length = page.position / float(self.sample_rate) def pprint(self): return "Ogg Vorbis, %.2f seconds, %d bps" % (self.length, self.bitrate) + class OggVCommentDict(VCommentDict): """Vorbis comments embedded in an Ogg bitstream.""" @@ -82,7 +87,7 @@ class OggVCommentDict(VCommentDict): if page.serial == info.serial: pages.append(page) complete = page.complete or (len(page.packets) > 1) - data = OggPage.to_packets(pages)[0][7:] # Strip off "\x03vorbis". + data = OggPage.to_packets(pages)[0][7:] # Strip off "\x03vorbis". super(OggVCommentDict, self).__init__(data) def _inject(self, fileobj): @@ -109,6 +114,7 @@ class OggVCommentDict(VCommentDict): new_pages = OggPage.from_packets(packets, old_pages[0].sequence) OggPage.replace(fileobj, old_pages, new_pages) + class OggVorbis(OggFileType): """An Ogg Vorbis file.""" @@ -117,12 +123,15 @@ class OggVorbis(OggFileType): _Error = OggVorbisHeaderError _mimes = ["audio/vorbis", "audio/x-vorbis"] + @staticmethod def score(filename, fileobj, header): return (header.startswith("OggS") * ("\x01vorbis" in header)) - score = staticmethod(score) + Open = OggVorbis + def delete(filename): """Remove tags from a file.""" + OggVorbis(filename).delete() diff --git a/lib/mutagen/optimfrog.py b/mutagen/optimfrog.py similarity index 82% rename from lib/mutagen/optimfrog.py rename to mutagen/optimfrog.py index c1d8f49f..24a87af8 100644 --- a/lib/mutagen/optimfrog.py +++ b/mutagen/optimfrog.py @@ -5,8 +5,6 @@ # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. -# -# $Id: optimfrog.py 3923 2006-10-21 15:07:13Z luks $ """OptimFROG audio streams with APEv2 tags. @@ -23,30 +21,35 @@ For more information, see http://www.losslessaudio.org/ __all__ = ["OptimFROG", "Open", "delete"] import struct -from lib.mutagen.apev2 import APEv2File, error, delete -class OptimFROGHeaderError(error): pass +from mutagen.apev2 import APEv2File, error, delete + + +class OptimFROGHeaderError(error): + pass + class OptimFROGInfo(object): """OptimFROG stream information. Attributes: - channels - number of audio channels - length - file length in seconds, as a float - sample_rate - audio sampling rate in Hz + + * channels - number of audio channels + * length - file length in seconds, as a float + * sample_rate - audio sampling rate in Hz """ def __init__(self, fileobj): header = fileobj.read(76) if (len(header) != 76 or not header.startswith("OFR ") or - struct.unpack("` + """ _Info = TrueAudioInfo _mimes = ["audio/x-tta"] + @staticmethod def score(filename, fileobj, header): return (header.startswith("ID3") + header.startswith("TTA") + filename.lower().endswith(".tta") * 2) - score = staticmethod(score) + Open = TrueAudio -class EasyTrueAudio(TrueAudio): - """Like MP3, but uses EasyID3 for tags.""" - from lib.mutagen.easyid3 import EasyID3 as ID3 +class EasyTrueAudio(TrueAudio): + """Like MP3, but uses EasyID3 for tags. + + :ivar info: :class:`TrueAudioInfo` + :ivar tags: :class:`EasyID3 ` + """ + + from mutagen.easyid3 import EasyID3 as ID3 + ID3 = ID3 diff --git a/lib/mutagen/wavpack.py b/mutagen/wavpack.py similarity index 78% rename from lib/mutagen/wavpack.py rename to mutagen/wavpack.py index af99f38a..1a2db818 100644 --- a/lib/mutagen/wavpack.py +++ b/mutagen/wavpack.py @@ -5,8 +5,6 @@ # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. -# -# $Id: wavpack.py 3997 2007-02-25 21:44:53Z piman $ """WavPack reading and writing. @@ -16,22 +14,26 @@ http://www.wavpack.com/ for more information. __all__ = ["WavPack", "Open", "delete"] -from lib.mutagen.apev2 import APEv2File, error, delete -from lib.mutagen._util import cdata +from mutagen.apev2 import APEv2File, error, delete +from mutagen._util import cdata -class WavPackHeaderError(error): pass + +class WavPackHeaderError(error): + pass RATES = [6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000, 192000] + class WavPackInfo(object): """WavPack stream information. Attributes: - channels - number of audio channels (1 or 2) - length - file length in seconds, as a float - sample_rate - audio sampling rate in Hz - version - WavPack stream version + + * channels - number of audio channels (1 or 2) + * length - file length in seconds, as a float + * sample_rate - audio sampling rate in Hz + * version - WavPack stream version """ def __init__(self, fileobj): @@ -48,10 +50,14 @@ class WavPackInfo(object): def pprint(self): return "WavPack, %.2f seconds, %d Hz" % (self.length, self.sample_rate) + class WavPack(APEv2File): _Info = WavPackInfo _mimes = ["audio/x-wavpack"] + @staticmethod def score(filename, fileobj, header): return header.startswith("wvpk") * 2 - score = staticmethod(score) + + +Open = WavPack