Exemple #1
0
 def test_read_puz_locked_puzzle(self):
     puz_object = puz.read('fixtures/puz/nyt_locked.puz')
     puzzle = crossword.from_puz(puz_object)
     for x, y in puzzle.cells:
         self.assertEqual(puzzle[x, y].cell, None)
     self.assertEqual(puzzle[0, 0].solution, 'B')
     self.assertEqual(puzzle[14, 14].solution, 'N')
Exemple #2
0
 def test_to_ipuz_only_include_ipuz_specific_data(self):
     puz_object = puz.read('fixtures/puz/chronicle_20140815.puz')
     puzzle = crossword.from_puz(puz_object)
     ipuz_dict = crossword.to_ipuz(puzzle)
     self.assertNotIn('puzzletype', ipuz_dict)
     self.assertNotIn('fileversion', ipuz_dict)
     self.assertNotIn('extensions', ipuz_dict)
Exemple #3
0
 def test_read_puz_locked_puzzle(self):
     puz_object = puz.read('fixtures/puz/nyt_locked.puz')
     puzzle = crossword.from_puz(puz_object)
     for x, y in puzzle.cells:
         self.assertEqual(puzzle[x, y].cell, None)
     self.assertEqual(puzzle[0, 0].solution, 'B')
     self.assertEqual(puzzle[14, 14].solution, 'N')
 def test_to_ipuz_only_include_ipuz_specific_data(self):
     puz_object = puz.read('fixtures/puz/chronicle_20140815.puz')
     puzzle = crossword.from_puz(puz_object)
     ipuz_dict = crossword.to_ipuz(puzzle)
     self.assertNotIn('puzzletype', ipuz_dict)
     self.assertNotIn('fileversion', ipuz_dict)
     self.assertNotIn('extensions', ipuz_dict)
Exemple #5
0
 def test_read_and_write_round_trip(self):
     puz_object = puz.read('fixtures/puz/chronicle_20140815.puz')
     puzzle = crossword.from_puz(puz_object)
     new_puz_object = crossword.to_puz(puzzle)
     for attr in dir(puz_object):
         if not callable(getattr(puz_object, attr)):
             self.assertEqual(getattr(puz_object, attr),
                              getattr(new_puz_object, attr))
Exemple #6
0
 def test_read_puz_to_crossword(self):
     puz_object = puz.read('fixtures/puz/chronicle_20140815.puz')
     puzzle = crossword.from_puz(puz_object)
     self.assertEqual(puzzle.meta.title, 'Que Pasa? - August 15, 2014')
     self.assertEqual(puzzle.meta.creator,
                      'by Ian Livengood / Edited by Brad Wilber ')
     self.assertEqual(puzzle.block, '.')
     self.assertEqual(puzzle.clues.across[67], 'Jupiter, but not Zeus')
     self.assertEqual(puzzle.clues.down[60], 'Cadenza automaker')
Exemple #7
0
 def test_all_fixtures(self):
     for f in glob.glob('../puzfiles/*.puz'):
         puz_obj = puz.read(f)
         loaded_obj = crossword.to_puz(crossword.from_puz(puz_obj))
         for attr in dir(puz_obj):
             if not callable(getattr(puz_obj, attr)):
                 eq = getattr(puz_obj, attr) == getattr(loaded_obj, attr)
                 if not eq:
                     print(attr, eq)
 def test_all_fixtures(self):
     for f in glob.glob('../puzfiles/*.puz'):
         puz_obj = puz.read(f)
         loaded_obj = crossword.to_puz(crossword.from_puz(puz_obj))
         for attr in dir(puz_obj):
             if not callable(getattr(puz_obj, attr)):
                 eq = getattr(puz_obj, attr) == getattr(loaded_obj, attr)
                 if not eq:
                     print(attr, eq)
Exemple #9
0
 def test_read_and_write_round_trip(self):
     puz_object = puz.read('fixtures/puz/chronicle_20140815.puz')
     puzzle = crossword.from_puz(puz_object)
     new_puz_object = crossword.to_puz(puzzle)
     for attr in dir(puz_object):
         if not callable(getattr(puz_object, attr)):
             self.assertEqual(
                 getattr(puz_object, attr),
                 getattr(new_puz_object, attr)
             )
Exemple #10
0
 def test_read_puz_to_crossword(self):
     puz_object = puz.read('fixtures/puz/chronicle_20140815.puz')
     puzzle = crossword.from_puz(puz_object)
     self.assertEqual(
         puzzle.meta.title,
         'Que Pasa? - August 15, 2014'
     )
     self.assertEqual(
         puzzle.meta.creator,
         'by Ian Livengood / Edited by Brad Wilber '
     )
     self.assertEqual(puzzle.block, '.')
     self.assertEqual(puzzle.clues.across[67], 'Jupiter, but not Zeus')
     self.assertEqual(puzzle.clues.down[60], 'Cadenza automaker')
Exemple #11
0
def parse_puz(contents, filename):
    rebus_shorthands = list("⚷⚳♇♆⛢♄♃♂♁♀☿♹♸♷♶♵♴♳⅘⅗⅖⅕♚♛♜♝♞♟⚅⚄⚃⚂⚁⚀♣♦♥♠+&%$@?*zyxwvutsrqponmlkjihgfedcba0987654321")

    try:
        puzobj = puz.load(contents)
        puzzle = crossword.from_puz(puzobj)
    except puz.PuzzleFormatError as e:
        emsg = e.message
        if "<html>" in contents.decode('utf-8').lower():
            emsg += " (looks like html)"
        raise xdfile.PuzzleParseError(emsg)

    grid_dict = dict(list(zip(string.ascii_uppercase, string.ascii_uppercase)))

    xd = xdfile.xdfile('', filename)

    xd.set_header("Author", puzobj.author)
    xd.set_header("Copyright", puzobj.copyright)
    xd.set_header("Notes", puzobj.notes)
    xd.set_header("Postscript", "".join(x for x in puzobj.postscript if ord(x) >= ord(' ')))
    xd.set_header("Preamble", puzobj.preamble)

    xd.set_header("Title", puzobj.title)

    used_rebuses = {}  # [puz_rebus_gridvalue_as_string] -> our_rebus_gridvalue
    rebus = {}  # [our_rebus_gridvalue] -> full_cell
    r = puzobj.rebus()
    if r.has_rebus():
        grbs = puzobj.extensions[b"GRBS"]
        if sum(x for x in grbs if x != 0) > 0:   # check for an actual rebus
            for pair in puzobj.extensions[b"RTBL"].decode("cp1252").split(";"):
                pair = pair.strip()
                if not pair:
                    continue
                key, value = pair.split(":")
                rebuskey = rebus_shorthands.pop()
                used_rebuses[key] = rebuskey
                rebus[rebuskey] = decode(value)

            rebustr = xdfile.REBUS_SEP.join([("%s=%s" % (k, v)) for k, v in sorted(rebus.items())])
            xd.set_header("Rebus", rebustr)

    for r, row in enumerate(puzzle):
        rowstr = ""
        for c, cell in enumerate(row):
            if puzzle.block is None and cell.solution == '.':
                rowstr += xdfile.BLOCK_CHAR
            elif cell.solution == puzzle.block:
                rowstr += xdfile.BLOCK_CHAR
            elif cell.solution == ':':
                rowstr += xdfile.OPEN_CHAR
            elif cell == puzzle.empty:
                rowstr += xdfile.UNKNOWN_CHAR
            else:
                n = r * puzobj.width + c
                reb = puzobj.rebus()
                if reb.has_rebus() and n in reb.get_rebus_squares():
                    ch = str(reb.table[n] - 1)
                    rowstr += used_rebuses[ch]
                    cell.solution = rebus[used_rebuses[ch]]
                else:
                    ch = cell.solution
                    if ch not in grid_dict:
                        if ch in rebus_shorthands:
                            cellch = ch
                            rebus_shorthands.remove(ch)
                            warn("%s: unknown grid character '%s', assuming rebus of itself" % (filename, ch))
                        else:
                            cellch = rebus_shorthands.pop()
                            warn("%s: unknown grid character '%s', assuming rebus (as '%s')" % (filename, ch, cellch))

                        xd.set_header("Rebus", xd.get_header("Rebus") + " %s=%s" % (cellch, ch))

                        grid_dict[ch] = cellch
                    rowstr += grid_dict[ch]

        xd.grid.append(rowstr)

    assert xd.size() == (puzzle.width, puzzle.height), "non-matching grid sizes"

    # clues
    answers = {}

    for posdir, posnum, answer in xd.iteranswers():
        answers[posdir[0] + str(posnum)] = answer

    try:
        for number, clue in puzzle.clues.across():
            cluenum = "A" + str(number)
            if cluenum not in answers:
                raise xdfile.IncompletePuzzleParse(xd, "Clue number doesn't match grid: " + cluenum)
            xd.clues.append((("A", number), decode(clue), answers.get(cluenum, "")))

        # xd.append_clue_break()

        for number, clue in puzzle.clues.down():
            cluenum = "D" + str(number)
            if cluenum not in answers:
                raise xdfile.IncompletePuzzleParse(xd, "Clue doesn't match grid: " + cluenum)
            xd.clues.append((("D", number), decode(clue), answers.get(cluenum, "")))
    except KeyError as e:
        raise xdfile.IncompletePuzzleParse(xd, "Clue doesn't match grid: " + str(e))

    return xd
Exemple #12
0
def parse_puz(contents, filename):
    rebus_shorthands = list(
        "⚷⚳♇♆⛢♄♃♂♁♀☿♹♸♷♶♵♴♳⅘⅗⅖⅕♚♛♜♝♞♟⚅⚄⚃⚂⚁⚀♣♦♥♠+&%$@?*zyxwvutsrqponmlkjihgfedcba0987654321"
    )

    try:
        puzobj = puz.load(contents)
        puzzle = crossword.from_puz(puzobj)
    except puz.PuzzleFormatError as e:
        emsg = e.message
        if "<html>" in contents.decode('utf-8').lower():
            emsg += " (looks like html)"
        raise xdfile.PuzzleParseError(emsg)

    grid_dict = dict(list(zip(string.ascii_uppercase, string.ascii_uppercase)))

    xd = xdfile.xdfile('', filename)

    xd.set_header("Author", puzobj.author)
    xd.set_header("Copyright", puzobj.copyright)
    xd.set_header("Notes", puzobj.notes)
    xd.set_header("Postscript",
                  "".join(x for x in puzobj.postscript if ord(x) >= ord(' ')))
    xd.set_header("Preamble", puzobj.preamble)

    xd.set_header("Title", puzobj.title)

    used_rebuses = {}  # [puz_rebus_gridvalue_as_string] -> our_rebus_gridvalue
    rebus = {}  # [our_rebus_gridvalue] -> full_cell
    r = puzobj.rebus()
    if r.has_rebus():
        grbs = puzobj.extensions[b"GRBS"]
        if sum(x for x in grbs if x != 0) > 0:  # check for an actual rebus
            for pair in puzobj.extensions[b"RTBL"].decode("cp1252").split(";"):
                pair = pair.strip()
                if not pair:
                    continue
                key, value = pair.split(":")
                rebuskey = rebus_shorthands.pop()
                used_rebuses[key] = rebuskey
                rebus[rebuskey] = decode(value)

            rebustr = xdfile.REBUS_SEP.join([
                ("%s=%s" % (k, v)) for k, v in sorted(rebus.items())
            ])
            xd.set_header("Rebus", rebustr)

    for r, row in enumerate(puzzle):
        rowstr = ""
        for c, cell in enumerate(row):
            if puzzle.block is None and cell.solution == '.':
                rowstr += xdfile.BLOCK_CHAR
            elif cell.solution == puzzle.block:
                rowstr += xdfile.BLOCK_CHAR
            elif cell.solution == ':':
                rowstr += xdfile.OPEN_CHAR
            elif cell == puzzle.empty:
                rowstr += xdfile.UNKNOWN_CHAR
            else:
                n = r * puzobj.width + c
                reb = puzobj.rebus()
                if reb.has_rebus() and n in reb.get_rebus_squares():
                    ch = str(reb.table[n] - 1)
                    rowstr += used_rebuses[ch]
                    cell.solution = rebus[used_rebuses[ch]]
                else:
                    ch = cell.solution
                    if ch not in grid_dict:
                        if ch in rebus_shorthands:
                            cellch = ch
                            rebus_shorthands.remove(ch)
                            warn(
                                "%s: unknown grid character '%s', assuming rebus of itself"
                                % (filename, ch))
                        else:
                            cellch = rebus_shorthands.pop()
                            warn(
                                "%s: unknown grid character '%s', assuming rebus (as '%s')"
                                % (filename, ch, cellch))

                        xd.set_header(
                            "Rebus",
                            xd.get_header("Rebus") + " %s=%s" % (cellch, ch))

                        grid_dict[ch] = cellch
                    rowstr += grid_dict[ch]

        xd.grid.append(rowstr)

    assert xd.size() == (puzzle.width,
                         puzzle.height), "non-matching grid sizes"

    # clues
    answers = {}

    for posdir, posnum, answer in xd.iteranswers():
        answers[posdir[0] + str(posnum)] = answer

    try:
        for number, clue in puzzle.clues.across():
            cluenum = "A" + str(number)
            if cluenum not in answers:
                raise xdfile.IncompletePuzzleParse(
                    xd, "Clue number doesn't match grid: " + cluenum)
            xd.clues.append(
                (("A", number), decode(clue), answers.get(cluenum, "")))

        # xd.append_clue_break()

        for number, clue in puzzle.clues.down():
            cluenum = "D" + str(number)
            if cluenum not in answers:
                raise xdfile.IncompletePuzzleParse(
                    xd, "Clue doesn't match grid: " + cluenum)
            xd.clues.append(
                (("D", number), decode(clue), answers.get(cluenum, "")))
    except KeyError as e:
        raise xdfile.IncompletePuzzleParse(
            xd, "Clue doesn't match grid: " + str(e))

    return xd
Exemple #13
0
 def read_puzzle(self):
     puz_object = puz.read(
         '/Users/rachelprisock/Documents/Crosswords/NY_Time_Sat_Sample.puz')
     global puzzle
     puzzle = crossword.from_puz(puz_object)
Exemple #14
0
def parse_puz(contents):
    puz_object = puz.load(contents)
    puzzle = crossword.from_puz(puz_object)

    grid_dict = dict(zip(string.uppercase, string.uppercase))

    xd = xdfile.xdfile()

    md = dict([ (hdr_renames.get(k.lower(), k), v) for k, v in puzzle.meta() if v ])
    if " / " in md.get("author", ""):
        author, editor = md.get("author").split(" / ")
        editor = editor.strip()
        author = author.strip()
        author = author.lstrip("By ")
        editor = editor.lstrip("Edited by ")
        md["author"] = author
        md["editor"] = editor

    if "Washington Post" in md.get("copyright", ""):
        a = md["author"]
        if " - " in a:
            datestr, rest = a.split(" - ")
            md["date"] = reparse_date(datestr)
            if "By " in rest:
                md["title"], rest = rest.split(" By ")
            else:
                md["title"], rest = rest.split(" by ", 1)

            if "Edited by " in rest:
                md["author"], md["editor"] = rest.split(", Edited by ")
            elif "edited by " in rest:
                md["author"], md["editor"] = rest.split(", edited by ")
            else:
                md["author"] = rest

        md["copyright"] = md["copyright"].lstrip("Copyright")

    for k, v in sorted(md.items(), key=lambda x: hdr_order.index(x[0])):
        if v:
            k = k[0].upper() + k[1:].lower()
            v = decode(v.strip())
            v = v.replace(u"© ", "")
            xd.headers.append((k, v))

    answers = { }
    clue_num = 1

    for r, row in enumerate(puzzle):
        rowstr = ""
        for c, cell in enumerate(row):
            if puzzle.block is None and cell.solution == '.':
                rowstr += xdfile.BLOCK_CHAR
            elif puzzle.block == cell.solution:
                rowstr += xdfile.BLOCK_CHAR
            elif cell == puzzle.empty:
                rowstr += "."
            else:
                if cell.solution not in grid_dict:
                    grid_dict[cell.solution] = rebus_shorthands.pop()

                rowstr += grid_dict[cell.solution]

                # compute number shown in box
                new_clue = False
                if is_block(puzzle, c-1, r):  # across clue start
                    j = 0
                    answer = ""
                    while not is_block(puzzle, c+j, r):
                        answer += puzzle[c+j, r].solution
                        j += 1

                    if len(answer) > 1:
                        new_clue = True
                        answers["A"+str(clue_num)] = answer

                if is_block(puzzle, c, r-1):  # down clue start
                    j = 0
                    answer = ""
                    while not is_block(puzzle, c, r+j):
                        answer += puzzle[c, r+j].solution
                        j += 1

                    if len(answer) > 1:
                        new_clue = True
                        answers["D"+str(clue_num)] = answer

                if new_clue:
                    clue_num += 1
        xd.grid.append(rowstr)

    for number, clue in puzzle.clues.across():
        xd.clues.append((("A", number), decode(clue), answers["A"+str(number)]))

    for number, clue in puzzle.clues.down():
        xd.clues.append((("D", number), decode(clue), answers["D"+str(number)]))

    return xd
Exemple #15
0
def parse_puz(contents, filename):
    rebus_shorthands = list(u"♚♛♜♝♞♟⚅⚄⚃⚂⚁⚀♣♦♥♠Фθиλπφя+&%$@?*zyxwvutsrqponmlkjihgfedcba0987654321")

    if not filename.lower().endswith('.puz'):
        return
    puz_object = puz.load(contents)
    puzzle = crossword.from_puz(puz_object)

    grid_dict = dict(zip(string.uppercase, string.uppercase))

    xd = xdfile.xdfile()

    md = dict([ (k.lower(), v) for k, v in puzzle.meta() if v ])
    author = md.get("creator", "")
    if " / " in author:
        author, editor = author.split(" / ")
    else:
        editor = ""

    author = author.strip()
    editor = editor.strip()

    for editsep in [ "edited by ", "ed. " ]:
      try:
        i = author.lower().index(editsep)
        if i == 0:
            editor = author[len(editsep):]
            author = editor.split(",")[1]
        elif i > 0:
            assert not editor
            editor = author[i+len(editsep):]
            author = author[:i]
      except:
        pass

    author = author.strip()
    editor = editor.strip()

    while author.lower().startswith("by "):
        author = author[3:]

    if author and author[-1] in ",.":
        author = author[:-1]

    md["creator"] = author
    md["editor"] = editor

    for k, v in sorted(md.items(), key=lambda x: hdr_order.index(x[0])):
        if v:
            k = k[0].upper() + k[1:].lower()
            v = decode(v.strip())
            v = v.replace(u"©", "(c)")
            xd.headers.append((k, v))

    answers = { }
    clue_num = 1

    for r, row in enumerate(puzzle):
        rowstr = ""
        for c, cell in enumerate(row):
            if puzzle.block is None and cell.solution == '.':
                rowstr += xdfile.BLOCK_CHAR
            elif puzzle.block == cell.solution:
                rowstr += xdfile.BLOCK_CHAR
            elif cell == puzzle.empty:
                rowstr += "."
            else:
                if cell.solution not in grid_dict:
                    grid_dict[cell.solution] = rebus_shorthands.pop()

                rowstr += grid_dict[cell.solution]

                # compute number shown in box
                new_clue = False
                if is_block(puzzle, c-1, r):  # across clue start
                    j = 0
                    answer = ""
                    while not is_block(puzzle, c+j, r):
                        answer += puzzle[c+j, r].solution
                        j += 1

                    if len(answer) > 1:
                        new_clue = True
                        answers["A"+str(clue_num)] = answer

                if is_block(puzzle, c, r-1):  # down clue start
                    j = 0
                    answer = ""
                    while not is_block(puzzle, c, r+j):
                        answer += puzzle[c, r+j].solution
                        j += 1

                    if len(answer) > 1:
                        new_clue = True
                        answers["D"+str(clue_num)] = answer

                if new_clue:
                    clue_num += 1
        xd.grid.append(rowstr)

    for number, clue in puzzle.clues.across():
        xd.clues.append((("A", number), decode(clue), answers["A"+str(number)]))

    for number, clue in puzzle.clues.down():
        xd.clues.append((("D", number), decode(clue), answers["D"+str(number)]))

    return xd