Пример #1
0
def test_any_normalize(path):
    fsn = path2fsn(path)

    assert path2fsn(path) == fsn2norm(fsn)

    assert bytes2fsn(fsn2bytes(fsn, "utf-8"), "utf-8") == fsn2norm(fsn)

    if isinstance(path, text_type):
        assert text2fsn(path) == fsn2norm(text2fsn(path))
Пример #2
0
def test_surrogates():
    if os.name == "nt":
        assert fsn2bytes(u"\ud83d", "utf-16-le") == b"=\xd8"
        assert bytes2fsn(b"\xd8=", "utf-16-be") == u"\ud83d"

        with pytest.raises(ValueError):
            bytes2fsn(b"\xd8=a", "utf-16-be")

        with pytest.raises(ValueError):
            bytes2fsn(b"=\xd8a", "utf-16-le")

        # for utf-16-le we have a workaround
        assert bytes2fsn(b"=\xd8", "utf-16-le") == u"\ud83d"
        assert bytes2fsn(b"=\xd8=\xd8", "utf-16-le") == u"\ud83d\ud83d"

        with pytest.raises(ValueError):
            bytes2fsn(b"=\xd8\x00\x00", "utf-16-le")

        # 4 byte code point
        assert fsn2bytes(u"\U0001f600", "utf-16-le") == b"=\xd8\x00\xde"
        assert bytes2fsn(b"=\xd8\x00\xde", "utf-16-le") == u"\U0001f600"

        # 4 byte codepoint + lone surrogate
        assert bytes2fsn(b"=\xd8\x00\xde=\xd8", "utf-16-le") == \
            u"\U0001f600\ud83d"

        with pytest.raises(UnicodeDecodeError):
            bytes2fsn(b"a", "utf-16-le")

        assert fsn2bytes(u"\ud83d", "utf-8") == b"\xed\xa0\xbd"
        assert bytes2fsn(b"\xed\xa0\xbd", "utf-8") == u"\ud83d"

        assert fsnative(u"\ud83d") == u"\ud83d"
        assert fsn2text(u"\ud83d") == u"\ufffd"

        # at least don't fail...
        assert fsn2uri(u"C:\\\ud83d") == u"file:///C:/%ED%A0%BD"
    else:
        # this shouldn't fail and produce the same result on py2/3 at least.
        assert fsn2bytes(fsnative(u"\ud83d"), None) == b"\xed\xa0\xbd"
        text2fsn(fsn2text(fsnative(u"\ud83d")))

        if PY2 and isunicodeencoding():
            # under Python 2 we get surrogates, but we can't do anything about
            # it since most codecs don't treat that as an error
            assert fsn2text(fsnative(u"\ud83d")) == u"\ud83d"
        else:
            # under Python 3 the decoder don't allow surrogates
            assert fsn2text(fsnative(u"\ud83d")) == u"\ufffd\ufffd\ufffd"
Пример #3
0
def init(language=None):
    """Call this sometime at start before any register_translation()
    and before any gettext using libraries are loaded.

    Args:
        language (text_type or None): Either a language to use or None for the
            system derived default.
    """

    global _initialized

    set_i18n_envvars()
    fixup_i18n_envvars()

    print_d("LANGUAGE: %r" % environ.get("LANGUAGE"))
    print_d("LANG: %r" % environ.get("LANG"))

    try:
        locale.setlocale(locale.LC_ALL, '')
    except locale.Error:
        pass

    # XXX: these are our most user facing APIs, make sre they are not loaded
    # before we set the language. For GLib this is too late..
    assert "gi.repository.Gtk" not in sys.modules
    assert "gi.repository.Gst" not in sys.modules

    if language is not None:
        environ["LANGUAGE"] = text2fsn(language)
        print_d("LANGUAGE: %r" % environ.get("LANGUAGE"))

    _initialized = True
Пример #4
0
def test_any_filenames(path):
    if isinstance(path, fsnative):
        assert path2fsn(path) == fsn2norm(path)

    fsn = path2fsn(path)
    assert path2fsn(fsn) == fsn

    assert isinstance(fsn, fsnative)

    try:
        # never raises ValueError/TypError
        with open(fsn):
            pass
    except EnvironmentError:
        pass

    fsn2text(fsn).encode("utf-8")

    try:
        t = fsn2text(fsn, strict=True)
    except ValueError:
        pass
    else:
        assert fsn2norm(text2fsn(t)) == fsn2norm(fsn)

    data = fsn2bytes(fsn, "utf-8")
    assert fsn2bytes(bytes2fsn(data, "utf-8"), "utf-8") == data
Пример #5
0
def init(language=None):
    """Call this sometime at start before any register_translation()
    and before any gettext using libraries are loaded.

    Args:
        language (text_type or None): Either a language to use or None for the
            system derived default.
    """

    global _initialized

    set_i18n_envvars()
    fixup_i18n_envvars()

    print_d("LANGUAGE: %r" % environ.get("LANGUAGE"))
    print_d("LANG: %r" % environ.get("LANG"))

    try:
        locale.setlocale(locale.LC_ALL, '')
    except locale.Error:
        pass

    # XXX: these are our most user facing APIs, make sre they are not loaded
    # before we set the language. For GLib this is too late..
    assert "gi.repository.Gtk" not in sys.modules
    assert "gi.repository.Gst" not in sys.modules

    if language is not None:
        environ["LANGUAGE"] = text2fsn(language)
        print_d("LANGUAGE: %r" % environ.get("LANGUAGE"))

    _initialized = True
Пример #6
0
def test_fsn2text_strict():
    if os.name != "nt":
        path = bytes2fsn(b"\xff", None)
    else:
        path = u"\ud83d"

    if text2fsn(fsn2text(path)) != path:
        with pytest.raises(ValueError):
            fsn2text(path, strict=True)
Пример #7
0
def _dir_for(filelike):
    try:
        if isinstance(filelike, addinfourl):
            # if the "filelike" was created via urlopen
            # it is wrapped in an addinfourl object
            return os.path.dirname(path2fsn(filelike.fp.name))
        else:
            return os.path.dirname(path2fsn(filelike.name))
    except AttributeError:
        # Probably a URL
        return text2fsn(u'')
Пример #8
0
def ParsePLS(file):
    data = {}

    lines = file.read().decode('utf-8', 'replace').splitlines()

    if not lines or "[playlist]" not in lines.pop(0):
        return []

    for line in lines:
        try:
            head, val = line.strip().split("=", 1)
        except (TypeError, ValueError):
            continue
        else:
            head = head.lower()
            if head.startswith("length") and val == "-1":
                continue
            else:
                data[head] = val

    count = 1
    files = []
    warnings = []
    while True:
        if "file%d" % count in data:
            filename = text2fsn(data["file%d" % count])
            if filename.lower()[-4:] in [".pls", ".m3u"]:
                warnings.append(filename)
            else:
                irf = IRFile(filename)
                for key in ["title", "genre", "artist"]:
                    try:
                        irf[key] = data["%s%d" % (key, count)]
                    except KeyError:
                        pass
                try:
                    irf["~#length"] = int(data["length%d" % count])
                except (KeyError, TypeError, ValueError):
                    pass
                files.append(irf)
        else:
            break
        count += 1

    if warnings:
        WarningMessage(
            None, _("Unsupported file type"),
            _("Station lists can only contain locations of stations, "
              "not other station lists or playlists. The following locations "
              "cannot be loaded:\n%s") %
            "\n  ".join(map(util.escape, warnings))
        ).run()

    return files
Пример #9
0
def ParsePLS(file):
    data = {}

    lines = file.read().decode('utf-8', 'replace').splitlines()

    if not lines or "[playlist]" not in lines.pop(0):
        return []

    for line in lines:
        try:
            head, val = line.strip().split("=", 1)
        except (TypeError, ValueError):
            continue
        else:
            head = head.lower()
            if head.startswith("length") and val == "-1":
                continue
            else:
                data[head] = val

    count = 1
    files = []
    warnings = []
    while True:
        if "file%d" % count in data:
            filename = text2fsn(data["file%d" % count])
            if filename.lower()[-4:] in [".pls", ".m3u"]:
                warnings.append(filename)
            else:
                irf = IRFile(filename)
                for key in ["title", "genre", "artist"]:
                    try:
                        irf[key] = data["%s%d" % (key, count)]
                    except KeyError:
                        pass
                try:
                    irf["~#length"] = int(data["length%d" % count])
                except (KeyError, TypeError, ValueError):
                    pass
                files.append(irf)
        else:
            break
        count += 1

    if warnings:
        WarningMessage(
            None, _("Unsupported file type"),
            _("Station lists can only contain locations of stations, "
              "not other station lists or playlists. The following locations "
              "cannot be loaded:\n%s") %
            "\n  ".join(map(util.escape, warnings))
        ).run()

    return files
Пример #10
0
    def __rename(self, library):
        model = self.view.get_model()
        win = WritingWindow(self, len(model))
        win.show()
        was_changed = set()
        skip_all = False
        self.view.freeze_child_notify()

        for entry in model.itervalues():
            song = entry.song
            new_name = entry.new_name
            old_name = entry.name
            if new_name is None:
                continue

            try:
                library.rename(song, text2fsn(new_name), changed=was_changed)
            except Exception:
                util.print_exc()
                if skip_all:
                    continue
                RESPONSE_SKIP_ALL = 1
                msg = qltk.Message(
                    Gtk.MessageType.ERROR,
                    win,
                    _("Unable to rename file"),
                    _("Renaming <b>%(old-name)s</b> to <b>%(new-name)s</b> "
                      "failed. Possibly the target file already exists, "
                      "or you do not have permission to make the "
                      "new file or remove the old one.") % {
                          "old-name": util.escape(old_name),
                          "new-name": util.escape(new_name),
                      },
                    buttons=Gtk.ButtonsType.NONE)
                msg.add_button(_("Ignore _All Errors"), RESPONSE_SKIP_ALL)
                msg.add_icon_button(_("_Stop"), Icons.PROCESS_STOP,
                                    Gtk.ResponseType.CANCEL)
                msg.add_button(_("_Continue"), Gtk.ResponseType.OK)
                msg.set_default_response(Gtk.ResponseType.OK)
                resp = msg.run()
                skip_all |= (resp == RESPONSE_SKIP_ALL)
                # Preserve old behavior: shift-click is Ignore All
                mods = Gdk.Display.get_default().get_pointer()[3]
                skip_all |= mods & Gdk.ModifierType.SHIFT_MASK
                library.reload(song, changed=was_changed)
                if resp != Gtk.ResponseType.OK and resp != RESPONSE_SKIP_ALL:
                    break
            if win.step():
                break

        self.view.thaw_child_notify()
        win.destroy()
        library.changed(was_changed)
        self.save.set_sensitive(False)
Пример #11
0
    def __rename(self, library):
        model = self.view.get_model()
        win = WritingWindow(self, len(model))
        win.show()
        was_changed = set()
        skip_all = False
        self.view.freeze_child_notify()

        for entry in itervalues(model):
            song = entry.song
            new_name = entry.new_name
            old_name = entry.name
            if new_name is None:
                continue

            try:
                library.rename(song, text2fsn(new_name), changed=was_changed)
            except Exception:
                util.print_exc()
                if skip_all:
                    continue
                RESPONSE_SKIP_ALL = 1
                msg = qltk.Message(
                    Gtk.MessageType.ERROR, win, _("Unable to rename file"),
                    _("Renaming <b>%(old-name)s</b> to <b>%(new-name)s</b> "
                      "failed. Possibly the target file already exists, "
                      "or you do not have permission to make the "
                      "new file or remove the old one.") % {
                        "old-name": util.escape(old_name),
                        "new-name": util.escape(new_name),
                      },
                    buttons=Gtk.ButtonsType.NONE)
                msg.add_button(_("Ignore _All Errors"), RESPONSE_SKIP_ALL)
                msg.add_icon_button(_("_Stop"), Icons.PROCESS_STOP,
                                    Gtk.ResponseType.CANCEL)
                msg.add_button(_("_Continue"), Gtk.ResponseType.OK)
                msg.set_default_response(Gtk.ResponseType.OK)
                resp = msg.run()
                skip_all |= (resp == RESPONSE_SKIP_ALL)
                # Preserve old behavior: shift-click is Ignore All
                mods = Gdk.Display.get_default().get_pointer()[3]
                skip_all |= mods & Gdk.ModifierType.SHIFT_MASK
                library.reload(song, changed=was_changed)
                if resp != Gtk.ResponseType.OK and resp != RESPONSE_SKIP_ALL:
                    break
            if win.step():
                break

        self.view.thaw_child_notify()
        win.destroy()
        library.changed(was_changed)
        self.save.set_sensitive(False)
Пример #12
0
def _print_playing(app, fstring=None):
    from quodlibet.formats import AudioFile
    from quodlibet.pattern import Pattern

    if fstring is None:
        fstring = u"<artist~album~tracknumber~title>"
    else:
        fstring = arg2text(fstring)

    song = app.player.info
    if song is None:
        song = AudioFile({"~filename": fsnative(u"/")})
        song.sanitize()

    return text2fsn(Pattern(fstring).format(song) + u"\n")
Пример #13
0
def ParseM3U(fileobj):
    files = []
    pending_title = None
    lines = fileobj.read().decode('utf-8', 'replace').splitlines()
    for line in lines:
        line = line.strip()
        if line.startswith("#EXTINF:"):
            try:
                pending_title = line.split(",", 1)[1]
            except IndexError:
                pending_title = None
        elif line.startswith("http"):
            irf = IRFile(text2fsn(line))
            if pending_title:
                irf["title"] = pending_title
                pending_title = None
            files.append(irf)
    return files
Пример #14
0
def ParseM3U(fileobj):
    files = []
    pending_title = None
    lines = fileobj.read().decode('utf-8', 'replace').splitlines()
    for line in lines:
        line = line.strip()
        if line.startswith("#EXTINF:"):
            try:
                pending_title = line.split(",", 1)[1]
            except IndexError:
                pending_title = None
        elif line.startswith("http"):
            irf = IRFile(text2fsn(line))
            if pending_title:
                irf["title"] = pending_title
                pending_title = None
            files.append(irf)
    return files
Пример #15
0
    def test_import(self):
        pl_name = u"_€3 œufs à Noël"
        pl = FileBackedPlaylist(_TEMP_DIR, pl_name, None)
        pl.extend(SONGS)
        pl.write()
        new_fn = os.path.splitext(text2fsn(pl.name))[0] + '.m3u'
        new_path = os.path.join(pl.dir, new_fn)
        os.rename(pl.filename, new_path)
        added = self.bar._import_playlists([new_path], self.lib)
        self.failUnlessEqual(added, 1, msg="Failed to add '%s'" % new_path)
        os.unlink(new_path)
        pls = self.bar.playlists()
        self.failUnlessEqual(len(pls), 3)
        # Leading underscore makes it always the last entry
        imported = pls[-1]
        self.failUnlessEqual(imported.name, pl_name)

        def fns(songs):
            return [song('~filename') for song in songs]
        self.failUnlessEqual(fns(imported.songs), fns(pl.songs))
    def test_import(self):
        pl_name = u"_€3 œufs à Noël"
        pl = FileBackedPlaylist(_TEMP_DIR, pl_name, None)
        pl.extend(SONGS)
        pl.write()
        new_fn = os.path.splitext(text2fsn(pl.name))[0] + '.m3u'
        new_path = os.path.join(pl.dir, new_fn)
        os.rename(pl.filename, new_path)
        added = self.bar._import_playlists([new_path], self.lib)
        self.failUnlessEqual(added, 1, msg="Failed to add '%s'" % new_path)
        os.unlink(new_path)
        pls = self.bar.playlists()
        self.failUnlessEqual(len(pls), 3)
        # Leading underscore makes it always the last entry
        imported = pls[-1]
        self.failUnlessEqual(imported.name, pl_name)

        def fns(songs):
            return [song('~filename') for song in songs]

        self.failUnlessEqual(fns(imported.songs), fns(pl.songs))
Пример #17
0
def _status(app):
    player = app.player

    if player.paused:
        strings = ["paused"]
    else:
        strings = ["playing"]
    strings.append(type(app.browser).__name__)
    po = app.player_options
    strings.append("%0.3f" % player.volume)
    strings.append("shuffle" if po.shuffle else "inorder")
    strings.append("on" if po.repeat else "off")
    progress = 0
    if player.info:
        length = player.info.get("~#length", 0)
        if length:
            progress = player.get_position() / (length * 1000.0)
    strings.append("%0.3f" % progress)
    status = u" ".join(strings) + u"\n"

    return text2fsn(status)
Пример #18
0
def _dump_browsers(app):
    response = u""
    for i, b in enumerate(browsers.browsers):
        response += u"%d. %s\n" % (i, browsers.name(b))
    return text2fsn(response)
Пример #19
0
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

import os
import re
from typing import Iterable, Generator, Optional

import quodlibet
from quodlibet import print_d, print_w
from quodlibet.formats import AudioFile
from quodlibet.library.base import Library
from quodlibet.util.collection import (Playlist, XSPFBackedPlaylist,
                                       FileBackedPlaylist)
from senf import text2fsn, _fsnative, fsn2text

_DEFAULT_PLAYLIST_DIR = text2fsn(
    os.path.join(quodlibet.get_user_dir(), "playlists"))
"""Directory for playlist files"""

HIDDEN_RE = re.compile(r'^\.\w[^.]*')
"""Hidden-like files, to ignored"""


class PlaylistLibrary(Library[str, Playlist]):
    """A PlaylistLibrary listens to a SongLibrary, and keeps tracks of playlists
    of these songs.

    The library behaves like a dictionary: the keys are playlist names,
    the values are Playlist objects.
    """
    def __init__(self,
                 library: Library,
Пример #20
0
    def _rename(self, library):
        model = self.view.get_model()
        win = WritingWindow(self, len(model))
        win.show()
        was_changed = set()
        skip_all = self.__skip_interactive
        self.view.freeze_child_notify()
        should_move_art = config.getboolean("rename", "move_art")
        moveart_sets = {}
        remove_empty_dirs = config.getboolean("rename", "remove_empty_dirs")

        for entry in itervalues(model):
            if entry.new_name is None:
                continue
            song = entry.song
            old_name = entry.name
            old_pathfile = song['~filename']
            new_name = entry.new_name
            new_pathfile = ""
            # ensure target is a full path
            if os.path.abspath(new_name) != \
                   os.path.abspath(os.path.join(os.getcwd(), new_name)):
                new_pathfile = new_name
            else:
                # must be a relative pattern, so prefix the path
                new_pathfile = \
                    os.path.join(os.path.dirname(old_pathfile), new_name)

            try:
                library.rename(song, text2fsn(new_name), changed=was_changed)
            except Exception:
                util.print_exc()
                if skip_all:
                    continue
                RESPONSE_SKIP_ALL = 1
                msg = qltk.Message(
                    Gtk.MessageType.ERROR, win, _("Unable to rename file"),
                    _("Renaming <b>%(old-name)s</b> to <b>%(new-name)s</b> "
                      "failed. Possibly the target file already exists, "
                      "or you do not have permission to make the "
                      "new file or remove the old one.") % {
                        "old-name": util.escape(old_name),
                        "new-name": util.escape(new_name),
                      },
                    buttons=Gtk.ButtonsType.NONE)
                msg.add_button(_("Ignore _All Errors"), RESPONSE_SKIP_ALL)
                msg.add_icon_button(_("_Stop"), Icons.PROCESS_STOP,
                                    Gtk.ResponseType.CANCEL)
                msg.add_button(_("_Continue"), Gtk.ResponseType.OK)
                msg.set_default_response(Gtk.ResponseType.OK)
                resp = msg.run()
                skip_all |= (resp == RESPONSE_SKIP_ALL)
                # Preserve old behavior: shift-click is Ignore All
                mods = Gdk.Display.get_default().get_pointer()[3]
                skip_all |= mods & Gdk.ModifierType.SHIFT_MASK
                library.reload(song, changed=was_changed)
                if resp != Gtk.ResponseType.OK and resp != RESPONSE_SKIP_ALL:
                    break

            if should_move_art:
                self._moveart(moveart_sets, old_pathfile, new_pathfile, song)

            if remove_empty_dirs:
                path_old = os.path.dirname(old_pathfile)
                if not os.listdir(path_old):
                    try:
                        os.rmdir(path_old)
                        print_d("Removed empty directory: %r" % path_old, self)
                    except Exception:
                        util.print_exc()

            if win.step():
                break

        self.view.thaw_child_notify()
        win.destroy()
        library.changed(was_changed)
        self.save.set_sensitive(False)
Пример #21
0
def _dir_for(filelike):
    try:
        return os.path.dirname(path2fsn(filelike.name))
    except AttributeError:
        # Probably a URL
        return text2fsn(u'')
Пример #22
0
def test_text2fsn(text):
    assert isinstance(text2fsn(text), fsnative)
Пример #23
0
def _print_query_text(app):
    if app.browser.can_filter_text():
        return text2fsn(text_type(app.browser.get_filter_text()) + u"\n")
Пример #24
0
def fsencode(s):
    """Takes a `text_type` and returns a fsnative path"""

    return text2fsn(s)
Пример #25
0
 def path_activate(entry, *args):
     path = text2fsn(entry.get_text())
     if BansheeImport.USR_PATH != path:
         BansheeImport.USR_PATH = path
Пример #26
0
def test_text2fsn():
    with pytest.raises(TypeError):
        text2fsn(b"foo")
    assert text2fsn(u"foo") == fsnative(u"foo")
Пример #27
0
    def _rename(self, library):
        model = self.view.get_model()
        win = WritingWindow(self, len(model))
        win.show()
        was_changed = set()
        skip_all = self.__skip_interactive
        self.view.freeze_child_notify()
        should_move_art = config.getboolean("rename", "move_art")
        moveart_sets = {}
        remove_empty_dirs = config.getboolean("rename", "remove_empty_dirs")

        for entry in itervalues(model):
            if entry.new_name is None:
                continue
            song = entry.song
            old_name = entry.name
            old_pathfile = song['~filename']
            new_name = entry.new_name
            new_pathfile = ""
            # ensure target is a full path
            if os.path.abspath(new_name) != \
                   os.path.abspath(os.path.join(os.getcwd(), new_name)):
                new_pathfile = new_name
            else:
                # must be a relative pattern, so prefix the path
                new_pathfile = \
                    os.path.join(os.path.dirname(old_pathfile), new_name)

            try:
                library.rename(song, text2fsn(new_name), changed=was_changed)
            except Exception:
                util.print_exc()
                if skip_all:
                    continue
                RESPONSE_SKIP_ALL = 1
                msg = qltk.Message(
                    Gtk.MessageType.ERROR,
                    win,
                    _("Unable to rename file"),
                    _("Renaming <b>%(old-name)s</b> to <b>%(new-name)s</b> "
                      "failed. Possibly the target file already exists, "
                      "or you do not have permission to make the "
                      "new file or remove the old one.") % {
                          "old-name": util.escape(old_name),
                          "new-name": util.escape(new_name),
                      },
                    buttons=Gtk.ButtonsType.NONE)
                msg.add_button(_("Ignore _All Errors"), RESPONSE_SKIP_ALL)
                msg.add_icon_button(_("_Stop"), Icons.PROCESS_STOP,
                                    Gtk.ResponseType.CANCEL)
                msg.add_button(_("_Continue"), Gtk.ResponseType.OK)
                msg.set_default_response(Gtk.ResponseType.OK)
                resp = msg.run()
                skip_all |= (resp == RESPONSE_SKIP_ALL)
                # Preserve old behavior: shift-click is Ignore All
                mods = Gdk.Display.get_default().get_pointer()[3]
                skip_all |= mods & Gdk.ModifierType.SHIFT_MASK
                library.reload(song, changed=was_changed)
                if resp != Gtk.ResponseType.OK and resp != RESPONSE_SKIP_ALL:
                    break

            if should_move_art:
                self._moveart(moveart_sets, old_pathfile, new_pathfile, song)

            if remove_empty_dirs:
                path_old = os.path.dirname(old_pathfile)
                if not os.listdir(path_old):
                    try:
                        os.rmdir(path_old)
                        print_d("Removed empty directory: %r" % path_old, self)
                    except Exception:
                        util.print_exc()

            if win.step():
                break

        self.view.thaw_child_notify()
        win.destroy()
        library.changed(was_changed)
        self.save.set_sensitive(False)
Пример #28
0
def _dump_queue(app):
    window = app.window
    uris = []
    for song in window.playlist.q.get():
        uris.append(song("~uri"))
    return text2fsn(u"\n".join(uris) + u"\n")
Пример #29
0
 def Library(self):
     lib = SongFileLibrary(watch_dirs=[text2fsn(str(self.temp_path))])
     # Setup needs copools
     run_gtk_loop()
     return lib
Пример #30
0
def _dir_for(filelike):
    try:
        return os.path.dirname(path2fsn(filelike.name))
    except AttributeError:
        # Probably a URL
        return text2fsn(u'')
Пример #31
0
def test_text_fsn_roudntrip(text):
    if u"\x00" in text:
        return
    assert isinstance(fsn2text(text2fsn(text)), text_type)